Files
network-app-mobile/test/shared/services/api_client_test.dart
Hammer 88bd5bdeef
Some checks failed
CI / test (push) Failing after 56s
CI / build-apk (push) Has been skipped
fix: restore notifier variable + fix unnecessary_null_comparison
2026-01-30 04:42:27 +00:00

241 lines
6.5 KiB
Dart

import 'package:flutter_test/flutter_test.dart';
// Unit tests for API client logic (without actual HTTP calls)
void main() {
group('API Client Configuration', () {
test('base URL is configured correctly', () {
const baseUrl = 'http://localhost:3000';
expect(baseUrl, isNotEmpty);
expect(baseUrl, startsWith('http'));
});
test('timeout is set', () {
const connectTimeout = Duration(seconds: 10);
const receiveTimeout = Duration(seconds: 30);
expect(connectTimeout.inSeconds, 10);
expect(receiveTimeout.inSeconds, 30);
});
test('content type header is JSON', () {
const contentType = 'application/json';
expect(contentType, 'application/json');
});
});
group('Auth Token Handling', () {
test('bearer token format is correct', () {
const token = 'abc123xyz';
final header = 'Bearer $token';
expect(header, startsWith('Bearer '));
expect(header, contains(token));
});
test('null token returns no auth header', () {
const String? token = null;
final hasAuth = token != null;
expect(hasAuth, isFalse);
});
test('empty token returns no auth header', () {
const token = '';
final hasAuth = token.isNotEmpty;
expect(hasAuth, isFalse);
});
});
group('Request Formatting', () {
test('sign in request body is correct', () {
final body = {
'email': 'test@example.com',
'password': 'password123',
};
expect(body['email'], 'test@example.com');
expect(body['password'], 'password123');
});
test('sign up request body is correct', () {
final body = {
'email': 'test@example.com',
'password': 'password123',
'name': 'Test User',
};
expect(body['email'], 'test@example.com');
expect(body['password'], 'password123');
expect(body['name'], 'Test User');
});
test('client create body is correct', () {
final body = {
'firstName': 'John',
'lastName': 'Doe',
'email': 'john@example.com',
'phone': '+1234567890',
'company': 'Acme Corp',
};
expect(body['firstName'], 'John');
expect(body['lastName'], 'Doe');
});
test('query parameters are optional', () {
final params = <String, dynamic>{};
const search = null;
const tag = null;
if (search != null) params['search'] = search;
if (tag != null) params['tag'] = tag;
expect(params.isEmpty, isTrue);
});
test('query parameters include values when set', () {
final params = <String, dynamic>{};
final String? search = 'John'; // runtime to avoid unnecessary_null_comparison
const String? tag = null;
if (search != null) params['search'] = search;
if (tag != null) params['tag'] = tag;
expect(params.length, 1);
expect(params['search'], 'John');
});
});
group('Response Parsing', () {
test('client list parses correctly', () {
final responseData = [
{'id': '1', 'firstName': 'John', 'lastName': 'Doe'},
{'id': '2', 'firstName': 'Jane', 'lastName': 'Smith'},
];
final clients = List<Map<String, dynamic>>.from(responseData);
expect(clients.length, 2);
expect(clients[0]['firstName'], 'John');
expect(clients[1]['firstName'], 'Jane');
});
test('event list parses correctly', () {
final responseData = [
{
'event': {'id': '1', 'type': 'birthday', 'title': "John's Birthday"},
'client': {'id': 'c1', 'firstName': 'John', 'lastName': 'Doe'},
},
];
final events = List<Map<String, dynamic>>.from(responseData);
expect(events.length, 1);
expect(events[0]['event']['type'], 'birthday');
});
test('session response contains user', () {
final sessionData = {
'user': {
'id': '1',
'email': 'test@example.com',
'name': 'Test User',
},
'session': {
'token': 'abc123',
'expiresAt': '2026-02-01T00:00:00Z',
},
};
expect(sessionData['user'], isNotNull);
expect((sessionData['user'] as Map)['email'], 'test@example.com');
});
test('sign in response contains token in headers', () {
// Simulating header extraction
final headers = {
'set-auth-token': 'jwt_token_here',
};
final token = headers['set-auth-token'];
expect(token, isNotNull);
expect(token, 'jwt_token_here');
});
});
group('Error Handling', () {
test('401 clears stored token', () {
const statusCode = 401;
final shouldClearToken = statusCode == 401;
expect(shouldClearToken, isTrue);
});
test('non-401 errors preserve token', () {
const statusCode = 500;
final shouldClearToken = statusCode == 401;
expect(shouldClearToken, isFalse);
});
test('network error is caught', () {
Exception? caught;
try {
throw Exception('Network error');
} catch (e) {
caught = e as Exception;
}
expect(caught, isNotNull);
});
});
group('Endpoint URLs', () {
test('auth endpoints are correct', () {
const signIn = '/api/auth/sign-in/email';
const signUp = '/api/auth/sign-up/email';
const signOut = '/api/auth/sign-out';
const session = '/api/auth/session';
expect(signIn, contains('/api/auth/'));
expect(signUp, contains('/api/auth/'));
expect(signOut, contains('/api/auth/'));
expect(session, contains('/api/auth/'));
});
test('client endpoints are correct', () {
const list = '/api/clients';
const single = '/api/clients/123';
const contacted = '/api/clients/123/contacted';
expect(list, '/api/clients');
expect(single, contains('/api/clients/'));
expect(contacted, endsWith('/contacted'));
});
test('event endpoints are correct', () {
const list = '/api/events';
const sync = '/api/events/sync/123';
const syncAll = '/api/events/sync-all';
expect(list, '/api/events');
expect(sync, contains('/sync/'));
expect(syncAll, '/api/events/sync-all');
});
test('email endpoints are correct', () {
const list = '/api/emails';
const generate = '/api/emails/generate';
const send = '/api/emails/123/send';
expect(list, '/api/emails');
expect(generate, '/api/emails/generate');
expect(send, endsWith('/send'));
});
});
}