The Garage SDKs, in the open
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
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
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;
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user