From efd234fd4618facc5cdb36955b4e44a41b692c8c Mon Sep 17 00:00:00 2001 From: Larslllllll Date: Tue, 18 Aug 2026 22:16:55 +0200 Subject: [PATCH] =?UTF-8?q?fix(cli):=20restore=20auto-open=20in=20`sh1pt?= =?UTF-8?q?=20login`=20=E2=80=94=20drop=20explicit=20false=20default=20on?= =?UTF-8?q?=20--no-browser?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `.option('--no-browser', ..., false)` overrides the default Commander assigns to a negated boolean flag. `opts.browser` therefore resolved to `false` even when the flag was absent, so `opts.browser !== false` never held and the verification URL was never opened. That silently disabled auto-open for every user and made `--no-browser` a no-op. Removing the explicit default restores Commander's intended semantics: no flag -> opts.browser === true (browser opens, as documented) --no-browser -> opts.browser === false (browser stays closed) Adds packages/cli/src/commands/login.test.ts covering both directions plus a guard against the explicit default returning. --- packages/cli/src/commands/login.test.ts | 29 +++++++++++++++++++++++++ packages/cli/src/commands/login.ts | 2 +- 2 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 packages/cli/src/commands/login.test.ts diff --git a/packages/cli/src/commands/login.test.ts b/packages/cli/src/commands/login.test.ts new file mode 100644 index 00000000..dc5ea082 --- /dev/null +++ b/packages/cli/src/commands/login.test.ts @@ -0,0 +1,29 @@ +import { describe, expect, it } from 'vitest'; +import { loginCmd } from './login.js'; + +// Regression guard for the `--no-browser` flag. +// +// Commander derives a boolean option named `browser` from `--no-browser` and defaults +// it to `true`. Passing an explicit default of `false` as the third argument overrides +// that, so `opts.browser` resolves to `false` even when the user never passed the flag. +// The action then evaluates `opts.browser !== false` as false and never opens the +// verification URL, which silently disables auto-open for everyone and makes +// `--no-browser` a no-op. +describe('login command --no-browser option', () => { + it('does not declare an explicit default value', () => { + const option = loginCmd.options.find((candidate) => candidate.long === '--no-browser'); + expect(option).toBeDefined(); + expect(option?.attributeName()).toBe('browser'); + expect(option?.defaultValue).toBeUndefined(); + }); + + it('defaults browser to true when the flag is absent', () => { + loginCmd.parseOptions([]); + expect(loginCmd.opts().browser).toBe(true); + }); + + it('sets browser to false when --no-browser is passed', () => { + loginCmd.parseOptions(['--no-browser']); + expect(loginCmd.opts().browser).toBe(false); + }); +}); diff --git a/packages/cli/src/commands/login.ts b/packages/cli/src/commands/login.ts index d6d4f702..e7e87e0a 100644 --- a/packages/cli/src/commands/login.ts +++ b/packages/cli/src/commands/login.ts @@ -15,7 +15,7 @@ import { // the user approves on the page (or until the code expires). export const loginCmd = new Command('login') .description('Pair this CLI with your sh1pt.com account') - .option('--no-browser', 'do not auto-open the verification URL', false) + .option('--no-browser', 'do not auto-open the verification URL') .action(async (opts: { browser: boolean }) => { const existing = await readCredentials(); if (existing) {