import 'dart:convert'; import 'package:flutter_test/flutter_test.dart'; import 'package:http/http.dart' as http; import 'package:http/testing.dart'; import 'package:kooltap/models/remote_command.dart'; import 'package:kooltap/services/kooltap_api_client.dart'; KoolTapApiClient _clientReturning(http.Response response) { return KoolTapApiClient( client: MockClient((_) async => response), baseUrl: 'https://api.test', ); } http.Response _error(int status, String code, String message) { return http.Response( jsonEncode({ 'error': {'code': code, 'message': message}, }), status, ); } void main() { group('registerDevice', () { test('surfaces the server reason for a rejected code', () async { final client = _clientReturning( _error( 401, 'invalid_registration_code', 'Invalid or expired registration code', ), ); await expectLater( client.registerDevice( venueId: 'venue', deviceName: 'Bar', registrationCode: 'WRONG', ), throwsA( isA() .having((e) => e, 'type', isNot(isA())) .having((e) => e.code, 'code', 'invalid_registration_code') .having( (e) => e.message, 'message', 'Invalid or expired registration code', ), ), ); }); test('falls back to the reason phrase for a non-JSON error', () async { final client = _clientReturning( http.Response('', 502, reasonPhrase: 'Bad Gateway'), ); await expectLater( client.registerDevice( venueId: 'venue', deviceName: 'Bar', registrationCode: 'CODE', ), throwsA( isA().having( (e) => e.message, 'message', 'Bad Gateway', ), ), ); }); }); group('sync', () { test('treats a 401 as a revoked device token', () async { final client = _clientReturning( _error(401, 'invalid_token', 'Token revoked'), ); await expectLater( client.sync( token: 'token', request: const SyncRequest(deviceId: 'device', openTabs: []), ), throwsA(isA()), ); }); test('sends the app version', () async { late http.Request sent; final client = KoolTapApiClient( client: MockClient((request) async { sent = request; return http.Response('{}', 200); }), baseUrl: 'https://api.test', appVersion: '1.4.0', ); await client.sync( token: 'token', request: const SyncRequest(deviceId: 'device', openTabs: []), ); expect(sent.headers['X-App-Version'], '1.4.0'); }); test('treats a 426 as an app that must be updated', () async { final client = _clientReturning( _error(426, 'app_update_required', 'Update the app to version 1.4.0'), ); await expectLater( client.sync( token: 'token', request: const SyncRequest(deviceId: 'device', openTabs: []), ), throwsA( isA().having( (e) => e.message, 'message', 'Update the app to version 1.4.0', ), ), ); }); }); }