garage_auth, garage_entitlements, garage_iap and garage_ui, moved out of Garage-Services and Metro-Map-Maker into one public repo. MIT, one readme, docs under docs/. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013F4NWNvYcdeSgqbWMT1VQ7
96 lines
3.1 KiB
Dart
96 lines
3.1 KiB
Dart
import "package:flutter/foundation.dart";
|
|
import "package:flutter/services.dart";
|
|
import "package:flutter/widgets.dart";
|
|
import "package:flutter_test/flutter_test.dart";
|
|
import "package:garage_ui/garage_ui.dart";
|
|
import "package:garage_ui/platform/cursor_lock.dart";
|
|
|
|
import "support/test_scheme.dart";
|
|
|
|
// Drag-to-scrub used to be macOS only without anybody saying so. The moment
|
|
// the drag threshold was crossed the field handed everything over to
|
|
// CursorLock and ignored Flutters own pointer stream forever after - and
|
|
// CursorLock has no native handler off macOS, so on web (and windows/linux)
|
|
// the deltas it was waiting on never turned up. The field just froze on the
|
|
// value it started on.
|
|
|
|
Future<TextEditingController> pumpField(
|
|
WidgetTester tester, {
|
|
String text = "10.0",
|
|
}) async {
|
|
final controller = TextEditingController(text: text);
|
|
await tester.pumpWidget(
|
|
Directionality(
|
|
textDirection: TextDirection.ltr,
|
|
child: GarageTheme(
|
|
data: ThemeData(colorScheme: testScheme),
|
|
child: Center(
|
|
child: SizedBox(
|
|
width: 200,
|
|
child: TextField(
|
|
controller: controller,
|
|
features: const [InputFeature.scrub()],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
await tester.pump();
|
|
return controller;
|
|
}
|
|
|
|
void main() {
|
|
testWidgets("no native cursor lock - the pointer stream drives the scrub", (
|
|
tester,
|
|
) async {
|
|
debugDefaultTargetPlatformOverride = TargetPlatform.linux;
|
|
expect(CursorLock.isSupported, isFalse);
|
|
|
|
final controller = await pumpField(tester);
|
|
|
|
// real pointer moves arrive a few px at a time, so drive it that way
|
|
// rather than as one giant jump. default sensitivity is 0.1/px, and the
|
|
// first move only arms the drag (it's the one the click threshold eats),
|
|
// so 100 counted px = +10.
|
|
final gesture = await tester.startGesture(
|
|
tester.getCenter(find.byType(TextField)),
|
|
);
|
|
for (var i = 0; i < 21; i++) {
|
|
await gesture.moveBy(const Offset(5, 0));
|
|
await tester.pump();
|
|
}
|
|
await gesture.up();
|
|
await tester.pump();
|
|
|
|
expect(double.parse(controller.text), closeTo(20.0, 0.5));
|
|
debugDefaultTargetPlatformOverride = null;
|
|
});
|
|
|
|
testWidgets("with a native cursor lock the pointer stream is ignored", (
|
|
tester,
|
|
) async {
|
|
debugDefaultTargetPlatformOverride = TargetPlatform.macOS;
|
|
const channel = MethodChannel("garage/cursor_lock");
|
|
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger
|
|
.setMockMethodCallHandler(channel, (_) async => null);
|
|
|
|
final controller = await pumpField(tester);
|
|
|
|
final gesture = await tester.startGesture(
|
|
tester.getCenter(find.byType(TextField)),
|
|
);
|
|
for (var i = 0; i < 21; i++) {
|
|
await gesture.moveBy(const Offset(5, 0));
|
|
await tester.pump();
|
|
}
|
|
await gesture.up();
|
|
await tester.pump();
|
|
|
|
// the native side would have sent deltas back over the channel; nothing
|
|
// did here, so the value must not have budged.
|
|
expect(double.parse(controller.text), closeTo(10.0, 1e-9));
|
|
debugDefaultTargetPlatformOverride = null;
|
|
});
|
|
}
|