Skip to content
Merged
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
1 change: 1 addition & 0 deletions project-words.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ googlecolab
googlers
grayscale
highmem
inputbox
ipykernel
ipynb
jupyterclient
Expand Down
32 changes: 19 additions & 13 deletions src/test/e2e/connect-execute.e2e.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
createNotebook,
hasQuickPickItem,
KERNEL_SELECT_WAIT_MS,
safeExecuteCommand,
selectQuickPickItem,
selectQuickPicksInOrder,
} from './ui';
Expand All @@ -22,33 +23,38 @@ it('executes basic code cells', async () => {
await createNotebook(workbench);

// Connect to Colab.
await workbench.executeCommand('Notebook: Select Notebook Kernel');
await safeExecuteCommand(workbench, 'Notebook: Select Notebook Kernel');
// If the test is running on a machine with a configured Python environment,
// the "Select Another Kernel" option may appear instead of "Colab". If so, we
// need to click it first before selecting "Colab".
if (await hasQuickPickItem(driver, 'Select Another Kernel')) {
await selectQuickPickItem(driver, 'Select Another Kernel');
if (await hasQuickPickItem(driver, 'kernel', 'Select Another Kernel')) {
await selectQuickPickItem(driver, 'kernel', 'Select Another Kernel');
}
await selectQuickPicksInOrder(driver, [
'Colab',
'New Colab Server',
'CPU',
'Latest',
{ picker: 'kernel source', item: 'Colab' },
{ picker: 'Select a remote server', item: 'New Colab Server' },
{ picker: 'Select a variant', item: 'CPU' },
{ picker: 'Select a runtime version', item: 'Latest' },
]);
// Alias the server with the default name. We poll until the alias InputBox
// is actually shown before confirming, otherwise the ENTER keystroke can be
// delivered to the still-focused QuickPick from the previous step and lost.
await confirmInputBoxWithDefault(driver, 'Alias your server');
await selectQuickPickItem(driver, 'Python', KERNEL_SELECT_WAIT_MS);
await selectQuickPickItem(
driver,
'Select a Kernel',
'Python',
KERNEL_SELECT_WAIT_MS,
);

// Input code into the first cell.
let focusedCell: WebElement;
await workbench.executeCommand('Notebook: Edit Cell');
await safeExecuteCommand(workbench, 'Notebook: Edit Cell');
focusedCell = await driver.switchTo().activeElement();
await focusedCell.sendKeys('1 + 1');

// Add a second cell to display a data frame.
await workbench.executeCommand('Notebook: Insert Code Cell Below');
await safeExecuteCommand(workbench, 'Notebook: Insert Code Cell Below');
focusedCell = await driver.switchTo().activeElement();
await focusedCell.sendKeys(`import pandas as pd
df = pd.DataFrame({
Expand All @@ -58,14 +64,14 @@ df = pd.DataFrame({
df`);

// Add a third cell to plot the data frame.
await workbench.executeCommand('Notebook: Insert Code Cell Below');
await safeExecuteCommand(workbench, 'Notebook: Insert Code Cell Below');
focusedCell = await driver.switchTo().activeElement();
await focusedCell.sendKeys('df.plot()');

await workbench.executeCommand('Notebook: Run All');
await safeExecuteCommand(workbench, 'Notebook: Run All');
// Collapsing all cell outputs so execution status of all 3 cells are in
// the viewport.
await workbench.executeCommand('Notebook: Collapse All Cell Outputs');
await safeExecuteCommand(workbench, 'Notebook: Collapse All Cell Outputs');

await assertAllCellsExecutedSuccessfully(driver, workbench);
});
25 changes: 17 additions & 8 deletions src/test/e2e/mount-drive.e2e.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
hasQuickPickItem,
KERNEL_SELECT_WAIT_MS,
pushDialogButton,
safeExecuteCommand,
selectQuickPickItem,
selectQuickPickItemIfShown,
selectQuickPicksInOrder,
Expand All @@ -31,22 +32,30 @@ it('mounts Google Drive', async () => {
await createNotebook(workbench);
// Delete the initial empty cell first because Mount Drive command will
// insert code snippet in a new cell.
await workbench.executeCommand('Notebook: Delete Cell');
await safeExecuteCommand(workbench, 'Notebook: Delete Cell');

// Connect to Colab.
await workbench.executeCommand('Notebook: Select Notebook Kernel');
await safeExecuteCommand(workbench, 'Notebook: Select Notebook Kernel');
// If the test is running on a machine with a configured Python environment,
// the "Select Another Kernel" option may appear instead of "Colab". If so, we
// need to click it first before selecting "Colab".
if (await hasQuickPickItem(driver, 'Select Another Kernel')) {
await selectQuickPickItem(driver, 'Select Another Kernel');
if (await hasQuickPickItem(driver, 'kernel', 'Select Another Kernel')) {
await selectQuickPickItem(driver, 'kernel', 'Select Another Kernel');
}
await selectQuickPicksInOrder(driver, ['Colab', 'Auto Connect']);
await selectQuickPickItemIfShown(driver, 'Python', KERNEL_SELECT_WAIT_MS);
await selectQuickPicksInOrder(driver, [
{ picker: 'kernel source', item: 'Colab' },
{ picker: 'Select a remote server', item: 'Auto Connect' },
]);
await selectQuickPickItemIfShown(
driver,
'Select a Kernel',
'Python',
KERNEL_SELECT_WAIT_MS,
);

// Kick-off Drive mounting.
await workbench.executeCommand('Colab: Mount Google Drive to Server...');
await workbench.executeCommand('Notebook: Run All');
await safeExecuteCommand(workbench, 'Colab: Mount Google Drive to Server...');
await safeExecuteCommand(workbench, 'Notebook: Run All');
await pushDialogButton(
driver,
'Connect to Google Drive',
Expand Down
21 changes: 15 additions & 6 deletions src/test/e2e/resource-view.e2e.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
createNotebook,
hasQuickPickItem,
KERNEL_SELECT_WAIT_MS,
safeExecuteCommand,
selectQuickPickItem,
selectQuickPickItemIfShown,
selectQuickPicksInOrder,
Expand All @@ -28,18 +29,26 @@ it('renders resource tree view', async () => {
await createNotebook(workbench);

// Connect to Colab.
await workbench.executeCommand('Notebook: Select Notebook Kernel');
await safeExecuteCommand(workbench, 'Notebook: Select Notebook Kernel');
// If the test is running on a machine with a configured Python environment,
// the "Select Another Kernel" option may appear instead of "Colab". If so, we
// need to click it first before selecting "Colab".
if (await hasQuickPickItem(driver, 'Select Another Kernel')) {
await selectQuickPickItem(driver, 'Select Another Kernel');
if (await hasQuickPickItem(driver, 'kernel', 'Select Another Kernel')) {
await selectQuickPickItem(driver, 'kernel', 'Select Another Kernel');
}
await selectQuickPicksInOrder(driver, ['Colab', 'Auto Connect']);
await selectQuickPickItemIfShown(driver, 'Python', KERNEL_SELECT_WAIT_MS);
await selectQuickPicksInOrder(driver, [
{ picker: 'kernel source', item: 'Colab' },
{ picker: 'Select a remote server', item: 'Auto Connect' },
]);
await selectQuickPickItemIfShown(
driver,
'Select a Kernel',
'Python',
KERNEL_SELECT_WAIT_MS,
);

// Verify resource view in Colab activity bar.
await workbench.executeCommand('Colab: Focus on Resources View');
await safeExecuteCommand(workbench, 'Colab: Focus on Resources View');

const activityBar = workbench.getActivityBar();
const colabViewContainer = await activityBar.getViewControl('Colab');
Expand Down
47 changes: 32 additions & 15 deletions src/test/e2e/test-setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,14 @@ import { CONFIG } from '../../colab-config';
import { doOAuthSignIn, getOAuthDriver } from './auth';
import {
createNotebook,
pushDialogButtonIfShown,
dismissAnyOpenInput,
hasQuickPickItem,
KERNEL_SELECT_WAIT_MS,
pushDialogButton,
pushDialogButtonIfShown,
safeExecuteCommand,
selectQuickPickItem,
selectQuickPickItemIfShown,
KERNEL_SELECT_WAIT_MS,
} from './ui';

console.log('Running global E2E test setup...');
Expand Down Expand Up @@ -85,12 +87,16 @@ afterEach(async function () {
const workbench = new Workbench();
const vsCodeDriver = workbench.getDriver();
try {
// Dismiss any leftover QuickPick/InputBox so the upcoming command palette
// invocations actually open the command palette instead of being absorbed
// by an orphan picker. VS Code reuses one DOM `<input>` for all pickers.
await dismissAnyOpenInput(vsCodeDriver);
// Dismiss any leftover error/info modal first (e.g. a 504 surfaced by a
// previous best-effort 'Colab: Remove Server' that arrived after the
// earlier dismissal window closed). A modal blocks subsequent
// executeCommand() calls so we must clear it before doing anything else.
await pushDialogButtonIfShown(vsCodeDriver, 'OK', DIALOG_WAIT_MS);
await workbench.executeCommand('View: Close All Editors');
await safeExecuteCommand(workbench, 'View: Close All Editors');
// Close-all may surface a "Don't Save" prompt if any notebook is dirty.
await pushDialogButtonIfShown(vsCodeDriver, "Don't Save", DIALOG_WAIT_MS);
} catch (err) {
Expand All @@ -112,23 +118,33 @@ async function signIn(
await pushDialogButtonIfShown(vsCodeDriver, 'Acknowledge', DIALOG_WAIT_MS);

// Trigger Colab connection which will prompt for sign-in.
await workbench.executeCommand('Notebook: Select Notebook Kernel');
// If the test is running on a machine with a configured Python environment,
// the "Select Another Kernel" option may appear instead of "Colab". If so,
// we need to click it first before selecting "Colab". The kernel picker
// can take a while to populate while Jupyter is "Detecting Kernels", so
// these steps are given a longer-than-default budget.
await safeExecuteCommand(workbench, 'Notebook: Select Notebook Kernel');
// On a fresh notebook with no kernel association, Jupyter opens the
// kernel-source picker directly. On a machine that already has a Python
// environment associated with the notebook (e.g. a developer workstation),
// Jupyter opens the "Change kernel for ..." picker first, with a
// "Select Another Kernel..." option that transitions to the source picker.
// The kernel picker can take a while to populate while Jupyter is
// "Detecting Kernels", so these steps are given a longer-than-default
// budget.
if (
await hasQuickPickItem(
vsCodeDriver,
'kernel',
'Select Another Kernel',
KERNEL_SELECT_WAIT_MS,
)
) {
await selectQuickPickItem(vsCodeDriver, 'Select Another Kernel');
await selectQuickPickItem(vsCodeDriver, 'kernel', 'Select Another Kernel');
}
await selectQuickPickItem(vsCodeDriver, 'Colab');
await selectQuickPickItem(vsCodeDriver, 'Auto Connect');
await selectQuickPickItem(vsCodeDriver, 'kernel source', 'Colab');
// "Auto Connect" lives in the remote-server picker that Jupyter opens
// after the user picks "Colab" as a kernel source.
await selectQuickPickItem(
vsCodeDriver,
'Select a remote server',
'Auto Connect',
);

// Sign in.
await pushDialogButton(vsCodeDriver, 'Allow');
Expand All @@ -148,16 +164,17 @@ async function signIn(
// and closes before we can click.
await selectQuickPickItemIfShown(
vsCodeDriver,
'Select a Kernel',
'Python',
KERNEL_SELECT_WAIT_MS,
);
await workbench.executeCommand('Colab: Remove Server');
await safeExecuteCommand(workbench, 'Colab: Remove Server');
try {
await selectQuickPickItem(vsCodeDriver, 'Colab CPU');
await selectQuickPickItem(vsCodeDriver, 'Remove Server', 'Colab CPU');
} catch (err: unknown) {
console.warn('Could not select "Colab CPU" for cleanup.', err);
}
await workbench.executeCommand('View: Close All Editors');
await safeExecuteCommand(workbench, 'View: Close All Editors');
await pushDialogButtonIfShown(vsCodeDriver, "Don't Save", DIALOG_WAIT_MS);
} catch (err: unknown) {
console.warn(
Expand Down
Loading
Loading