Files
AFFiNE-Mirror/tests/affine-mobile/e2e/utils.ts
T
DarkSky 1d36e2e4b2 feat(core): improve mobile perf (#15317)
#### PR Dependency Tree


* **PR #15317** 👈

This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Virtualized mobile navigation with shell navigation and interactive
swipe menus; coordinated mobile back handling with interactive
phases/state restoration.
* Added shared auth request proxy and message-port based token handling
across mobile and worker flows.
* **Bug Fixes**
  * Hydrated remote worker error stacks for calls and observable errors.
* Improved SQLite FTS/indexer and nbstore optional text handling;
refined docs-search ref parsing and notification loading/retry.
* **Refactor / UX**
* Modal focus-preservation and pointer behavior updates; improved mobile
menu controls and back gesture plugins.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-23 00:23:21 +08:00

102 lines
2.8 KiB
TypeScript

import { expect, type Locator, type Page } from '@playwright/test';
export async function expandCollapsibleSection(page: Page, name: string) {
const divider = page.locator(`[data-collapsible]:has-text("${name}")`);
await divider.waitFor({ state: 'visible' });
// oxlint-disable-next-line prefer-dom-node-dataset
if ((await divider.getAttribute('data-collapsed')) === 'true') {
if ((await divider.getAttribute('role')) === 'switch') {
await divider.click();
} else {
await divider.getByRole('button').click();
}
}
await expect(divider).toHaveAttribute('data-collapsed', 'false');
const section = divider.locator(
'~ [data-testid="collapsible-section-content"]'
);
if ((await section.count()) > 0) {
await expect(section).toBeVisible();
return section;
}
return page.locator('body');
}
/**
* Click header "<" button
*/
export async function pageBack(page: Page) {
await page.getByTestId('page-header-back').tap();
}
export async function getAttrOfActiveElement(
page: Page,
attrName = 'data-testid'
) {
return await page.evaluate(name => {
const el = document.activeElement;
return el ? el.getAttribute(name) : '';
}, attrName);
}
/**
* Open the context menu of an navigation panel node
* @returns Menu Locator
*/
export async function openNavigationPanelNodeMenu(page: Page, node: Locator) {
await node.getByTestId('menu-trigger').tap();
const menu = page.getByRole('dialog');
await expect(menu).toBeVisible();
return menu;
}
export async function openNavigationPanelNodeSwipeMenu(
page: Page,
node: Locator
) {
if (page.context().browser()?.browserType().name() !== 'chromium') {
await node
.getByTestId('swipe-menu-trigger')
.evaluate(button =>
button.dispatchEvent(
new MouseEvent('click', { bubbles: true, cancelable: true })
)
);
return;
}
const box = await node.boundingBox();
if (!box) throw new Error('Navigation row is not visible');
const session = await page.context().newCDPSession(page);
try {
const y = box.y + box.height / 2;
await session.send('Input.dispatchTouchEvent', {
type: 'touchStart',
touchPoints: [{ x: box.x + box.width - 20, y }],
});
await session.send('Input.dispatchTouchEvent', {
type: 'touchMove',
touchPoints: [{ x: box.x, y }],
});
await session.send('Input.dispatchTouchEvent', {
type: 'touchEnd',
touchPoints: [],
});
} finally {
await session.detach();
}
}
export async function openTab(
page: Page,
name: 'home' | 'all' | 'Journal' | 'New Page'
) {
const tab = page.locator('#app-tabs').getByRole('tab', { name });
await expect(tab).toBeVisible();
await tab.click();
// oxlint-disable-next-line prefer-dom-node-dataset
const isActive = await tab.getAttribute('data-active');
expect(isActive).toBe('true');
}