refactor(e2e): create editor helpers (#54701)

This commit is contained in:
Oliver Eyton-Williams
2024-05-08 20:21:56 +02:00
committed by GitHub
parent c7d3b1303e
commit ca4e5db8b1
10 changed files with 93 additions and 82 deletions

View File

@@ -1,4 +1,7 @@
import { test, expect } from '@playwright/test';
import { getEditors } from './utils/editor';
test.use({ storageState: 'playwright/.auth/certified-user.json' });
test.describe('Challenge with editor', function () {
test('the shortcut "Ctrl + S" saves the code', async ({ page }) => {
@@ -6,7 +9,7 @@ test.describe('Challenge with editor', function () {
'/learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-2'
);
const editor = page.locator('textarea');
const editor = getEditors(page);
await editor.fill('Something funny');
await page.keyboard.down('Control');

View File

@@ -1,26 +1,6 @@
import { expect, test, type Page } from '@playwright/test';
import { expect, test } from '@playwright/test';
async function focusEditor({
page,
isMobile,
browserName
}: {
page: Page;
isMobile: boolean;
browserName: string;
}) {
const monacoEditor = page.getByLabel('Editor content');
// The editor has an overlay div, which prevents the click event from bubbling up in iOS Safari.
// This is a quirk in this browser-OS combination, and the workaround here is to use `.focus()`
// in place of `.click()` to focus on the editor.
// Ref: https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html
if (isMobile && browserName === 'webkit') {
await monacoEditor.focus();
} else {
await monacoEditor.click();
}
}
import { clearEditor, focusEditor } from './utils/editor';
test.describe('Editor Component', () => {
test('should allow the user to insert text', async ({
@@ -50,14 +30,7 @@ test.describe('Python Terminal', () => {
);
await focusEditor({ page, isMobile, browserName });
// First clear the editor
// TODO: replace with ControlOrMeta when it's supported
if (browserName === 'webkit') {
await page.keyboard.press('Meta+a');
} else {
await page.keyboard.press('Control+a');
}
await page.keyboard.press('Backspace');
await clearEditor({ page, browserName });
// Then enter invalid code
await page.keyboard.insertText('def');
const preview = page.getByTestId('preview-pane');

View File

@@ -2,11 +2,10 @@ import { test, expect } from '@playwright/test';
import translations from '../client/i18n/locales/english/translations.json';
import { authedPut } from './utils/request';
import { getEditors } from './utils/editor';
const course =
'/learn/javascript-algorithms-and-data-structures/basic-javascript/comment-your-javascript-code';
const editorPaneLabel =
'Editor content;Press Alt+F1 for Accessibility Options.';
test.use({ storageState: 'playwright/.auth/certified-user.json' });
@@ -41,9 +40,9 @@ test('User can interact with the app using the keyboard', async ({ page }) => {
await page.goto(course);
await expect(page.getByLabel(editorPaneLabel)).toBeFocused();
await page.getByLabel(editorPaneLabel).press('Escape');
await expect(page.getByLabel(editorPaneLabel)).not.toBeFocused();
await expect(getEditors(page)).toBeFocused();
await getEditors(page).press('Escape');
await expect(getEditors(page)).not.toBeFocused();
await page.keyboard.press('n');
const nextCourse = '**/declare-javascript-variables';
@@ -62,7 +61,7 @@ test('User can interact with the app using the keyboard', async ({ page }) => {
).toBeVisible();
await page.keyboard.press('e');
await expect(page.getByLabel(editorPaneLabel)).toBeFocused();
await expect(getEditors(page)).toBeFocused();
await page.keyboard.press('Control+Enter');
await expect(page.getByText('running test')).toBeVisible();

View File

@@ -1,5 +1,7 @@
import { test, expect } from '@playwright/test';
import { getEditors } from './utils/editor';
test.beforeEach(async ({ page }) => {
await page.goto(
'/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-15'
@@ -21,7 +23,7 @@ test.describe('MultifileEditor Component', () => {
// before moving onto other assertions.
// Note that using the `.all()` locator here would result a flaky test.
// Ref: https://github.com/freeCodeCamp/freeCodeCamp/pull/53031/files#r1500316812
const editors = page.getByLabel('Editor content');
const editors = getEditors(page);
await expect(editors).toHaveCount(2);
const test_string = 'TestString';

View File

@@ -1,5 +1,7 @@
import { test, expect, type Page } from '@playwright/test';
import translations from '../client/i18n/locales/english/translations.json';
import { getEditors } from './utils/editor';
const outputTexts = {
default: `
@@ -33,7 +35,7 @@ const insertTextInCodeEditor = async ({
.getByRole('tab', { name: translations.learn['editor-tabs'].code })
.click();
}
await page.getByLabel('Editor content').fill(text);
await getEditors(page).fill(text);
if (isMobile) {
await page
.getByRole('tab', { name: translations.learn['editor-tabs'].console })

View File

@@ -1,5 +1,6 @@
import { expect, test } from '@playwright/test';
import translations from '../client/i18n/locales/english/translations.json';
import { focusEditor } from './utils/editor';
test.beforeEach(async ({ page }) => {
await page.goto(
@@ -30,15 +31,7 @@ test.describe('Challenge Preview Component', () => {
browserName,
isMobile
}) => {
// The editor has an overlay div, which prevents the click event from bubbling up in iOS Safari.
// This is a quirk in this browser-OS combination, and the workaround here is to use `.focus()`
// in place of `.click()` to focus on the editor.
// Ref: https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html
if (isMobile && browserName === 'webkit') {
await page.getByLabel('Editor content').focus();
} else {
await page.getByLabel('Editor content').click();
}
await focusEditor({ page, isMobile, browserName });
await page.keyboard.insertText('<h1>FreeCodeCamp</h1>');
if (isMobile) {

View File

@@ -1,26 +1,25 @@
import { expect, test } from '@playwright/test';
import { clearEditor, focusEditor } from './utils/editor';
test.use({ storageState: 'playwright/.auth/certified-user.json' });
test.describe('Progress bar component', () => {
test('Should appear with the correct content after the user has submitted their code', async ({
page
page,
isMobile,
browserName
}) => {
await page.goto(
'/learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-2'
'/learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-3'
);
const monacoEditor = page.getByLabel('Editor content');
// Using focus instead of click since we're not testing if the editor
// behaves correctly, we're using it to complete the challenge.
await monacoEditor.focus();
await page.keyboard.press('Control+A');
//Meta + A works in webkit
await page.keyboard.press('Meta+A');
await page.keyboard.press('Backspace');
// If focusEditor fails, typically it's because the instructions are too
// large. There's a bug that means `scrollIntoView` does not work in the
// editor and so we have to pick less verbose challenges until that's fixed.
await focusEditor({ page, isMobile, browserName });
await clearEditor({ page, browserName });
await page.keyboard.insertText(
'<html><body><h1>CatPhotoApp</h1><h2>Cat Photos</h2></body></html>'
'<html><body><h1>CatPhotoApp</h1><h2>Cat Photos</h2><p>See more cat photos in our gallery.</p></body></html>'
);
await page.getByRole('button', { name: 'Check Your Code' }).click();
@@ -36,19 +35,15 @@ test.describe('Progress bar component', () => {
});
test('should appear in the completion modal after user has submitted their code', async ({
page
page,
isMobile,
browserName
}) => {
await page.goto(
'/learn/javascript-algorithms-and-data-structures/basic-javascript/declare-javascript-variables'
);
const monacoEditor = page.getByLabel('Editor content');
await monacoEditor.focus();
await page.keyboard.press('Control+A');
await page.keyboard.press('Meta+A');
await page.keyboard.press('Backspace');
await focusEditor({ page, isMobile, browserName });
await clearEditor({ page, browserName });
await page.keyboard.insertText('var myName;');

View File

@@ -1,6 +1,7 @@
import { test, expect } from '@playwright/test';
import translations from '../client/i18n/locales/english/translations.json';
import { clearEditor, focusEditor, getEditors } from './utils/editor';
test('should render the modal content correctly', async ({ page }) => {
await page.goto(
@@ -36,7 +37,7 @@ test('should render the modal content correctly', async ({ page }) => {
).toBeVisible();
});
test('User can reset challenge', async ({ page }) => {
test('User can reset challenge', async ({ page, isMobile, browserName }) => {
const initialText = 'CatPhotoApp';
const initialFrame = page
.frameLocator('iframe[title="challenge preview"]')
@@ -54,13 +55,11 @@ test('User can reset challenge', async ({ page }) => {
// Building the preview can take a while
await expect(initialFrame).toBeVisible({ timeout: 10000 });
const editorPaneLabel =
'Editor content;Press Alt+F1 for Accessibility Options.';
// Modify the text in the editor pane, clearing first, otherwise the existing
// text will be selected before typing
await page.getByLabel(editorPaneLabel).fill('');
await page.getByLabel(editorPaneLabel).fill(updatedText);
await focusEditor({ page, isMobile, browserName });
await clearEditor({ page, browserName });
await getEditors(page).fill(updatedText);
await expect(updatedFrame).toBeVisible({ timeout: 10000 });
// Run the tests so the lower jaw updates (later we confirm that the update
@@ -95,11 +94,9 @@ test('User can reset classic challenge', async ({ page, isMobile }) => {
'/learn/javascript-algorithms-and-data-structures/basic-javascript/comment-your-javascript-code'
);
const editorPaneLabel =
'Editor content;Press Alt+F1 for Accessibility Options.';
const challengeSolution = '// This is in-line comment';
await page.getByLabel(editorPaneLabel).fill(challengeSolution);
await getEditors(page).fill(challengeSolution);
const submitButton = page.getByRole('button', {
name: isMobile ? translations.buttons.run : translations.buttons['run-test']

View File

@@ -2,11 +2,10 @@ import { APIRequestContext, Page, expect, test } from '@playwright/test';
import translations from '../client/i18n/locales/english/translations.json';
import { authedPut } from './utils/request';
import { getEditors } from './utils/editor';
const course =
'/learn/javascript-algorithms-and-data-structures/basic-javascript/comment-your-javascript-code';
const editorPaneLabel =
'Editor content;Press Alt+F1 for Accessibility Options.';
test.use({ storageState: 'playwright/.auth/certified-user.json' });
@@ -23,7 +22,7 @@ const enableKeyboardShortcuts = async (request: APIRequestContext) => {
const openModal = async (page: Page) => {
// The editor pane is focused by default, so we need to escape or it will
// capture the keyboard shortcuts
await page.getByLabel(editorPaneLabel).press('Escape');
await getEditors(page).press('Escape');
await page.keyboard.press('Shift+?');
};

48
e2e/utils/editor.ts Normal file
View File

@@ -0,0 +1,48 @@
import { type Page } from '@playwright/test';
/**
* Retrieves any editor elements on the page.
* @param page - The Playwright page object.
* @returns The editor elements.
*/
export function getEditors(page: Page) {
return page.getByLabel(
'Editor content;Press Alt+F1 for Accessibility Options'
);
}
export async function focusEditor({
page,
isMobile,
browserName
}: {
page: Page;
isMobile: boolean;
browserName: string;
}) {
// The editor has an overlay div, which prevents the click event from bubbling up in iOS Safari.
// This is a quirk in this browser-OS combination, and the workaround here is to use `.focus()`
// in place of `.click()` to focus on the editor.
// Ref: https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html
if (isMobile && browserName === 'webkit') {
await getEditors(page).focus();
} else {
await getEditors(page).click();
}
}
export async function clearEditor({
page,
browserName
}: {
page: Page;
browserName: string;
}) {
// TODO: replace with ControlOrMeta when it's supported
if (browserName === 'webkit') {
await page.keyboard.press('Meta+a');
} else {
await page.keyboard.press('Control+a');
}
await page.keyboard.press('Backspace');
}