diff --git a/tests/e2e/markdown-tab-scroll-restore.spec.ts b/tests/e2e/markdown-tab-scroll-restore.spec.ts index 02362dd822a..1b84c425270 100644 --- a/tests/e2e/markdown-tab-scroll-restore.spec.ts +++ b/tests/e2e/markdown-tab-scroll-restore.spec.ts @@ -11,7 +11,8 @@ import { } from './helpers/markdown-editor-fixture' test('restores the Markdown viewport when an image gains height after a tab switch', async ({ - orcaPage + orcaPage, + registerPostElectronShutdownCleanup }, testInfo) => { await waitForSessionReady(orcaPage) await waitForActiveWorktree(orcaPage) @@ -21,83 +22,80 @@ test('restores the Markdown viewport when an image gains height after a tab swit let otherPath: string | null = null let imagePath: string | null = null - try { - const sections = Array.from( - { length: 100 }, - (_, index) => `## Section ${index}\n\nParagraph ${index}. Scroll restoration testing text.` - ).join('\n\n') - filePath = await createMarkdownFixture( - context, - directory, - 'image-scroll', - testInfo.workerIndex, - `# Image scroll\n\n![Scroll restoration image](tall.svg)\n\n${sections}` - ) - imagePath = path.join(path.dirname(filePath), 'tall.svg') - await writeFile( - imagePath, - '' - ) - otherPath = await createMarkdownFixture( - context, - directory, - 'other-tab', - testInfo.workerIndex, - '# Other tab' - ) - await openMarkdownFixture(orcaPage, context, otherPath) - await waitForRichMarkdownEditor(orcaPage) - await openMarkdownFixture(orcaPage, context, filePath) - const editor = await waitForRichMarkdownEditor(orcaPage) - const image = editor.getByRole('img', { name: 'Scroll restoration image' }) - await expect - .poll(() => - image.evaluate((element) => - element instanceof HTMLImageElement ? element.naturalHeight : 0 - ) - ) - .toBe(1500) - const viewport = orcaPage.locator('.rich-markdown-editor-shell .overflow-auto') - await viewport.evaluate((element) => { - element.scrollTop = 4000 - }) - const heading = editor.getByRole('heading', { name: 'Section 45', exact: true }) - const originalTop = await heading.evaluate((element) => element.getBoundingClientRect().top) - - await orcaPage - .locator('[data-tab-id]') - .filter({ hasText: path.basename(otherPath) }) - .click() - // Model image dimensions arriving after restoration, independent of the host's decode speed. - const pendingImage = await orcaPage.addStyleTag({ - content: - '.rich-markdown-editor img[alt="Scroll restoration image"] { height: 1px !important; }' - }) - await orcaPage - .locator('[data-tab-id]') - .filter({ hasText: path.basename(filePath) }) - .click() - await expect.poll(() => viewport.evaluate((element) => element.scrollTop)).toBe(4000) - await pendingImage.evaluate((element) => element.remove()) - await expect - .poll(() => image.evaluate((element) => element.getBoundingClientRect().height)) - .toBeGreaterThan(500) - // Let Chromium apply its scroll-anchor adjustment before checking the final viewport. - await viewport.evaluate( - () => - new Promise((resolve) => { - requestAnimationFrame(() => requestAnimationFrame(() => resolve())) - }) - ) - await expect.poll(() => viewport.evaluate((element) => element.scrollTop)).toBe(4000) - await expect - .poll(() => heading.evaluate((element) => element.getBoundingClientRect().top)) - .toBe(originalTop) - } finally { + registerPostElectronShutdownCleanup(async () => { await cleanupMarkdownFixture(filePath) await cleanupMarkdownFixture(otherPath) if (imagePath) { await rm(imagePath, { force: true }) } - } + }) + + const sections = Array.from( + { length: 100 }, + (_, index) => `## Section ${index}\n\nParagraph ${index}. Scroll restoration testing text.` + ).join('\n\n') + filePath = await createMarkdownFixture( + context, + directory, + 'image-scroll', + testInfo.workerIndex, + `# Image scroll\n\n![Scroll restoration image](tall.svg)\n\n${sections}` + ) + imagePath = path.join(path.dirname(filePath), 'tall.svg') + await writeFile( + imagePath, + '' + ) + otherPath = await createMarkdownFixture( + context, + directory, + 'other-tab', + testInfo.workerIndex, + '# Other tab' + ) + await openMarkdownFixture(orcaPage, context, otherPath) + await waitForRichMarkdownEditor(orcaPage) + await openMarkdownFixture(orcaPage, context, filePath) + const editor = await waitForRichMarkdownEditor(orcaPage) + const image = editor.getByRole('img', { name: 'Scroll restoration image' }) + await expect + .poll(() => + image.evaluate((element) => (element instanceof HTMLImageElement ? element.naturalHeight : 0)) + ) + .toBe(1500) + const viewport = orcaPage.locator('.rich-markdown-editor-shell .overflow-auto') + await viewport.evaluate((element) => { + element.scrollTop = 4000 + }) + const heading = editor.getByRole('heading', { name: 'Section 45', exact: true }) + const originalTop = await heading.evaluate((element) => element.getBoundingClientRect().top) + + await orcaPage + .locator('[data-tab-id]') + .filter({ hasText: path.basename(otherPath) }) + .click() + // Model image dimensions arriving after restoration, independent of the host's decode speed. + const pendingImage = await orcaPage.addStyleTag({ + content: '.rich-markdown-editor img[alt="Scroll restoration image"] { height: 1px !important; }' + }) + await orcaPage + .locator('[data-tab-id]') + .filter({ hasText: path.basename(filePath) }) + .click() + await expect.poll(() => viewport.evaluate((element) => element.scrollTop)).toBe(4000) + await pendingImage.evaluate((element) => element.remove()) + await expect + .poll(() => image.evaluate((element) => element.getBoundingClientRect().height)) + .toBeGreaterThan(500) + // Let Chromium apply its scroll-anchor adjustment before checking the final viewport. + await viewport.evaluate( + () => + new Promise((resolve) => { + requestAnimationFrame(() => requestAnimationFrame(() => resolve())) + }) + ) + await expect.poll(() => viewport.evaluate((element) => element.scrollTop)).toBe(4000) + await expect + .poll(() => heading.evaluate((element) => element.getBoundingClientRect().top)) + .toBeCloseTo(originalTop, 1) })