test: regressie eetmoment-labels — zes labels zichtbaar, niet transparant/afgeknipt (t_a1d49160)
This commit is contained in:
parent
85ef8ba2de
commit
fbfe7e5121
1 changed files with 123 additions and 0 deletions
123
tests/eetmoment-labels.spec.js
Normal file
123
tests/eetmoment-labels.spec.js
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
const { test, expect } = require('@playwright/test');
|
||||
|
||||
/**
|
||||
* Regressietest: eetmoment-labels (icon + naam) zichtbaar in dagboek.
|
||||
*
|
||||
* Achtergrond (kaart t_a1d49160): "Eetmoment-labels niet zichtbaar in dagboek —
|
||||
* icon+naam tekst valt weg". Niet reproduceerbaar tegen lokale app noch live;
|
||||
* template/CSS zijn sinds de initiële commit correct. Deze test borgt dat alle
|
||||
* zes eetmomentkaarten hun icon + naam tonen, niet transparant en niet
|
||||
* afgeknipt — voor lege én gevulde kaarten, op mobiel én desktop.
|
||||
*
|
||||
* Determinisme: de dagboek-data wordt per scenario geseed via localStorage
|
||||
* (addInitScript) en er wordt gewacht tot de fadeIn-stagger-animatie klaar is
|
||||
* (opacity === 1) voordat er geassert wordt. Computed styles, geen screenshots.
|
||||
*/
|
||||
|
||||
const MOMENTS = [
|
||||
{ id: 'Ontbijt', name: 'Ontbijt', icon: '🥐' },
|
||||
{ id: 'Tussendoor 1', name: 'Tussendoor 1', icon: '☕' },
|
||||
{ id: 'Lunch', name: 'Lunch', icon: '🥪' },
|
||||
{ id: 'Tussendoor 2', name: 'Tussendoor 2', icon: '🍎' },
|
||||
{ id: 'Avondeten', name: 'Avondeten', icon: '🍲' },
|
||||
{ id: 'Tussendoor 3', name: 'Tussendoor 3', icon: '🍪' },
|
||||
];
|
||||
|
||||
function todayStr() {
|
||||
const d = new Date();
|
||||
const p = (n) => String(n).padStart(2, '0');
|
||||
return `${d.getFullYear()}-${p(d.getMonth() + 1)}-${p(d.getDate())}`;
|
||||
}
|
||||
|
||||
function buildDiaryJson(filled) {
|
||||
const day = {};
|
||||
for (const m of MOMENTS) {
|
||||
day[m.id] = filled
|
||||
? [{ item: { naam: 'Volkoren brood', kh: '50.0', n: '1' }, portie: 30 }]
|
||||
: [];
|
||||
}
|
||||
return JSON.stringify({ [todayStr()]: day });
|
||||
}
|
||||
|
||||
/** Seed dagboek-data in een verse context en open het dagboek-tabblad. */
|
||||
async function openDiary(page, filled) {
|
||||
await page.addInitScript((json) => {
|
||||
localStorage.setItem('koolhydraat-dagboek', json);
|
||||
}, buildDiaryJson(filled));
|
||||
await page.goto('/');
|
||||
await page.locator('#navDagboek').click();
|
||||
|
||||
// Wacht tot alle 6 kaarten gerenderd zijn én de fadeIn-stagger (0.35s +
|
||||
// maximaal 5 * 50ms delay) volledig is afgelopen — anders is opacity nog 0.
|
||||
await expect(page.locator('.eetmoment-card')).toHaveCount(6, { timeout: 5000 });
|
||||
await expect
|
||||
.poll(() =>
|
||||
page.locator('.eetmoment-card').last().evaluate((el) => getComputedStyle(el).opacity)
|
||||
, { timeout: 5000 })
|
||||
.toBe('1');
|
||||
}
|
||||
|
||||
/** Assert per kaart: icon+naam aanwezig, zichtbaar, niet transparant, niet afgeknipt. */
|
||||
async function expectAllLabelsVisible(page) {
|
||||
const cards = page.locator('.eetmoment-card');
|
||||
expect(await cards.count()).toBe(6);
|
||||
|
||||
for (let i = 0; i < MOMENTS.length; i++) {
|
||||
const m = MOMENTS[i];
|
||||
const card = cards.nth(i);
|
||||
const header = card.locator('.eetmoment-header');
|
||||
const icon = card.locator('.eetmoment-icon');
|
||||
const name = card.locator('.eetmoment-name');
|
||||
|
||||
// Template: juiste moment-id, icon en naam aanwezig
|
||||
await expect(header).toHaveAttribute('data-moment', m.id);
|
||||
await expect(icon).toHaveText(m.icon, { timeout: 3000 });
|
||||
await expect(name).toHaveText(m.name, { timeout: 3000 });
|
||||
|
||||
// Computed style: zichtbaar + niet transparant + niet afgeknipt
|
||||
for (const el of [icon, name]) {
|
||||
const cs = await el.evaluate((node) => {
|
||||
const style = getComputedStyle(node);
|
||||
const r = node.getBoundingClientRect();
|
||||
const cardR = node.closest('.eetmoment-card').getBoundingClientRect();
|
||||
const alpha = (style.color.match(/rgba?\(([^)]+)\)/) || [])[1];
|
||||
const a = alpha ? parseFloat(alpha.split(',')[3] ?? '1') : 1;
|
||||
return {
|
||||
display: style.display,
|
||||
visibility: style.visibility,
|
||||
opacity: parseFloat(style.opacity),
|
||||
colorAlpha: Number.isNaN(a) ? 1 : a,
|
||||
w: r.width,
|
||||
h: r.height,
|
||||
insideCard: r.bottom <= cardR.bottom + 1 && r.top >= cardR.top - 1,
|
||||
};
|
||||
});
|
||||
|
||||
expect(cs.display, `${m.id}: ${el === icon ? 'icon' : 'naam'} display`).not.toBe('none');
|
||||
expect(cs.visibility, `${m.id}: ${el === icon ? 'icon' : 'naam'} visibility`).toBe('visible');
|
||||
expect(cs.opacity, `${m.id}: ${el === icon ? 'icon' : 'naam'} opacity`).toBeGreaterThan(0.99);
|
||||
expect(cs.colorAlpha, `${m.id}: ${el === icon ? 'icon' : 'naam'} transparant`).toBeGreaterThan(0);
|
||||
expect(cs.w, `${m.id}: ${el === icon ? 'icon' : 'naam'} breedte 0`).toBeGreaterThan(0);
|
||||
expect(cs.h, `${m.id}: ${el === icon ? 'icon' : 'naam'} hoogte 0`).toBeGreaterThan(0);
|
||||
expect(cs.insideCard, `${m.id}: ${el === icon ? 'icon' : 'naam'} afgeknipt`).toBe(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
test.describe('Eetmoment-labels — icon+naam zichtbaar (regressie t_a1d49160)', () => {
|
||||
for (const filled of [false, true]) {
|
||||
const label = filled ? 'gevuld' : 'leeg';
|
||||
test(`${label}: alle zes labels zichtbaar, niet transparant/afgeknipt (mobiel)`, async ({ page }) => {
|
||||
await openDiary(page, filled);
|
||||
await expectAllLabelsVisible(page);
|
||||
});
|
||||
|
||||
test.describe(`desktop viewport (${label})`, () => {
|
||||
test.use({ viewport: { width: 1280, height: 800 } });
|
||||
test('alle zes labels zichtbaar, niet transparant/afgeknipt', async ({ page }) => {
|
||||
await openDiary(page, filled);
|
||||
await expectAllLabelsVisible(page);
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
Loading…
Add table
Reference in a new issue