Skip to content

Commit 6ff27a6

Browse files
authored
test: Add firefox support for playwright pasteInMonaco (#1463)
Doesn't seem to be a single solution that works in all 3 browsers in headless mode, but between 2 solutions we can cover pasting in all 3 browsers
1 parent ee1cd54 commit 6ff27a6

5 files changed

Lines changed: 40 additions & 20 deletions

File tree

tests/console.spec.ts

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,6 @@ test.afterAll(async () => {
1717
});
1818

1919
test.describe('console input tests', () => {
20-
test.beforeEach(async () => {
21-
// Find the console input
22-
const consoleInput = page.locator('.console-input');
23-
24-
// Monaco editor doesn't have a native input, so need to just click into it and type on the page
25-
// https://github.com/microsoft/playwright/issues/14126
26-
await consoleInput.click();
27-
});
28-
2920
test('print commands get logged', async () => {
3021
const message = `Hello ${shortid()}!`;
3122
const command = `print("${message}")`;

tests/notebook.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { test, expect } from '@playwright/test';
2-
import { pasteInMonaco } from './utils';
32
import shortid from 'shortid';
3+
import { pasteInMonaco } from './utils';
44

55
test('test creating a file, saving it, closing it, re-opening it, running it, then deleting it', async ({
66
page,

tests/table-operations.spec.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,6 @@ test.beforeEach(async ({ page }) => {
109109
await page.goto('');
110110

111111
const consoleInput = page.locator('.console-input');
112-
await consoleInput.click();
113112

114113
const command = makeTableCommand(undefined, TableTypes.AllTypes);
115114

@@ -516,7 +515,6 @@ test('advanced settings', async ({ page }) => {
516515

517516
await test.step('create 2nd table', async () => {
518517
const consoleInput = page.locator('.console-input');
519-
await consoleInput.click();
520518

521519
const command = makeTableCommand(table2Name, TableTypes.AllTypes);
522520

tests/table.spec.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
import { test, expect, Page } from '@playwright/test';
2-
import { makeTableCommand, pasteInMonaco, TableTypes } from './utils';
2+
import { makeTableCommand, pasteInMonaco } from './utils';
33

44
// Run tests serially since they all use the same table
55
test.describe.configure({ mode: 'serial' });
66

77
async function openSimpleTable(page: Page) {
88
const consoleInput = page.locator('.console-input');
9-
await consoleInput.click();
109

1110
const command = makeTableCommand();
1211

@@ -42,7 +41,6 @@ test('can open a simple table', async ({ page }) => {
4241
test('can open a table with column header groups', async ({ page }) => {
4342
await page.goto('');
4443
const consoleInput = page.locator('.console-input');
45-
await consoleInput.click();
4644

4745
const command = `${makeTableCommand('column_header_group')}
4846
column_groups = [{ 'name': 'YandZ', 'children': ['y', 'z'] }, { 'name': 'All', 'children': ['x', 'YandZ'], 'color': 'white' }]
@@ -71,7 +69,6 @@ test('can open a table with column header groups and hidden columns', async ({
7169
}) => {
7270
await page.goto('');
7371
const consoleInput = page.locator('.console-input');
74-
await consoleInput.click();
7572

7673
const command = `${makeTableCommand('column_header_group')}
7774
column_groups = [{ 'name': 'YandZ', 'children': ['y', 'z'] }, { 'name': 'All', 'children': ['x', 'YandZ'], 'color': 'white' }]

tests/utils.ts

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { Locator, expect, Page } from '@playwright/test';
2+
import os from 'node:os';
23
import shortid from 'shortid';
34

45
export enum TableTypes {
@@ -99,18 +100,44 @@ export async function typeInMonaco(
99100
}
100101

101102
/**
102-
* Pastes text into a monaco input
103+
* Pastes text into a monaco input. The input will have focus after pasting.
103104
* @param locator Locator to use for monaco editor
104105
* @param text Text to be pasted
105106
*/
106107
export async function pasteInMonaco(
107108
locator: Locator,
108109
text: string
109110
): Promise<void> {
111+
const page = locator.page();
112+
const isMac = os.platform() === 'darwin';
113+
const modifier = isMac ? 'Meta' : 'Control';
114+
115+
// Create a hidden textarea with the contents to paste
116+
const inputId = await page.evaluate(async evalText => {
117+
const tempInput = document.createElement('textarea');
118+
tempInput.id = 'super-secret-temp-input-id';
119+
tempInput.value = evalText;
120+
tempInput.style.width = '0';
121+
tempInput.style.height = '0';
122+
document.body.appendChild(tempInput);
123+
tempInput.select();
124+
return tempInput.id;
125+
}, text);
126+
127+
// Copy the contents of the textarea which was selected above
128+
await page.keyboard.press(`${modifier}+C`);
129+
130+
// Remove the textarea
131+
await page.evaluate(id => {
132+
document.getElementById(id)?.remove();
133+
}, inputId);
134+
135+
// Focus monaco
136+
await locator.click();
137+
110138
const browserName = locator.page().context().browser()?.browserType().name();
111-
if (browserName === 'firefox') {
112-
await typeInMonaco(locator, text);
113-
} else {
139+
if (browserName === 'webkit') {
140+
// Webkit doesn't seem to paste w/ the keyboard shortcut in headless mode
114141
await locator.locator('textarea').evaluate(async (element, evalText) => {
115142
const clipboardData = new DataTransfer();
116143
clipboardData.setData('text/plain', evalText);
@@ -119,6 +146,13 @@ export async function pasteInMonaco(
119146
});
120147
element.dispatchEvent(clipboardEvent);
121148
}, text);
149+
} else {
150+
await page.keyboard.press(`${modifier}+V`);
151+
}
152+
153+
if (text.length > 0) {
154+
// Sanity check the paste happened
155+
await expect(locator.locator('textarea')).not.toBeEmpty();
122156
}
123157
}
124158

0 commit comments

Comments
 (0)