mirror of
https://github.com/rustdesk/rustdesk.git
synced 2026-11-04 00:33:12 +00:00
* test: remove tests that do not pin user-visible behavior Apply the AGENTS.md test rules to the existing Rust and Flutter suites. A test is kept when it is the only coverage of user- or API-visible behavior, the regression test of a reported or fixed bug, a security boundary (one test per rejection class), or a check against an external reference. Tests that assert private state or the order of internal steps, pin review-round corner cases, or repeat what a kept test already covers are removed. Rust: 679 -> 298 tests. Dart: 118 -> 45 tests. Test-only helpers left without callers go with them (applyLastOnlineStateForTesting, terminalKeyboardRowWidth, debugBufferedInputCount, tokio's test-util dev feature), and cfg gates and visibility that existed only for the deleted tests are narrowed. Runtime behavior is unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WS1HTjp6UQuG43KEcQPq1R * test: keep tests that pin security and user-visible behavior Restore six tests that review showed are the only coverage of their behavior: - update metadata rejects an artifact file name with path components; - ICE candidates from another session are dropped; - KCP delivers every multi-segment frame queued before a close; - set_files rejects an empty name in a multi-file transfer; - a lopsided elongated cursor keeps its centre hotspot (#16242); - toggling Show hidden during a pending same-path read issues a new read. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WS1HTjp6UQuG43KEcQPq1R * test: keep offline update and key-exchange downgrade rejections Restore three tests that are the only coverage of their rejection class: - offline update metadata rejects a signed artifact with an http or credential-bearing URL; - offline verification rejects a renamed local file and a version that does not match the release; - a key-exchange pick lowered in transit leaves both sides unable to decrypt, so a v0 fallback after a failed v1 decrypt cannot pass unnoticed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WS1HTjp6UQuG43KEcQPq1R * test: keep the decomposed-grapheme and reconnect-cancel tests Each catches a plausible wrong change that passes every kept test: mapping the first scalar under a locked Ctrl turns é into \x05, and a reconnect that does not fail pending reads leaves them hanging until the 30 s timeout. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WS1HTjp6UQuG43KEcQPq1R --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
97 lines
3.5 KiB
Dart
97 lines
3.5 KiB
Dart
import 'package:flutter/gestures.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_hbb/models/terminal_mouse_handler.dart';
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:xterm/xterm.dart';
|
|
|
|
const _captureMouse = '\x1b[?1007l\x1b[?1000h\x1b[?1002h\x1b[?1006h\x1b[?1003h';
|
|
|
|
void main() {
|
|
late Terminal terminal;
|
|
late TerminalController controller;
|
|
late List<String> output;
|
|
|
|
setUp(() {
|
|
output = [];
|
|
terminal = Terminal()..onOutput = output.add;
|
|
controller = TerminalController();
|
|
});
|
|
|
|
Future<TerminalViewState> mount(WidgetTester tester) async {
|
|
await tester.pumpWidget(MaterialApp(
|
|
home: Align(
|
|
alignment: Alignment.topLeft,
|
|
child: Padding(
|
|
padding: const EdgeInsets.only(left: 30, top: 50),
|
|
child: SizedBox(
|
|
width: 400,
|
|
height: 120,
|
|
child: TerminalMouseInteraction(terminal, controller: controller),
|
|
),
|
|
),
|
|
),
|
|
));
|
|
terminal.write(List.generate(80, (i) => 'line $i\r\n').join());
|
|
await tester.pump();
|
|
final view = tester.state<TerminalViewState>(find.byType(TerminalView));
|
|
expect(view.widget.scrollController!.offset, greaterThan(0));
|
|
return view;
|
|
}
|
|
|
|
Future<void> scrollTrackpad(
|
|
WidgetTester tester, Offset point, double distance) async {
|
|
final pointer = TestPointer(2, PointerDeviceKind.trackpad);
|
|
await tester.sendEventToBinding(pointer.panZoomStart(point));
|
|
await tester.sendEventToBinding(
|
|
pointer.panZoomUpdate(point, pan: Offset(0, distance)));
|
|
await tester.sendEventToBinding(
|
|
pointer.panZoomUpdate(point, pan: Offset(0, distance * 2)));
|
|
await tester.sendEventToBinding(pointer.panZoomEnd());
|
|
await tester.pump();
|
|
}
|
|
|
|
testWidgets('alternate screen reports trackpad after main-screen history',
|
|
(tester) async {
|
|
final view = await mount(tester);
|
|
terminal.write('\x1b[?1049h$_captureMouse');
|
|
await tester.pump();
|
|
final render = view.renderTerminal;
|
|
final point = render.localToGlobal(
|
|
Offset(render.cellSize.width * 2.5, render.lineHeight * 1.5));
|
|
await scrollTrackpad(tester, point, render.lineHeight * 3);
|
|
|
|
expect(output, isNotEmpty);
|
|
expect(output, everyElement('\x1b[<64;3;2M'));
|
|
expect(view.widget.scrollController!.offset, 0);
|
|
expect(controller.selection, isNull);
|
|
}, variant: TargetPlatformVariant.only(TargetPlatform.macOS));
|
|
|
|
testWidgets('leaving alternate screen restores local trackpad scrollback',
|
|
(tester) async {
|
|
final view = await mount(tester);
|
|
terminal.write('\x1b[?1049h$_captureMouse');
|
|
await tester.pump();
|
|
terminal.write('\x1b[?1003l\x1b[?1002l\x1b[?1000l\x1b[?1006l\x1b[?1049l');
|
|
await tester.pump();
|
|
final before = view.widget.scrollController!.offset;
|
|
await scrollTrackpad(
|
|
tester, view.renderTerminal.localToGlobal(const Offset(40, 40)), 48);
|
|
|
|
expect(output, isEmpty);
|
|
expect(view.widget.scrollController!.offset, lessThan(before));
|
|
}, variant: TargetPlatformVariant.only(TargetPlatform.macOS));
|
|
|
|
testWidgets('alternate screen without mouse capture still simulates arrows',
|
|
(tester) async {
|
|
final view = await mount(tester);
|
|
terminal.write('\x1b[?1049h');
|
|
await tester.pump();
|
|
await scrollTrackpad(
|
|
tester, view.renderTerminal.localToGlobal(const Offset(40, 40)), -48);
|
|
|
|
expect(output, isNotEmpty);
|
|
expect(output, everyElement('\x1b[B'));
|
|
expect(view.widget.scrollController!.offset, 0);
|
|
}, variant: TargetPlatformVariant.only(TargetPlatform.macOS));
|
|
}
|