// Device-independent correctness guard: a drawn point must map to the right // NORMALIZED page coordinate through a non-identity (zoomed) transform, so ink // stays glued to the page under zoom/pan. 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); testWidgets('a stylus point maps to correct normalized coords at 2x zoom', (tester) async { final committed = []; final controller = TransformationController() ..value = (Matrix4.identity()..scaleByDouble(2.0, 2.0, 2.0, 1)); addTearDown(controller.dispose); await tester.pumpWidget(MaterialApp( home: Scaffold( body: Center( child: SizedBox( width: pageSize.width, height: pageSize.height, child: PenCanvas( pageWidget: Container(color: const Color(0xFFEEEEEE)), pageSize: pageSize, strokes: const [], transformationController: controller, tool: CanvasTool.pen, color: const Color(0xFF000000), strokeWidth: 0.004, onStrokeComplete: committed.add, onEraseStroke: (_, __) {}, ), ), ), ), )); // Down at the canvas-local point (200, 300). At 2x scale, scene = (100,150), // normalized = (100/400, 150/600) = (0.25, 0.25). final topLeft = tester.getTopLeft(find.byType(PenCanvas)); final g = await tester.startGesture(topLeft + const Offset(200, 300), kind: PointerDeviceKind.stylus); await g.moveBy(const Offset(8, 8)); // make it a stroke, not a tap await g.up(); await tester.pump(); expect(committed, hasLength(1)); final first = committed.single.points.first; expect(first.x, closeTo(0.25, 1e-3)); expect(first.y, closeTo(0.25, 1e-3)); }); }