feat: replace xterm with flutter_alacritty for true industrial-grade rendering

This commit is contained in:
2026-08-01 19:53:30 +08:00
parent 7e4236e2f3
commit 562662c1bd
12 changed files with 744 additions and 375 deletions

View File

@@ -1,49 +1,51 @@
// 端到端集成测试:桌面端连接层 ↔ Rust 服务端。
// 端到端集成测试:桌面端连接层RttyPtyBackend↔ Rust 服务端。
//
// 运行前需先启动 Rust 服务端cd .. && cargo run
// 运行flutter test test/e2e_ws_test.dart
import 'package:flutter_test/flutter_test.dart';
import 'package:xterm/xterm.dart';
import 'dart:typed_data';
import 'package:rtty_desktop/src/rtty_client.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:rtty_desktop/src/rtty_pty_backend.dart';
import 'support.dart';
void main() {
TestWidgetsFlutterBinding.ensureInitialized();
test('RttyClient connects to Rust server and renders command output',
test('RttyPtyBackend connects to Rust server and receives raw ANSI output',
() async {
if (!await isServerUp('127.0.0.1', 8080)) {
markTestSkipped('Rtty server not running');
return;
}
final terminal = Terminal();
final client = RttyClient(terminal);
final backend = RttyPtyBackend();
final states = <ConnState>[];
String? sessionId;
final raw = StringBuffer();
client.onStateChanged = (s) => states.add(s);
client.onReady = (id, cols, rows) => sessionId = '$id:$cols:$rows';
client.onRawData = (d) => raw.write(d);
backend.onStateChanged = (s) => states.add(s);
backend.onReady = (id, cols, rows) => sessionId = '$id:$cols:$rows';
backend.output.listen((Uint8List b) {
raw.write(String.fromCharCodes(b));
});
await client.connect(host: '127.0.0.1', port: 8080);
await backend.connect(host: '127.0.0.1', port: 8080);
// 等待连接就绪socket 已连接 + 收到 ready 帧)。
final deadline = DateTime.now().add(const Duration(seconds: 5));
while ((!client.isConnected || sessionId == null) &&
while ((backend.state != ConnState.connected || sessionId == null) &&
DateTime.now().isBefore(deadline)) {
await Future<void>.delayed(const Duration(milliseconds: 100));
}
expect(client.isConnected, isTrue,
expect(backend.state, ConnState.connected,
reason: '未能连接服务端 states=$states');
expect(sessionId, isNotNull,
reason: '未收到 ready 帧 states=$states');
expect(sessionId, isNotNull, reason: '未收到 ready 帧 states=$states');
// 发送命令,等待回显。
client.sendInput('echo RTTY_E2E_${DateTime.now().millisecondsSinceEpoch}\r\n');
backend.write(Uint8List.fromList(
'echo RTTY_E2E_${DateTime.now().millisecondsSinceEpoch}\r\n'.codeUnits));
String? matchedLine;
final outDeadline = DateTime.now().add(const Duration(seconds: 8));
@@ -57,9 +59,9 @@ void main() {
expect(matchedLine, isNotNull,
reason: '未捕获到命令回显。流末尾:'
'${raw.toString().split('').length > 200 ? raw.toString().substring(raw.toString().length - 200) : raw.toString()}');
'${raw.toString().length > 200 ? raw.toString().substring(raw.toString().length - 200) : raw.toString()}');
await client.disconnect();
expect(client.state, ConnState.disconnected);
await backend.close();
expect(backend.state, ConnState.disconnected);
});
}