104 lines
3.9 KiB
JavaScript
104 lines
3.9 KiB
JavaScript
/**
|
|
* E2E tests for the mobile bottom toolbar clearance (BUG-073).
|
|
*
|
|
* The fixed bottom bar (#mobile-toolbar, 64px + safe-area) used to cover the
|
|
* last pixels of every document/page: the clearance rule targeted the dead
|
|
* `.main-layout` selector instead of `.main-body`, so #content-area reached
|
|
* behind the bar and the end of the content was unreachable.
|
|
*
|
|
* Runs only under the `chromium-mobile` Playwright project (viewport ≤ 768px);
|
|
* skipped on the desktop project that the CI job executes — same convention
|
|
* as mobile-editor.spec.js / config-mobile.spec.js.
|
|
*
|
|
* Run:
|
|
* npx playwright test tests/e2e/mobile-toolbar.spec.js --project=chromium-mobile
|
|
* pwsh scripts/run-e2e-local.ps1 --project=chromium-mobile -g "BUG-073"
|
|
* (ObsiGate listening on http://localhost:2029, auth disabled)
|
|
*/
|
|
|
|
import { test, expect } from '@playwright/test';
|
|
|
|
const MOBILE_MAX_WIDTH = 768;
|
|
const LONG_DOC = 'ANALYSE_REVIEW.md';
|
|
|
|
async function boot(page) {
|
|
await page.goto('/');
|
|
await page
|
|
.waitForSelector('#app:not(.hidden)', { timeout: 15000 })
|
|
.catch(() => {});
|
|
}
|
|
|
|
/** Wait for the async markdown render, then confirm the area actually scrolls. */
|
|
async function openLongDocument(page) {
|
|
await page.evaluate((p) => window.TabManager.open('TestVault', p), LONG_DOC);
|
|
await expect(page.locator('#content-area .md-content')).toBeAttached({ timeout: 15000 });
|
|
await expect
|
|
.poll(
|
|
() =>
|
|
page.evaluate(() => {
|
|
const area = document.getElementById('content-area');
|
|
return area.scrollHeight > area.clientHeight;
|
|
}),
|
|
{ timeout: 15000 },
|
|
)
|
|
.toBe(true);
|
|
}
|
|
|
|
/** Geometry of #content-area vs the fixed #mobile-toolbar bar. */
|
|
async function measure(page) {
|
|
return page.evaluate(() => {
|
|
const area = document.getElementById('content-area').getBoundingClientRect();
|
|
const bar = document.getElementById('mobile-toolbar').getBoundingClientRect();
|
|
return { areaBottom: area.bottom, barTop: bar.top, barVisible: bar.height > 0 };
|
|
});
|
|
}
|
|
|
|
test.describe('Mobile bottom toolbar clearance (BUG-073)', () => {
|
|
test('content area ends above the fixed bottom toolbar', async ({ page, viewport }) => {
|
|
test.skip((viewport?.width ?? 0) > MOBILE_MAX_WIDTH, 'Mobile viewport required');
|
|
await boot(page);
|
|
|
|
const toolbar = page.locator('#mobile-toolbar');
|
|
await expect(toolbar).toBeVisible();
|
|
|
|
// Open a long document so the layout is in its real document-view state.
|
|
await openLongDocument(page);
|
|
await expect(page.locator('#content-area')).toBeVisible();
|
|
|
|
// The scroll container itself must stop at (or above) the bar — 1px
|
|
// tolerance for subpixel rounding.
|
|
await expect
|
|
.poll(async () => {
|
|
const m = await measure(page);
|
|
return m.areaBottom - m.barTop;
|
|
})
|
|
.toBeLessThanOrEqual(1);
|
|
});
|
|
|
|
test('the end of a long document scrolls clear of the toolbar', async ({ page, viewport }) => {
|
|
test.skip((viewport?.width ?? 0) > MOBILE_MAX_WIDTH, 'Mobile viewport required');
|
|
await boot(page);
|
|
|
|
await openLongDocument(page);
|
|
|
|
// Scroll to the very end: the last rendered element must sit above the bar.
|
|
await page.evaluate(() => {
|
|
const area = document.getElementById('content-area');
|
|
area.scrollTop = area.scrollHeight;
|
|
});
|
|
|
|
const result = await page.evaluate(() => {
|
|
const area = document.getElementById('content-area');
|
|
const barTop = document.getElementById('mobile-toolbar').getBoundingClientRect().top;
|
|
// Last element of the rendered document (markdown root or content child).
|
|
const root = area.querySelector('.md-content') || area.lastElementChild;
|
|
let last = root;
|
|
if (root && root.lastElementChild) last = root.lastElementChild;
|
|
const lastBottom = last ? last.getBoundingClientRect().bottom : area.getBoundingClientRect().bottom;
|
|
return { lastBottom, barTop };
|
|
});
|
|
|
|
expect(result.lastBottom).toBeLessThanOrEqual(result.barTop + 1);
|
|
});
|
|
});
|