275 lines
10 KiB
JavaScript
275 lines
10 KiB
JavaScript
const { test, expect } = require('@playwright/test');
|
|
|
|
const BASE = 'https://eetdagboek.vantwout.dev';
|
|
|
|
/**
|
|
* Helpers for glucose tests — inline per eetmoment
|
|
*/
|
|
|
|
/** Navigate to diary tab and wait for render */
|
|
async function openDiary(page) {
|
|
await page.locator('#navDagboek').click();
|
|
await page.waitForTimeout(600);
|
|
// Wait for nuchter card to render
|
|
await expect(page.locator('.nuchter-card')).toBeVisible({ timeout: 5000 });
|
|
}
|
|
|
|
/** Fill a glucose input and trigger save-on-blur */
|
|
async function setGlucoseValue(page, momentKey, value) {
|
|
const input = page.locator(`input.glucose-input[data-moment="${momentKey}"]`);
|
|
await input.fill(String(value));
|
|
// Trigger blur — saves to localStorage and re-renders just the glucose UI
|
|
await input.evaluate(el => el.blur());
|
|
// Wait for re-render to complete
|
|
await page.waitForTimeout(400);
|
|
}
|
|
|
|
/** Get the parent glucose container for a given moment */
|
|
function glucoseContainer(page, momentKey) {
|
|
if (momentKey === 'nuchter') {
|
|
return page.locator('.nuchter-card');
|
|
}
|
|
return page.locator(`.glucose-inline[data-moment-key="${momentKey}"]`);
|
|
}
|
|
|
|
/** Get status text element for a given moment */
|
|
function statusText(page, momentKey) {
|
|
if (momentKey === 'nuchter') {
|
|
return page.locator('.nuchter-card .glucose-status-text');
|
|
}
|
|
return page.locator(`.glucose-inline[data-moment-key="${momentKey}"] .glucose-status-text`);
|
|
}
|
|
|
|
// =============================================================================
|
|
|
|
test.describe('Glucose-metingen — invoer, validatie, kleurcodering, persistentie', () => {
|
|
|
|
// ---- 1. Glucose-sectie zichtbaar ----
|
|
|
|
test('1. glucose section has 4 input fields with correct labels and target ranges', async ({ page }) => {
|
|
await page.goto(BASE);
|
|
await openDiary(page);
|
|
|
|
// Nuchter card structure
|
|
await expect(page.locator('.nuchter-card')).toBeVisible();
|
|
await expect(page.locator('.nuchter-card-label')).toHaveText('Nuchter (voor ontbijt)');
|
|
await expect(page.locator('.nuchter-card-range')).toHaveText('< 5.4');
|
|
|
|
// Inline glucose in eetmoment cards (Ontbijt, Lunch, Avondeten)
|
|
const moments = [
|
|
{ key: 'naOntbijt', label: 'Ontbijt', range: '5.4\u20136.7' },
|
|
{ key: 'naLunch', label: 'Lunch', range: '5.4\u20136.7' },
|
|
{ key: 'naAvondeten', label: 'Avondeten', range: '5.4\u20136.7' },
|
|
];
|
|
|
|
// 3 inline glucose items should exist
|
|
const inlineItems = page.locator('.glucose-inline');
|
|
await expect(inlineItems).toHaveCount(3);
|
|
|
|
for (let i = 0; i < moments.length; i++) {
|
|
const m = moments[i];
|
|
const container = page.locator(`.glucose-inline[data-moment-key="${m.key}"]`);
|
|
await expect(container.locator('.glucose-inline-label')).toHaveText(m.label);
|
|
await expect(container.locator('.glucose-inline-range')).toHaveText(m.range);
|
|
}
|
|
|
|
// Input attributes — check 4 inputs
|
|
const inputMoments = ['nuchter', 'naOntbijt', 'naLunch', 'naAvondeten'];
|
|
for (const moment of inputMoments) {
|
|
const input = page.locator(`input.glucose-input[data-moment="${moment}"]`);
|
|
await expect(input).toHaveAttribute('step', '0.1');
|
|
await expect(input).toHaveAttribute('min', '0');
|
|
await expect(input).toHaveAttribute('max', '30');
|
|
await expect(input).toHaveAttribute('inputmode', 'decimal');
|
|
await expect(input).toHaveAttribute('placeholder', '\u2014');
|
|
}
|
|
});
|
|
|
|
// ---- 2. Nuchter binnen range (groen) ----
|
|
|
|
test('2. nuchter waarde 5.1 (binnen < 5.4) toont groene indicator', async ({ page }) => {
|
|
await page.goto(BASE);
|
|
await openDiary(page);
|
|
|
|
await setGlucoseValue(page, 'nuchter', 5.1);
|
|
|
|
const container = glucoseContainer(page, 'nuchter');
|
|
await expect(container).toHaveClass(/glucose-good/);
|
|
await expect(container.locator('.glucose-status-icon')).toContainText('\u2705'); // ✅
|
|
await expect(container.locator('.glucose-status-text')).toHaveText('Binnen range');
|
|
});
|
|
|
|
// ---- 3. Nuchter ≥ 5.4 (rood) ----
|
|
|
|
test('3. nuchter waarde 5.4 (te hoog, ≥ 5.4) toont rode indicator', async ({ page }) => {
|
|
await page.goto(BASE);
|
|
await openDiary(page);
|
|
|
|
await setGlucoseValue(page, 'nuchter', 5.4);
|
|
|
|
const container = glucoseContainer(page, 'nuchter');
|
|
await expect(container).toHaveClass(/glucose-bad/);
|
|
await expect(container.locator('.glucose-status-text')).toHaveText('Te hoog');
|
|
});
|
|
|
|
// ---- 4. Postprandiaal < 5.4 (rood/te laag) ----
|
|
|
|
test('4. naOntbijt waarde 5.3 (te laag, < 5.4) toont rode indicator', async ({ page }) => {
|
|
await page.goto(BASE);
|
|
await openDiary(page);
|
|
|
|
await setGlucoseValue(page, 'naOntbijt', 5.3);
|
|
|
|
const container = glucoseContainer(page, 'naOntbijt');
|
|
await expect(container).toHaveClass(/glucose-bad/);
|
|
await expect(container.locator('.glucose-status-text')).toHaveText('Te laag');
|
|
});
|
|
|
|
// ---- 5. Postprandiaal binnen range (groen) ----
|
|
|
|
test('5. naOntbijt waarde 6.0 (binnen 5.4\u20136.7) toont groene indicator', async ({ page }) => {
|
|
await page.goto(BASE);
|
|
await openDiary(page);
|
|
|
|
await setGlucoseValue(page, 'naOntbijt', 6.0);
|
|
|
|
const container = glucoseContainer(page, 'naOntbijt');
|
|
await expect(container).toHaveClass(/glucose-good/);
|
|
await expect(container.locator('.glucose-status-text')).toHaveText('Binnen range');
|
|
});
|
|
|
|
// ---- 6. Postprandiaal > 6.7 (rood/te hoog) ----
|
|
|
|
test('6. naLunch waarde 6.8 (te hoog, > 6.7) toont rode indicator', async ({ page }) => {
|
|
await page.goto(BASE);
|
|
await openDiary(page);
|
|
|
|
await setGlucoseValue(page, 'naLunch', 6.8);
|
|
|
|
const container = glucoseContainer(page, 'naLunch');
|
|
await expect(container).toHaveClass(/glucose-bad/);
|
|
await expect(container.locator('.glucose-status-text')).toHaveText('Te hoog');
|
|
});
|
|
|
|
// ---- 7. Leeg veld — grijze 'nog meten' indicator ----
|
|
|
|
test('7. lege velden tonen grijze nog-meten indicator', async ({ page }) => {
|
|
await page.goto(BASE);
|
|
await openDiary(page);
|
|
|
|
// Nuchter card should start empty
|
|
const nuchter = glucoseContainer(page, 'nuchter');
|
|
await expect(nuchter).toHaveClass(/glucose-empty/);
|
|
await expect(nuchter.locator('.glucose-status-text')).toHaveText('Nog meten');
|
|
await expect(nuchter.locator('.glucose-status-icon')).toContainText('\u23F9');
|
|
|
|
// Inline items should start empty
|
|
const inlineMoments = ['naOntbijt', 'naLunch', 'naAvondeten'];
|
|
for (const moment of inlineMoments) {
|
|
const container = glucoseContainer(page, moment);
|
|
await expect(container).toHaveClass(/glucose-empty/);
|
|
await expect(container.locator('.glucose-status-text')).toHaveText('Nog meten');
|
|
}
|
|
|
|
// All inputs should have empty value
|
|
const inputs = page.locator('.glucose-input');
|
|
const inputCount = await inputs.count();
|
|
expect(inputCount).toBe(4);
|
|
for (let i = 0; i < inputCount; i++) {
|
|
await expect(inputs.nth(i)).toHaveValue('');
|
|
}
|
|
});
|
|
|
|
// ---- 8. Persistentie — waarde blijft na page reload ----
|
|
|
|
test('8. persistentie: waarde blijft na page reload bewaard', async ({ page }) => {
|
|
await page.goto(BASE);
|
|
await openDiary(page);
|
|
|
|
// Set a nuchter value
|
|
await setGlucoseValue(page, 'nuchter', 5.1);
|
|
|
|
// Verify it's shown correctly
|
|
let container = glucoseContainer(page, 'nuchter');
|
|
await expect(container).toHaveClass(/glucose-good/);
|
|
await expect(container.locator('.glucose-status-text')).toHaveText('Binnen range');
|
|
await expect(container.locator('.glucose-input')).toHaveValue('5.1');
|
|
|
|
// Reload the page
|
|
await page.goto(BASE);
|
|
await openDiary(page);
|
|
|
|
// Value should still be there
|
|
container = glucoseContainer(page, 'nuchter');
|
|
await expect(container).toHaveClass(/glucose-good/);
|
|
await expect(container.locator('.glucose-status-text')).toHaveText('Binnen range');
|
|
await expect(container.locator('.glucose-input')).toHaveValue('5.1');
|
|
});
|
|
|
|
// ---- 9. Datum-navigatie — andere datum andere waarden ----
|
|
|
|
test('9. datum-navigatie: andere datum toont lege glucose waarden', async ({ page }) => {
|
|
await page.goto(BASE);
|
|
await openDiary(page);
|
|
|
|
// Set a nuchter value for today
|
|
await setGlucoseValue(page, 'nuchter', 5.1);
|
|
|
|
// Verify today shows the value
|
|
let container = glucoseContainer(page, 'nuchter');
|
|
await expect(container).toHaveClass(/glucose-good/);
|
|
|
|
// Navigate to tomorrow
|
|
await page.locator('#dayNext').click();
|
|
await page.waitForTimeout(600);
|
|
|
|
// Tomorrow should have all empty glucose fields
|
|
container = glucoseContainer(page, 'nuchter');
|
|
await expect(container).toHaveClass(/glucose-empty/);
|
|
await expect(container.locator('.glucose-status-text')).toHaveText('Nog meten');
|
|
await expect(container.locator('.glucose-input')).toHaveValue('');
|
|
|
|
// Also check the other moments are empty too
|
|
for (const moment of ['naOntbijt', 'naLunch', 'naAvondeten']) {
|
|
const otherContainer = glucoseContainer(page, moment);
|
|
await expect(otherContainer).toHaveClass(/glucose-empty/);
|
|
}
|
|
|
|
// Navigate back to today
|
|
await page.locator('#dayToday').click();
|
|
await page.waitForTimeout(600);
|
|
|
|
// Today's value should still be there
|
|
container = glucoseContainer(page, 'nuchter');
|
|
await expect(container).toHaveClass(/glucose-good/);
|
|
await expect(container.locator('.glucose-status-text')).toHaveText('Binnen range');
|
|
await expect(container.locator('.glucose-input')).toHaveValue('5.1');
|
|
});
|
|
|
|
// ---- 10. Decimale invoer — step 0.1 ----
|
|
|
|
test('10. decimale invoer: step 0.1 accepteert 5.5 en 6.2 correct', async ({ page }) => {
|
|
await page.goto(BASE);
|
|
await openDiary(page);
|
|
|
|
// Check step attribute
|
|
const input = page.locator('input.glucose-input[data-moment="nuchter"]');
|
|
await expect(input).toHaveAttribute('step', '0.1');
|
|
|
|
// Enter 5.5 (decimal)
|
|
await setGlucoseValue(page, 'nuchter', 5.5);
|
|
let container = glucoseContainer(page, 'nuchter');
|
|
await expect(container.locator('.glucose-input')).toHaveValue('5.5');
|
|
// 5.5 ≥ 5.4 for nuchter → should be bad/Te hoog
|
|
await expect(container).toHaveClass(/glucose-bad/);
|
|
await expect(container.locator('.glucose-status-text')).toHaveText('Te hoog');
|
|
|
|
// Now test a postprandial decimal value
|
|
await setGlucoseValue(page, 'naOntbijt', 6.2);
|
|
container = glucoseContainer(page, 'naOntbijt');
|
|
await expect(container.locator('.glucose-input')).toHaveValue('6.2');
|
|
await expect(container).toHaveClass(/glucose-good/);
|
|
await expect(container.locator('.glucose-status-text')).toHaveText('Binnen range');
|
|
});
|
|
|
|
});
|