Files
MindSift/e2e/screenshots.mjs
T
sandrodachandClaude Opus 5.5 4e39b367bd
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 1m30s
release: v0.2 – collaboration docs, richer demo data, new screenshots
- Turn the collaboration plan into module docs (Doku/modules/collaboration.md)
  describing the implemented state; remove Doku/plans
- Header version comes from the build: git tag via APP_VERSION (CI passes
  it for tag builds), otherwise "<package version>-dev"; package 0.2.0
- Sample data (setup option and demo mode): six inbox thoughts, two task
  lists with Kanban states, subtasks and due dates, shopping and packing
  lists, three notes in folders incl. a long nested outline; demo mode
  shares the note and two lists with user/user
- e2e/screenshots.sh renews the README screenshots from demo data
- README: live collaboration, editor sharing, image tags, version badge

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 15:32:31 +01:00

85 lines
3.5 KiB
JavaScript

// Takes the README screenshots from a fresh server in demo mode (sample data of admin/admin).
// Usage: e2e/screenshots.sh (builds the image) or MINDSIFT_URL=… SHOTS_DIR=… node screenshots.mjs
import { chromium } from 'playwright';
const BASE = process.env.MINDSIFT_URL || 'http://localhost:18080';
const OUT = process.env.SHOTS_DIR || '../screenshots';
const DESKTOP = { viewport: { width: 1518, height: 886 }, deviceScaleFactor: 2 };
const MOBILE = { viewport: { width: 390, height: 844 }, deviceScaleFactor: 2, isMobile: true, hasTouch: true };
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
async function login(user) {
const res = await fetch(`${BASE}/api/v1/auth/login`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ login: user, password: user }),
});
if (!res.ok) throw new Error(`login ${user}: ${res.status}`);
return (await res.json()).token;
}
async function open(browser, token, options) {
const ctx = await browser.newContext({ ...options, colorScheme: 'dark', locale: 'de-DE' });
await ctx.addInitScript((t) => localStorage.setItem('mindsift_jwt_token', t), token);
const page = await ctx.newPage();
page.on('pageerror', (e) => console.log('PAGEERROR', e.message));
await page.goto(BASE);
await page.waitForLoadState('networkidle');
return page;
}
const tab = (page, name) => page.getByRole('button', { name: new RegExp(name) }).first().click();
async function shot(page, file) {
await sleep(800); // animations
await page.mouse.move(0, 0);
await page.screenshot({ path: `${OUT}/${file}` });
console.log(`OK ${file}`);
}
const main = async () => {
const admin = await login('admin');
const user = await login('user');
const browser = await chromium.launch({ args: ['--lang=de-DE'] });
const page = await open(browser, admin, DESKTOP);
await tab(page, 'Triage');
await shot(page, 'Triage_desktop.png');
await tab(page, 'Aufgaben');
await page.getByText('Homelab', { exact: true }).first().click().catch(() => {});
await page.getByRole('button', { name: /Kanban|Board/ }).first().click().catch(() => {});
await shot(page, 'aufgaben_desktop.png');
// The demo user edits a bullet of the shared note, so the screenshot shows lock and presence
const other = await open(browser, user, DESKTOP);
await tab(other, 'Workspace');
await other.getByText(/^Homelab 2\.0/).first().click();
await other.waitForFunction(() => document.querySelectorAll('textarea').length > 5, null, { timeout: 10000 });
await other.getByText('Endlich Platz für die Dienste', { exact: false }).first().click();
await other.keyboard.press('End');
await other.keyboard.type(': Paperless und Immich', { delay: 20 });
await tab(page, 'Workspace');
await page.getByText(/^Homelab 2\.0/).first().click();
await page.waitForFunction(() => document.querySelectorAll('textarea').length > 5, null, { timeout: 10000 });
await page.getByText('User', { exact: false }).first().waitFor({ timeout: 15000 }).catch(() => {});
await sleep(2000);
await shot(page, 'workspace_desktop.png');
await tab(page, 'Listen');
await page.getByText('Wocheneinkauf', { exact: true }).first().click().catch(() => {});
await shot(page, 'Listen_desktop.png');
const mobile = await open(browser, admin, MOBILE);
await mobile.getByText('Später im Browser weiter nutzen').click({ timeout: 5000 }).catch(() => {}); // install prompt
await shot(mobile, 'Mobile_Triage.png');
await browser.close();
};
main().catch((e) => {
console.error(e);
process.exit(1);
});