- NEVO dataset (2328 voedingsmiddelen) met zoekfunctie - Dagboek met eetmomenten, koolhydratenlimiet en progress bar - Maaltijden opslaan + nesten in dagboek + eenmalig/permanent bewerken - Portie-systeem met steppers per NEVO-categorie - Vorteq amber/goud branding met Karby logo - Voedingscentrum links per product - 8 Playwright e2e tests (100% groen) - PWA met offline support Kanban board: koolhydraat-app
86 lines
3.4 KiB
JavaScript
86 lines
3.4 KiB
JavaScript
const { test, expect } = require('@playwright/test');
|
|
|
|
const BASE = 'https://eetdagboek.vantwout.dev';
|
|
|
|
test.describe('Karby Eetdagboek', () => {
|
|
|
|
test('page loads with correct title and elements', async ({ page }) => {
|
|
await page.goto(BASE);
|
|
await expect(page).toHaveTitle('Karby');
|
|
await expect(page.locator('.search-input')).toBeVisible();
|
|
await expect(page.locator('.cat-btn').first()).toBeVisible();
|
|
await expect(page.locator('#navZoeken')).toBeVisible();
|
|
await expect(page.locator('#navDagboek')).toBeVisible();
|
|
await expect(page.locator('#navMaaltijden')).toBeVisible();
|
|
});
|
|
|
|
test('search returns results and opens detail modal', async ({ page }) => {
|
|
await page.goto(BASE);
|
|
await page.locator('.search-input').fill('aardappel');
|
|
await page.waitForTimeout(800);
|
|
const results = page.locator('.food-item');
|
|
await expect(results.first()).toBeVisible({ timeout: 5000 });
|
|
await results.first().click();
|
|
await expect(page.locator('#detailModal')).not.toHaveClass(/hidden/, { timeout: 5000 });
|
|
await page.locator('#detailModal .modal-close').click();
|
|
await expect(page.locator('#detailModal')).toHaveClass(/hidden/, { timeout: 3000 });
|
|
});
|
|
|
|
test('category filters work', async ({ page }) => {
|
|
await page.goto(BASE);
|
|
await page.locator('.cat-btn').filter({ hasText: 'Brood' }).click();
|
|
await page.waitForTimeout(500);
|
|
const activeBtn = page.locator('.cat-btn.active');
|
|
await expect(activeBtn).toBeVisible();
|
|
});
|
|
|
|
test('add item to diary via eetmoment flow', async ({ page }) => {
|
|
await page.goto(BASE);
|
|
await page.locator('.search-input').fill('brood');
|
|
await page.waitForTimeout(800);
|
|
await page.locator('.food-item').first().click();
|
|
await page.waitForTimeout(500);
|
|
// Detail modal with Add button
|
|
await expect(page.locator('#detailAddBtn')).toBeVisible({ timeout: 3000 });
|
|
});
|
|
|
|
test('diary tab shows date navigation', async ({ page }) => {
|
|
await page.goto(BASE);
|
|
await page.locator('#navDagboek').click();
|
|
await page.waitForTimeout(500);
|
|
await expect(page.locator('.day-navigator')).toBeVisible({ timeout: 3000 });
|
|
await expect(page.locator('.day-nav-btn').first()).toBeVisible();
|
|
await expect(page.locator('.day-nav-today')).toBeVisible();
|
|
});
|
|
|
|
test('settings modal opens', async ({ page }) => {
|
|
await page.goto(BASE);
|
|
// Click settings gear icon
|
|
await page.locator('#settingsBtn').click();
|
|
await page.waitForTimeout(500);
|
|
await expect(page.locator('#settingsModal')).not.toHaveClass(/hidden/, { timeout: 3000 });
|
|
// Close
|
|
await page.locator('#settingsModal .modal-close').click();
|
|
await expect(page.locator('#settingsModal')).toHaveClass(/hidden/, { timeout: 2000 });
|
|
});
|
|
|
|
test('maaltijden tab shows saved meals section', async ({ page }) => {
|
|
await page.goto(BASE);
|
|
await page.locator('#navMaaltijden').click();
|
|
await page.waitForTimeout(500);
|
|
await expect(page.locator('#tabMaaltijden')).toBeVisible();
|
|
});
|
|
|
|
test('contrast: key elements have visible colors', async ({ page }) => {
|
|
await page.goto(BASE);
|
|
// Nav buttons should have visible text color (not transparent)
|
|
const navBtns = page.locator('.nav-btn');
|
|
const count = await navBtns.count();
|
|
expect(count).toBeGreaterThan(0);
|
|
for (let i = 0; i < count; i++) {
|
|
const color = await navBtns.nth(i).evaluate(el => getComputedStyle(el).color);
|
|
expect(color).not.toBe('rgba(0, 0, 0, 0)');
|
|
}
|
|
});
|
|
|
|
});
|