// Widget-level smoke tests. // // These drive the real UI against a FakeIperf3Runner: no MethodChannel, no // native library, no device. That is only possible because the presentation // layer depends on the Iperf3Runner interface rather than on Iperf3Service. import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:iperf3gui/domain/models/iperf3_event.dart'; import 'package:iperf3gui/domain/models/iperf3_result.dart'; import 'package:iperf3gui/main.dart'; import 'support/fake_iperf3_runner.dart'; void main() { testWidgets('App smoke test', (WidgetTester tester) async { await tester.pumpWidget(Iperf3GuiApp(runner: FakeIperf3Runner())); expect(find.text('iperf3-gui'), findsOneWidget); expect(find.text('GO'), findsOneWidget); expect(find.text('Ready'), findsOneWidget); }); testWidgets('runs a test and renders streamed results', (tester) async { final runner = FakeIperf3Runner(); runner.onRun = (config) async { runner.emit(Iperf3Start( targetHost: config.server, targetPort: config.port, protocol: 'TCP', streamCount: config.parallelStreams, )); runner.emit(const Iperf3Interval( start: 0, end: 1, bytes: 98566144, bitsPerSecond: 788410352, )); await Future.delayed(Duration.zero); return const Iperf3Result(rawOutput: '', exitCode: 0); }; await tester.pumpWidget(Iperf3GuiApp(runner: runner)); await tester.tap(find.text('GO')); await tester.pumpAndSettle(); expect(runner.runCallCount, equals(1)); expect(find.text('Test complete'), findsOneWidget); expect(find.textContaining('788 Mbits/sec'), findsWidgets); // The stat row is driven by the parsed interval series. expect(find.text('peak'), findsOneWidget); }); testWidgets('shows a stop button while running and can stop', (tester) async { final runner = FakeIperf3Runner(); final gate = Completer(); runner.onRun = (_) => gate.future; await tester.pumpWidget(Iperf3GuiApp(runner: runner)); await tester.tap(find.text('GO')); await tester.pump(); expect(find.text('STOP'), findsOneWidget); expect(find.text('Running…'), findsOneWidget); await tester.tap(find.text('STOP')); await tester.pump(); expect(runner.stopCallCount, equals(1)); gate.complete(const Iperf3Result( rawOutput: '', exitCode: 0, stopped: true)); await tester.pumpAndSettle(); expect(find.text('Stopped'), findsOneWidget); }); testWidgets('rejects an empty server address', (tester) async { final runner = FakeIperf3Runner(); await tester.pumpWidget(Iperf3GuiApp(runner: runner)); await tester.enterText(find.byType(TextField).first, ''); await tester.tap(find.text('GO')); await tester.pumpAndSettle(); expect(runner.runCallCount, equals(0)); expect(find.textContaining('Invalid configuration'), findsOneWidget); }); }