190 lines
6.4 KiB
Dart
190 lines
6.4 KiB
Dart
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:dio/dio.dart';
|
|
|
|
import 'package:lanebow/services/public_event_service.dart';
|
|
import 'package:lanebow/utils/web_storage.dart';
|
|
|
|
class FakeHttp implements PublicHttpClient {
|
|
Response<dynamic>? lastResponse;
|
|
Map<String, dynamic>? lastHeaders;
|
|
String? lastPath;
|
|
dynamic lastData;
|
|
|
|
int statusCode = 200;
|
|
Map<String, dynamic> responseData = const {'ok': true};
|
|
|
|
@override
|
|
Future<Response<dynamic>> get(String path, {Map<String, dynamic>? headers}) async {
|
|
lastPath = path;
|
|
lastData = null;
|
|
lastHeaders = headers;
|
|
if (statusCode >= 400) {
|
|
throw DioException(
|
|
requestOptions: RequestOptions(path: path),
|
|
response: Response(requestOptions: RequestOptions(path: path), statusCode: statusCode, data: responseData),
|
|
type: DioExceptionType.badResponse,
|
|
);
|
|
}
|
|
lastResponse = Response(requestOptions: RequestOptions(path: path), statusCode: statusCode, data: responseData);
|
|
return lastResponse!;
|
|
}
|
|
|
|
@override
|
|
Future<Response<dynamic>> post(String path, {data, Map<String, dynamic>? headers}) async {
|
|
lastPath = path;
|
|
lastData = data;
|
|
lastHeaders = headers;
|
|
if (statusCode >= 400) {
|
|
throw DioException(
|
|
requestOptions: RequestOptions(path: path),
|
|
response: Response(requestOptions: RequestOptions(path: path), statusCode: statusCode, data: responseData),
|
|
type: DioExceptionType.badResponse,
|
|
);
|
|
}
|
|
lastResponse = Response(requestOptions: RequestOptions(path: path), statusCode: statusCode, data: responseData);
|
|
return lastResponse!;
|
|
}
|
|
|
|
@override
|
|
Future<Response<dynamic>> put(String path, {data, Map<String, dynamic>? headers}) async {
|
|
lastPath = path;
|
|
lastData = data;
|
|
lastHeaders = headers;
|
|
if (statusCode >= 400) {
|
|
throw DioException(
|
|
requestOptions: RequestOptions(path: path),
|
|
response: Response(requestOptions: RequestOptions(path: path), statusCode: statusCode, data: responseData),
|
|
type: DioExceptionType.badResponse,
|
|
);
|
|
}
|
|
lastResponse = Response(requestOptions: RequestOptions(path: path), statusCode: statusCode, data: responseData);
|
|
return lastResponse!;
|
|
}
|
|
}
|
|
|
|
void main() {
|
|
group('PublicEventService.enter', () {
|
|
test('saves token when response includes token', () async {
|
|
final fake = FakeHttp()
|
|
..statusCode = 200
|
|
..responseData = {'token': 'TKN', 'event': {'id': 1}};
|
|
final svc = PublicEventService.forTest(fake);
|
|
final hash = 'abc123';
|
|
|
|
// ensure empty
|
|
WebStorage.removeItem(PublicEventService.tokenKey(hash));
|
|
|
|
final data = await svc.enter(hash, password: 'pw');
|
|
expect(data['token'], 'TKN');
|
|
expect(WebStorage.getItem(PublicEventService.tokenKey(hash)), 'TKN');
|
|
expect(fake.lastPath, '/api/public/$hash');
|
|
});
|
|
|
|
test('removes saved token on 401/403', () async {
|
|
final fake = FakeHttp()
|
|
..statusCode = 401
|
|
..responseData = {'message': 'unauthorized'};
|
|
final svc = PublicEventService.forTest(fake);
|
|
final hash = 'abc401';
|
|
|
|
// preset token
|
|
WebStorage.setItem(PublicEventService.tokenKey(hash), 'OLD');
|
|
|
|
await expectLater(
|
|
svc.enter(hash, password: 'wrong'),
|
|
throwsA(isA<DioException>()),
|
|
);
|
|
expect(WebStorage.getItem(PublicEventService.tokenKey(hash)), isNull);
|
|
});
|
|
});
|
|
|
|
group('PublicEventService.updateScore', () {
|
|
test('sends Authorization header when token saved', () async {
|
|
final fake = FakeHttp()
|
|
..statusCode = 200
|
|
..responseData = {'ok': true};
|
|
final svc = PublicEventService.forTest(fake);
|
|
final hash = 'hhh';
|
|
WebStorage.setItem(PublicEventService.tokenKey(hash), 'TKN2');
|
|
|
|
await svc.updateScore(
|
|
hash,
|
|
participantId: '10',
|
|
gameNumber: 1,
|
|
score: 200,
|
|
handicap: 0,
|
|
);
|
|
|
|
expect(fake.lastPath, '/api/public/$hash/score');
|
|
expect(fake.lastHeaders?['Authorization'], 'Bearer TKN2');
|
|
expect(fake.lastData['participantId'], '10');
|
|
expect(fake.lastData['gameNumber'], 1);
|
|
expect(fake.lastData['score'], 200);
|
|
});
|
|
});
|
|
|
|
group('PublicEventService.fetchEvent', () {
|
|
test('uses GET and Authorization header when token saved', () async {
|
|
final fake = FakeHttp()
|
|
..statusCode = 200
|
|
..responseData = {'event': {'id': 'E1'}};
|
|
final svc = PublicEventService.forTest(fake);
|
|
final hash = 'fetch1';
|
|
WebStorage.setItem(PublicEventService.tokenKey(hash), 'TKF');
|
|
|
|
final data = await svc.fetchEvent(hash);
|
|
expect(data['event']['id'], 'E1');
|
|
expect(fake.lastPath, '/api/public/$hash');
|
|
expect(fake.lastHeaders?['Authorization'], 'Bearer TKF');
|
|
});
|
|
});
|
|
|
|
group('PublicEventService.enter edge cases', () {
|
|
test('404 does not remove saved token', () async {
|
|
final fake = FakeHttp()
|
|
..statusCode = 404
|
|
..responseData = {'message': 'not found'};
|
|
final svc = PublicEventService.forTest(fake);
|
|
final hash = 'nf404';
|
|
WebStorage.setItem(PublicEventService.tokenKey(hash), 'KEEP');
|
|
await expectLater(svc.enter(hash), throwsA(isA<DioException>()));
|
|
expect(WebStorage.getItem(PublicEventService.tokenKey(hash)), 'KEEP');
|
|
});
|
|
});
|
|
|
|
group('PublicEventService.addGuest', () {
|
|
test('sends payload and header', () async {
|
|
final fake = FakeHttp()
|
|
..statusCode = 200
|
|
..responseData = {'ok': true};
|
|
final svc = PublicEventService.forTest(fake);
|
|
final hash = 'guest';
|
|
WebStorage.setItem(PublicEventService.tokenKey(hash), 'TG');
|
|
|
|
await svc.addGuest(hash, name: '홍길동', phone: '010', gender: 'M', average: 190);
|
|
expect(fake.lastPath, '/api/public/$hash/guest');
|
|
expect(fake.lastHeaders?['Authorization'], 'Bearer TG');
|
|
expect(fake.lastData['name'], '홍길동');
|
|
expect(fake.lastData['phone'], '010');
|
|
expect(fake.lastData['gender'], 'M');
|
|
expect(fake.lastData['average'], 190);
|
|
});
|
|
});
|
|
|
|
group('PublicEventService.updateScore errors', () {
|
|
test('propagates server error 500', () async {
|
|
final fake = FakeHttp()
|
|
..statusCode = 500
|
|
..responseData = {'message': 'oops'};
|
|
final svc = PublicEventService.forTest(fake);
|
|
final hash = 'err';
|
|
WebStorage.setItem(PublicEventService.tokenKey(hash), 'TE');
|
|
|
|
await expectLater(
|
|
svc.updateScore(hash, participantId: 'p1', gameNumber: 1, score: 100),
|
|
throwsA(isA<DioException>()),
|
|
);
|
|
});
|
|
});
|
|
}
|