Skip to content

Commit

Permalink
E2E tests: reticulate stop/restart test (#5956)
Browse files Browse the repository at this point in the history
Test stop/restart functionality with reticulate.

Web only as electron uses native dialog as part of process

### QA Notes

All tests pass.
  • Loading branch information
testlabauto authored Jan 10, 2025
1 parent 14bff09 commit 9fe7a3e
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 24 deletions.
10 changes: 2 additions & 8 deletions test/e2e/infra/fixtures/interpreter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,8 @@ export class Interpreter {

await test.step(`Select interpreter via Quick Access: ${interpreterType}`, async () => {
interpreterType === 'Python'
? await this.console.selectInterpreter(InterpreterType.Python, DESIRED_PYTHON)
: await this.console.selectInterpreter(InterpreterType.R, DESIRED_R);

if (waitForReady) {
interpreterType === 'Python'
? await this.console.waitForReady('>>>', 30000)
: await this.console.waitForReady('>', 30000);
}
? await this.console.selectInterpreter(InterpreterType.Python, DESIRED_PYTHON, waitForReady)
: await this.console.selectInterpreter(InterpreterType.R, DESIRED_R, waitForReady);
});
};

Expand Down
6 changes: 3 additions & 3 deletions test/e2e/tests/_test.setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,13 +109,13 @@ export const test = base.extend<TestFixtures, WorkerFixtures>({
}, { scope: 'worker', auto: true, timeout: 60000 }],

interpreter: [async ({ app, page }, use) => {
const setInterpreter = async (desiredInterpreter: 'Python' | 'R') => {
const setInterpreter = async (desiredInterpreter: 'Python' | 'R', waitForReady = true) => {
const currentInterpreter = await page.locator('.top-action-bar-interpreters-manager').textContent() || '';

if (!currentInterpreter.startsWith(desiredInterpreter)) {
desiredInterpreter === 'Python'
? await app.workbench.interpreter.startInterpreterViaQuickAccess('Python')
: await app.workbench.interpreter.startInterpreterViaQuickAccess('R');
? await app.workbench.interpreter.startInterpreterViaQuickAccess('Python', waitForReady)
: await app.workbench.interpreter.startInterpreterViaQuickAccess('R', waitForReady);
}
};

Expand Down
77 changes: 64 additions & 13 deletions test/e2e/tests/reticulate/reticulate.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,7 @@ test.describe('Reticulate', {
}, () => {
test.beforeAll(async function ({ app, userSettings }) {
try {
// remove this once https://github.com/posit-dev/positron/issues/5226
// is resolved
await userSettings.set([
['kernelSupervisor.enable', 'false'],
['positron.reticulate.enabled', 'true']
]);

Expand All @@ -32,6 +29,10 @@ test.describe('Reticulate', {
}
});

// if running tests in sequence, we will need to skip waiting for ready because interpreters
// will already be running
let sequential = false;

test('R - Verify Basic Reticulate Functionality [C...]', async function ({ app, r, interpreter }) {

await app.workbench.console.pasteCodeToConsole('reticulate::repl_python()');
Expand All @@ -46,19 +47,69 @@ test.describe('Reticulate', {
}

await app.workbench.console.waitForReady('>>>');
await app.workbench.console.pasteCodeToConsole('x=100');
await app.workbench.console.sendEnterKey();

await interpreter.set('R');
await verifyReticulateFunctionality(app, interpreter, false);

await app.workbench.console.pasteCodeToConsole('y<-reticulate::py$x');
await app.workbench.console.sendEnterKey();
await app.workbench.layouts.enterLayout('fullSizedAuxBar');
sequential = true;

});

test('R - Verify Reticulate Stop/Restart Functionality [C...]', async function ({ app, interpreter }) {

// web only test but we don't have another way to skip electron tests
if (!app.web) {
return;
}

await app.workbench.interpreter.selectInterpreter('Python', 'Python (reticulate)', !sequential);

await verifyReticulateFunctionality(app, interpreter, sequential);

await app.workbench.layouts.enterLayout('stacked');

await app.workbench.console.barPowerButton.click();

await app.workbench.console.waitForConsoleContents('shut down successfully');

await app.code.driver.page.locator('.positron-console').getByRole('button', { name: 'Restart R' }).click();

await app.workbench.console.waitForReady('>');

await expect(async () => {
const variablesMap = await app.workbench.variables.getFlatVariables();
expect(variablesMap.get('y')).toStrictEqual({ value: '100', type: 'int' });
}).toPass({ timeout: 60000 });
await app.code.driver.page.locator('.positron-console').locator('.action-bar-button-drop-down-arrow').click();

await app.code.driver.page.locator('.action-label', { hasText: 'Python (reticulate)' }).hover();

await app.code.driver.page.keyboard.press('Enter');

await app.code.driver.page.locator('.positron-console').getByRole('button', { name: 'Restart Python' }).click();

await app.workbench.console.waitForReady('>>>');

await verifyReticulateFunctionality(app, interpreter, sequential);

});
});

async function verifyReticulateFunctionality(app, interpreter, sequential) {

await app.workbench.console.pasteCodeToConsole('x=100');
await app.workbench.console.sendEnterKey();

await app.workbench.console.barClearButton.click();

await interpreter.set('R', !sequential);

await app.workbench.console.pasteCodeToConsole('y<-reticulate::py$x');
await app.workbench.console.sendEnterKey();

await app.workbench.console.barClearButton.click();

await app.workbench.layouts.enterLayout('fullSizedAuxBar');

await expect(async () => {
const variablesMap = await app.workbench.variables.getFlatVariables();
expect(variablesMap.get('y')).toStrictEqual({ value: '100', type: 'int' });
}).toPass({ timeout: 60000 });

await app.workbench.layouts.enterLayout('stacked');
};

0 comments on commit 9fe7a3e

Please sign in to comment.