Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion test/e2e/pages/notebooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { QuickAccess } from './quickaccess';
import { basename } from 'path';
import test, { expect, FrameLocator, Locator } from '@playwright/test';
import { HotKeys } from './hotKeys.js';
import { DEPRIORITIZED_PYTHON_SOURCES } from './sessions';
import { ALLOW_DEPRIORITIZED_PYTHON_FALLBACK, DEPRIORITIZED_PYTHON_SOURCES } from './sessions';
import { escapeRegExp } from '../utils/strings';

const KERNEL_DROPDOWN = 'a.kernel-label';
Expand Down Expand Up @@ -94,6 +94,7 @@ export class Notebooks {
await this.quickinput.type(desiredKernel);
await this.quickinput.selectQuickInputElementContaining(`${kernelGroup} ${desiredKernel}`, {
deprioritize: kernelGroup === 'Python' ? DEPRIORITIZED_PYTHON_SOURCES : undefined,
allowDeprioritizedFallback: ALLOW_DEPRIORITIZED_PYTHON_FALLBACK,
});
await this.quickinput.waitForQuickInputClosed();

Expand Down
4 changes: 3 additions & 1 deletion test/e2e/pages/notebooksPositron.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { QuickAccess } from './quickaccess';
import test, { expect, Locator } from '@playwright/test';
import { HotKeys } from './hotKeys.js';
import { ContextMenu, MenuItemState } from './dialog-contextMenu.js';
import { ACTIVE_STATUS_ICON, DEPRIORITIZED_PYTHON_SOURCES, DISCONNECTED_STATUS_ICON, IDLE_STATUS_ICON, SessionState } from './sessions.js';
import { ACTIVE_STATUS_ICON, ALLOW_DEPRIORITIZED_PYTHON_FALLBACK, DEPRIORITIZED_PYTHON_SOURCES, DISCONNECTED_STATUS_ICON, IDLE_STATUS_ICON, SessionState } from './sessions.js';
import { basename, relative } from 'path';

const DEFAULT_TIMEOUT = 10000;
Expand Down Expand Up @@ -2024,6 +2024,7 @@ export class Kernel extends KernelBase {
timeout: 1000,
force: false,
deprioritize: kernelGroup === 'Python' ? DEPRIORITIZED_PYTHON_SOURCES : undefined,
allowDeprioritizedFallback: ALLOW_DEPRIORITIZED_PYTHON_FALLBACK,
});
await this.quickinput.waitForQuickInputClosed();
});
Expand Down Expand Up @@ -2088,6 +2089,7 @@ export class Kernel extends KernelBase {
timeout: 1000,
force: false,
deprioritize: kernelGroup === 'Python' ? DEPRIORITIZED_PYTHON_SOURCES : undefined,
allowDeprioritizedFallback: ALLOW_DEPRIORITIZED_PYTHON_FALLBACK,
});
await this.quickinput.waitForQuickInputClosed();
this.code.logger.log(`Selected kernel: ${desiredKernel}`);
Expand Down
27 changes: 15 additions & 12 deletions test/e2e/pages/quickInput.ts
Original file line number Diff line number Diff line change
Expand Up @@ -185,28 +185,31 @@ export class QuickInput {

async selectQuickInputElementContaining(
text: string,
{ timeout, force = true, deprioritize }: { timeout?: number; force?: boolean; deprioritize?: string[] } = {},
{ timeout, force = true, deprioritize, allowDeprioritizedFallback = false }: { timeout?: number; force?: boolean; deprioritize?: string[]; allowDeprioritizedFallback?: boolean } = {},
): Promise<string> {
const matches = this.code.driver.currentPage
.locator(`${QuickInput.QUICK_INPUT_RESULT}[aria-label*="${text}"]`);

// By default select the first matching row. When `deprioritize` is set and
// several rows share `text` (e.g. a project venv and a base pyenv both
// labeled "Python 3.10.12"), prefer the first row whose aria-label contains
// none of the deprioritized source markers. Falls back to the first match
// when every match is deprioritized (e.g. a platform where only the base
// interpreter is installed).
// none of the deprioritized source markers. When every match is
// deprioritized the intended row has not registered yet, so throw and let
// the caller's retry reopen the picker: clicking a base install instead
// starts the wrong (often unusable) interpreter and defers the failure to a
// downstream timeout. Pass `allowDeprioritizedFallback` where only base
// installs exist (Windows/macOS CI).
let target = matches.first();
if (deprioritize?.length) {
await expect(target).toBeVisible({ timeout });
const count = await matches.count();
for (let i = 0; i < count; i++) {
const row = matches.nth(i);
const ariaLabel = (await row.getAttribute('aria-label')) ?? '';
if (!deprioritize.some(source => ariaLabel.includes(source))) {
target = row;
break;
}
const ariaLabels = await matches.evaluateAll(rows => rows.map(row => row.getAttribute('aria-label') ?? ''));
const preferred = ariaLabels.findIndex(label => !deprioritize.some(source => label.includes(source)));
if (preferred >= 0) {
target = matches.nth(preferred);
} else if (!allowDeprioritizedFallback) {
throw new Error(
`No non-deprioritized quick pick row matching "${text}". Deprioritized matches: ${JSON.stringify(ariaLabels)}`
);
}
}

Expand Down
8 changes: 8 additions & 0 deletions test/e2e/pages/sessions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,13 @@ export const DISCONNECTED_STATUS_ICON = '.codicon-positron-runtime-status-discon
// the quick pick label produced by getRuntimeSourceAndShortName.
export const DEPRIORITIZED_PYTHON_SOURCES = ['(Pyenv', '(Global', '(System', '(Unknown'];

// Whether clicking a deprioritized row is acceptable when it is the only match.
// The Linux CI images provide a venv interpreter at the selected version, so rows
// that are all deprioritized there mean the venv has not registered yet and the
// selection should be retried. Windows and macOS CI install a bare System/Pyenv
// Python, where every row is legitimately deprioritized.
export const ALLOW_DEPRIORITIZED_PYTHON_FALLBACK = process.platform !== 'linux';

// Quickpick labels - keep in sync with languageRuntimeActions.ts
const INTERPRETER_SESSIONS_LABEL = 'Interpreter Sessions';
const START_NEW_CONSOLE_SESSION_LABEL = 'Start New Console Session';
Expand Down Expand Up @@ -549,6 +556,7 @@ export class Sessions {
await this.quickinput.selectQuickInputElementContaining(`${language} ${version}`, {
timeout: 2000,
deprioritize: language === 'Python' ? DEPRIORITIZED_PYTHON_SOURCES : undefined,
allowDeprioritizedFallback: ALLOW_DEPRIORITIZED_PYTHON_FALLBACK,
});
} catch (e) {
// Auto-discovery is intermittent: POSITRON_PY_VER_SEL's interpreter
Expand Down
Loading