Files
BadNote/test/pen_coordinate_widget_test.dart
Akiba So 3cfb793803
Some checks failed
CI / Windows build (push) Has been cancelled
test: ink coordinate mapping through zoom (device-independent)
A stylus point drawn at 2x zoom maps to the correct normalized page coordinate
(canvas-local 200,300 → scene 100,150 → normalized 0.25,0.25), guarding that ink
stays glued to the page under zoom/pan — the core own-canvas invariant.

flutter analyze lib/editor clean; 238/238 tests (+1).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 03:49:44 +08:00

59 lines
2.0 KiB
Dart

// 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 = <PenStroke>[];
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 <PenStroke>[],
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));
});
}