127 lines
3.7 KiB
Dart
127 lines
3.7 KiB
Dart
import 'dart:ui';
|
|
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
|
|
import 'package:userfront/features/dashboard/domain/dashboard_providers.dart';
|
|
import 'package:userfront/features/dashboard/domain/models.dart';
|
|
import 'package:userfront/i18n.dart';
|
|
|
|
AuditLogEntry _log(String id) {
|
|
return AuditLogEntry.fromJson({
|
|
'event_id': id,
|
|
'timestamp': '2026-02-06T00:00:00Z',
|
|
'status': 'success',
|
|
'session_id': 's-$id',
|
|
});
|
|
}
|
|
|
|
Future<void> _drainMicrotasks() async {
|
|
for (var i = 0; i < 5; i++) {
|
|
await Future<void>.delayed(Duration.zero);
|
|
}
|
|
}
|
|
|
|
void main() {
|
|
TestWidgetsFlutterBinding.ensureInitialized();
|
|
final dispatcher = TestWidgetsFlutterBinding.instance.platformDispatcher;
|
|
dispatcher.localeTestValue = const Locale('ko');
|
|
dispatcher.localesTestValue = const [Locale('ko')];
|
|
|
|
tearDownAll(() {
|
|
dispatcher.clearLocaleTestValue();
|
|
dispatcher.clearLocalesTestValue();
|
|
});
|
|
|
|
test('AuthTimelineNotifier는 초기 페이지를 로드한다', () async {
|
|
final cursors = <String?>[];
|
|
final container = ProviderContainer(
|
|
overrides: [
|
|
authTimelineFetcherProvider.overrideWithValue(({String? cursor}) async {
|
|
cursors.add(cursor);
|
|
return AuditPage(items: [_log('1')], nextCursor: 'next');
|
|
}),
|
|
],
|
|
);
|
|
|
|
container.read(authTimelineProvider.notifier);
|
|
|
|
await _drainMicrotasks();
|
|
|
|
final state = container.read(authTimelineProvider);
|
|
expect(state.items.length, 1);
|
|
expect(state.nextCursor, 'next');
|
|
expect(cursors, [null]);
|
|
container.dispose();
|
|
});
|
|
|
|
test('AuthTimelineNotifier는 다음 커서를 사용해 추가 로드한다', () async {
|
|
final cursors = <String?>[];
|
|
final container = ProviderContainer(
|
|
overrides: [
|
|
authTimelineFetcherProvider.overrideWithValue(({String? cursor}) async {
|
|
cursors.add(cursor);
|
|
if (cursor == null) {
|
|
return AuditPage(items: [_log('1')], nextCursor: 'next');
|
|
}
|
|
return AuditPage(items: [_log('2')], nextCursor: '');
|
|
}),
|
|
],
|
|
);
|
|
|
|
final notifier = container.read(authTimelineProvider.notifier);
|
|
await _drainMicrotasks();
|
|
await notifier.loadMore();
|
|
|
|
final state = container.read(authTimelineProvider);
|
|
expect(state.items.map((e) => e.eventId).toList(), ['1', '2']);
|
|
expect(cursors, [null, 'next']);
|
|
container.dispose();
|
|
});
|
|
|
|
test('AuthTimelineNotifier는 커서가 없으면 추가 로드를 하지 않는다', () async {
|
|
var callCount = 0;
|
|
final container = ProviderContainer(
|
|
overrides: [
|
|
authTimelineFetcherProvider.overrideWithValue(({String? cursor}) async {
|
|
callCount += 1;
|
|
return AuditPage(items: [_log('1')], nextCursor: '');
|
|
}),
|
|
],
|
|
);
|
|
|
|
final notifier = container.read(authTimelineProvider.notifier);
|
|
await _drainMicrotasks();
|
|
await notifier.loadMore();
|
|
|
|
expect(callCount, 1);
|
|
expect(container.read(authTimelineProvider).items.length, 1);
|
|
container.dispose();
|
|
});
|
|
|
|
test('AuthTimelineNotifier는 실패 시 오류 메시지를 보관한다', () async {
|
|
final container = ProviderContainer(
|
|
overrides: [
|
|
authTimelineFetcherProvider.overrideWithValue(({String? cursor}) async {
|
|
throw Exception('fail');
|
|
}),
|
|
],
|
|
);
|
|
|
|
container.read(authTimelineProvider.notifier);
|
|
|
|
await _drainMicrotasks();
|
|
|
|
final state = container.read(authTimelineProvider);
|
|
expect(state.items.isEmpty, true);
|
|
expect(
|
|
state.error,
|
|
tr(
|
|
'msg.userfront.dashboard.timeline.load_error',
|
|
fallback: '접속이력을 불러오지 못했습니다.',
|
|
),
|
|
);
|
|
container.dispose();
|
|
});
|
|
}
|