From 7aa4b29d560cfe6d36677ac4bc7cfde9668609e3 Mon Sep 17 00:00:00 2001 From: forgejo-backport-action Date: Mon, 20 Apr 2026 14:23:22 +0200 Subject: [PATCH] [v15.0/forgejo] fix: CodeMirror e2e test (#12199) **Backport:** https://codeberg.org/forgejo/forgejo/pulls/12151 I tried a lot, but this seems to work. I know it is ugly, but checking and waiting after every action seems to make it stable. At least it succeeded five times in a row and the CI seemed to be under load due to the dependency updates. Maybe it is worth a try... Co-authored-by: Beowulf Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/12199 Reviewed-by: Beowulf Co-authored-by: forgejo-backport-action Co-committed-by: forgejo-backport-action --- tests/e2e/codemirror.test.e2e.ts | 66 ++++++++++++-------------------- 1 file changed, 25 insertions(+), 41 deletions(-) diff --git a/tests/e2e/codemirror.test.e2e.ts b/tests/e2e/codemirror.test.e2e.ts index 466b9f1fd3..c3dc6f0fcd 100644 --- a/tests/e2e/codemirror.test.e2e.ts +++ b/tests/e2e/codemirror.test.e2e.ts @@ -21,17 +21,21 @@ async function enterFilename(page: Page, filename: string) { } async function pressEnter(page: Page) { - // eslint-disable-next-line playwright/no-wait-for-timeout - await page.waitForTimeout(5); await page.keyboard.press('Enter', {delay: 5}); - // eslint-disable-next-line playwright/no-wait-for-timeout - await page.waitForTimeout(10); } async function type(page: Page, text: string) { await page.keyboard.type(text, {delay: 10}); } +async function validate(page: Page, expected: string) { + await expect(async () => { + const internal = await page.evaluate(() => Array.from(window.codeEditors)[0].state.doc.toString()); + expect(internal).toStrictEqual(expected); + }).toPass(); + await expect(page.locator('#edit_area')).toHaveValue(expected); +} + test('New file editor', async ({page}) => { const response = await page.goto('/user2/repo1/_new/master', {waitUntil: 'domcontentloaded'}); expect(response?.status()).toBe(200); @@ -39,21 +43,19 @@ test('New file editor', async ({page}) => { await enterFilename(page, `f.txt`); const editor = page.locator('.cm-content'); - const backingTextArea = page.locator('#edit_area'); await editor.click(); + await type(page, 'This'); await pressEnter(page); + await validate(page, 'This\n'); + await type(page, 'is'); await pressEnter(page); - await type(page, 'Frogejo!'); + await validate(page, 'This\nis\n'); - const expected = 'This\nis\nFrogejo!'; - await expect(async () => { - const internal = await page.evaluate(() => Array.from(window.codeEditors)[0].state.doc.toString()); - expect(internal).toStrictEqual(expected); - }).toPass(); - await expect(backingTextArea).toHaveValue(expected); + await type(page, 'Frogejo!'); + await validate(page, 'This\nis\nFrogejo!'); }); test('New file with autocomplete and indent', async ({page}) => { @@ -63,26 +65,20 @@ test('New file with autocomplete and indent', async ({page}) => { await enterFilename(page, 'f.html'); const editor = page.locator('.cm-content'); - const backingTextArea = page.locator('#edit_area'); await expect(editor).toHaveAttribute('data-language', 'html', {timeout: 3000}); await editor.click(); await type(page, ''); await pressEnter(page); - await type(page, ''); - await pressEnter(page); - await type(page, 'Frogejo is the future'); + await validate(page, '<html>\n \n</html>'); - const expected = '<html>\n <head>\n <title>Frogejo is the future\n \n'; - await expect(async () => { - const internal = await page.evaluate(() => Array.from(window.codeEditors)[0].state.doc.toString()); - expect(internal).toStrictEqual(expected); - }).toPass(); - await expect(backingTextArea).toHaveValue(expected); + await type(page, ''); + await pressEnter(page); + await validate(page, '\n \n \n \n'); + + await type(page, 'Frogejo is the future'); + await validate(page, '<html>\n <head>\n <title>Frogejo is the future\n \n'); }); test('Preview for markdown file', async ({page}) => { @@ -105,10 +101,7 @@ test('Set from query', async ({page}) => { const response = await page.goto('/user2/repo1/_new/master?value=This\\nis\\\\nFrogejo!', {waitUntil: 'domcontentloaded'}); expect(response?.status()).toBe(200); - await expect(async () => { - const internal = await page.evaluate(() => Array.from(window.codeEditors)[0].state.doc.toString()); - expect(internal).toStrictEqual('This\nis\\nFrogejo!'); - }).toPass(); + await validate(page, 'This\nis\\nFrogejo!'); }); test('Search in file', async ({page}) => { @@ -122,10 +115,7 @@ test('Search in file', async ({page}) => { const toggleByWord = page.locator('label[for="search_by_word"]'); const nextButton = page.locator('button[aria-label="Next find"]'); - await expect(async () => { - const internal = await page.evaluate(() => Array.from(window.codeEditors)[0].state.doc.toString()); - expect(internal).toStrictEqual('This\nis\nFrogejo!\nthIs'); - }).toPass(); + await validate(page, 'This\nis\nFrogejo!\nthIs'); await editor.click(); @@ -180,10 +170,7 @@ test('Replace in file', async ({page}) => { const searchField = page.locator('.fj-search input[name="search"]'); const replaceField = page.locator('.fj-search input[name="replace"]'); - await expect(async () => { - const internal = await page.evaluate(() => Array.from(window.codeEditors)[0].state.doc.toString()); - expect(internal).toStrictEqual('This\nis\nFrogejo!\nthIs'); - }).toPass(); + await validate(page, 'This\nis\nFrogejo!\nthIs'); await editor.click(); @@ -196,10 +183,7 @@ test('Replace in file', async ({page}) => { await page.getByRole('button', {name: 'Replace all'}).click(); - await expect(async () => { - const internal = await page.evaluate(() => Array.from(window.codeEditors)[0].state.doc.toString()); - expect(internal).toStrictEqual('ThBlub\nBlub\nFrogejo!\nthBlub'); - }).toPass(); + await validate(page, 'ThBlub\nBlub\nFrogejo!\nthBlub'); }); test('Do not open search if search button not available', async ({page}) => {