test: eraser path widget guard (device-independent)
Some checks failed
CI / Windows build (push) Has been cancelled
Some checks failed
CI / Windows build (push) Has been cancelled
A stylus pass through a committed stroke in eraser mode fires onEraseStroke for it; a pass far from any stroke erases nothing. Locks in the eraser path (the user reported eraser reliability issues) as a regression guard without a device. flutter analyze lib/editor clean; 237/237 tests (+2). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
101
test/pen_eraser_widget_test.dart
Normal file
101
test/pen_eraser_widget_test.dart
Normal file
@@ -0,0 +1,101 @@
|
||||
// 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<PenStroke> strokes,
|
||||
required void Function(int, List<PenStroke>) 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 = <int>[];
|
||||
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 = <int>[];
|
||||
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);
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user