cyberhybridhub/test/admin/widgets/sync_run_expansion_tile_test.dart
2026-05-31 11:17:12 -05:00

149 lines
4.4 KiB
Dart

import 'package:cyberhybridhub/admin/models/backfill_sync_item.dart';
import 'package:cyberhybridhub/admin/models/sync_run_event.dart';
import 'package:cyberhybridhub/admin/repositories/sync_run_log_repository.dart';
import 'package:cyberhybridhub/admin/widgets/sync_run_expansion_tile.dart';
import 'package:cyberhybridhub/theme/app_theme.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
SyncRunEvent _event({
required int id,
required String kind,
required DateTime startedAt,
String? error,
SyncRunSeverity severity = SyncRunSeverity.ok,
SyncRunStatus status = SyncRunStatus.success,
}) {
return SyncRunEvent(
id: id,
kind: kind,
startedAt: startedAt,
finishedAt: startedAt.add(const Duration(minutes: 1)),
rowsWritten: kind == 'cleanup' ? 0 : 100,
rowsRemoved: kind == 'cleanup' ? 4200 : 0,
error: error,
severity: severity,
status: status,
durationMs: 60000,
summary: error ?? '100 bar rows written',
);
}
void main() {
testWidgets('shows severity chip and full error text when expanded', (
WidgetTester tester,
) async {
const String errorText =
'AlpacaMarketDataException: getBarsRange rate limited: 429';
final SyncRunEvent event = _event(
id: 7,
kind: 'backfill',
startedAt: DateTime.utc(2026, 5, 27, 10),
error: errorText,
severity: SyncRunSeverity.rateLimit,
status: SyncRunStatus.failed,
);
await tester.pumpWidget(
MaterialApp(
theme: buildAppTheme(),
home: Scaffold(
body: SyncRunExpansionTile(
event: event,
now: DateTime.utc(2026, 5, 27, 12),
),
),
),
);
expect(find.text('Partial success'), findsNothing);
expect(find.textContaining('Failed'), findsWidgets);
expect(find.textContaining('Rate limited'), findsNothing);
await tester.tap(find.byType(ExpansionTile));
await tester.pumpAndSettle();
expect(find.byKey(const Key('sync-run-error-7')), findsOneWidget);
expect(find.text(errorText), findsWidgets);
expect(find.textContaining('raw'), findsNothing);
expect(find.text('HTTP status'), findsOneWidget);
expect(find.text('429'), findsOneWidget);
});
testWidgets('renders very long error text without raw field labels', (
WidgetTester tester,
) async {
tester.view.physicalSize = const Size(800, 1600);
tester.view.devicePixelRatio = 1.0;
addTearDown(tester.view.reset);
final String longError = 'E' * 500;
final SyncRunEvent event = _event(
id: 8,
kind: 'backfill',
startedAt: DateTime.utc(2026, 5, 27, 10),
error: longError,
severity: SyncRunSeverity.error,
status: SyncRunStatus.failed,
);
await tester.pumpWidget(
MaterialApp(
theme: buildAppTheme(),
home: Scaffold(
body: SyncRunExpansionTile(event: event),
),
),
);
await tester.tap(find.byType(ExpansionTile));
await tester.pumpAndSettle();
expect(find.text(longError), findsWidgets);
expect(find.textContaining('"raw"'), findsNothing);
});
testWidgets('backfill items show Alpaca start wire string for DB spot checks', (
WidgetTester tester,
) async {
const String slotWire = '2026-05-26T08:00:00Z';
final SyncRunEvent event = SyncRunEvent(
id: 9,
kind: 'backfill',
startedAt: DateTime.utc(2026, 5, 27, 10),
finishedAt: DateTime.utc(2026, 5, 27, 10, 1),
rowsWritten: 0,
rowsRemoved: 0,
severity: SyncRunSeverity.warning,
status: SyncRunStatus.partial,
durationMs: 60000,
summary: '0 bar rows written',
error: 'partial sync saved (0 rows)',
backfillItems: <BackfillSyncItem>[
BackfillSyncItem(
slotStart: DateTime.utc(2026, 5, 26, 8),
slotStartWire: slotWire,
symbols: <String>['A', 'AA'],
),
],
);
await tester.pumpWidget(
MaterialApp(
theme: buildAppTheme(),
home: Scaffold(
body: SyncRunExpansionTile(event: event),
),
),
);
await tester.tap(find.byType(ExpansionTile));
await tester.pumpAndSettle();
expect(find.text(slotWire), findsOneWidget);
expect(find.textContaining('2 assets: A, AA'), findsOneWidget);
expect(
find.textContaining('Backfill fetches (Alpaca start / raw.slot_start)'),
findsOneWidget,
);
});
}