127 lines
4.0 KiB
Dart
127 lines
4.0 KiB
Dart
import 'dart:convert';
|
|
|
|
import 'package:ac_web/Api/Api.dart';
|
|
import 'package:ac_web/Layouts/DesktopView.dart';
|
|
import 'package:ac_web/Layouts/MainApp.dart';
|
|
import 'package:ac_web/Layouts/MobileView.dart';
|
|
import 'package:ac_web/Pages/AgentAvailabilities.dart';
|
|
import 'package:ac_web/Widgets/LatestReportEntry.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:http/http.dart' as http;
|
|
import 'package:http/testing.dart';
|
|
|
|
/// The pages talk to `AcApi.instance`, so every test runs against a mocked
|
|
/// backend instead of a real one.
|
|
void configureMockedApi() {
|
|
final client = MockClient((request) async {
|
|
|
|
final String path = request.url.path;
|
|
|
|
if (path.endsWith('agents')) {
|
|
return http.Response(
|
|
jsonEncode([
|
|
{
|
|
'Name': 'Ada',
|
|
'Type': 'CODER',
|
|
'LastSeen': '2026-08-28T12:00:00Z',
|
|
'Status': 'WORKING',
|
|
'Tasks': <dynamic>[],
|
|
},
|
|
]),
|
|
200,
|
|
headers: {'content-type': 'application/json'},
|
|
);
|
|
}
|
|
|
|
if (path.endsWith('reports')) {
|
|
return http.Response(
|
|
jsonEncode([
|
|
{
|
|
'Id': 'report-1',
|
|
'Title': 'Nightly log',
|
|
'Author': 'Ada',
|
|
'Timestamp': '2026-08-27T10:00:00Z',
|
|
'Type': 'LOG',
|
|
'Text': 'All good.',
|
|
},
|
|
]),
|
|
200,
|
|
headers: {'content-type': 'application/json'},
|
|
);
|
|
}
|
|
|
|
return http.Response('Not found', 404);
|
|
});
|
|
|
|
AcApi.configure(const ApiConfig(host: 'api.local', port: 5000), httpClient: client);
|
|
}
|
|
|
|
/// Lets the futures of the mocked api complete. `pumpAndSettle` cannot be used
|
|
/// here because the loading state shows an endlessly spinning indicator.
|
|
Future<void> settleApiCalls(WidgetTester tester) async {
|
|
await tester.pump();
|
|
await tester.pump();
|
|
}
|
|
|
|
/// Resizes the test window and restores it again after the test.
|
|
void setWindowSize(WidgetTester tester, Size size) {
|
|
tester.view.physicalSize = size;
|
|
tester.view.devicePixelRatio = 1.0;
|
|
addTearDown(tester.view.reset);
|
|
}
|
|
|
|
void main() {
|
|
setUp(configureMockedApi);
|
|
tearDown(AcApi.reset);
|
|
|
|
testWidgets('narrow windows show the mobile layout with its navigation bar', (tester) async {
|
|
setWindowSize(tester, const Size(400, 800));
|
|
|
|
await tester.pumpWidget(const MainApp());
|
|
|
|
expect(find.byType(MobileView), findsOneWidget);
|
|
expect(find.byType(DesktopView), findsNothing);
|
|
expect(find.byType(NavigationBar), findsOneWidget);
|
|
|
|
// The latest reports page is the one the mobile view starts on.
|
|
expect(find.byType(CircularProgressIndicator), findsOneWidget);
|
|
|
|
await settleApiCalls(tester);
|
|
|
|
expect(find.byType(LatestReportEntry), findsOneWidget);
|
|
expect(find.text('Nightly log'), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('wide windows show all three columns next to each other', (tester) async {
|
|
setWindowSize(tester, const Size(DesktopView.minimumWidth + 200, 900));
|
|
|
|
await tester.pumpWidget(const MainApp());
|
|
await settleApiCalls(tester);
|
|
|
|
expect(find.byType(DesktopView), findsOneWidget);
|
|
expect(find.byType(MobileView), findsNothing);
|
|
|
|
// Reports on the left, the latest reports in the center, agents on the right.
|
|
expect(find.text('Code Review'), findsOneWidget);
|
|
expect(find.byType(LatestReportEntry), findsOneWidget);
|
|
expect(find.byType(AgentAvailabilities), findsOneWidget);
|
|
expect(find.text('Ada'), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('a failing api is reported instead of spinning forever', (tester) async {
|
|
AcApi.configure(
|
|
const ApiConfig(host: 'api.local', port: 5000),
|
|
httpClient: MockClient((request) async => throw http.ClientException('offline')),
|
|
);
|
|
|
|
setWindowSize(tester, const Size(400, 800));
|
|
|
|
await tester.pumpWidget(const MainApp());
|
|
await settleApiCalls(tester);
|
|
|
|
expect(find.byType(CircularProgressIndicator), findsNothing);
|
|
expect(find.textContaining('Could not load reports'), findsOneWidget);
|
|
});
|
|
}
|