Operand

pro bo? no.

gram: docs

> ./e2e/tests/find-replace-shortcuts.spec.ts

import { expect, test } from '@playwright/test';
import { EditorPage } from '../helpers/editor-page';
async function findShortcut(page: import('@playwright/test').Page): Promise<string> {
const isMac = await page.evaluate(() => navigator.platform.toUpperCase().includes('MAC'));
return isMac ? 'Meta+f' : 'Control+f';
}
async function getEditorScrollTop(page: import('@playwright/test').Page): Promise<number> {
return page.evaluate(() => {
const root = document.querySelector<HTMLElement>('[data-testid="docx-editor"]');
if (!root) return 0;
const scroller = Array.from(root.querySelectorAll<HTMLElement>('*')).find((el) => {
const style = getComputedStyle(el);
return (
el.scrollHeight > el.clientHeight + 100 &&
(style.overflowY === 'auto' || style.overflowY === 'scroll')
);
});
return scroller?.scrollTop ?? 0;
});
}
async function findUniqueLastPagePhrase(page: import('@playwright/test').Page): Promise<string> {
const phrase = await page.evaluate(() => {
const pages = Array.from(document.querySelectorAll<HTMLElement>('.layout-page'));
const lastPage = pages[pages.length - 1];
if (!lastPage) return null;
const lastPageText = lastPage.textContent ?? '';
if (lastPageText.includes('scrollToPage(3)')) return 'scrollToPage(3)';
const paintedText = Array.from(
document.querySelectorAll<HTMLElement>(
'.layout-page-content span[data-pm-start][data-pm-end]'
)
)
.map((span) => span.textContent ?? '')
.join('');
const documentText = window.__DOCX_EDITOR_E2E__?.agentGetDocumentText() || paintedText;
if (!documentText) return null;
const spans = Array.from(
lastPage.querySelectorAll<HTMLElement>(
'.layout-page-content span[data-pm-start][data-pm-end]'
)
);
for (const span of spans) {
const text = (span.textContent ?? '').trim();
if (text.length < 24) continue;
for (let start = 0; start <= Math.min(12, text.length - 24); start += 1) {
const candidate = text.slice(start, Math.min(text.length, start + 32)).trim();
if (candidate.length < 20) continue;
if (documentText.indexOf(candidate) === documentText.lastIndexOf(candidate)) {
return candidate;
}
}
}
return null;
});
expect(phrase, 'demo document should expose a unique phrase on the last page').toBeTruthy();
return phrase!;
}
test.describe('Find/replace shortcuts', () => {
test('opens editor find by default', async ({ page }) => {
const editor = new EditorPage(page);
await editor.goto();
await editor.waitForReady();
await editor.newDocument();
await editor.focus();
await page.keyboard.press(await findShortcut(page));
await editor.findReplaceDialog.waitFor();
});
test('can leave native browser find shortcut alone', async ({ page }) => {
await page.goto('/?e2e=1&disableFindReplaceShortcuts=1');
const editor = new EditorPage(page);
await editor.waitForReady();
await editor.newDocument();
await editor.focus();
await page.keyboard.press(await findShortcut(page));
await expect(editor.findReplaceDialog).toHaveCount(0);
});
test('find scrolls the paged view to a match on a later page', async ({ page }) => {
const editor = new EditorPage(page);
await editor.goto();
await editor.waitForReady();
const totalPages = await page.waitForFunction(
() => {
const total = window.__DOCX_EDITOR_E2E__?.getTotalPages() ?? 0;
return total > 1 ? total : false;
},
{ timeout: 10000 }
);
await page.evaluate(
(pageNumber) => {
window.__DOCX_EDITOR_E2E__?.scrollToPage(pageNumber);
},
await totalPages.jsonValue()
);
await page.waitForFunction(() => {
const pages = document.querySelectorAll<HTMLElement>('.layout-page');
const lastPage = pages[pages.length - 1];
if (!lastPage) return false;
const rect = lastPage.getBoundingClientRect();
return rect.bottom > 0 && rect.top < window.innerHeight;
});
const phrase = await findUniqueLastPagePhrase(page);
await page.evaluate(() => {
const root = document.querySelector<HTMLElement>('[data-testid="docx-editor"]');
const scroller = root
? Array.from(root.querySelectorAll<HTMLElement>('*')).find((el) => {
const style = getComputedStyle(el);
return (
el.scrollHeight > el.clientHeight + 100 &&
(style.overflowY === 'auto' || style.overflowY === 'scroll')
);
})
: null;
scroller?.scrollTo({ top: 0 });
});
const initialScrollTop = await getEditorScrollTop(page);
await page.keyboard.press(await findShortcut(page));
await editor.findReplaceDialog.waitFor();
await page.locator('#find-text').fill(phrase);
await page.locator('#find-text').press('Enter');
await page.waitForFunction(
(start) => {
const root = document.querySelector<HTMLElement>('[data-testid="docx-editor"]');
if (!root) return false;
const scroller = Array.from(root.querySelectorAll<HTMLElement>('*')).find((el) => {
const style = getComputedStyle(el);
return (
el.scrollHeight > el.clientHeight + 100 &&
(style.overflowY === 'auto' || style.overflowY === 'scroll')
);
});
return (scroller?.scrollTop ?? 0) > start + 50;
},
initialScrollTop,
{ timeout: 10000 }
);
await page.waitForFunction(
(expected) => window.__DOCX_EDITOR_E2E__?.agentSelection()?.selectedText === expected,
phrase
);
});
test('searches as the find term changes instead of reusing previous matches', async ({
page,
}) => {
const editor = new EditorPage(page);
await editor.gotoEmpty();
await editor.waitForReady();
await editor.focus();
await editor.typeText('alpha beta gamma');
await page.keyboard.press(await findShortcut(page));
await editor.findReplaceDialog.waitFor();
await page.locator('#find-text').fill('alpha');
await page.waitForFunction(
() => window.__DOCX_EDITOR_E2E__?.agentSelection()?.selectedText === 'alpha'
);
await page.locator('#find-text').fill('gamma');
await page.waitForFunction(
() => window.__DOCX_EDITOR_E2E__?.agentSelection()?.selectedText === 'gamma'
);
});
test('enter advances live search results without resetting to the first match', async ({
page,
}) => {
const editor = new EditorPage(page);
await editor.gotoEmpty();
await editor.waitForReady();
await editor.focus();
await editor.typeText('alpha beta alpha gamma');
await page.keyboard.press(await findShortcut(page));
await editor.findReplaceDialog.waitFor();
await page.locator('#find-text').fill('alpha');
await page.waitForFunction(() => {
const selection = window.__DOCX_EDITOR_E2E__?.agentSelection();
return selection?.selectedText === 'alpha' && selection.before === '';
});
await page.locator('#find-text').press('Enter');
await page.waitForFunction(() => {
const selection = window.__DOCX_EDITOR_E2E__?.agentSelection();
return selection?.selectedText === 'alpha' && selection.before === 'alpha beta ';
});
await page.waitForTimeout(400);
await expect
.poll(() => page.evaluate(() => window.__DOCX_EDITOR_E2E__?.agentSelection()?.before ?? ''))
.toBe('alpha beta ');
});
});