Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into merge/1.95.0
Browse files Browse the repository at this point in the history
  • Loading branch information
jmcphers committed Dec 13, 2024
2 parents 5fdbc9e + 2584800 commit 08c3e38
Show file tree
Hide file tree
Showing 16 changed files with 166 additions and 43 deletions.
32 changes: 28 additions & 4 deletions test/automation/src/positron/positronPopups.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ const NOTIFICATION_TOAST = '.notification-toast';
*/
export class PositronPopups {

toastLocator = this.code.driver.getLocator(NOTIFICATION_TOAST);

constructor(private code: Code) { }

async popupCurrentlyOpen() {
Expand Down Expand Up @@ -78,14 +80,36 @@ export class PositronPopups {
}
async waitForToastToDisappear() {
this.code.logger.log('Waiting for toast to be detacted');
const toastLocator = this.code.driver.getLocator(NOTIFICATION_TOAST);
await toastLocator.waitFor({ state: 'detached', timeout: 20000 });
await this.toastLocator.waitFor({ state: 'detached', timeout: 20000 });
}

async waitForToastToAppear() {
this.code.logger.log('Waiting for toast to be attached');
const toastLocator = this.code.driver.getLocator(NOTIFICATION_TOAST);
await toastLocator.waitFor({ state: 'attached', timeout: 20000 });
await this.toastLocator.waitFor({ state: 'attached', timeout: 20000 });
}

async verifyToastDoesNotAppear(timeoutMs: number = 3000): Promise<void> {
const startTime = Date.now();

while (Date.now() - startTime < timeoutMs) {
const count = await this.toastLocator.count();
if (count > 0) {
throw new Error('Toast appeared unexpectedly');
}

this.code.wait(1000);
}

this.code.logger.log('Verified: Toast did not appear');
}

async closeAllToasts() {
const count = await this.toastLocator.count();
this.code.logger.log(`Closing ${count} toasts`);
for (let i = 0; i < count; i++) {
await this.toastLocator.nth(i).hover();
await this.code.driver.page.locator(`${NOTIFICATION_TOAST} .codicon-notifications-clear`).click();
}
}

async waitForModalDialogBox() {
Expand Down
4 changes: 2 additions & 2 deletions test/automation/src/positron/positronVariables.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,9 +140,9 @@ export class PositronVariables {

async selectVariablesGroup(name: string) {
await this.code.driver.page.locator(VARIABLES_GROUP_SELECTOR).click();
await this.code.driver.page.locator('a.action-menu-item', { hasText: name }).isVisible();
await this.code.driver.page.locator('a.action-menu-item', { hasText: name }).first().isVisible();
await this.code.wait(500);
await this.code.driver.page.locator('a.action-menu-item', { hasText: name }).click();
await this.code.driver.page.locator('a.action-menu-item', { hasText: name }).first().click();
}

async clickDatabaseIconForVariableRow(rowName: string) {
Expand Down
2 changes: 1 addition & 1 deletion test/e2e/features/apps/shiny.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ test.use({
suiteId: __filename
});

test.describe('Shiny Application', { tag: [tags.APPS, tags.VIEWER] }, () => {
test.describe('Shiny Application', { tag: [tags.APPS, tags.VIEWER, tags.WIN] }, () => {
test.beforeAll(async function ({ app }) {
try {
await app.workbench.extensions.installExtension('posit.shiny', true);
Expand Down
2 changes: 1 addition & 1 deletion test/e2e/features/console/console-ansi.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ test.use({
suiteId: __filename
});

test.describe('Console ANSI styling', { tag: [tags.CRITICAL, tags.CONSOLE] }, () => {
test.describe('Console ANSI styling', { tag: [tags.CRITICAL, tags.CONSOLE, tags.WIN] }, () => {
test.beforeEach(async function ({ app }) {
await app.workbench.positronLayouts.enterLayout('fullSizedPanel');
});
Expand Down
2 changes: 1 addition & 1 deletion test/e2e/features/console/console-clipboard.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ test.use({
suiteId: __filename
});

test.describe('Console - Clipboard', { tag: [tags.CONSOLE] }, () => {
test.describe('Console - Clipboard', { tag: [tags.CONSOLE, tags.WIN] }, () => {
test('Python - Copy from console & paste to console [C608100]', async function ({ app, python }) {
await testBody(app);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,9 @@ test.use({
});

test.describe('Headless Data Explorer - Large Data Frame', {
tag: [tags.WEB, tags.DATA_EXPLORER, tags.DUCK_DB]
tag: [tags.WEB, tags.DATA_EXPLORER, tags.DUCK_DB, tags.WIN]
}, () => {
// python fixture not actually needed but serves as a long wait so that we can be sure
// headless/duckdb open will work
test.beforeEach(async function ({ app, python }) {
test.beforeEach(async function ({ app }) {
await app.workbench.positronLayouts.enterLayout('stacked');
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -179,5 +179,64 @@ df2 = pd.DataFrame(data)`;
}).toPass({ timeout: 60000 });

await app.workbench.positronLayouts.enterLayout('stacked');
await app.workbench.positronDataExplorer.closeDataExplorer();
});

test('Python - Open Data Explorer for the second time brings focus back [C1078833]', async function ({ app, python }) {

const script = `import pandas as pd
from pydataset import data
Data_Frame = data('mtcars')`;
await app.workbench.positronConsole.executeCode('Python', script, '>>>');
await app.workbench.quickaccess.runCommand('workbench.panel.positronVariables.focus');

if (app.web) {
await app.workbench.positronVariables.selectVariablesGroup(`${process.env.POSITRON_PY_VER_SEL!}`);
}

await expect(async () => {
await app.workbench.positronVariables.doubleClickVariableRow('Data_Frame');
await app.code.driver.getLocator('.label-name:has-text("Data: Data_Frame")').innerText();
}).toPass();

// Now move focus out of the the data explorer pane
await app.workbench.editors.newUntitledFile();
await app.workbench.quickaccess.runCommand('workbench.panel.positronVariables.focus');
await app.workbench.positronVariables.doubleClickVariableRow('Data_Frame');

await expect(async () => {
await app.code.driver.getLocator('.label-name:has-text("Data: Data_Frame")').innerText();
}).toPass();

await app.workbench.positronDataExplorer.closeDataExplorer();
await app.workbench.quickaccess.runCommand('workbench.panel.positronVariables.focus');
});

test('Python - Check blank spaces in data explorer [C1078835]', async function ({ app, python }) {

const script = `import pandas as pd
df = pd.DataFrame({'x': ["a ", "a", " ", ""]})`;
await app.workbench.positronConsole.executeCode('Python', script, '>>>');

if (app.web) {
await app.workbench.positronVariables.selectVariablesGroup(`${process.env.POSITRON_PY_VER_SEL!}`);
}

await expect(async () => {
await app.workbench.positronVariables.doubleClickVariableRow('df');
await app.code.driver.getLocator('.label-name:has-text("Data: df")').innerText();
}).toPass();

await expect(async () => {
const tableData = await app.workbench.positronDataExplorer.getDataExplorerTableData();

expect(tableData[0]).toStrictEqual({ 'x': 'a·' });
expect(tableData[1]).toStrictEqual({ 'x': 'a' });
expect(tableData[2]).toStrictEqual({ 'x': '···' });
expect(tableData[3]).toStrictEqual({ 'x': '<empty>' });
expect(tableData.length).toBe(4);
}).toPass({ timeout: 60000 });

await app.workbench.positronDataExplorer.closeDataExplorer();
});
});
25 changes: 24 additions & 1 deletion test/e2e/features/data-explorer/data-explorer-r.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,11 @@ test.describe('Data Explorer - R ', {

});

test('R - Open Data Explorer for the second time brings focus back [C701143]', async function ({ app, r }) {
test.skip('R - Open Data Explorer for the second time brings focus back [C701143]', {
annotation: [{ type: 'issue', description: 'https://github.com/posit-dev/positron/issues/5714' }]
}, async function ({ app, r }) {
// Regression test for https://github.com/posit-dev/positron/issues/4197
// and https://github.com/posit-dev/positron/issues/5714
const script = `Data_Frame <- mtcars`;
await app.workbench.positronConsole.executeCode('R', script, '>');
await app.workbench.quickaccess.runCommand('workbench.panel.positronVariables.focus');
Expand All @@ -99,4 +102,24 @@ test.describe('Data Explorer - R ', {
await app.workbench.positronDataExplorer.closeDataExplorer();
await app.workbench.quickaccess.runCommand('workbench.panel.positronVariables.focus');
});

test('R - Check blank spaces in data explorer [C1078834]', async function ({ app, r }) {
const script = `df = data.frame(x = c("a ", "a", " ", ""))`;
await app.workbench.positronConsole.executeCode('R', script, '>');

await expect(async () => {
await app.workbench.positronVariables.doubleClickVariableRow('df');
await app.code.driver.getLocator('.label-name:has-text("Data: df")').innerText();
}).toPass();

await expect(async () => {
const tableData = await app.workbench.positronDataExplorer.getDataExplorerTableData();

expect(tableData[0]).toStrictEqual({ 'x': 'a·' });
expect(tableData[1]).toStrictEqual({ 'x': 'a' });
expect(tableData[2]).toStrictEqual({ 'x': '···' });
expect(tableData[3]).toStrictEqual({ 'x': '<empty>' });
expect(tableData.length).toBe(4);
}).toPass({ timeout: 60000 });
});
});
4 changes: 1 addition & 3 deletions test/e2e/features/data-explorer/duckdb-sparklines.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,7 @@ test.use({
test.describe('Data Explorer - DuckDB Column Summary', {
tag: [tags.WEB, tags.WIN, tags.CRITICAL, tags.DATA_EXPLORER, tags.DUCK_DB]
}, () => {
// python fixture not actually needed but serves as a long wait so that we can be sure
// headless/duckdb open will work
test('Verifies basic duckdb column summary functionality [C1053635]', async function ({ app, python }) {
test('Verifies basic duckdb column summary functionality [C1053635]', async function ({ app }) {

await app.workbench.positronQuickaccess.openDataFile(join(app.workspacePathOrFolder, 'data-files', '100x100', '100x100.parquet'));

Expand Down
2 changes: 1 addition & 1 deletion test/e2e/features/editor/fast-execution.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ test.use({

const FILENAME = 'fast-execution.r';

test.describe('R Fast Execution', { tag: [tags.WEB, tags.EDITOR] }, () => {
test.describe('R Fast Execution', { tag: [tags.WEB, tags.EDITOR, tags.WIN] }, () => {
test('Verify fast execution is not out of order [C712539]', async function ({ app, r }) {
await app.workbench.quickaccess.openFile(join(app.workspacePathOrFolder, 'workspaces', 'fast-statement-execution', FILENAME));

Expand Down
6 changes: 3 additions & 3 deletions test/e2e/features/help/help.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ test.use({

test.describe('Help', { tag: [tags.HELP] }, () => {

test('Python - Verifies basic help functionality [C633814]', async function ({ app, python }) {
test('Python - Verifies basic help functionality [C633814]', { tag: [tags.WIN] }, async function ({ app, python }) {
await app.workbench.positronConsole.executeCode('Python', `?load`, '>>>');

await expect(async () => {
Expand All @@ -21,7 +21,7 @@ test.describe('Help', { tag: [tags.HELP] }, () => {

});

test('R - Verifies basic help functionality [C633813]', async function ({ app, r }) {
test('R - Verifies basic help functionality [C633813]', { tag: [tags.WIN] }, async function ({ app, r }) {
await app.workbench.positronConsole.executeCode('R', `?load()`, '>');

await expect(async () => {
Expand All @@ -32,7 +32,7 @@ test.describe('Help', { tag: [tags.HELP] }, () => {
});

test('Verifies help panel can be opened when empty and also can be resized smaller and remember resize height [C640934]', async function ({ app, logger }) {

// Not running on windows as the size calculation is off for the resolution in CI
const positronHelp = app.workbench.positronHelp;
const helpContainerLocator = positronHelp.getHelpContainer();
const helpPanelHeaderLocator = positronHelp.getHelpHeader();
Expand Down
2 changes: 1 addition & 1 deletion test/e2e/features/layouts/layouts.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ test.use({
suiteId: __filename
});

test.describe('Layouts', { tag: [tags.WEB, tags.LAYOUTS] }, () => {
test.describe('Layouts', { tag: [tags.WEB, tags.LAYOUTS, tags.WIN] }, () => {

test.describe('Stacked Layout', () => {

Expand Down
20 changes: 8 additions & 12 deletions test/e2e/features/new-project-wizard/new-project-python.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ test.beforeEach(async function ({ app }) {
await app.workbench.positronConsole.waitForReadyOrNoInterpreter();
});

// Not running conda test on windows becuase conda reeks havoc on selecting the correct python interpreter
test.describe('Python - New Project Wizard', { tag: [tags.NEW_PROJECT_WIZARD] }, () => {
const defaultProjectName = 'my-python-project';

Expand Down Expand Up @@ -43,7 +44,7 @@ test.describe('Python - New Project Wizard', { tag: [tags.NEW_PROJECT_WIZARD] },
await app.workbench.quickaccess.runCommand('workbench.action.toggleAuxiliaryBar');
});

test('Create a new Venv environment [C627912]', { tag: [tags.CRITICAL] }, async function ({ app, page }) {
test('Create a new Venv environment [C627912]', { tag: [tags.CRITICAL, tags.WIN] }, async function ({ app, page }) {
// This is the default behavior for a new Python Project in the Project Wizard
const projSuffix = addRandomNumSuffix('_new_venv');
const pw = app.workbench.positronNewProjectWizard;
Expand All @@ -54,15 +55,13 @@ test.describe('Python - New Project Wizard', { tag: [tags.NEW_PROJECT_WIZARD] },
await pw.navigate(ProjectWizardNavigateAction.CREATE);
await pw.currentOrNewWindowSelectionModal.currentWindowButton.click();
await expect(page.getByRole('button', { name: `Explorer Section: ${defaultProjectName + projSuffix}` })).toBeVisible({ timeout: 20000 });
await expect(app.workbench.positronConsole.activeConsole.getByText('>>>')).toBeVisible({ timeout: 45000 });
await expect(app.workbench.positronConsole.activeConsole.getByText('>>>')).toBeVisible({ timeout: 100000 });
await app.workbench.quickaccess.runCommand('workbench.action.toggleAuxiliaryBar');
await app.workbench.positronConsole.barClearButton.click();
await app.workbench.quickaccess.runCommand('workbench.action.toggleAuxiliaryBar');
});

test.skip('With ipykernel already installed [C609619]', {
annotation: [{ type: 'issue', description: 'https://github.com/posit-dev/positron/issues/5286' }]
}, async function ({ app, page, python }) {
test('With ipykernel already installed [C609619]', { tag: [tags.WIN] }, async function ({ app, page, python }) {
const projSuffix = addRandomNumSuffix('_ipykernelInstalled');
const pw = app.workbench.positronNewProjectWizard;
const pythonFixtures = new PositronPythonFixtures(app);
Expand Down Expand Up @@ -94,12 +93,10 @@ test.describe('Python - New Project Wizard', { tag: [tags.NEW_PROJECT_WIZARD] },
await pw.navigate(ProjectWizardNavigateAction.CREATE);
await pw.currentOrNewWindowSelectionModal.currentWindowButton.click();
await expect(page.getByRole('button', { name: `Explorer Section: ${defaultProjectName + projSuffix}` })).toBeVisible({ timeout: 20000 });
await expect(app.workbench.positronConsole.activeConsole.getByText('>>>')).toBeVisible({ timeout: 45000 });
await expect(app.workbench.positronConsole.activeConsole.getByText('>>>')).toBeVisible({ timeout: 90000 });
});

test.skip('With ipykernel not already installed [C609617]', {
annotation: [{ type: 'issue', description: 'https://github.com/posit-dev/positron/issues/5286' }]
}, async function ({ app, page }) {
test('With ipykernel not already installed [C609617]', { tag: [tags.WIN] }, async function ({ app, page }) {
const projSuffix = addRandomNumSuffix('_noIpykernel');
const pw = app.workbench.positronNewProjectWizard;
const pythonFixtures = new PositronPythonFixtures(app);
Expand Down Expand Up @@ -143,7 +140,7 @@ test.describe('Python - New Project Wizard', { tag: [tags.NEW_PROJECT_WIZARD] },

// If ipykernel was successfully installed during the new project initialization,
// the console should be ready without any prompts to install ipykernel
await expect(app.workbench.positronConsole.activeConsole.getByText('>>>')).toBeVisible({ timeout: 45000 });
await expect(app.workbench.positronConsole.activeConsole.getByText('>>>')).toBeVisible({ timeout: 90000 });
await app.workbench.quickaccess.runCommand('workbench.action.toggleAuxiliaryBar');
await app.workbench.positronConsole.barClearButton.click();
await app.workbench.quickaccess.runCommand('workbench.action.toggleAuxiliaryBar');
Expand All @@ -165,7 +162,7 @@ test.describe('Python - New Project Wizard', { tag: [tags.NEW_PROJECT_WIZARD] },
// Open the new project in the current window and wait for the console to be ready
await pw.currentOrNewWindowSelectionModal.currentWindowButton.click();
await expect(page.getByRole('button', { name: `Explorer Section: ${defaultProjectName + projSuffix}` })).toBeVisible({ timeout: 20000 });
await expect(app.workbench.positronConsole.activeConsole.getByText('>>>')).toBeVisible({ timeout: 45000 });
await expect(app.workbench.positronConsole.activeConsole.getByText('>>>')).toBeVisible({ timeout: 90000 });

// Verify git-related files are present
await expect(async () => {
Expand All @@ -186,4 +183,3 @@ test.describe('Python - New Project Wizard', { tag: [tags.NEW_PROJECT_WIZARD] },
function addRandomNumSuffix(name: string): string {
return `${name}_${Math.floor(Math.random() * 1000000)}`;
}

Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ test.describe('R - New Project Wizard', { tag: [tags.NEW_PROJECT_WIZARD] }, () =
// here, but it's timing out in CI, so it is not included for now.
});

test('R - Accept Renv install [C633084]', async function ({ app, r }) {
test('R - Accept Renv install [C633084]', { tag: [tags.WIN] }, async function ({ app, r }) {
const projSuffix = addRandomNumSuffix('_installRenv');
const pw = app.workbench.positronNewProjectWizard;
// Create a new R project - select Renv and install
Expand Down Expand Up @@ -78,7 +78,7 @@ test.describe('R - New Project Wizard', { tag: [tags.NEW_PROJECT_WIZARD] }, () =
);
});

test('R - Renv already installed [C656251]', async function ({ app }) {
test('R - Renv already installed [C656251]', { tag: [tags.WIN] }, async function ({ app }) {
// Renv will already be installed from the previous test - which is why tests are marked as "serial"
const projSuffix = addRandomNumSuffix('_renvAlreadyInstalled');
const pw = app.workbench.positronNewProjectWizard;
Expand All @@ -104,7 +104,7 @@ test.describe('R - New Project Wizard', { tag: [tags.NEW_PROJECT_WIZARD] }, () =
);
});

test('R - Cancel Renv install [C656252]', async function ({ app }) {
test('R - Cancel Renv install [C656252]', { tag: [tags.WIN] }, async function ({ app }) {
const projSuffix = addRandomNumSuffix('_cancelRenvInstall');
const pw = app.workbench.positronNewProjectWizard;
// Remove renv package so we are prompted to install it again
Expand Down Expand Up @@ -138,7 +138,7 @@ test.describe('R - New Project Wizard', { tag: [tags.NEW_PROJECT_WIZARD] }, () =
test.describe('Jupyter - New Project Wizard', () => {
const defaultProjectName = 'my-jupyter-notebook';

test('Jupyter Project Defaults [C629352]', { tag: [tags.CRITICAL] }, async function ({ app }) {
test('Jupyter Project Defaults [C629352]', { tag: [tags.CRITICAL, tags.WIN] }, async function ({ app }) {
const projSuffix = addRandomNumSuffix('_defaults');
const pw = app.workbench.positronNewProjectWizard;
await pw.startNewProject(ProjectType.JUPYTER_NOTEBOOK);
Expand Down
2 changes: 1 addition & 1 deletion test/e2e/features/notebook/notebook-large-python.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ test.use({

// Note that this test is too heavy to pass on web and windows
test.describe('Large Python Notebook', {
tag: [tags.NOTEBOOK]
tag: [tags.NOTEBOOK, tags.WIN]
}, () => {

test('Python - Large notebook execution [C983592]', async function ({ app, python }) {
Expand Down
Loading

0 comments on commit 08c3e38

Please sign in to comment.