From 88ed4bf391612846ec0b465ef5888c23494f4763 Mon Sep 17 00:00:00 2001 From: Jeroen Schweitzer Date: Mon, 18 May 2026 18:06:38 +0200 Subject: [PATCH] T-126 follow-up: cover argv_dispatch branches (gate at 95) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 5 unit tests for the _argv unwrap handler — the e2e test only hit the happy path; this covers the missing-args, non-list-args, and parseArgv-error branches the coverage gate needed. Co-Authored-By: Claude --- test/cli/argv_dispatch_test.dart | 61 ++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 test/cli/argv_dispatch_test.dart diff --git a/test/cli/argv_dispatch_test.dart b/test/cli/argv_dispatch_test.dart new file mode 100644 index 00000000..80af5524 --- /dev/null +++ b/test/cli/argv_dispatch_test.dart @@ -0,0 +1,61 @@ +/// Unit tests for the `_argv` unwrap handler (T-126). +/// +/// Exercises the two branches the e2e test doesn't reliably hit: +/// 1. `args.argv` not a List → userError +/// 2. argv parses to an ArgvError → that error flows back through +library; + +import 'package:clide/src/cli/argv_dispatch.dart'; +import 'package:clide/src/daemon/dispatcher.dart'; +import 'package:clide/src/ipc/envelope.dart'; +import 'package:clide/src/ipc/schema_v1.dart'; +import 'package:test/test.dart'; + +void main() { + late DaemonDispatcher d; + + setUp(() { + d = DaemonDispatcher(); + registerArgvUnwrap(d); + }); + + test('valid argv → parsed and re-dispatched (round-trip via ping)', () async { + final res = await d.dispatch(IpcRequest(id: 'x', cmd: argvSentinelCmd, args: { + 'argv': ['ping'], + })); + expect(res.ok, isTrue); + expect(res.id, 'x'); + expect(res.data['pong'], isTrue); + }); + + test('args.argv missing → userError', () async { + final res = await d.dispatch(IpcRequest(id: 'y', cmd: argvSentinelCmd, args: const {})); + expect(res.ok, isFalse); + expect(res.error?.kind, IpcErrorKind.userError); + expect(res.error?.message, contains('argv')); + }); + + test('args.argv is not a list → userError', () async { + final res = await d.dispatch(IpcRequest(id: 'z', cmd: argvSentinelCmd, args: { + 'argv': 'not a list', + })); + expect(res.ok, isFalse); + expect(res.error?.kind, IpcErrorKind.userError); + }); + + test('argv that fails parseArgv → that error flows back unmodified', () async { + final res = await d.dispatch(IpcRequest(id: 'p', cmd: argvSentinelCmd, args: { + 'argv': const [], // empty argv triggers parseArgv usage error + })); + expect(res.ok, isFalse); + expect(res.error?.kind, IpcErrorKind.userError); + expect(res.error?.message, contains('usage')); + }); + + test('outer request id is preserved on the response', () async { + final res = await d.dispatch(IpcRequest(id: 'unique-id-123', cmd: argvSentinelCmd, args: { + 'argv': ['ping'], + })); + expect(res.id, 'unique-id-123'); + }); +}