| Add a Mandelbrot example app, and a V kernel worth demonstrating 81540bb nandithebull 6h ago | 1 | // Widget-level checks on the explorer. These need the native library on the |
| 2 | // loader path: |
| 3 | // |
| 4 | // cd example && LD_LIBRARY_PATH=../build flutter test |
| 5 | import 'package:flutter/material.dart'; |
| 6 | import 'package:flutter_test/flutter_test.dart'; |
| 7 | import 'package:vflutter_ffi_example/main.dart'; |
| 8 | |
| 9 | /// pumpAndSettle cannot be used here: the in-flight-render spinner animates |
| 10 | /// indefinitely, and rendering runs on real isolates outside the fake clock. |
| 11 | Future<void> settle(WidgetTester tester) async { |
| 12 | for (var i = 0; i < 20; i++) { |
| 13 | await tester.pump(const Duration(milliseconds: 50)); |
| 14 | } |
| 15 | } |
| 16 | |
| 17 | void main() { |
| 18 | /// The side panel only exists in the wide layout, so size the surface like a |
| 19 | /// desktop window rather than the 800x600 test default. |
| 20 | Future<void> pumpWide(WidgetTester tester) async { |
| 21 | tester.view.physicalSize = const Size(1400, 900); |
| 22 | tester.view.devicePixelRatio = 1.0; |
| 23 | addTearDown(tester.view.reset); |
| 24 | await tester.pumpWidget(const ExampleApp()); |
| 25 | await tester.pump(const Duration(milliseconds: 100)); |
| 26 | } |
| 27 | |
| 28 | testWidgets('starts at the documented defaults, not the slider maxima', |
| 29 | (tester) async { |
| 30 | await pumpWide(tester); |
| 31 | |
| 32 | final sliders = tester.widgetList<Slider>(find.byType(Slider)).toList(); |
| 33 | expect(sliders, hasLength(2)); |
| 34 | expect(sliders[0].value, 400, reason: 'iterations should default to 400'); |
| 35 | expect(sliders[1].value, 4, reason: 'isolates should default to 4'); |
| 36 | }); |
| 37 | |
| 38 | testWidgets('reset restores the framing without touching iterations', |
| 39 | (tester) async { |
| 40 | await pumpWide(tester); |
| 41 | |
| 42 | // Move the iteration slider off its default, then reset the view. |
| 43 | await tester.drag(find.byType(Slider).first, const Offset(200, 0)); |
| 44 | await settle(tester); |
| 45 | final changed = |
| 46 | tester.widgetList<Slider>(find.byType(Slider)).first.value; |
| 47 | expect(changed, greaterThan(400), |
| 48 | reason: 'the drag should have raised the iteration count'); |
| 49 | |
| 50 | await tester.tap(find.text('Reset view')); |
| 51 | await settle(tester); |
| 52 | |
| 53 | // Reset owns pan/zoom only: the iteration setting must survive it. |
| 54 | expect(tester.widgetList<Slider>(find.byType(Slider)).first.value, changed); |
| 55 | expect(find.textContaining('zoom 1.0x'), findsOneWidget); |
| 56 | }); |
| 57 | |
| 58 | testWidgets('narrow layout lays out without overflowing', (tester) async { |
| 59 | // Regression guard: the controls used to be a ListView nested inside the |
| 60 | // page's ListView, which threw "Vertical viewport was given unbounded |
| 61 | // height" and broke the whole mobile layout. |
| 62 | tester.view.physicalSize = const Size(420, 900); |
| 63 | tester.view.devicePixelRatio = 1.0; |
| 64 | addTearDown(tester.view.reset); |
| 65 | |
| 66 | await tester.pumpWidget(const ExampleApp()); |
| 67 | await tester.pump(const Duration(milliseconds: 100)); |
| 68 | |
| 69 | expect(tester.takeException(), isNull); |
| 70 | }); |
| 71 | } |