diff --git a/CLAUDE.md b/CLAUDE.md
index c6bc20fa..654b7843 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -627,7 +627,7 @@
The `automated` field accepts three values: `true` (fully automated), `assisted` (human-in-the-loop), `false` (fully manual)
When marking a TC `automated: true`, ensure a non-`[assisted]` integration test exists in `src/__integration-tests__/suite/` on the same branch
When marking a TC `automated: assisted`, ensure an `[assisted]`-tagged integration test exists in `src/__integration-tests__/suite/` on the same branch. See TESTING.md § "Assisted mode" for the `[assisted]` tag convention.
- Use `automated: false` for scenarios that can't be integration-tested at all (e.g., requires AI assistant interaction, platform-specific behaviour). See TESTING.md § "QuickPick limitation" for what can and cannot be automated.
+ Use `automated: false` for scenarios that can't be integration-tested at all (e.g., requires AI assistant interaction, platform-specific behaviour). See TESTING.md § "QuickPick and InputBox dismissal" for what can and cannot be automated.
Mark `automated: true` or `automated: assisted` based on unit tests alone — the validator only checks integration tests
packages/rangelink-vscode-extension/scripts/validate-qa-coverage.sh
diff --git a/packages/rangelink-vscode-extension/TESTING.md b/packages/rangelink-vscode-extension/TESTING.md
index a0023bae..607a7b76 100644
--- a/packages/rangelink-vscode-extension/TESTING.md
+++ b/packages/rangelink-vscode-extension/TESTING.md
@@ -75,13 +75,29 @@ Integration tests run inside a real VS Code process via `@vscode/test-cli`. They
pnpm test:release
```
-### QuickPick limitation
+### QuickPick and InputBox dismissal
-VS Code's extension host test runner provides no API to interact with QuickPick UI — tests cannot programmatically select items, dismiss pickers, or read picker contents. A QuickPick that opens during a test **will stall the test indefinitely** because it blocks the command from completing, and there is no way to dismiss it from test code.
+VS Code's extension host test runner provides no API to programmatically select QuickPick items or interact with dialogs. However, `workbench.action.closeQuickOpen` can programmatically dismiss QuickPicks and InputBoxes — meaning tests that open a picker, read its logged content, and dismiss it **can now be fully automated**.
-**Workaround — command bypass:** Many TCs that involve a QuickPick as a means to an end (e.g., "bind via picker, verify toast") can be automated by calling the underlying command directly (`rangelink.bindToTerminalHere`, `rangelink.bindToTextEditorHere`) to bypass the picker entirely, then asserting the outcome via log-based UI assertions.
+**`openAndDismiss` helper:** The pattern for automated picker-open-and-dismiss is encapsulated in `openAndDismiss(command)`:
-**What cannot be fully automated:** TCs that verify picker content itself (item ordering, badges, grouping, placeholder text) or dialog interaction (confirmation buttons, cancel behavior) require a human to open/dismiss the picker. Mark these `automated: assisted` in the QA YAML — the test automates setup and validates content via log-based QuickPick assertions while the human performs the mechanical UI action. See [Assisted mode](#assisted-mode-assisted-tests) below. Only TCs that genuinely cannot be tested even with human-in-the-loop assistance should remain `automated: false`.
+```typescript
+// Fires the command (which opens a QuickPick), waits for render + log emission,
+// dismisses with closeQuickOpen, then settles.
+await openAndDismiss(CMD_BIND_TO_DESTINATION);
+const items = extractQuickPickItemsLogged(logCapture.getLinesSince('before-test'));
+// assert on items as usual
+```
+
+**Workaround — command bypass:** TCs that use a picker as a means to an end (e.g., "bind via picker, verify toast") can be automated by calling the underlying command directly (`rangelink.bindToTerminalHere`, `rangelink.bindToTextEditorHere`) to bypass the picker entirely.
+
+**What still requires assisted mode:** TCs that need to:
+
+- Select a specific item from a picker (closeQuickOpen only dismisses, it cannot choose)
+- Navigate a multi-picker flow (select item in picker A → picker B opens → verify B's content)
+- Verify dialog interactions (confirmation buttons with Yes/No)
+
+Mark these `automated: assisted` in the QA YAML. See [Assisted mode](#assisted-mode-assisted-tests) below. Only TCs that genuinely cannot be tested even with human-in-the-loop assistance should remain `automated: false`.
See https://github.com/couimet/rangeLink/issues/483 for the full triage of automatable vs manual TCs.
diff --git a/packages/rangelink-vscode-extension/qa/qa-test-cases-v1.1.0.yaml b/packages/rangelink-vscode-extension/qa/qa-test-cases-v1.1.0.yaml
index 4f26218f..1fb15c21 100644
--- a/packages/rangelink-vscode-extension/qa/qa-test-cases-v1.1.0.yaml
+++ b/packages/rangelink-vscode-extension/qa/qa-test-cases-v1.1.0.yaml
@@ -40,7 +40,7 @@ test_cases:
steps:
- 'Click the $(link) RangeLink item in the status bar'
expected_result: "A QuickPick menu opens titled 'RangeLink Menu'. Menu items are visible."
- automated: assisted
+ automated: true
- id: status-bar-menu-003
feature: 'R-M Status Bar Menu'
@@ -50,7 +50,7 @@ test_cases:
steps:
- 'Press Cmd+R Cmd+M'
expected_result: 'Same QuickPick menu opens as clicking the status bar item.'
- automated: assisted
+ automated: true
- id: status-bar-menu-004
labels:
@@ -73,7 +73,7 @@ test_cases:
- 'Open the R-M menu (keybinding or status bar click)'
- 'Observe the menu items'
expected_result: "Menu contains 'Jump to Bound Destination' with the destination name shown. 'Unbind Destination' is also visible."
- automated: assisted
+ automated: true
- id: status-bar-menu-006
feature: 'R-M Status Bar Menu'
@@ -84,7 +84,7 @@ test_cases:
- 'Open the R-M menu'
- 'Observe the first item'
expected_result: "Menu shows a bind item that opens the destination picker. 'Jump to Bound Destination' is absent."
- automated: assisted
+ automated: true
- id: status-bar-menu-007
feature: 'R-M Status Bar Menu'
@@ -198,7 +198,7 @@ test_cases:
- 'Open R-D picker'
- 'Press Escape without selecting anything'
expected_result: 'Picker closes. Binding state is unchanged.'
- automated: assisted
+ automated: true
- id: bind-to-destination-011
labels:
@@ -236,7 +236,7 @@ test_cases:
- 'Open R-D destination picker (Cmd+R Cmd+D or Ctrl+R Ctrl+D)'
- 'Observe the picker items'
expected_result: 'Picker shows inline terminal items up to maxInline limit, "More terminals..." overflow item, inline file items (current-in-group), "More files..." overflow item, and standard command items (Go to Link, Show Version Info).'
- automated: assisted
+ automated: true
- id: bind-to-destination-014
feature: 'R-D Bind to Destination'
@@ -275,7 +275,7 @@ test_cases:
- "Click a terminal tab (e.g., 'Gamma') to make it the active terminal"
- 'Open the terminal picker via R-D or R-M'
expected_result: "'Gamma' shows an 'active' badge in the picker. Other terminals have no badge."
- automated: assisted
+ automated: true
- id: terminal-picker-002
feature: 'Terminal Picker'
@@ -286,7 +286,7 @@ test_cases:
steps:
- 'Open the terminal picker'
expected_result: "'Beta' shows a 'bound' badge. 'Gamma' shows an 'active' badge."
- automated: assisted
+ automated: true
- id: terminal-picker-003
feature: 'Terminal Picker'
@@ -297,7 +297,7 @@ test_cases:
- "Click the 'Beta' terminal tab to make it active"
- 'Open the terminal picker'
expected_result: "'Beta' shows a combined 'bound · active' badge (both indicators present on the same item)."
- automated: assisted
+ automated: true
- id: terminal-picker-004
feature: 'Terminal Picker'
@@ -308,7 +308,7 @@ test_cases:
steps:
- 'Open the terminal picker'
expected_result: "'Beta' is the first item in the terminal list, regardless of the order terminals were opened."
- automated: assisted
+ automated: true
- id: terminal-picker-005
feature: 'Terminal Picker'
@@ -319,7 +319,7 @@ test_cases:
steps:
- 'Open the terminal picker'
expected_result: "'Beta' (bound) is first. 'Gamma' (active, not bound) is second. Remaining terminals follow in any order."
- automated: assisted
+ automated: true
- id: terminal-picker-006
labels:
@@ -332,7 +332,7 @@ test_cases:
steps:
- 'Open the terminal picker'
expected_result: 'Hidden background terminals do not appear in the picker. Only user-visible terminals are listed.'
- automated: assisted
+ automated: true
- id: terminal-picker-007
feature: 'Terminal Picker'
@@ -343,7 +343,7 @@ test_cases:
steps:
- 'Open R-D picker'
expected_result: "All terminals appear inline. No 'More terminals...' item is visible."
- automated: assisted
+ automated: true
- id: terminal-picker-008
feature: 'Terminal Picker'
@@ -354,7 +354,7 @@ test_cases:
steps:
- 'Open R-D picker or terminal sub-section of R-M'
expected_result: "Only 3 terminals shown inline. A 'More terminals...' item appears at the bottom of the terminal section."
- automated: assisted
+ automated: true
- id: terminal-picker-009
feature: 'Terminal Picker'
@@ -385,7 +385,7 @@ test_cases:
- 'Set rangelink.terminalPicker.maxInline = 2 in VS Code settings'
- 'Open R-D picker'
expected_result: "Only 2 terminals shown inline. 'More terminals...' appears. Previously all 4 were inline with higher maxInline."
- automated: assisted
+ automated: true
- id: terminal-picker-012
feature: 'Terminal Picker'
@@ -397,7 +397,7 @@ test_cases:
- 'Open R-M menu'
- 'Observe the terminal entries in the menu'
expected_result: 'Terminal picker items appear inline within the R-M menu. Selecting one binds that terminal.'
- automated: assisted
+ automated: true
- id: terminal-picker-013
feature: 'Terminal Picker'
@@ -408,7 +408,7 @@ test_cases:
- 'Press Cmd+R Cmd+D'
- 'Observe that terminal entries are part of the combined destination picker'
expected_result: 'Terminal entries appear in the R-D picker with the same badges and ordering as when accessed from R-M.'
- automated: assisted
+ automated: true
# ---------------------------------------------------------------------------
# Section 4 — File Picker
@@ -423,7 +423,7 @@ test_cases:
steps:
- 'Open R-D picker'
expected_result: "src/utils/helper.ts appears at the top of the file list with a 'bound' badge."
- automated: assisted
+ automated: true
- id: file-picker-002
feature: 'File Picker'
@@ -436,7 +436,7 @@ test_cases:
- 'Click src/index.ts to make it active in tab group 1'
- 'Open R-D picker'
expected_result: 'src/index.ts appears before other files in tab group 1 within the picker.'
- automated: assisted
+ automated: true
- id: file-picker-003
feature: 'File Picker'
@@ -447,7 +447,7 @@ test_cases:
- 'Open both files in the editor'
- 'Open R-D picker (file section)'
expected_result: 'Both index.ts files appear with enough path context to distinguish them (e.g., utils/index.ts and types/index.ts).'
- automated: assisted
+ automated: true
- id: file-picker-004
feature: 'File Picker'
@@ -457,7 +457,7 @@ test_cases:
steps:
- 'Open R-D picker'
expected_result: "The open file entries appear inline in the picker. No 'More files...' item."
- automated: assisted
+ automated: true
- id: file-picker-005
feature: 'File Picker'
@@ -467,7 +467,7 @@ test_cases:
steps:
- 'Open R-D picker'
expected_result: "Only the inline limit of files is shown. A 'More files...' item appears at the bottom of the file section."
- automated: assisted
+ automated: true
- id: file-picker-006
feature: 'File Picker'
@@ -510,7 +510,7 @@ test_cases:
steps:
- 'Open R-M menu'
expected_result: 'File entries appear inline within the R-M menu. Selecting one binds the file as the destination.'
- automated: assisted
+ automated: true
- id: file-picker-010
feature: 'File Picker'
@@ -532,7 +532,7 @@ test_cases:
steps:
- 'Open R-D destination picker'
expected_result: 'All three files appear with unique disambiguating path fragments that distinguish their locations.'
- automated: assisted
+ automated: true
- id: file-picker-012
feature: 'File Picker'
@@ -542,7 +542,7 @@ test_cases:
steps:
- 'Open R-D destination picker'
expected_result: 'File descriptions contain only badges and tab group labels — no disambiguation path prefix.'
- automated: assisted
+ automated: true
# ---------------------------------------------------------------------------
# Section 5 — Clipboard Preservation
@@ -697,7 +697,7 @@ test_cases:
- 'Press Escape to dismiss without selecting anything'
- 'Press Cancel — test reads clipboard and asserts it still equals the sentinel'
expected_result: 'Clipboard contains the sentinel value. assertClipboardRestored passes — no preserve cycle was triggered because the operation was cancelled before any transport.'
- automated: assisted
+ automated: true
- id: clipboard-preservation-010
labels:
@@ -1730,7 +1730,7 @@ test_cases:
steps:
- 'Press Cmd+R Cmd+G'
expected_result: 'An input box appears with placeholder text indicating it expects a RangeLink (e.g., path/to/file.ts#L10).'
- automated: assisted
+ automated: true
# go-to-link-002 removed — Ctrl+R Ctrl+G on Win/Linux tests VS Code's keybinding
# resolution, not RangeLink behavior. Both bindings are declared in package.json;
@@ -1911,7 +1911,7 @@ test_cases:
- 'Confirm the .png file is NOT listed'
- 'Press Escape to dismiss'
expected_result: 'The .png file does not appear in the picker despite being open. The .txt file does appear. The isBinaryFile filter in the R-D picker is the upstream defense; runtime rejection in PasteDestinationManager.bindTextEditor is a defense-in-depth layer covered by unit tests.'
- automated: assisted
+ automated: true
- id: editor-binding-validation-005
feature: 'Editor Binding Validation'
@@ -2242,7 +2242,7 @@ test_cases:
- 'Press Cmd+R Cmd+L'
- 'Observe — destination picker should appear'
expected_result: 'Destination picker opens. Selecting a destination binds it and sends the RangeLink. Escape dismisses silently with no clipboard write.'
- automated: assisted
+ automated: true
- id: core-send-commands-r-p-001
labels:
@@ -2258,7 +2258,7 @@ test_cases:
- "Select 'RangeLink: Send Portable Link'"
- 'Observe — destination picker should appear'
expected_result: 'Destination picker opens (not a silent clipboard fallback). Selecting a destination binds it and sends the portable link.'
- automated: assisted
+ automated: true
- id: core-send-commands-r-v-001
labels:
@@ -2273,7 +2273,7 @@ test_cases:
- 'Select text'
- "Open Command Palette, select 'RangeLink: Send Selected Text'"
expected_result: 'Destination picker opens. Selecting a destination sends the selected text to it.'
- automated: assisted
+ automated: true
# ---------------------------------------------------------------------------
# Section — Text Editor Destination
@@ -2820,7 +2820,7 @@ test_cases:
- 'Press Cmd+R Cmd+D to open destination picker'
- 'Observe the picker items'
expected_result: 'The custom AI assistant appears in the picker with its configured extensionName, after the built-in destinations'
- automated: assisted
+ automated: true
- id: custom-ai-assistant-004
labels:
@@ -2872,7 +2872,7 @@ test_cases:
- 'Press Cmd+R Cmd+D to open destination picker'
- 'Observe order of custom AI assistants in the picker'
expected_result: 'Custom AI assistants appear after built-in destinations, in the same order as defined in settings.json'
- automated: assisted
+ automated: true
- id: custom-ai-assistant-008
labels:
@@ -3097,15 +3097,15 @@ test_cases:
- id: github-copilot-chat-001
feature: 'Built-in AI Assistants'
- scenario: 'GitHub Copilot Chat appears in destination picker when extension is active'
+ scenario: 'GitHub Copilot Chat appears in destination picker when available'
preconditions:
- - 'GitHub Copilot Chat extension (GitHub.copilot-chat) is installed and active'
+ - 'VS Code has built-in workbench.action.chat.open command (present in all modern VS Code)'
- 'No destination currently bound'
steps:
- 'Open destination picker via R-D or Command Palette → "Bind to Destination"'
- 'Confirm "GitHub Copilot Chat" item appears in the AI Assistants group'
expected_result: '"GitHub Copilot Chat" is listed in the AI Assistants group of the destination picker'
- automated: false
+ automated: true
- id: github-copilot-chat-002
labels:
diff --git a/packages/rangelink-vscode-extension/src/__integration-tests__/helpers/assistedTestHelper.ts b/packages/rangelink-vscode-extension/src/__integration-tests__/helpers/assistedTestHelper.ts
index db2f1e9c..50a7ee38 100644
--- a/packages/rangelink-vscode-extension/src/__integration-tests__/helpers/assistedTestHelper.ts
+++ b/packages/rangelink-vscode-extension/src/__integration-tests__/helpers/assistedTestHelper.ts
@@ -4,22 +4,8 @@ import * as vscode from 'vscode';
const nodeConsole = new Console(process.stdout, process.stderr);
-const ASSISTED_BANNER_WIDTH = 60;
-const BANNER_LINE = '═'.repeat(ASSISTED_BANNER_WIDTH);
-const SECTION_LINE = '─'.repeat(ASSISTED_BANNER_WIDTH);
-
-/**
- * Prints a visible banner at suite start explaining the assisted mode workflow.
- * Call this in suiteSetup() for any suite containing [assisted] tests.
- */
-export const printAssistedBanner = (): void => {
- nodeConsole.log(`\n${BANNER_LINE}`);
- nodeConsole.log('ASSISTED TEST MODE');
- nodeConsole.log('Tests tagged [assisted] will pause for human interaction.');
- nodeConsole.log('Instructions appear as a persistent VS Code notification.');
- nodeConsole.log('Click Cancel on the notification when you have completed the action.');
- nodeConsole.log(BANNER_LINE);
-};
+const SECTION_LINE_WIDTH = 60;
+const SECTION_LINE = '─'.repeat(SECTION_LINE_WIDTH);
/**
* Pauses the test until the human completes a UI action.
diff --git a/packages/rangelink-vscode-extension/src/__integration-tests__/helpers/index.ts b/packages/rangelink-vscode-extension/src/__integration-tests__/helpers/index.ts
index 8759a6a8..9a5ca9ef 100644
--- a/packages/rangelink-vscode-extension/src/__integration-tests__/helpers/index.ts
+++ b/packages/rangelink-vscode-extension/src/__integration-tests__/helpers/index.ts
@@ -1,9 +1,4 @@
-export {
- type HumanVerdict,
- printAssistedBanner,
- waitForHuman,
- waitForHumanVerdict,
-} from './assistedTestHelper';
+export { type HumanVerdict, waitForHuman, waitForHumanVerdict } from './assistedTestHelper';
export {
assertTerminalBufferContains,
assertTerminalBufferEquals,
@@ -49,12 +44,12 @@ export { createLogger } from './logHelpers';
export { navigateViaHandleLinkClick } from './navigationHelpers';
export { loadSettingsProfile, resetRangelinkSettings } from './settingsHelpers';
export { standardSuite } from './standardSuite';
-export type { StandardSuiteOptions } from './standardSuite';
export { createAndBindTerminal, createTerminal, findTerminalItems } from './terminalHelpers';
export {
activateExtension,
getExtensionVersion,
getWorkspaceRoot,
+ openAndDismiss,
POLL_INTERVAL_MS,
POLL_TIMEOUT_MS,
settle,
diff --git a/packages/rangelink-vscode-extension/src/__integration-tests__/helpers/standardSuite.ts b/packages/rangelink-vscode-extension/src/__integration-tests__/helpers/standardSuite.ts
index 81a7e954..0c880b51 100644
--- a/packages/rangelink-vscode-extension/src/__integration-tests__/helpers/standardSuite.ts
+++ b/packages/rangelink-vscode-extension/src/__integration-tests__/helpers/standardSuite.ts
@@ -1,30 +1,14 @@
-import { printAssistedBanner } from './assistedTestHelper';
import { closeAllEditors } from './fileHelpers';
import { createLogger } from './logHelpers';
import { resetRangelinkSettings } from './settingsHelpers';
import { activateExtension, settle } from './testEnv';
-export interface StandardSuiteOptions {
- assisted?: boolean;
-}
-
-export const standardSuite = (
- name: string,
- options: StandardSuiteOptions,
- fn: (log: (msg: string) => void) => void,
-): void => {
+export const standardSuite = (name: string, fn: (log: (msg: string) => void) => void): void => {
suite(name, () => {
const log = createLogger(name);
suiteSetup(async () => {
await activateExtension();
- const assisted = options.assisted ?? false;
- log(
- `[DEBUG] standardSuite.assisted=${assisted} (${options.assisted === undefined ? 'default' : 'provided'})`,
- );
- if (assisted) {
- printAssistedBanner();
- }
});
setup(async () => {
diff --git a/packages/rangelink-vscode-extension/src/__integration-tests__/helpers/testEnv.ts b/packages/rangelink-vscode-extension/src/__integration-tests__/helpers/testEnv.ts
index 14cef8a7..8e1fa53c 100644
--- a/packages/rangelink-vscode-extension/src/__integration-tests__/helpers/testEnv.ts
+++ b/packages/rangelink-vscode-extension/src/__integration-tests__/helpers/testEnv.ts
@@ -29,3 +29,29 @@ export const getExtensionVersion = (): string => {
export const settle = (ms: number = SETTLE_MS): Promise =>
new Promise((resolve) => setTimeout(resolve, ms));
+
+/**
+ * Open a QuickPick or InputBox via command, dismiss it with closeQuickOpen, and return after
+ * the promise settles. The caller inspects log-captured items after this resolves.
+ */
+export const openAndDismiss = async (command: string): Promise => {
+ const promise = vscode.commands.executeCommand(command);
+ await settle();
+ const deadline = Date.now() + POLL_TIMEOUT_MS;
+ // Retry dismissal until the command resolves — the picker may be slow to render on loaded CI.
+ for (;;) {
+ await vscode.commands.executeCommand('workbench.action.closeQuickOpen');
+ const done = await Promise.race([
+ promise.then(() => true),
+ settle(POLL_INTERVAL_MS).then(() => false),
+ ]);
+ if (done) break;
+ if (Date.now() >= deadline) {
+ throw new Error(
+ `openAndDismiss: "${command}" did not resolve within ${POLL_TIMEOUT_MS}ms deadline`,
+ );
+ }
+ }
+ await promise;
+ await settle();
+};
diff --git a/packages/rangelink-vscode-extension/src/__integration-tests__/suite/bindToDestination.test.ts b/packages/rangelink-vscode-extension/src/__integration-tests__/suite/bindToDestination.test.ts
index 15372469..45a02384 100644
--- a/packages/rangelink-vscode-extension/src/__integration-tests__/suite/bindToDestination.test.ts
+++ b/packages/rangelink-vscode-extension/src/__integration-tests__/suite/bindToDestination.test.ts
@@ -3,6 +3,7 @@ import * as path from 'node:path';
import * as vscode from 'vscode';
+import { CMD_BIND_TO_DESTINATION } from '../../constants/commandIds';
import {
assertNoStatusBarMsgLogged,
assertStatusBarMsgLogged,
@@ -15,6 +16,7 @@ import {
findTerminalItems,
findTestItemsByPrefix,
getLogCapture,
+ openAndDismiss,
parseQuickPickItemsFromLogLine,
settle,
standardSuite,
@@ -22,7 +24,7 @@ import {
waitForHumanVerdict,
} from '../helpers';
-standardSuite('R-D Bind to Destination', { assisted: true }, (log) => {
+standardSuite('R-D Bind to Destination', (log) => {
const terminals: vscode.Terminal[] = [];
const tmpFileUris: vscode.Uri[] = [];
@@ -289,7 +291,7 @@ standardSuite('R-D Bind to Destination', { assisted: true }, (log) => {
log('✓ No rebind toast — original binding preserved (human verdict + state invariant)');
});
- test('[assisted] bind-to-destination-010: Escape from destination picker dismisses without changing binding', async () => {
+ test('bind-to-destination-010: Escape from destination picker dismisses without changing binding', async () => {
await createTerminal('rl-btd-010', terminals);
await vscode.commands.executeCommand('rangelink.bindToTerminalHere');
await settle();
@@ -297,7 +299,7 @@ standardSuite('R-D Bind to Destination', { assisted: true }, (log) => {
const logCapture = getLogCapture();
logCapture.mark('before-btd-010');
- await waitForHuman('bind-to-destination-010', 'Press Cmd+R Cmd+D, then Escape');
+ await openAndDismiss(CMD_BIND_TO_DESTINATION);
const lines = logCapture.getLinesSince('before-btd-010');
diff --git a/packages/rangelink-vscode-extension/src/__integration-tests__/suite/builtInAiAssistants.test.ts b/packages/rangelink-vscode-extension/src/__integration-tests__/suite/builtInAiAssistants.test.ts
index 31ce2673..e31dd44c 100644
--- a/packages/rangelink-vscode-extension/src/__integration-tests__/suite/builtInAiAssistants.test.ts
+++ b/packages/rangelink-vscode-extension/src/__integration-tests__/suite/builtInAiAssistants.test.ts
@@ -2,17 +2,23 @@ import assert from 'node:assert';
import * as vscode from 'vscode';
-import { CMD_BIND_TO_CLAUDE_CODE, CMD_UNBIND_DESTINATION } from '../../constants/commandIds';
+import {
+ CMD_BIND_TO_CLAUDE_CODE,
+ CMD_BIND_TO_DESTINATION,
+ CMD_UNBIND_DESTINATION,
+} from '../../constants/commandIds';
import {
activateExtension,
cleanupFiles,
closeAllEditors,
createLogger,
createWorkspaceFile,
+ extractQuickPickItemsLogged,
getLogCapture,
+ openAndDismiss,
openEditor,
- printAssistedBanner,
settle,
+ standardSuite,
waitForHuman,
} from '../helpers';
@@ -22,7 +28,6 @@ suite('Built-in AI Assistants', () => {
suiteSetup(async () => {
await activateExtension();
- printAssistedBanner();
});
teardown(async () => {
@@ -138,3 +143,22 @@ suite('Built-in AI Assistants', () => {
log('✓ Warm paste: content arrived without cold-start refocus');
});
});
+
+standardSuite('Built-in AI Assistants — Destination Picker', (log) => {
+ test('github-copilot-chat-001: GitHub Copilot Chat appears in destination picker when available', async () => {
+ const logCapture = getLogCapture();
+ logCapture.mark('before-copilot-001');
+
+ await openAndDismiss(CMD_BIND_TO_DESTINATION);
+
+ const lines = logCapture.getLinesSince('before-copilot-001');
+ const items = extractQuickPickItemsLogged(lines);
+ assert.ok(items, 'Expected showQuickPick log entry — was the picker opened?');
+
+ const copilotItem = items!.find((item) => item.displayName === 'GitHub Copilot Chat');
+ assert.ok(copilotItem, 'Expected "GitHub Copilot Chat" in the destination picker items');
+ assert.strictEqual(copilotItem!.itemKind, 'bindable');
+
+ log('✓ github-copilot-chat-001 — log confirms "GitHub Copilot Chat" appears in R-D picker');
+ });
+});
diff --git a/packages/rangelink-vscode-extension/src/__integration-tests__/suite/clipboardPreservation.test.ts b/packages/rangelink-vscode-extension/src/__integration-tests__/suite/clipboardPreservation.test.ts
index 343524ee..549ad16c 100644
--- a/packages/rangelink-vscode-extension/src/__integration-tests__/suite/clipboardPreservation.test.ts
+++ b/packages/rangelink-vscode-extension/src/__integration-tests__/suite/clipboardPreservation.test.ts
@@ -22,6 +22,7 @@ import {
createTerminal,
createWorkspaceFile,
loadSettingsProfile,
+ openAndDismiss,
openEditor,
settle,
standardSuite,
@@ -30,7 +31,7 @@ import {
writeClipboardSentinel,
} from '../helpers';
-standardSuite('Clipboard Preservation', {}, (_log) => {
+standardSuite('Clipboard Preservation', (_log) => {
let testFileUri: vscode.Uri;
let editor: vscode.TextEditor;
let capturing: CapturingTerminal;
@@ -117,7 +118,7 @@ standardSuite('Clipboard Preservation', {}, (_log) => {
});
});
-standardSuite('Clipboard Preservation — Assisted', { assisted: true }, (log) => {
+standardSuite('Clipboard Preservation — Assisted', (log) => {
const tmpFileUris: vscode.Uri[] = [];
const tmpTerminals: vscode.Terminal[] = [];
@@ -299,28 +300,26 @@ standardSuite('Clipboard Preservation — Assisted', { assisted: true }, (log) =
log('✓ Clipboard changed from sentinel and phrase landed in destination file after R-V');
});
- test('[assisted] clipboard-preservation-009: always mode — dismissed picker leaves clipboard unchanged', async () => {
+ test('clipboard-preservation-009: always mode — dismissed picker leaves clipboard unchanged', async () => {
await vscode.commands.executeCommand(CMD_UNBIND_DESTINATION);
const lines = Array.from({ length: 5 }, (_, i) => `line ${i + 1}`);
const fileUri = createWorkspaceFile('cbp-009', lines.join('\n') + '\n');
tmpFileUris.push(fileUri);
- await openEditor(fileUri);
+ const SELECTION_START_LINE = 0;
+ const SELECTION_END_LINE = 2;
+ const SELECTION_COLUMN = 0;
+
+ const editor009 = await openEditor(fileUri);
+ editor009.selection = new vscode.Selection(
+ new vscode.Position(SELECTION_START_LINE, SELECTION_COLUMN),
+ new vscode.Position(SELECTION_END_LINE, SELECTION_COLUMN),
+ );
await settle();
await writeClipboardSentinel();
- await waitForHuman(
- 'clipboard-preservation-009',
- `clipboard.preserve="always", no destination bound. Select lines, press Cmd+R Cmd+L (picker opens), press Escape. Sentinel: "${CLIPBOARD_SENTINEL}".`,
- [
- '1. Click into the test file (cbp-009-...)',
- '2. Select a few lines',
- '3. Press Cmd+R Cmd+L — the destination picker opens (no destination is bound)',
- '4. Press Escape to dismiss without selecting anything',
- '5. Press Cancel to continue (test asserts clipboard still has the sentinel)',
- ],
- );
+ await openAndDismiss(CMD_COPY_LINK_RELATIVE);
await assertClipboardRestored('clipboard-preservation-009: always + picker dismissed');
log('✓ Clipboard unchanged after picker dismissed (no operation performed)');
diff --git a/packages/rangelink-vscode-extension/src/__integration-tests__/suite/commandRegistration.test.ts b/packages/rangelink-vscode-extension/src/__integration-tests__/suite/commandRegistration.test.ts
index 14b41d5a..6a600727 100644
--- a/packages/rangelink-vscode-extension/src/__integration-tests__/suite/commandRegistration.test.ts
+++ b/packages/rangelink-vscode-extension/src/__integration-tests__/suite/commandRegistration.test.ts
@@ -60,7 +60,7 @@ const EXPECTED_COMMAND_IDS = [
'rangelink.handleFilePathClick',
] as const;
-standardSuite('Command Registration', {}, (_log) => {
+standardSuite('Command Registration', (_log) => {
let registeredCommands: string[];
suiteSetup(async () => {
diff --git a/packages/rangelink-vscode-extension/src/__integration-tests__/suite/contextMenuEditorContent.test.ts b/packages/rangelink-vscode-extension/src/__integration-tests__/suite/contextMenuEditorContent.test.ts
index 2b0af177..216b54c3 100644
--- a/packages/rangelink-vscode-extension/src/__integration-tests__/suite/contextMenuEditorContent.test.ts
+++ b/packages/rangelink-vscode-extension/src/__integration-tests__/suite/contextMenuEditorContent.test.ts
@@ -26,7 +26,7 @@ import {
const FILE_CONTENT = 'line 1\nline 2\nline 3\nline 4\n';
const CONTEXT_IS_BOUND_KEY = 'rangelink.isBound';
-standardSuite('Context Menus — Editor Content', { assisted: true }, (log) => {
+standardSuite('Context Menus — Editor Content', (log) => {
const terminals: vscode.Terminal[] = [];
const tmpFileUris: vscode.Uri[] = [];
let originalMultiLinePasteWarning: unknown;
diff --git a/packages/rangelink-vscode-extension/src/__integration-tests__/suite/contextMenuEditorTab.test.ts b/packages/rangelink-vscode-extension/src/__integration-tests__/suite/contextMenuEditorTab.test.ts
index 5a52bb3d..cfa6d042 100644
--- a/packages/rangelink-vscode-extension/src/__integration-tests__/suite/contextMenuEditorTab.test.ts
+++ b/packages/rangelink-vscode-extension/src/__integration-tests__/suite/contextMenuEditorTab.test.ts
@@ -23,7 +23,7 @@ import {
const FILE_CONTENT = 'editor-tab context-menu test file\n';
const CONTEXT_IS_BOUND_KEY = 'rangelink.isBound';
-standardSuite('Context Menus — Editor Tab', { assisted: true }, (log) => {
+standardSuite('Context Menus — Editor Tab', (log) => {
const terminals: vscode.Terminal[] = [];
const tmpFileUris: vscode.Uri[] = [];
diff --git a/packages/rangelink-vscode-extension/src/__integration-tests__/suite/contextMenuExplorer.test.ts b/packages/rangelink-vscode-extension/src/__integration-tests__/suite/contextMenuExplorer.test.ts
index 719420d8..c653d94b 100644
--- a/packages/rangelink-vscode-extension/src/__integration-tests__/suite/contextMenuExplorer.test.ts
+++ b/packages/rangelink-vscode-extension/src/__integration-tests__/suite/contextMenuExplorer.test.ts
@@ -26,7 +26,7 @@ import {
const FILE_CONTENT = 'explorer context-menu test file\n';
const CONTEXT_IS_BOUND_KEY = 'rangelink.isBound';
-standardSuite('Context Menus — Explorer', { assisted: true }, (log) => {
+standardSuite('Context Menus — Explorer', (log) => {
const terminals: vscode.Terminal[] = [];
const tmpFileUris: vscode.Uri[] = [];
diff --git a/packages/rangelink-vscode-extension/src/__integration-tests__/suite/contextMenuTerminal.test.ts b/packages/rangelink-vscode-extension/src/__integration-tests__/suite/contextMenuTerminal.test.ts
index d40306e0..a3234148 100644
--- a/packages/rangelink-vscode-extension/src/__integration-tests__/suite/contextMenuTerminal.test.ts
+++ b/packages/rangelink-vscode-extension/src/__integration-tests__/suite/contextMenuTerminal.test.ts
@@ -29,7 +29,7 @@ import {
const CONTEXT_IS_BOUND_KEY = 'rangelink.isBound';
-standardSuite('Context Menus — Terminal', { assisted: true }, (log) => {
+standardSuite('Context Menus — Terminal', (log) => {
const terminals: vscode.Terminal[] = [];
const tmpFileUris: vscode.Uri[] = [];
diff --git a/packages/rangelink-vscode-extension/src/__integration-tests__/suite/coreSendCommands.test.ts b/packages/rangelink-vscode-extension/src/__integration-tests__/suite/coreSendCommands.test.ts
index dd26465e..92e43f21 100644
--- a/packages/rangelink-vscode-extension/src/__integration-tests__/suite/coreSendCommands.test.ts
+++ b/packages/rangelink-vscode-extension/src/__integration-tests__/suite/coreSendCommands.test.ts
@@ -7,6 +7,8 @@ import {
CMD_BIND_TO_TEXT_EDITOR_HERE,
CMD_COPY_LINK_ONLY_RELATIVE,
CMD_COPY_LINK_RELATIVE,
+ CMD_COPY_PORTABLE_LINK_RELATIVE,
+ CMD_PASTE_TO_DESTINATION,
CMD_TERMINAL_PASTE_SELECTED_TEXT,
CMD_UNBIND_DESTINATION,
} from '../../constants/commandIds';
@@ -24,6 +26,7 @@ import {
createWorkspaceFile,
extractQuickPickItemsLogged,
getLogCapture,
+ openAndDismiss,
openEditor,
settle,
standardSuite,
@@ -35,7 +38,7 @@ import {
const NO_TERMINAL_SELECTION_MSG =
'RangeLink: No text selected in the terminal. Select text and try again.';
-standardSuite('Core Send Commands', { assisted: true }, (log) => {
+standardSuite('Core Send Commands', (log) => {
const tmpFileUris: vscode.Uri[] = [];
const tmpTerminals: vscode.Terminal[] = [];
@@ -339,7 +342,7 @@ standardSuite('Core Send Commands', { assisted: true }, (log) => {
log('✓ R-V with no bound destination opens picker (log-based)');
});
- test('[assisted] core-send-commands-r-l-005: R-L with no bound destination opens picker', async () => {
+ test('core-send-commands-r-l-005: R-L with no bound destination opens picker', async () => {
const fileUri = createWorkspaceFile('csc-r-l-005', 'test content\n');
tmpFileUris.push(fileUri);
const doc = await vscode.workspace.openTextDocument(fileUri);
@@ -350,14 +353,7 @@ standardSuite('Core Send Commands', { assisted: true }, (log) => {
const logCaptureRl005 = getLogCapture();
logCaptureRl005.mark('before-r-l-005');
- await waitForHuman(
- 'core-send-commands-r-l-005',
- 'No destination bound. "test" is already selected.',
- [
- 'Press Cmd+R Cmd+L — the RangeLink destination picker opens',
- 'Press Escape to dismiss the picker, then click Cancel',
- ],
- );
+ await openAndDismiss(CMD_COPY_LINK_RELATIVE);
const itemsRl005 = extractQuickPickItemsLogged(logCaptureRl005.getLinesSince('before-r-l-005'));
assert.ok(
@@ -368,7 +364,7 @@ standardSuite('Core Send Commands', { assisted: true }, (log) => {
log('✓ R-L with no destination opens picker (log-based)');
});
- test('[assisted] core-send-commands-r-p-001: Send Portable Link with no bound destination opens picker', async () => {
+ test('core-send-commands-r-p-001: Send Portable Link with no bound destination opens picker', async () => {
const fileUri = createWorkspaceFile('csc-r-p-001', 'test content\n');
tmpFileUris.push(fileUri);
const doc = await vscode.workspace.openTextDocument(fileUri);
@@ -379,14 +375,7 @@ standardSuite('Core Send Commands', { assisted: true }, (log) => {
const logCaptureRp001 = getLogCapture();
logCaptureRp001.mark('before-r-p-001');
- await waitForHuman(
- 'core-send-commands-r-p-001',
- 'No destination bound. "test" is already selected.',
- [
- 'Press Cmd+Shift+P → "RangeLink: Send Portable Link" — the RangeLink destination picker opens',
- 'Press Escape to dismiss the picker, then click Cancel',
- ],
- );
+ await openAndDismiss(CMD_COPY_PORTABLE_LINK_RELATIVE);
const itemsRp001 = extractQuickPickItemsLogged(logCaptureRp001.getLinesSince('before-r-p-001'));
assert.ok(
@@ -397,7 +386,7 @@ standardSuite('Core Send Commands', { assisted: true }, (log) => {
log('✓ Send Portable Link with no destination opens picker (log-based)');
});
- test('[assisted] core-send-commands-r-v-001: Send Selected Text with no bound destination opens picker', async () => {
+ test('core-send-commands-r-v-001: Send Selected Text with no bound destination opens picker', async () => {
const fileUri = createWorkspaceFile('csc-r-v-001', 'test content\n');
tmpFileUris.push(fileUri);
const doc = await vscode.workspace.openTextDocument(fileUri);
@@ -408,14 +397,7 @@ standardSuite('Core Send Commands', { assisted: true }, (log) => {
const logCaptureRv001 = getLogCapture();
logCaptureRv001.mark('before-r-v-001');
- await waitForHuman(
- 'core-send-commands-r-v-001',
- 'No destination bound. "test" is already selected.',
- [
- 'Press Cmd+Shift+P → "RangeLink: Send Selected Text" — the RangeLink destination picker opens',
- 'Press Escape to dismiss the picker, then click Cancel',
- ],
- );
+ await openAndDismiss(CMD_PASTE_TO_DESTINATION);
const itemsRv001 = extractQuickPickItemsLogged(logCaptureRv001.getLinesSince('before-r-v-001'));
assert.ok(
diff --git a/packages/rangelink-vscode-extension/src/__integration-tests__/suite/customAiAssistants.test.ts b/packages/rangelink-vscode-extension/src/__integration-tests__/suite/customAiAssistants.test.ts
index 9e361722..328c897c 100644
--- a/packages/rangelink-vscode-extension/src/__integration-tests__/suite/customAiAssistants.test.ts
+++ b/packages/rangelink-vscode-extension/src/__integration-tests__/suite/customAiAssistants.test.ts
@@ -2,6 +2,7 @@ import assert from 'node:assert';
import * as vscode from 'vscode';
+import { CMD_BIND_TO_DESTINATION } from '../../constants/commandIds';
import {
assertClipboardChanged,
assertClipboardRestored,
@@ -11,6 +12,7 @@ import {
createAndOpenFile,
extractQuickPickItemsLogged,
getLogCapture,
+ openAndDismiss,
settle,
standardSuite,
waitForHuman,
@@ -20,7 +22,7 @@ import {
const EXPECTED_CUSTOM_ASSISTANTS_COUNT = 6;
const EXPECTED_CUSTOM_AI_REGISTRATIONS = 5;
-standardSuite('Custom AI Assistants', {}, (_log) => {
+standardSuite('Custom AI Assistants', (_log) => {
test('custom-ai-assistant-001: three-tier config is parsed and logged at activation', () => {
const logCapture = getLogCapture();
const allLines = logCapture.getAllLines();
@@ -204,20 +206,12 @@ standardSuite('Custom AI Assistants', {}, (_log) => {
});
});
-standardSuite('Custom AI Assistants — Destination Picker (Assisted)', { assisted: true }, (log) => {
- test('[assisted] custom-ai-assistant-003: custom AI assistant appears in R-D destination picker with configured display name', async () => {
+standardSuite('Custom AI Assistants — Destination Picker', (log) => {
+ test('custom-ai-assistant-003: custom AI assistant appears in R-D destination picker with configured display name', async () => {
const logCapture = getLogCapture();
logCapture.mark('before-003');
- await waitForHuman(
- 'custom-ai-assistant-003',
- 'Open R-D picker (Cmd+R Cmd+D), observe that Dummy AI entries appear, then press Escape',
- [
- '1. Press Cmd+R Cmd+D to open the destination picker',
- '2. Observe the list — confirm "Dummy AI (Tier 1)" appears',
- '3. Press Escape to close without selecting',
- ],
- );
+ await openAndDismiss(CMD_BIND_TO_DESTINATION);
const lines = logCapture.getLinesSince('before-003');
const items = extractQuickPickItemsLogged(lines);
@@ -230,19 +224,11 @@ standardSuite('Custom AI Assistants — Destination Picker (Assisted)', { assist
log('✓ custom-ai-assistant-003 — log confirms "Dummy AI (Tier 1)" appears in R-D picker');
});
- test('[assisted] custom-ai-assistant-007: multiple custom AI assistants listed in user-defined order', async () => {
+ test('custom-ai-assistant-007: multiple custom AI assistants listed in user-defined order', async () => {
const logCapture = getLogCapture();
logCapture.mark('before-007');
- await waitForHuman(
- 'custom-ai-assistant-007',
- 'Open R-D picker (Cmd+R Cmd+D), observe Dummy AI order (Tier 1 → Tier 2 → Tier 3 → Template → Fallback), then press Escape',
- [
- '1. Press Cmd+R Cmd+D to open the destination picker',
- '2. Observe custom AI assistants appear in order: Tier 1, Tier 2, Tier 3, Template, Fallback',
- '3. Press Escape to close without selecting',
- ],
- );
+ await openAndDismiss(CMD_BIND_TO_DESTINATION);
const lines = logCapture.getLinesSince('before-007');
const items = extractQuickPickItemsLogged(lines);
@@ -277,7 +263,7 @@ standardSuite('Custom AI Assistants — Destination Picker (Assisted)', { assist
});
});
-standardSuite('Custom AI Assistants — Cold Start', { assisted: true }, (log) => {
+standardSuite('Custom AI Assistants — Cold Start', (log) => {
const tmpFileUris: vscode.Uri[] = [];
teardown(async () => {
@@ -333,7 +319,7 @@ standardSuite('Custom AI Assistants — Cold Start', { assisted: true }, (log) =
});
});
-standardSuite('Custom AI Assistants — Paste Flow', { assisted: true }, (log) => {
+standardSuite('Custom AI Assistants — Paste Flow', (log) => {
const tmpFileUris: vscode.Uri[] = [];
suiteSetup(async () => {
diff --git a/packages/rangelink-vscode-extension/src/__integration-tests__/suite/dirtyBufferWarning.test.ts b/packages/rangelink-vscode-extension/src/__integration-tests__/suite/dirtyBufferWarning.test.ts
index 15197748..85a1222d 100644
--- a/packages/rangelink-vscode-extension/src/__integration-tests__/suite/dirtyBufferWarning.test.ts
+++ b/packages/rangelink-vscode-extension/src/__integration-tests__/suite/dirtyBufferWarning.test.ts
@@ -27,7 +27,7 @@ import {
writeClipboardSentinel,
} from '../helpers';
-standardSuite('Dirty Buffer Warning', { assisted: true }, (_log) => {
+standardSuite('Dirty Buffer Warning', (_log) => {
let testFileUri: vscode.Uri;
suiteSetup(async () => {
@@ -389,7 +389,7 @@ standardSuite('Dirty Buffer Warning', { assisted: true }, (_log) => {
});
});
-standardSuite('Dirty Buffer Warning — Dialog Interaction', { assisted: true }, (log) => {
+standardSuite('Dirty Buffer Warning — Dialog Interaction', (log) => {
let testFileUri: vscode.Uri;
suiteSetup(async () => {
diff --git a/packages/rangelink-vscode-extension/src/__integration-tests__/suite/editorBindingValidation.test.ts b/packages/rangelink-vscode-extension/src/__integration-tests__/suite/editorBindingValidation.test.ts
index 80e8be31..e67c1151 100644
--- a/packages/rangelink-vscode-extension/src/__integration-tests__/suite/editorBindingValidation.test.ts
+++ b/packages/rangelink-vscode-extension/src/__integration-tests__/suite/editorBindingValidation.test.ts
@@ -4,7 +4,7 @@ import * as path from 'node:path';
import * as vscode from 'vscode';
-import { CMD_UNBIND_DESTINATION } from '../../constants/commandIds';
+import { CMD_BIND_TO_DESTINATION, CMD_UNBIND_DESTINATION } from '../../constants/commandIds';
import {
cleanupFiles,
closeAllEditors,
@@ -13,13 +13,13 @@ import {
findTestItemsByPrefix,
getLogCapture,
getWorkspaceRoot,
+ openAndDismiss,
settle,
standardSuite,
- waitForHuman,
waitForHumanVerdict,
} from '../helpers';
-standardSuite('Editor Binding Validation', { assisted: true }, (log) => {
+standardSuite('Editor Binding Validation', (log) => {
const tmpFileUris: vscode.Uri[] = [];
teardown(async () => {
@@ -92,7 +92,7 @@ standardSuite('Editor Binding Validation', { assisted: true }, (log) => {
log('✓ Settings UI hides file path/bind commands (human verdict)');
});
- test('[assisted] editor-binding-validation-004: binary .png file is excluded from R-D destination picker', async () => {
+ test('editor-binding-validation-004: binary .png file is excluded from R-D destination picker', async () => {
// Minimal PNG magic bytes — enough for VSCode to detect as binary
const PNG_MAGIC = new Uint8Array([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]);
const pngPath = path.join(getWorkspaceRoot(), `__rl-test-ebv-004-${Date.now()}.png`);
@@ -116,17 +116,7 @@ standardSuite('Editor Binding Validation', { assisted: true }, (log) => {
const logCapture = getLogCapture();
logCapture.mark('before-ebv-004');
- await waitForHuman(
- 'editor-binding-validation-004',
- 'A .txt file is open in col 1, a .png in col 2. Press Cmd+R Cmd+D and Escape — .png must not appear in picker.',
- [
- '1. The .txt control file is open in column 1, the .png is open in column 2',
- '2. Press Cmd+R Cmd+D to open the destination picker',
- '3. Confirm the .txt file IS listed (positive control)',
- '4. Confirm no .png file appears in the list',
- '5. Press Escape to dismiss',
- ],
- );
+ await openAndDismiss(CMD_BIND_TO_DESTINATION);
const lines = logCapture.getLinesSince('before-ebv-004');
const items = extractQuickPickItemsLogged(lines);
diff --git a/packages/rangelink-vscode-extension/src/__integration-tests__/suite/filePathNavigation.test.ts b/packages/rangelink-vscode-extension/src/__integration-tests__/suite/filePathNavigation.test.ts
index affaf07b..cdaa5f67 100644
--- a/packages/rangelink-vscode-extension/src/__integration-tests__/suite/filePathNavigation.test.ts
+++ b/packages/rangelink-vscode-extension/src/__integration-tests__/suite/filePathNavigation.test.ts
@@ -16,7 +16,7 @@ import {
const NON_EXISTENT_PATH_SETTLE_MS = 1000;
-standardSuite('File Path Navigation', {}, (_log) => {
+standardSuite('File Path Navigation', (_log) => {
let testFileUri: vscode.Uri;
let anchorFileUri: vscode.Uri;
diff --git a/packages/rangelink-vscode-extension/src/__integration-tests__/suite/filePicker.test.ts b/packages/rangelink-vscode-extension/src/__integration-tests__/suite/filePicker.test.ts
index ad32b894..a0d43c9e 100644
--- a/packages/rangelink-vscode-extension/src/__integration-tests__/suite/filePicker.test.ts
+++ b/packages/rangelink-vscode-extension/src/__integration-tests__/suite/filePicker.test.ts
@@ -4,6 +4,7 @@ import * as path from 'node:path';
import * as vscode from 'vscode';
+import { CMD_BIND_TO_DESTINATION, CMD_OPEN_STATUS_BAR_MENU } from '../../constants/commandIds';
import {
cleanupFiles,
closeAllEditors,
@@ -12,6 +13,7 @@ import {
findTestItemsByPrefix,
getLogCapture,
getWorkspaceRoot,
+ openAndDismiss,
parseQuickPickItemsFromLogLine,
settle,
standardSuite,
@@ -21,7 +23,7 @@ import {
const SEPARATOR_KIND = -1;
const FILE_OVERFLOW_THRESHOLD = 5;
-standardSuite('File Picker', { assisted: true }, (log) => {
+standardSuite('File Picker', (log) => {
const tmpFileUris: vscode.Uri[] = [];
teardown(async () => {
@@ -35,7 +37,7 @@ standardSuite('File Picker', { assisted: true }, (log) => {
const findTestFileItems = (items: Record[]): Record[] =>
findTestItemsByPrefix(items, '__rl-test-fp-');
- test('[assisted] file-picker-001: bound file appears first with bound badge', async () => {
+ test('file-picker-001: bound file appears first with bound badge', async () => {
const uriA = await createAndOpenFile(
'fp-001-a',
'line 1\nline 2\n',
@@ -56,7 +58,7 @@ standardSuite('File Picker', { assisted: true }, (log) => {
const logCapture = getLogCapture();
logCapture.mark('before-fp-001');
- await waitForHuman('file-picker-001', 'Press Cmd+R Cmd+D, then Escape');
+ await openAndDismiss(CMD_BIND_TO_DESTINATION);
const lines = logCapture.getLinesSince('before-fp-001');
const items = extractQuickPickItemsLogged(lines);
@@ -92,7 +94,7 @@ standardSuite('File Picker', { assisted: true }, (log) => {
log('✓ Bound file first with full semantic state + description');
});
- test('[assisted] file-picker-002: active file appears before others in its group', async () => {
+ test('file-picker-002: active file appears before others in its group', async () => {
const uriA = await createAndOpenFile(
'fp-002-a',
'file a\n',
@@ -111,7 +113,7 @@ standardSuite('File Picker', { assisted: true }, (log) => {
const logCapture = getLogCapture();
logCapture.mark('before-fp-002');
- await waitForHuman('file-picker-002', 'Press Cmd+R Cmd+D, then Escape');
+ await openAndDismiss(CMD_BIND_TO_DESTINATION);
const lines = logCapture.getLinesSince('before-fp-002');
const items = extractQuickPickItemsLogged(lines);
@@ -147,7 +149,7 @@ standardSuite('File Picker', { assisted: true }, (log) => {
log('✓ Files ordered by ViewColumn (Tab Group 1 before Tab Group 2)');
});
- test('[assisted] file-picker-003: same base name shows path disambiguation', async () => {
+ test('file-picker-003: same base name shows path disambiguation', async () => {
const wsRoot = getWorkspaceRoot();
const subDirA = path.join(wsRoot, 'src', 'dirA');
const subDirB = path.join(wsRoot, 'src', 'dirB');
@@ -176,7 +178,7 @@ standardSuite('File Picker', { assisted: true }, (log) => {
const logCapture = getLogCapture();
logCapture.mark('before-fp-003');
- await waitForHuman('file-picker-003', 'Press Cmd+R Cmd+D, then Escape');
+ await openAndDismiss(CMD_BIND_TO_DESTINATION);
const lines = logCapture.getLinesSince('before-fp-003');
const items = extractQuickPickItemsLogged(lines);
@@ -224,14 +226,14 @@ standardSuite('File Picker', { assisted: true }, (log) => {
log('✓ Path disambiguation validated with disambiguator in descriptions');
});
- test('[assisted] file-picker-004: open files appear as inline items in destination picker', async () => {
+ test('file-picker-004: open files appear as inline items in destination picker', async () => {
const uri = await createAndOpenFile('fp-004', 'content\n', undefined, tmpFileUris);
const fn = path.basename(uri.fsPath);
const logCapture = getLogCapture();
logCapture.mark('before-fp-004');
- await waitForHuman('file-picker-004', 'Press Cmd+R Cmd+D, then Escape');
+ await openAndDismiss(CMD_BIND_TO_DESTINATION);
const lines = logCapture.getLinesSince('before-fp-004');
const items = extractQuickPickItemsLogged(lines);
@@ -260,7 +262,7 @@ standardSuite('File Picker', { assisted: true }, (log) => {
log('✓ File appears inline in R-D picker — full assertion');
});
- test('[assisted] file-picker-005: overflow shows "More files..." when exceeding inline limit', async () => {
+ test('file-picker-005: overflow shows "More files..." when exceeding inline limit', async () => {
for (let i = 1; i <= FILE_OVERFLOW_THRESHOLD; i++) {
await createAndOpenFile(`fp-005-${i}`, `file ${i}\n`, undefined, tmpFileUris);
}
@@ -268,7 +270,7 @@ standardSuite('File Picker', { assisted: true }, (log) => {
const logCapture = getLogCapture();
logCapture.mark('before-fp-005');
- await waitForHuman('file-picker-005', 'Press Cmd+R Cmd+D, then Escape');
+ await openAndDismiss(CMD_BIND_TO_DESTINATION);
const lines = logCapture.getLinesSince('before-fp-005');
const items = extractQuickPickItemsLogged(lines);
@@ -537,7 +539,7 @@ standardSuite('File Picker', { assisted: true }, (log) => {
log('✓ Secondary picker shows path disambiguation');
});
- test('[assisted] file-picker-011: three files with same name show deeper disambiguation paths', async () => {
+ test('file-picker-011: three files with same name show deeper disambiguation paths', async () => {
const wsRoot = getWorkspaceRoot();
const dirA = path.join(wsRoot, 'src', 'a', 'nested');
const dirB = path.join(wsRoot, 'src', 'b', 'nested');
@@ -577,7 +579,7 @@ standardSuite('File Picker', { assisted: true }, (log) => {
const logCapture = getLogCapture();
logCapture.mark('before-fp-011');
- await waitForHuman('file-picker-011', 'Press Cmd+R Cmd+D, then Escape');
+ await openAndDismiss(CMD_BIND_TO_DESTINATION);
const lines = logCapture.getLinesSince('before-fp-011');
const items = extractQuickPickItemsLogged(lines);
@@ -632,7 +634,7 @@ standardSuite('File Picker', { assisted: true }, (log) => {
log('✓ Three same-name files: same label/displayName, unique disambiguated descriptions');
});
- test('[assisted] file-picker-012: unique file names have no disambiguator in description', async () => {
+ test('file-picker-012: unique file names have no disambiguator in description', async () => {
const uriA = await createAndOpenFile(
'fp-012-alpha',
'file a\n',
@@ -651,7 +653,7 @@ standardSuite('File Picker', { assisted: true }, (log) => {
const logCapture = getLogCapture();
logCapture.mark('before-fp-012');
- await waitForHuman('file-picker-012', 'Press Cmd+R Cmd+D, then Escape');
+ await openAndDismiss(CMD_BIND_TO_DESTINATION);
const lines = logCapture.getLinesSince('before-fp-012');
const items = extractQuickPickItemsLogged(lines);
@@ -687,14 +689,14 @@ standardSuite('File Picker', { assisted: true }, (log) => {
log('✓ Unique file names: no disambiguator, ordered by ViewColumn');
});
- test('[assisted] file-picker-009: file picker appears inline in R-M menu when unbound', async () => {
+ test('file-picker-009: file picker appears inline in R-M menu when unbound', async () => {
const uri = await createAndOpenFile('fp-009', 'content\n', undefined, tmpFileUris);
const fn = path.basename(uri.fsPath);
const logCapture = getLogCapture();
logCapture.mark('before-fp-009');
- await waitForHuman('file-picker-009', 'Open R-M menu (Cmd+R Cmd+M), then Escape');
+ await openAndDismiss(CMD_OPEN_STATUS_BAR_MENU);
const lines = logCapture.getLinesSince('before-fp-009');
const items = extractQuickPickItemsLogged(lines);
diff --git a/packages/rangelink-vscode-extension/src/__integration-tests__/suite/filenameOnlyNavigation.test.ts b/packages/rangelink-vscode-extension/src/__integration-tests__/suite/filenameOnlyNavigation.test.ts
index e3949668..d0bf4f94 100644
--- a/packages/rangelink-vscode-extension/src/__integration-tests__/suite/filenameOnlyNavigation.test.ts
+++ b/packages/rangelink-vscode-extension/src/__integration-tests__/suite/filenameOnlyNavigation.test.ts
@@ -18,7 +18,7 @@ import {
const DUPLICATE_FILE_CONTENT = 'duplicate file content\n';
-standardSuite('Filename-Only Navigation Fallback', {}, (_log) => {
+standardSuite('Filename-Only Navigation Fallback', (_log) => {
let uniqueFilename: string;
let uniqueFilePath: string;
let relativeFilePath: string;
diff --git a/packages/rangelink-vscode-extension/src/__integration-tests__/suite/goToRangeLink.test.ts b/packages/rangelink-vscode-extension/src/__integration-tests__/suite/goToRangeLink.test.ts
index 2bd77d2c..95f53192 100644
--- a/packages/rangelink-vscode-extension/src/__integration-tests__/suite/goToRangeLink.test.ts
+++ b/packages/rangelink-vscode-extension/src/__integration-tests__/suite/goToRangeLink.test.ts
@@ -3,6 +3,7 @@ import * as path from 'node:path';
import * as vscode from 'vscode';
+import { CMD_GO_TO_RANGELINK } from '../../constants/commandIds';
import {
assertInputBoxLogged,
assertToastLogged,
@@ -11,6 +12,7 @@ import {
createAndOpenFile,
extractQuickPickItemsLogged,
getLogCapture,
+ openAndDismiss,
settle,
standardSuite,
waitForHuman,
@@ -36,7 +38,7 @@ const assertUserCancelledInputLogged = (lines: string[]): void => {
assert.ok(found, 'Expected GoToRangeLinkCommand.execute "User cancelled input" debug log');
};
-standardSuite('R-G Go to Link', { assisted: true }, (log) => {
+standardSuite('R-G Go to Link', (log) => {
const tmpFileUris: vscode.Uri[] = [];
teardown(async () => {
@@ -46,11 +48,11 @@ standardSuite('R-G Go to Link', { assisted: true }, (log) => {
await settle();
});
- test('[assisted] go-to-link-001: Cmd+R Cmd+G opens the Go to Link input box', async () => {
+ test('go-to-link-001: Cmd+R Cmd+G opens the Go to Link input box', async () => {
const logCapture = getLogCapture();
logCapture.mark('before-gtl-001');
- await waitForHuman('go-to-link-001', 'Press Cmd+R Cmd+G, then Escape the input box');
+ await openAndDismiss(CMD_GO_TO_RANGELINK);
const lines = logCapture.getLinesSince('before-gtl-001');
diff --git a/packages/rangelink-vscode-extension/src/__integration-tests__/suite/linkGeneration.test.ts b/packages/rangelink-vscode-extension/src/__integration-tests__/suite/linkGeneration.test.ts
index c1e8e6b8..12dc2630 100644
--- a/packages/rangelink-vscode-extension/src/__integration-tests__/suite/linkGeneration.test.ts
+++ b/packages/rangelink-vscode-extension/src/__integration-tests__/suite/linkGeneration.test.ts
@@ -17,7 +17,7 @@ import {
const LOGGER = new NoOpLogger();
-standardSuite('Link Generation', {}, (_log) => {
+standardSuite('Link Generation', (_log) => {
const tmpFileUris: vscode.Uri[] = [];
suiteTeardown(async () => {
@@ -157,7 +157,7 @@ standardSuite('Link Generation', {}, (_log) => {
});
});
-standardSuite('Link Generation — Clickable Links (Assisted)', { assisted: true }, (log) => {
+standardSuite('Link Generation — Clickable Links (Assisted)', (log) => {
const tmpFileUris: vscode.Uri[] = [];
teardown(async () => {
diff --git a/packages/rangelink-vscode-extension/src/__integration-tests__/suite/navigationClamping.test.ts b/packages/rangelink-vscode-extension/src/__integration-tests__/suite/navigationClamping.test.ts
index 00b56ae0..69711c57 100644
--- a/packages/rangelink-vscode-extension/src/__integration-tests__/suite/navigationClamping.test.ts
+++ b/packages/rangelink-vscode-extension/src/__integration-tests__/suite/navigationClamping.test.ts
@@ -18,7 +18,7 @@ import {
const LINE_COUNT = 10;
const LINE_CONTENT = 'abcdefghijklmnopqrst';
-standardSuite('Navigation Clamping', {}, (_log) => {
+standardSuite('Navigation Clamping', (_log) => {
let testFilename: string;
let testFileUri: vscode.Uri;
diff --git a/packages/rangelink-vscode-extension/src/__integration-tests__/suite/navigationPrecision.test.ts b/packages/rangelink-vscode-extension/src/__integration-tests__/suite/navigationPrecision.test.ts
index 38373600..5a5bad96 100644
--- a/packages/rangelink-vscode-extension/src/__integration-tests__/suite/navigationPrecision.test.ts
+++ b/packages/rangelink-vscode-extension/src/__integration-tests__/suite/navigationPrecision.test.ts
@@ -15,7 +15,7 @@ import {
standardSuite,
} from '../helpers';
-standardSuite('Navigation Precision', {}, (_log) => {
+standardSuite('Navigation Precision', (_log) => {
let testFilename: string;
let testFileUri: vscode.Uri;
diff --git a/packages/rangelink-vscode-extension/src/__integration-tests__/suite/navigationToastSettings.test.ts b/packages/rangelink-vscode-extension/src/__integration-tests__/suite/navigationToastSettings.test.ts
index f4953f5f..ae2c3d26 100644
--- a/packages/rangelink-vscode-extension/src/__integration-tests__/suite/navigationToastSettings.test.ts
+++ b/packages/rangelink-vscode-extension/src/__integration-tests__/suite/navigationToastSettings.test.ts
@@ -16,7 +16,7 @@ import {
standardSuite,
} from '../helpers';
-standardSuite('Navigation Toast Settings', {}, (_log) => {
+standardSuite('Navigation Toast Settings', (_log) => {
let testFilename: string;
let testFileUri: vscode.Uri;
diff --git a/packages/rangelink-vscode-extension/src/__integration-tests__/suite/platformKeybindings.test.ts b/packages/rangelink-vscode-extension/src/__integration-tests__/suite/platformKeybindings.test.ts
index 072685e7..b356e987 100644
--- a/packages/rangelink-vscode-extension/src/__integration-tests__/suite/platformKeybindings.test.ts
+++ b/packages/rangelink-vscode-extension/src/__integration-tests__/suite/platformKeybindings.test.ts
@@ -10,7 +10,7 @@ import {
waitForHumanVerdict,
} from '../helpers';
-standardSuite('Platform Keybindings', { assisted: true }, (_log) => {
+standardSuite('Platform Keybindings', (_log) => {
const tmpFileUris: vscode.Uri[] = [];
suiteTeardown(async () => {
diff --git a/packages/rangelink-vscode-extension/src/__integration-tests__/suite/releaseNotifier.test.ts b/packages/rangelink-vscode-extension/src/__integration-tests__/suite/releaseNotifier.test.ts
index c079e3b2..49bdfcec 100644
--- a/packages/rangelink-vscode-extension/src/__integration-tests__/suite/releaseNotifier.test.ts
+++ b/packages/rangelink-vscode-extension/src/__integration-tests__/suite/releaseNotifier.test.ts
@@ -13,7 +13,7 @@ const getReleaseNotifier = () => {
return ext.exports.releaseNotifier;
};
-standardSuite('Release Notifier', { assisted: true }, (log) => {
+standardSuite('Release Notifier', (log) => {
test('release-notifier-001: first install stores version silently without notification', async () => {
const notifier = getReleaseNotifier();
await notifier.setLastNotifiedVersion(undefined);
diff --git a/packages/rangelink-vscode-extension/src/__integration-tests__/suite/sendFilePath.test.ts b/packages/rangelink-vscode-extension/src/__integration-tests__/suite/sendFilePath.test.ts
index 4dfbf703..2346df0f 100644
--- a/packages/rangelink-vscode-extension/src/__integration-tests__/suite/sendFilePath.test.ts
+++ b/packages/rangelink-vscode-extension/src/__integration-tests__/suite/sendFilePath.test.ts
@@ -28,7 +28,7 @@ import {
writeClipboardSentinel,
} from '../helpers';
-standardSuite('Send File Path', { assisted: true }, (log) => {
+standardSuite('Send File Path', (log) => {
const tmpFileUris: vscode.Uri[] = [];
const tmpTerminals: vscode.Terminal[] = [];
diff --git a/packages/rangelink-vscode-extension/src/__integration-tests__/suite/smartPadding.test.ts b/packages/rangelink-vscode-extension/src/__integration-tests__/suite/smartPadding.test.ts
index 71600b0e..3855ff80 100644
--- a/packages/rangelink-vscode-extension/src/__integration-tests__/suite/smartPadding.test.ts
+++ b/packages/rangelink-vscode-extension/src/__integration-tests__/suite/smartPadding.test.ts
@@ -13,7 +13,7 @@ import {
waitForActiveEditor,
} from '../helpers';
-standardSuite('Smart Padding — Editor-to-Editor R-V', {}, (log) => {
+standardSuite('Smart Padding — Editor-to-Editor R-V', (log) => {
let sourceFileUri: vscode.Uri;
let destFileUri: vscode.Uri;
diff --git a/packages/rangelink-vscode-extension/src/__integration-tests__/suite/statusBarMenu.test.ts b/packages/rangelink-vscode-extension/src/__integration-tests__/suite/statusBarMenu.test.ts
index a3fc2481..115eb461 100644
--- a/packages/rangelink-vscode-extension/src/__integration-tests__/suite/statusBarMenu.test.ts
+++ b/packages/rangelink-vscode-extension/src/__integration-tests__/suite/statusBarMenu.test.ts
@@ -2,13 +2,18 @@ import assert from 'node:assert';
import * as vscode from 'vscode';
-import { CMD_BIND_TO_TERMINAL_HERE, CMD_UNBIND_DESTINATION } from '../../constants/commandIds';
+import {
+ CMD_BIND_TO_TERMINAL_HERE,
+ CMD_OPEN_STATUS_BAR_MENU,
+ CMD_UNBIND_DESTINATION,
+} from '../../constants/commandIds';
import {
assertQuickPickItemsLogged,
cleanupFiles,
createWorkspaceFile,
extractQuickPickItemsLogged,
getLogCapture,
+ openAndDismiss,
settle,
standardSuite,
TERMINAL_READY_MS,
@@ -18,18 +23,18 @@ import {
const SEPARATOR_KIND = -1;
-standardSuite('R-M Status Bar Menu', { assisted: true }, (log) => {
+standardSuite('R-M Status Bar Menu', (log) => {
const tmpFileUris: vscode.Uri[] = [];
suiteTeardown(async () => {
cleanupFiles(tmpFileUris);
});
- test('[assisted] status-bar-menu-002: clicking the status bar item opens the R-M menu', async () => {
+ test('status-bar-menu-002: invoking openStatusBarMenu command opens the R-M menu', async () => {
const logCapture = getLogCapture();
logCapture.mark('before-menu-002');
- await waitForHuman('status-bar-menu-002', 'Click the RangeLink status bar item, then Escape');
+ await openAndDismiss(CMD_OPEN_STATUS_BAR_MENU);
const lines = logCapture.getLinesSince('before-menu-002');
const items = extractQuickPickItemsLogged(lines);
@@ -59,7 +64,7 @@ standardSuite('R-M Status Bar Menu', { assisted: true }, (log) => {
log('✓ Unbound menu: no Jump item, correct structure');
});
- test('[assisted] status-bar-menu-003: Cmd+R Cmd+M keybinding opens the R-M menu', async () => {
+ test('status-bar-menu-003: invoking openStatusBarMenu command opens the R-M menu', async () => {
const testFileUri = createWorkspaceFile('menu-003', 'line 1\nline 2\n');
tmpFileUris.push(testFileUri);
const doc = await vscode.workspace.openTextDocument(testFileUri);
@@ -69,7 +74,7 @@ standardSuite('R-M Status Bar Menu', { assisted: true }, (log) => {
const logCapture = getLogCapture();
logCapture.mark('before-menu-003');
- await waitForHuman('status-bar-menu-003', 'Press Cmd+R Cmd+M, then Escape');
+ await openAndDismiss(CMD_OPEN_STATUS_BAR_MENU);
const lines = logCapture.getLinesSince('before-menu-003');
const items = extractQuickPickItemsLogged(lines);
@@ -96,10 +101,10 @@ standardSuite('R-M Status Bar Menu', { assisted: true }, (log) => {
],
);
- log('✓ Keybinding menu: no Jump item, correct structure');
+ log('✓ Direct command menu: no Jump item, correct structure');
});
- test('[assisted] status-bar-menu-005: R-M menu shows Jump to Bound Destination when bound', async () => {
+ test('status-bar-menu-005: R-M menu shows Jump to Bound Destination when bound', async () => {
const terminal = vscode.window.createTerminal({ name: 'rl-menu-test' });
terminal.show(true);
await settle(TERMINAL_READY_MS);
@@ -111,7 +116,7 @@ standardSuite('R-M Status Bar Menu', { assisted: true }, (log) => {
const logCapture = getLogCapture();
logCapture.mark('before-menu-005');
- await waitForHuman('status-bar-menu-005', 'Open R-M menu (Cmd+R Cmd+M), then Escape');
+ await openAndDismiss(CMD_OPEN_STATUS_BAR_MENU);
const lines = logCapture.getLinesSince('before-menu-005');
assertQuickPickItemsLogged(lines, [
@@ -148,23 +153,14 @@ standardSuite('R-M Status Bar Menu', { assisted: true }, (log) => {
log('✓ Status bar item shows correct text and tooltip');
});
- test('[assisted] status-bar-menu-006: R-M menu shows destination picker items when no destination is bound', async () => {
+ test('status-bar-menu-006: R-M menu shows destination picker items when no destination is bound', async () => {
await vscode.commands.executeCommand(CMD_UNBIND_DESTINATION);
await settle();
const logCapture = getLogCapture();
logCapture.mark('before-006');
- await waitForHuman(
- 'status-bar-menu-006',
- 'No destination bound. Open the R-M menu (Cmd+R Cmd+M), observe the first item and the absence of "Jump to Bound Destination", then press Escape.',
- [
- '1. Press Cmd+R Cmd+M to open the R-M menu',
- '2. Confirm the first item says "No bound destination. Choose below to bind:"',
- '3. Confirm there is NO "Jump to Bound Destination" item',
- '4. Press Escape to dismiss, then click Cancel',
- ],
- );
+ await openAndDismiss(CMD_OPEN_STATUS_BAR_MENU);
const lines = logCapture.getLinesSince('before-006');
const items = extractQuickPickItemsLogged(lines);
diff --git a/packages/rangelink-vscode-extension/src/__integration-tests__/suite/terminalPicker.test.ts b/packages/rangelink-vscode-extension/src/__integration-tests__/suite/terminalPicker.test.ts
index f8697895..7323dbc5 100644
--- a/packages/rangelink-vscode-extension/src/__integration-tests__/suite/terminalPicker.test.ts
+++ b/packages/rangelink-vscode-extension/src/__integration-tests__/suite/terminalPicker.test.ts
@@ -2,6 +2,7 @@ import assert from 'node:assert';
import * as vscode from 'vscode';
+import { CMD_BIND_TO_DESTINATION, CMD_OPEN_STATUS_BAR_MENU } from '../../constants/commandIds';
import {
cleanupFiles,
closeAllEditors,
@@ -11,6 +12,7 @@ import {
findTerminalItems,
getLogCapture,
loadSettingsProfile,
+ openAndDismiss,
parseQuickPickItemsFromLogLine,
settle,
standardSuite,
@@ -22,7 +24,7 @@ const TERMINAL_OVERFLOW_COUNT = 6;
const MAX_INLINE_DEFAULT = 5;
const FILE_OVERFLOW_THRESHOLD = 5;
-standardSuite('Terminal Picker', { assisted: true }, (log) => {
+standardSuite('Terminal Picker', (log) => {
const terminals: vscode.Terminal[] = [];
teardown(async () => {
@@ -35,7 +37,7 @@ standardSuite('Terminal Picker', { assisted: true }, (log) => {
await settle();
});
- test('[assisted] terminal-picker-001: active terminal is marked with active badge', async () => {
+ test('terminal-picker-001: active terminal is marked with active badge', async () => {
const t1 = await createTerminal('rl-tp-001-a', terminals);
await createTerminal('rl-tp-001-b', terminals);
t1.show(true);
@@ -44,7 +46,7 @@ standardSuite('Terminal Picker', { assisted: true }, (log) => {
const logCapture = getLogCapture();
logCapture.mark('before-tp-001');
- await waitForHuman('terminal-picker-001', 'Press Cmd+R Cmd+D, then Escape');
+ await openAndDismiss(CMD_BIND_TO_DESTINATION);
const lines = logCapture.getLinesSince('before-tp-001');
const items = extractQuickPickItemsLogged(lines);
@@ -83,7 +85,7 @@ standardSuite('Terminal Picker', { assisted: true }, (log) => {
log('✓ Active terminal: all 6 fields. Non-active: no badge, no isActive');
});
- test('[assisted] terminal-picker-002: bound terminal is marked with bound badge', async () => {
+ test('terminal-picker-002: bound terminal is marked with bound badge', async () => {
await createTerminal('rl-tp-002', terminals);
await vscode.commands.executeCommand('rangelink.bindToTerminalHere');
await settle();
@@ -94,7 +96,7 @@ standardSuite('Terminal Picker', { assisted: true }, (log) => {
const logCapture = getLogCapture();
logCapture.mark('before-tp-002');
- await waitForHuman('terminal-picker-002', 'Press Cmd+R Cmd+D, then Escape');
+ await openAndDismiss(CMD_BIND_TO_DESTINATION);
const lines = logCapture.getLinesSince('before-tp-002');
const items = extractQuickPickItemsLogged(lines);
@@ -133,7 +135,7 @@ standardSuite('Terminal Picker', { assisted: true }, (log) => {
log('✓ Bound first (all 6 fields), active other second');
});
- test('[assisted] terminal-picker-003: terminal that is both active and bound shows dual badge', async () => {
+ test('terminal-picker-003: terminal that is both active and bound shows dual badge', async () => {
const t = await createTerminal('rl-tp-003', terminals);
await vscode.commands.executeCommand('rangelink.bindToTerminalHere');
t.show(true);
@@ -142,7 +144,7 @@ standardSuite('Terminal Picker', { assisted: true }, (log) => {
const logCapture = getLogCapture();
logCapture.mark('before-tp-003');
- await waitForHuman('terminal-picker-003', 'Press Cmd+R Cmd+D, then Escape');
+ await openAndDismiss(CMD_BIND_TO_DESTINATION);
const lines = logCapture.getLinesSince('before-tp-003');
const items = extractQuickPickItemsLogged(lines);
@@ -173,7 +175,7 @@ standardSuite('Terminal Picker', { assisted: true }, (log) => {
log('✓ Dual badge: all 6 fields validated');
});
- test('[assisted] terminal-picker-004: bound terminal always appears first in the list', async () => {
+ test('terminal-picker-004: bound terminal always appears first in the list', async () => {
await createTerminal('rl-tp-004-b', terminals);
await vscode.commands.executeCommand('rangelink.bindToTerminalHere');
await settle();
@@ -182,7 +184,7 @@ standardSuite('Terminal Picker', { assisted: true }, (log) => {
const logCapture = getLogCapture();
logCapture.mark('before-tp-004');
- await waitForHuman('terminal-picker-004', 'Press Cmd+R Cmd+D, then Escape');
+ await openAndDismiss(CMD_BIND_TO_DESTINATION);
const lines = logCapture.getLinesSince('before-tp-004');
const items = extractQuickPickItemsLogged(lines);
@@ -221,7 +223,7 @@ standardSuite('Terminal Picker', { assisted: true }, (log) => {
log('✓ Bound terminal first — all 6 fields');
});
- test('[assisted] terminal-picker-005: active non-bound terminal appears second', async () => {
+ test('terminal-picker-005: active non-bound terminal appears second', async () => {
await createTerminal('rl-tp-005-a', terminals);
await vscode.commands.executeCommand('rangelink.bindToTerminalHere');
await settle();
@@ -232,7 +234,7 @@ standardSuite('Terminal Picker', { assisted: true }, (log) => {
const logCapture = getLogCapture();
logCapture.mark('before-tp-005');
- await waitForHuman('terminal-picker-005', 'Press Cmd+R Cmd+D, then Escape');
+ await openAndDismiss(CMD_BIND_TO_DESTINATION);
const lines = logCapture.getLinesSince('before-tp-005');
const items = extractQuickPickItemsLogged(lines);
@@ -271,13 +273,13 @@ standardSuite('Terminal Picker', { assisted: true }, (log) => {
log('✓ Bound first, active second — all 6 fields');
});
- test('[assisted] terminal-picker-006: hidden IDE terminals are absent from the picker', async () => {
+ test('terminal-picker-006: hidden IDE terminals are absent from the picker', async () => {
await createTerminal('rl-tp-006', terminals);
const logCapture = getLogCapture();
logCapture.mark('before-tp-006');
- await waitForHuman('terminal-picker-006', 'Press Cmd+R Cmd+D, then Escape');
+ await openAndDismiss(CMD_BIND_TO_DESTINATION);
const lines = logCapture.getLinesSince('before-tp-006');
const items = extractQuickPickItemsLogged(lines);
@@ -308,14 +310,14 @@ standardSuite('Terminal Picker', { assisted: true }, (log) => {
log('✓ Only the test terminal appears — full field validation');
});
- test('[assisted] terminal-picker-007: all terminals shown inline when within maxInline limit', async () => {
+ test('terminal-picker-007: all terminals shown inline when within maxInline limit', async () => {
await createTerminal('rl-tp-007-a', terminals);
await createTerminal('rl-tp-007-b', terminals);
const logCapture = getLogCapture();
logCapture.mark('before-tp-007');
- await waitForHuman('terminal-picker-007', 'Press Cmd+R Cmd+D, then Escape');
+ await openAndDismiss(CMD_BIND_TO_DESTINATION);
const lines = logCapture.getLinesSince('before-tp-007');
const items = extractQuickPickItemsLogged(lines);
@@ -360,7 +362,7 @@ standardSuite('Terminal Picker', { assisted: true }, (log) => {
log('✓ Both terminals inline, full field validation');
});
- test('[assisted] terminal-picker-008: overflow shows "More terminals..." when exceeding maxInline', async () => {
+ test('terminal-picker-008: overflow shows "More terminals..." when exceeding maxInline', async () => {
for (let i = 1; i <= TERMINAL_OVERFLOW_COUNT; i++) {
await createTerminal(`rl-tp-008-${i}`, terminals);
}
@@ -368,7 +370,7 @@ standardSuite('Terminal Picker', { assisted: true }, (log) => {
const logCapture = getLogCapture();
logCapture.mark('before-tp-008');
- await waitForHuman('terminal-picker-008', 'Press Cmd+R Cmd+D, then Escape');
+ await openAndDismiss(CMD_BIND_TO_DESTINATION);
const lines = logCapture.getLinesSince('before-tp-008');
const items = extractQuickPickItemsLogged(lines);
@@ -525,7 +527,7 @@ standardSuite('Terminal Picker', { assisted: true }, (log) => {
log('✓ Parent picker reopened with identical items');
});
- test('[assisted] terminal-picker-011: maxInline setting changes overflow threshold', async () => {
+ test('terminal-picker-011: maxInline setting changes overflow threshold', async () => {
await loadSettingsProfile('terminal-picker-low', log);
const LOW_MAX_INLINE = 2;
const TC_TERMINAL_COUNT = 3;
@@ -537,7 +539,7 @@ standardSuite('Terminal Picker', { assisted: true }, (log) => {
const logCapture = getLogCapture();
logCapture.mark('before-tp-011');
- await waitForHuman('terminal-picker-011', 'Press Cmd+R Cmd+D, then Escape');
+ await openAndDismiss(CMD_BIND_TO_DESTINATION);
const lines = logCapture.getLinesSince('before-tp-011');
const items = extractQuickPickItemsLogged(lines);
@@ -586,13 +588,13 @@ standardSuite('Terminal Picker', { assisted: true }, (log) => {
log('✓ maxInline=2: overflow + active inline terminal fully validated');
});
- test('[assisted] terminal-picker-012: terminal picker appears inline in R-M menu when unbound', async () => {
+ test('terminal-picker-012: terminal picker appears inline in R-M menu when unbound', async () => {
await createTerminal('rl-tp-012', terminals);
const logCapture = getLogCapture();
logCapture.mark('before-tp-012');
- await waitForHuman('terminal-picker-012', 'Open R-M menu (Cmd+R Cmd+M), then Escape');
+ await openAndDismiss(CMD_OPEN_STATUS_BAR_MENU);
const lines = logCapture.getLinesSince('before-tp-012');
const items = extractQuickPickItemsLogged(lines);
@@ -628,13 +630,13 @@ standardSuite('Terminal Picker', { assisted: true }, (log) => {
log('✓ Terminal inline in R-M menu with full description');
});
- test('[assisted] terminal-picker-013: terminal picker appears inline in R-D destination picker', async () => {
+ test('terminal-picker-013: terminal picker appears inline in R-D destination picker', async () => {
await createTerminal('rl-tp-013', terminals);
const logCapture = getLogCapture();
logCapture.mark('before-tp-013');
- await waitForHuman('terminal-picker-013', 'Press Cmd+R Cmd+D, then Escape');
+ await openAndDismiss(CMD_BIND_TO_DESTINATION);
const lines = logCapture.getLinesSince('before-tp-013');
const items = extractQuickPickItemsLogged(lines);
@@ -665,7 +667,7 @@ standardSuite('Terminal Picker', { assisted: true }, (log) => {
log('✓ Terminal inline in R-D picker — full fields');
});
- test('[assisted] bind-to-destination-013: R-D picker shows both overflow items when many terminals and files are open', async () => {
+ test('bind-to-destination-013: R-D picker shows both overflow items when many terminals and files are open', async () => {
for (let i = 1; i <= TERMINAL_OVERFLOW_COUNT; i++) {
await createTerminal(`rl-btd-013-${i}`, terminals);
}
@@ -686,7 +688,7 @@ standardSuite('Terminal Picker', { assisted: true }, (log) => {
const logCapture = getLogCapture();
logCapture.mark('before-btd-013');
- await waitForHuman('bind-to-destination-013', 'Press Cmd+R Cmd+D, then Escape');
+ await openAndDismiss(CMD_BIND_TO_DESTINATION);
const lines = logCapture.getLinesSince('before-btd-013');
const items = extractQuickPickItemsLogged(lines);
diff --git a/packages/rangelink-vscode-extension/src/__integration-tests__/suite/textEditorDestination.test.ts b/packages/rangelink-vscode-extension/src/__integration-tests__/suite/textEditorDestination.test.ts
index 7c645316..cfbf63fc 100644
--- a/packages/rangelink-vscode-extension/src/__integration-tests__/suite/textEditorDestination.test.ts
+++ b/packages/rangelink-vscode-extension/src/__integration-tests__/suite/textEditorDestination.test.ts
@@ -19,7 +19,7 @@ import {
waitForHuman,
} from '../helpers';
-standardSuite('Text Editor Destination', { assisted: true }, (log) => {
+standardSuite('Text Editor Destination', (log) => {
const tmpFileUris: vscode.Uri[] = [];
teardown(async () => {
diff --git a/packages/rangelink-vscode-extension/src/__integration-tests__/suite/unbind.test.ts b/packages/rangelink-vscode-extension/src/__integration-tests__/suite/unbind.test.ts
index fcd5beea..2e7038ea 100644
--- a/packages/rangelink-vscode-extension/src/__integration-tests__/suite/unbind.test.ts
+++ b/packages/rangelink-vscode-extension/src/__integration-tests__/suite/unbind.test.ts
@@ -12,7 +12,7 @@ import {
standardSuite,
} from '../helpers';
-standardSuite('Unbind Destination', {}, (_log) => {
+standardSuite('Unbind Destination', (_log) => {
let testFileUri: vscode.Uri;
suiteSetup(async () => {
diff --git a/packages/rangelink-vscode-extension/src/__integration-tests__/suite/untitledNavigation.test.ts b/packages/rangelink-vscode-extension/src/__integration-tests__/suite/untitledNavigation.test.ts
index faae13b9..2de33bb8 100644
--- a/packages/rangelink-vscode-extension/src/__integration-tests__/suite/untitledNavigation.test.ts
+++ b/packages/rangelink-vscode-extension/src/__integration-tests__/suite/untitledNavigation.test.ts
@@ -70,7 +70,7 @@ const navigateToUntitledLink = (
});
};
-standardSuite('Untitled File Navigation', {}, (_log) => {
+standardSuite('Untitled File Navigation', (_log) => {
let untitledDoc: vscode.TextDocument;
let untitledDisplayName: string;