cover the T-410 epic's pane handlers and Activity tab

The epic's new lib surface dropped coverage to 94.87% (floor 95). Add
the missing tests: the command-bus → _send path end-to-end in the pane
(effort respawn with --effort, invalid-level notice, both pickers,
set_permission_mode write, sidebar navigation messages, /memory
editor.open, /help summary, TUI-only notice without a session write)
and ActivityTabView's USAGE block + placeholder branch. 95.14% after.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-06-12 14:34:07 +02:00
co-authored by Claude Fable 5
parent 5a5b60a148
commit 57978c54c5
2 changed files with 126 additions and 0 deletions
@@ -0,0 +1,37 @@
/// Direct tests for ActivityTabView (T-415): the USAGE block renders parsed
/// /usage values; the empty state still shows under the control strip.
library;
import 'package:clide/builtin/claude/src/claude_stats.dart';
import 'package:clide/builtin/claude/src/claude_status.dart' show ClaudeUsage;
import 'package:clide/builtin/claude/src/meta_sidebar/activity_tab.dart';
import 'package:flutter_test/flutter_test.dart';
import '../../helpers/kernel_fixture.dart';
import '../../helpers/widget_harness.dart';
void main() {
late KernelFixture f;
setUp(() async => f = await KernelFixture.create());
tearDown(() => f.dispose());
testWidgets('renders the USAGE block from parsed /usage values', (tester) async {
const usage = ClaudeUsage(session: '15% used · resets Jun 12, 3:39pm', week: '53% used · resets Jun 15, 6:59pm', weekSonnet: '0% used');
await tester.pumpWidget(harness(f, const ActivityTabView(stats: ClaudeStats(), primaryStatus: null, config: null, usage: usage)));
await tester.pump();
expect(find.text('USAGE'), findsOneWidget);
expect(find.text('15% used · resets Jun 12, 3:39pm'), findsOneWidget);
expect(find.text('53% used · resets Jun 15, 6:59pm'), findsOneWidget);
expect(find.text('0% used'), findsOneWidget);
});
testWidgets('no stats and no usage → the control strip plus the placeholder', (tester) async {
await tester.pumpWidget(harness(f, const ActivityTabView(stats: ClaudeStats(), primaryStatus: null, config: null)));
await tester.pump();
expect(find.text('SESSION'), findsOneWidget); // controls always present
expect(find.text('No activity recorded yet.'), findsOneWidget);
expect(find.text('USAGE'), findsNothing);
});
}
+89
View File
@@ -339,4 +339,93 @@ void main() {
expect(created, hasLength(1));
expect(proc.killed, isFalse);
});
// ---- T-410 epic: bus-driven owned commands (T-412/T-413/T-414) ----------
// The sidebar controls publish slash-command text on builtin.claude/command;
// the primary pane executes it through _send — the same path as typing.
group('command bus → owned slash commands', () {
Future<void> command(WidgetTester tester, String text) => act(tester, () => f.services.messages.publish('builtin.claude', 'command', {'text': text}));
testWidgets('/effort <level> respawns the session carrying --effort (T-412)', (tester) async {
await mount(tester, const ClaudePane(showChrome: false));
expect(created, hasLength(1));
await command(tester, '/effort xhigh');
expect(created, hasLength(2), reason: 'effort change = respawn');
final args = spawnArgs.last;
final i = args.indexOf('--effort');
expect(i, isNonNegative, reason: 'args: $args');
expect(args[i + 1], 'xhigh');
// The pane records the level on the session status (the wire never
// reports effort).
expect(orch.byId('primary')!.session.status.effort, 'xhigh');
});
testWidgets('/effort with an unknown level notices and does NOT respawn (T-412)', (tester) async {
await mount(tester, const ClaudePane(showChrome: false));
await command(tester, '/effort warp9');
expect(created, hasLength(1));
expect(find.textContaining('unknown effort "warp9"'), findsOneWidget);
});
testWidgets('bare /effort opens the effort picker in the interaction zone (T-412)', (tester) async {
await mount(tester, const ClaudePane(showChrome: false));
await command(tester, '/effort');
expect(find.byType(ModelPickerCard), findsOneWidget);
expect(find.text('effort'), findsOneWidget); // the picker title
});
testWidgets('/permissions <mode> sends set_permission_mode (T-413)', (tester) async {
await mount(tester, const ClaudePane(showChrome: false));
await command(tester, '/permissions plan');
final proc = created.single;
expect(proc.writes.any((w) => w.contains('set_permission_mode') && w.contains('"plan"')), isTrue, reason: proc.writes.join('\n'));
});
testWidgets('bare /permissions opens the mode picker (T-413)', (tester) async {
await mount(tester, const ClaudePane(showChrome: false));
await command(tester, '/permissions');
expect(find.byType(ModelPickerCard), findsOneWidget);
expect(find.text('permissions'), findsOneWidget);
});
testWidgets('/status and /config navigate the Claude sidebar (T-413)', (tester) async {
final tabs = <String?>[];
final sub = f.services.messages.subscribe(publisher: 'builtin.claude', channel: 'meta.tab').listen((m) => tabs.add(m.data['tab'] as String?));
addTearDown(sub.cancel);
await mount(tester, const ClaudePane(showChrome: false));
await command(tester, '/status');
await command(tester, '/config');
await command(tester, '/mcp');
expect(tabs, ['activity', 'config', 'config']);
});
testWidgets('/memory opens CLAUDE.md in the editor (T-413)', (tester) async {
final opened = <String?>[];
f.ipc.stub('editor.open', (args) async {
opened.add(args['path'] as String?);
return IpcResponse.ok(id: '', data: const {});
});
await mount(tester, const ClaudePane(showChrome: false));
await command(tester, '/memory');
expect(opened, ['/repo-a/CLAUDE.md']);
});
testWidgets('/help renders a local clide summary card (T-413)', (tester) async {
await mount(tester, const ClaudePane(showChrome: false));
await command(tester, '/help');
expect(find.textContaining('clide commands:'), findsOneWidget);
expect(find.text('clide'), findsOneWidget); // synthetic card attribution
});
testWidgets('a TUI-only command becomes a notice card, never reaching the session (T-411)', (tester) async {
await mount(tester, const ClaudePane(showChrome: false));
final before = created.single.writes.length;
await command(tester, '/doctor');
expect(find.textContaining('/doctor is a Claude Code TUI command'), findsOneWidget);
expect(created.single.writes.length, before, reason: 'nothing forwarded');
});
});
}