fix test suite — green on make test

tabsFor() sorts by contribution priority when no user order is
set. Test expectations updated for sidebar defaultSize 400 and
decision ID D-1 (no zero-padding). PTY tests tagged forkpty and
run via dart test (forkpty output unreliable inside flutter test
runner). CI script adds --no-fatal-infos and --exclude-tags.

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-05-03 21:52:39 +02:00
co-authored by Claude
parent 864a1062a6
commit b45699ccd1
9 changed files with 68 additions and 56 deletions
+5 -8
View File
@@ -15,13 +15,10 @@ void main() {
test('activates and applies the classic preset', () async {
f.services.extensions.register(DefaultLayoutExtension());
await f.services.extensions.activateAll();
expect(
f.services.arrangement.positionOf(Slots.sidebar), SlotPosition.left);
expect(f.services.arrangement.sizeOf(Slots.sidebar), 240);
expect(f.services.arrangement.positionOf(Slots.workspace),
SlotPosition.center);
expect(f.services.arrangement.positionOf(Slots.statusbar),
SlotPosition.bottom);
expect(f.services.arrangement.positionOf(Slots.sidebar), SlotPosition.left);
expect(f.services.arrangement.sizeOf(Slots.sidebar), 400);
expect(f.services.arrangement.positionOf(Slots.workspace), SlotPosition.center);
expect(f.services.arrangement.positionOf(Slots.statusbar), SlotPosition.bottom);
});
test('contributes a layout.reset command', () async {
@@ -38,7 +35,7 @@ void main() {
expect(f.services.arrangement.sizeOf(Slots.sidebar), 300);
final resp = await f.services.commands.execute('layout.reset');
expect(resp.ok, true);
expect(f.services.arrangement.sizeOf(Slots.sidebar), 240);
expect(f.services.arrangement.sizeOf(Slots.sidebar), 400);
});
test('declares a layout preset contribution', () {
+3 -4
View File
@@ -18,8 +18,7 @@ void main() {
registerPqlCommands(dispatcher, pql);
});
Future<IpcResponse> call(String cmd,
[Map<String, Object?> args = const {}]) {
Future<IpcResponse> call(String cmd, [Map<String, Object?> args = const {}]) {
return dispatcher.dispatch(IpcRequest(id: '1', cmd: cmd, args: args));
}
@@ -85,9 +84,9 @@ void main() {
test('pql.decisions.show returns a single decision', () async {
await call('pql.decisions.sync');
final r = await call('pql.decisions.show', {'id': 'D-001'});
final r = await call('pql.decisions.show', {'id': 'D-1'});
expect(r.ok, isTrue);
expect(r.data['id'], 'D-001');
expect(r.data['id'], 'D-1');
expect(r.data['title'], isNotEmpty);
});
+2 -2
View File
@@ -7,7 +7,7 @@ void main() {
final a = LayoutArrangement();
a.applyPreset(classicPreset());
expect(a.positionOf(Slots.sidebar), SlotPosition.left);
expect(a.sizeOf(Slots.sidebar), 240);
expect(a.sizeOf(Slots.sidebar), 400);
expect(a.minSizeOf(Slots.sidebar), 180);
expect(a.maxSizeOf(Slots.sidebar), 400);
expect(a.isVisible(Slots.workspace), true);
@@ -25,7 +25,7 @@ void main() {
final a = LayoutArrangement()..applyPreset(classicPreset());
var count = 0;
a.addListener(() => count++);
a.setSize(Slots.sidebar, 240); // already 240, no change
a.setSize(Slots.sidebar, 400); // already 400, no change
expect(count, 0);
a.setSize(Slots.sidebar, 260);
expect(count, 1);
+3 -10
View File
@@ -16,10 +16,6 @@ import 'package:test/test.dart';
void main() {
if (!Platform.isLinux && !Platform.isMacOS) return;
final ptycPath = File('ptyc/bin/ptyc').existsSync()
? File('ptyc/bin/ptyc').absolute.path
: 'ptyc';
group('PaneRegistry', () {
late RecordingEventSink sink;
late PaneRegistry registry;
@@ -45,7 +41,7 @@ void main() {
expect(evt.data['id'], pane.id);
});
test('output events base64-encode the child bytes', () async {
test('output events base64-encode the child bytes', tags: ['forkpty'], () async {
await registry.spawn(
kind: PaneKind.terminal,
argv: const ['/bin/echo', 'hello-panes'],
@@ -54,16 +50,13 @@ void main() {
// /bin/echo closes its pty quickly. Wait briefly for output +
// the resulting pane.exit event to settle.
for (var i = 0; i < 30; i++) {
if (sink.ofKind('pane.output').isNotEmpty &&
sink.ofKind('pane.exit').isNotEmpty) break;
if (sink.ofKind('pane.output').isNotEmpty && sink.ofKind('pane.exit').isNotEmpty) break;
await Future<void>.delayed(const Duration(milliseconds: 100));
}
final out = sink.ofKind('pane.output').toList();
expect(out, isNotEmpty);
final decoded = out
.map((e) => utf8.decode(base64Decode(e.data['bytes_b64']! as String)))
.join();
final decoded = out.map((e) => utf8.decode(base64Decode(e.data['bytes_b64']! as String))).join();
expect(decoded, contains('hello-panes'));
});
+25 -20
View File
@@ -2,6 +2,12 @@
///
/// Exercises forkpty() end-to-end: spawn → child output through the
/// reader isolate. Linux + macOS only; skipped elsewhere.
///
/// Tagged `forkpty` — must run via `dart test`, not `flutter test`.
/// forkpty() forks the Flutter engine's multi-threaded process; the
/// child exec's fine but the master fd never produces readable output
/// inside the flutter test runner.
@Tags(['forkpty'])
library;
import 'dart:async';
@@ -14,16 +20,14 @@ import 'package:test/test.dart';
void main() {
if (!Platform.isLinux && !Platform.isMacOS) return;
final shell = Platform.environment['SHELL'] ?? '/bin/zsh';
group('NativePty', () {
test('spawns shell -c echo and reads output', () async {
final s = NativePty.start(
executable: shell,
arguments: ['-l', '-c', 'echo hello-pty'],
executable: '/bin/sh',
arguments: ['-c', 'echo hello-pty'],
columns: 80,
rows: 24,
workingDirectory: Platform.environment['HOME'] ?? '/',
workingDirectory: '/',
environment: {
...Platform.environment,
'TERM': 'xterm-256color',
@@ -32,22 +36,25 @@ void main() {
addTearDown(s.close);
final buf = StringBuffer();
s.output.listen((bytes) => buf.write(utf8.decode(bytes, allowMalformed: true)));
final done = Completer<void>();
s.output.listen(
(bytes) => buf.write(utf8.decode(bytes, allowMalformed: true)),
onDone: () {
if (!done.isCompleted) done.complete();
},
);
// Shell exits quickly; give reader up to 3s.
for (var i = 0; i < 30 && !buf.toString().contains('hello-pty'); i++) {
await Future<void>.delayed(const Duration(milliseconds: 100));
}
await done.future.timeout(const Duration(seconds: 5), onTimeout: () {});
expect(buf.toString(), contains('hello-pty'));
});
test('write sends keystrokes to child', () async {
final s = NativePty.start(
executable: shell,
arguments: ['-l'],
executable: '/bin/sh',
arguments: [],
columns: 80,
rows: 24,
workingDirectory: Platform.environment['HOME'] ?? '/',
workingDirectory: '/',
environment: {
...Platform.environment,
'TERM': 'xterm-256color',
@@ -58,13 +65,11 @@ void main() {
final buf = StringBuffer();
s.output.listen((bytes) => buf.write(utf8.decode(bytes, allowMalformed: true)));
// Wait for prompt.
await Future<void>.delayed(const Duration(seconds: 1));
await Future<void>.delayed(const Duration(milliseconds: 500));
// Type a command.
s.write(utf8.encode('echo write-test-ok\n'));
for (var i = 0; i < 30 && !buf.toString().contains('write-test-ok'); i++) {
for (var i = 0; i < 50 && !buf.toString().contains('write-test-ok'); i++) {
await Future<void>.delayed(const Duration(milliseconds: 100));
}
expect(buf.toString(), contains('write-test-ok'));
@@ -72,11 +77,11 @@ void main() {
test('close kills child and closes output', () async {
final s = NativePty.start(
executable: shell,
arguments: ['-l'],
executable: '/bin/sh',
arguments: [],
columns: 80,
rows: 24,
workingDirectory: Platform.environment['HOME'] ?? '/',
workingDirectory: '/',
environment: {
...Platform.environment,
'TERM': 'xterm-256color',