Files
BaronSSO/baron-sso/userfront/test/dashboard_providers_test.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();
});
}