Skip to content

Commit 15b431d

Browse files
authored
E2E test: adding reticulate tests back in (#7218)
Reticulate tests were removed when we merged the multisession test updates. Just getting them back in there now as multisession aware tests. ### QA Notes @:reticulate @:web
1 parent a287854 commit 15b431d

File tree

6 files changed

+288
-195
lines changed

6 files changed

+288
-195
lines changed
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (C) 2025 Posit Software, PBC. All rights reserved.
3+
* Licensed under the Elastic License 2.0. See LICENSE.txt for license information.
4+
*--------------------------------------------------------------------------------------------*/
5+
6+
import { expect } from '@playwright/test';
7+
import { Application } from '../../../infra/index.js';
8+
9+
export async function verifyReticulateFunctionality(
10+
app: Application,
11+
rSessionId: string,
12+
pythonSessionId: string = 'Python (reticulate)',
13+
value = '200',
14+
value2 = '400',
15+
value3 = '6'): Promise<void> {
16+
// Verify that reticulate is installed
17+
// Create a variable in Python and expect to be able to access it from R
18+
await app.workbench.sessions.select(pythonSessionId);
19+
20+
await app.workbench.console.pasteCodeToConsole(`x=${value}`);
21+
await app.workbench.console.sendEnterKey();
22+
23+
await app.workbench.console.clearButton.click();
24+
25+
await app.workbench.sessions.select(rSessionId);
26+
27+
await app.workbench.console.pasteCodeToConsole('y<-reticulate::py$x');
28+
await app.workbench.console.sendEnterKey();
29+
30+
await app.workbench.console.clearButton.click();
31+
32+
await app.workbench.layouts.enterLayout('fullSizedAuxBar');
33+
34+
await expect(async () => {
35+
const variablesMap = await app.workbench.variables.getFlatVariables();
36+
expect(variablesMap.get('y')).toStrictEqual({ value: value, type: 'int' });
37+
}).toPass({ timeout: 10000 });
38+
39+
await app.workbench.layouts.enterLayout('stacked');
40+
41+
// Create a variable in R and expect to be able to access it from Python
42+
await app.workbench.console.pasteCodeToConsole(`y <- ${value2}L`);
43+
await app.workbench.console.sendEnterKey();
44+
45+
// Executing reticulate::repl_python() should not start a new interpreter
46+
// but should move focus to the reticulate interpreter
47+
await app.workbench.console.pasteCodeToConsole(`reticulate::repl_python(input = "z = ${value3}")`);
48+
await app.workbench.console.sendEnterKey();
49+
50+
// Expect that focus changed to the reticulate console
51+
await app.workbench.sessions.expectSessionPickerToBe(pythonSessionId);
52+
await app.workbench.console.pasteCodeToConsole('print(r.y)');
53+
await app.workbench.console.sendEnterKey();
54+
await app.workbench.console.waitForConsoleContents(value2);
55+
56+
await app.workbench.console.pasteCodeToConsole('print(z)');
57+
await app.workbench.console.sendEnterKey();
58+
await app.workbench.console.waitForConsoleContents(value3);
59+
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (C) 2025 Posit Software, PBC. All rights reserved.
3+
* Licensed under the Elastic License 2.0. See LICENSE.txt for license information.
4+
*--------------------------------------------------------------------------------------------*/
5+
6+
import { test, tags } from '../_test.setup';
7+
import { verifyReticulateFunctionality } from './helpers/verifyReticulateFunction.js';
8+
9+
test.use({
10+
suiteId: __filename
11+
});
12+
13+
// In order to run this test on Windows, I think we need to set the env var:
14+
// RETICULATE_PYTHON
15+
// to the installed python path
16+
17+
test.describe('Reticulate', {
18+
tag: [tags.RETICULATE, tags.WEB],
19+
}, () => {
20+
test.beforeAll(async function ({ app, userSettings }) {
21+
try {
22+
await userSettings.set([
23+
['positron.reticulate.enabled', 'true']
24+
]);
25+
26+
} catch (e) {
27+
await app.code.driver.takeScreenshot('reticulateSetup');
28+
throw e;
29+
}
30+
});
31+
32+
test('R - Verify Basic Reticulate Functionality using reticulate::repl_python() with multiple sessions', async function ({ app, sessions }) {
33+
34+
const rSessionMetaData = await sessions.start('r');
35+
36+
await app.workbench.console.pasteCodeToConsole('reticulate::repl_python()', true);
37+
38+
try {
39+
await app.workbench.console.waitForConsoleContents('Yes/no/cancel');
40+
await app.workbench.console.typeToConsole('no');
41+
await app.workbench.console.sendEnterKey();
42+
} catch {
43+
// Prompt did not appear
44+
}
45+
46+
await app.workbench.popups.installIPyKernel();
47+
48+
await app.workbench.console.waitForReadyAndStarted('>>>');
49+
50+
await verifyReticulateFunctionality(app, rSessionMetaData.id);
51+
52+
const rSessionMetaData2 = await sessions.start('r', { reuse: false });
53+
54+
await app.workbench.console.pasteCodeToConsole('reticulate::repl_python()', true);
55+
56+
try {
57+
await app.workbench.console.waitForConsoleContents('Yes/no/cancel');
58+
await app.workbench.console.typeToConsole('no');
59+
await app.workbench.console.sendEnterKey();
60+
} catch {
61+
// Prompt did not appear
62+
}
63+
64+
await app.workbench.popups.installIPyKernel();
65+
66+
await app.workbench.console.waitForReadyAndStarted('>>>');
67+
68+
await verifyReticulateFunctionality(app, rSessionMetaData2.id, 'Python (reticulate) - 2', '300', '500', '7');
69+
70+
});
71+
});
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (C) 2024 Posit Software, PBC. All rights reserved.
3+
* Licensed under the Elastic License 2.0. See LICENSE.txt for license information.
4+
*--------------------------------------------------------------------------------------------*/
5+
6+
import { test, tags } from '../_test.setup';
7+
import { verifyReticulateFunctionality } from './helpers/verifyReticulateFunction.js';
8+
9+
test.use({
10+
suiteId: __filename
11+
});
12+
13+
// In order to run this test on Windows, I think we need to set the env var:
14+
// RETICULATE_PYTHON
15+
// to the installed python path
16+
17+
test.describe('Reticulate', {
18+
tag: [tags.RETICULATE, tags.WEB],
19+
}, () => {
20+
test.beforeAll(async function ({ app, userSettings }) {
21+
try {
22+
await userSettings.set([
23+
['positron.reticulate.enabled', 'true']
24+
]);
25+
26+
} catch (e) {
27+
await app.code.driver.takeScreenshot('reticulateSetup');
28+
throw e;
29+
}
30+
});
31+
32+
test('R - Verify Basic Reticulate Functionality using reticulate::repl_python()', async function ({ app, sessions }) {
33+
34+
const rSessionMetaData = await sessions.start('r');
35+
36+
await app.workbench.console.pasteCodeToConsole('reticulate::repl_python()', true);
37+
38+
try {
39+
await app.workbench.console.waitForConsoleContents('Yes/no/cancel');
40+
await app.workbench.console.typeToConsole('no');
41+
await app.workbench.console.sendEnterKey();
42+
} catch {
43+
// Prompt did not appear
44+
}
45+
46+
await app.workbench.popups.installIPyKernel();
47+
48+
await app.workbench.console.waitForReadyAndStarted('>>>');
49+
50+
await verifyReticulateFunctionality(app, rSessionMetaData.id);
51+
52+
});
53+
});
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (C) 2024 Posit Software, PBC. All rights reserved.
3+
* Licensed under the Elastic License 2.0. See LICENSE.txt for license information.
4+
*--------------------------------------------------------------------------------------------*/
5+
6+
import { test, tags } from '../_test.setup';
7+
8+
test.use({
9+
suiteId: __filename
10+
});
11+
12+
// In order to run this test on Windows, I think we need to set the env var:
13+
// RETICULATE_PYTHON
14+
// to the installed python path
15+
16+
test.describe('Reticulate', {
17+
tag: [tags.RETICULATE, tags.WEB],
18+
}, () => {
19+
test.beforeAll(async function ({ app, userSettings }) {
20+
try {
21+
await userSettings.set([
22+
['positron.reticulate.enabled', 'true']
23+
]);
24+
25+
} catch (e) {
26+
await app.code.driver.takeScreenshot('reticulateSetup');
27+
throw e;
28+
}
29+
});
30+
31+
test('R - Verify Reticulate Restart', {
32+
tag: [tags.RETICULATE, tags.CONSOLE]
33+
}, async function ({ app, sessions }) {
34+
35+
await sessions.start('pythonReticulate');
36+
37+
await app.workbench.sessions.expectSessionPickerToBe('Python (reticulate)');
38+
39+
await app.workbench.sessions.restart('Python (reticulate)', { waitForIdle: false });
40+
41+
await app.code.driver.page.locator('.positron-modal-dialog-box').getByRole('button', { name: 'Yes' }).click();
42+
43+
await app.workbench.console.waitForReadyAndStarted('>>>', 30000);
44+
45+
});
46+
});
47+
48+
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (C) 2025 Posit Software, PBC. All rights reserved.
3+
* Licensed under the Elastic License 2.0. See LICENSE.txt for license information.
4+
*--------------------------------------------------------------------------------------------*/
5+
6+
import { test, tags } from '../_test.setup';
7+
import { verifyReticulateFunctionality } from './helpers/verifyReticulateFunction.js';
8+
9+
test.use({
10+
suiteId: __filename
11+
});
12+
13+
// In order to run this test on Windows, I think we need to set the env var:
14+
// RETICULATE_PYTHON
15+
// to the installed python path
16+
17+
test.describe('Reticulate', {
18+
tag: [tags.RETICULATE, tags.WEB],
19+
}, () => {
20+
test.beforeAll(async function ({ app, userSettings }) {
21+
try {
22+
await userSettings.set([
23+
['positron.reticulate.enabled', 'true']
24+
]);
25+
26+
} catch (e) {
27+
await app.code.driver.takeScreenshot('reticulateSetup');
28+
throw e;
29+
}
30+
});
31+
32+
test('R - Verify Reticulate Stop/Start Functionality', async function ({ app, sessions }) {
33+
34+
await sessions.start('pythonReticulate');
35+
36+
await app.workbench.popups.installIPyKernel();
37+
38+
await app.workbench.console.waitForReadyAndStarted('>>>', 30000);
39+
40+
await verifyReticulateFunctionality(app, `R ${process.env.POSITRON_R_VER_SEL!}`);
41+
42+
await app.workbench.sessions.delete(`R ${process.env.POSITRON_R_VER_SEL!}`);
43+
44+
// await app.workbench.sessions.delete('Python (reticulate)'); // doesn't seem to work on exited session
45+
46+
await app.workbench.console.waitForConsoleContents('exited');
47+
48+
await sessions.start('pythonReticulate');
49+
50+
await app.workbench.console.waitForReadyAndStarted('>>>', 30000);
51+
52+
await verifyReticulateFunctionality(app, `R ${process.env.POSITRON_R_VER_SEL!} - 2`, 'Python (reticulate) - 2');
53+
54+
});
55+
56+
});
57+

0 commit comments

Comments
 (0)