Ein MEW-Band mit 1000 Seiten bereitete vorher jede Seite vor und zeichnete alle, bevor er sich zeigte – Minuten und Gigabytes. e2e/pdf.spec.js mit einem 400-Seiten-PDF (e2e/make_pdf.py, pypdf). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
71 lines
3.3 KiB
JavaScript
71 lines
3.3 KiB
JavaScript
// A big PDF (a scanned volume of 400 pages, e2e/make_pdf.py): it opens at once, only the
|
|
// pages near the view are drawn, the end can be reached, and opening can be cancelled.
|
|
const path = require('path');
|
|
const { test, expect } = require('@playwright/test');
|
|
|
|
test.use({ storageState: path.join(__dirname, '.auth', 'user.json') });
|
|
test.describe.configure({ mode: 'serial' });
|
|
|
|
const PDF = path.join(__dirname, '.auth', 'big.pdf');
|
|
let bookId = null;
|
|
|
|
let pageErrors = [];
|
|
test.beforeEach(({ page }) => {
|
|
pageErrors = [];
|
|
page.on('pageerror', e => pageErrors.push(String(e)));
|
|
});
|
|
test.afterEach(() => {
|
|
expect(pageErrors, 'errors in the page').toEqual([]);
|
|
});
|
|
|
|
async function ready(page) {
|
|
await page.goto('/#books');
|
|
await page.waitForLoadState('networkidle');
|
|
await page.waitForFunction(() => typeof openBook === 'function' && Array.isArray(_lastBookListData));
|
|
}
|
|
|
|
const drawn = page => page.evaluate(() =>
|
|
[...document.querySelectorAll('#reader-content canvas.pdf-page')].filter(c => c.width > 0).length);
|
|
|
|
test('the big PDF goes in', async ({ page }) => {
|
|
await ready(page);
|
|
await page.locator('#book-file-input').setInputFiles(PDF);
|
|
await page.waitForFunction(() => _lastBookListData.some(b => b.title === 'Dicker Band'), null, { timeout: 30000 });
|
|
bookId = await page.evaluate(() => _lastBookListData.find(b => b.title === 'Dicker Band').id);
|
|
});
|
|
|
|
test('it opens with every page placed, only those near the view drawn', async ({ page }) => {
|
|
await ready(page);
|
|
await page.evaluate(id => openBook(id), bookId);
|
|
await page.waitForFunction(() => _readPos && _readPos.ready, null, { timeout: 20000 });
|
|
await expect(page.locator('#reader-content .pdf-page-wrapper')).toHaveCount(400);
|
|
await expect(page.locator('.pdf-loading-overlay')).toHaveCount(0);
|
|
await expect.poll(() => drawn(page)).toBeGreaterThan(0);
|
|
expect(await drawn(page)).toBeLessThan(30);
|
|
// To the end: the last page gets drawn, the first ones are let go.
|
|
await page.evaluate(() => { const c = document.getElementById('reader-content'); c.scrollTop = c.scrollHeight; });
|
|
await expect.poll(() => page.evaluate(() => document.querySelector('#pdf-page-400 canvas').width > 0)).toBe(true);
|
|
await expect.poll(() => page.evaluate(() => document.querySelector('#pdf-page-1 canvas').width)).toBe(0);
|
|
expect(await drawn(page)).toBeLessThan(30);
|
|
await page.evaluate(() => closeReader());
|
|
});
|
|
|
|
test('opening can be cancelled, and another book opens after it', async ({ page }) => {
|
|
await ready(page);
|
|
// Slow the file down so the opening is still under way.
|
|
await page.route(`**/books/${bookId}/data/`, async route => {
|
|
await new Promise(r => setTimeout(r, 1500));
|
|
await route.continue().catch(() => {});
|
|
});
|
|
const p = page.evaluate(id => openBook(id).then(() => 'done', e => 'error ' + e), bookId);
|
|
await expect(page.locator('.reader-opening-cancel')).toBeVisible({ timeout: 5000 });
|
|
await page.locator('.reader-opening-cancel').click();
|
|
await expect(page.locator('#reader-overlay')).toBeHidden();
|
|
expect(await p).toBe('done');
|
|
await page.unroute(`**/books/${bookId}/data/`);
|
|
// Opening it again works, all the way.
|
|
await page.evaluate(id => openBook(id), bookId);
|
|
await page.waitForFunction(() => _readPos && _readPos.ready, null, { timeout: 20000 });
|
|
await page.evaluate(() => closeReader());
|
|
await page.request.post(`/books/${bookId}/delete/`);
|
|
});
|