// Device-independent widget test of the eraser path (the user reported eraser // reliability issues). A stylus drag through a committed stroke in eraser mode // must fire onEraseStroke for that stroke. import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:badnote/editor/canvas/pen_canvas.dart'; import 'package:badnote/editor/canvas/pen_stroke.dart'; void main() { const pageSize = Size(400, 600); // A horizontal stroke through the normalized center (0.5, 0.5). PenStroke centerStroke() => PenStroke( points: const [ PenPoint(0.4, 0.5, 0.5), PenPoint(0.5, 0.5, 0.5), PenPoint(0.6, 0.5, 0.5), ], color: 0xFF000000, width: 0.004, kind: PenStrokeKind.pen, ); Widget host({ required List strokes, required void Function(int, List) onErase, required TransformationController controller, }) => MaterialApp( home: Scaffold( body: Center( child: SizedBox( width: pageSize.width, height: pageSize.height, child: PenCanvas( pageWidget: Container(color: const Color(0xFFEEEEEE)), pageSize: pageSize, strokes: strokes, transformationController: controller, tool: CanvasTool.eraser, color: const Color(0xFF000000), strokeWidth: 0.004, onStrokeComplete: (_) {}, onEraseStroke: onErase, ), ), ), ), ); testWidgets('eraser tool: a stylus pass over a stroke fires onEraseStroke', (tester) async { final erased = []; final controller = TransformationController(); addTearDown(controller.dispose); await tester.pumpWidget(host( strokes: [centerStroke()], onErase: (i, _) => erased.add(i), controller: controller, )); // Drag a stylus vertically through the screen center (= normalized 0.5,0.5, // where the stroke sits). final center = tester.getCenter(find.byType(PenCanvas)); final g = await tester.startGesture(center + const Offset(0, -20), kind: PointerDeviceKind.stylus); await g.moveBy(const Offset(0, 20)); await g.moveBy(const Offset(0, 20)); await g.up(); await tester.pump(); expect(erased, contains(0), reason: 'the center stroke should be erased'); }); testWidgets('eraser tool: a pass far from any stroke erases nothing', (tester) async { final erased = []; final controller = TransformationController(); addTearDown(controller.dispose); await tester.pumpWidget(host( strokes: [centerStroke()], onErase: (i, _) => erased.add(i), controller: controller, )); // Drag in the top-left corner, far from the centered stroke. final topLeft = tester.getTopLeft(find.byType(PenCanvas)); final g = await tester.startGesture(topLeft + const Offset(10, 10), kind: PointerDeviceKind.stylus); await g.moveBy(const Offset(5, 5)); await g.up(); await tester.pump(); expect(erased, isEmpty); }); }