Files
rustdesk/flutter/test/cursor_default_test.dart
rustdeskandClaude Opus 5.5 f48b6c0d72 cursor: say what Future.sync defers, and give the default cursor time on a slow runner
The comment on the fetch in restorePixels read as if the fetch were put
off; it runs at once, and Future.sync only turns its throw into an error
the await hands over later, which is what keeps the notify out of the
build.

cursor_default_test gave the default cursor 100 ms to decode, which a
slow runner may miss. It cannot wait for the cursor itself, since asking
for it would make it; it now waits 500 ms.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EZ49AbZJYfm8NTp5yDPMab
2026-09-25 11:55:39 +08:00

67 lines
2.4 KiB
Dart

import 'dart:io';
import 'package:flutter/services.dart';
import 'package:flutter_custom_cursor/flutter_custom_cursor.dart';
import 'package:flutter_hbb/common.dart';
import 'package:flutter_hbb/generated_bridge.dart' show CursorShape;
import 'package:flutter_hbb/models/model.dart';
import 'package:flutter_hbb/native/custom_cursor.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:uuid/uuid.dart';
// A file of its own: nothing else in this isolate has made the default cursor before the model.
/// A core that keeps no shape.
class _Cursor extends CursorModel {
_Cursor(FFI ffi) : super(WeakReference(ffi));
@override
Future<CursorShape?> fetchCursorShape(String id) => Future.value(null);
@override
bool get showsRemoteCursor => false;
}
class _FFI extends Fake implements FFI {
_FFI() {
ffiModel = FfiModel(WeakReference(this));
cursorModel = _Cursor(this);
}
@override
final SessionID sessionId = const Uuid().v4obj();
@override
late final FfiModel ffiModel;
@override
late final CursorModel cursorModel;
}
String? _key(MouseCursor cursor) =>
cursor is FlutterCustomMemoryImageCursor ? cursor.key : null;
void main() {
final binding = TestWidgetsFlutterBinding.ensureInitialized();
final channel = Platform.isWindows
? SystemChannels.mouseCursor
: const MethodChannel('flutter_custom_cursor');
binding.defaultBinaryMessenger.setMockMethodCallHandler(channel,
(call) async => (call.arguments as Map<dynamic, dynamic>)['name']);
test('a shape the core cannot give shows the default cursor at once',
() async {
final ffi = _FFI();
final cursor = ffi.cursorModel;
final pixels = Uint8List.fromList(List.generate(8 * 8 * 4, (i) => i % 256));
await ffi.ffiModel.handleCursorData('1', 0, 0, 8, 8, pixels);
final shown = _key(buildCursorOfCache(cursor, 1.0, cursor.cache));
final evt = {'id': '2'};
ffi.ffiModel.updateLastCursorId(evt);
ffi.ffiModel.handleCursorId(evt);
// Not a wait for the default cursor itself: asking for it would make it.
await Future<void>.delayed(const Duration(milliseconds: 500));
expect(cursor.cache, isNull);
final built = _key(buildCursorOfCache(
cursor, 1.0, cursor.cache ?? preDefaultCursor.cache));
expect(built, isNot(shown));
expect(built, contains('_${kPreDefaultCursorId}_'));
cursor.disposeImages();
});
}