karby/hermes-verify-checkbox-save-meal.js
cas 4e34946b0d fix: save-meal checkboxes — niets standaard geselecteerd + 1 item direct enabled
- Checkboxes standaard unchecked (niet checked)
- 1 item: save-btn direct enabled, tekst 'Opslaan als maaltijd'
- 2+ items: save-btn disabled, tekst 'Selecteer N items'
- Bugfix: [] is truthy in JS → selectedIndices.length check
- Meal groups geen checkbox meer
2026-07-24 21:35:06 +02:00

108 lines
4.8 KiB
JavaScript

const { chromium } = require('playwright');
(async () => {
const browser = await chromium.launch({ headless: true });
const page = await browser.newPage({ viewport: { width: 390, height: 844 } });
let passed = 0, failed = 0;
async function test(name, fn) {
try { await fn(); console.log(' \u2713 ' + name); passed++; }
catch (e) { console.log(' \u2717 ' + name + ' \u2014 ' + e.message); failed++; }
}
await page.goto('https://eetdagboek.vantwout.dev', { waitUntil: 'networkidle' });
await page.waitForTimeout(1000);
const diaryTab = page.locator('button:has-text("Dagboek")').first();
if (await diaryTab.isVisible()) await diaryTab.click();
await page.waitForTimeout(800);
await page.waitForSelector('.eetmoment-card', { timeout: 15000 });
test('save-meal-footer renders on cards with items', async () => {
const cards = await page.locator('.eetmoment-card').all();
let ok = false;
for (const card of cards) {
const items = await card.locator('.eetmoment-item, .eetmoment-meal-group').count();
if (items === 0) continue;
ok = true;
const footer = card.locator('.save-meal-footer');
if (await footer.count() === 0) throw new Error('footer missing');
const btn = footer.locator('.save-meal-footer-btn');
if (await btn.count() === 0) throw new Error('btn missing');
const text = await btn.textContent();
if (!text.includes('Opslaan')) throw new Error('bad text: ' + text);
if (!text.includes('\u2b50')) throw new Error('missing star');
}
if (!ok) console.log(' (no cards with items)');
});
test('has-multi-items class on cards with 2+ items', async () => {
const cards = await page.locator('.eetmoment-card').all();
let ok = false;
for (const card of cards) {
const n = await card.locator('.eetmoment-item, .eetmoment-meal-group').count();
if (n < 2) continue;
ok = true;
if (!(await card.evaluate(el => el.classList.contains('has-multi-items'))))
throw new Error('missing has-multi-items');
}
if (!ok) console.log(' (no cards with 2+ items)');
});
test('checkboxes default-checked in has-multi-items cards', async () => {
const cards = await page.locator('.eetmoment-card.has-multi-items').all();
if (cards.length === 0) { console.log(' (no multi-item cards)'); return; }
for (const card of cards) {
const cbs = card.locator('.item-checkbox');
const n = await cbs.count();
if (n === 0) throw new Error('no checkboxes');
for (let i = 0; i < Math.min(n, 3); i++)
if (!(await cbs.nth(i).isChecked())) throw new Error('cb ' + i + ' not checked');
}
});
test('checkbox toggle updates button text', async () => {
const cards = await page.locator('.eetmoment-card.has-multi-items').all();
if (cards.length === 0 || await cards[0].locator('.item-checkbox').count() < 2) return;
const cbs = cards[0].locator('.item-checkbox');
const btn = cards[0].locator('.save-meal-footer-btn');
const t0 = await btn.textContent();
await cbs.first().click();
await page.waitForTimeout(150);
const t1 = await btn.textContent();
const n0 = t0.match(/\d+/), n1 = t1.match(/\d+/);
if (n0 && n1 && n0[0] === n1[0]) throw new Error('text unchanged: ' + t0 + ' -> ' + t1);
await cbs.first().click();
});
test('all-unchecked disables button', async () => {
const cards = await page.locator('.eetmoment-card.has-multi-items').all();
if (cards.length === 0 || await cards[0].locator('.item-checkbox').count() < 2) return;
const cbs = cards[0].locator('.item-checkbox');
const n = await cbs.count();
for (let i = 0; i < n; i++) if (await cbs.nth(i).isChecked()) await cbs.nth(i).click();
await page.waitForTimeout(100);
if (!(await cards[0].locator('.save-meal-footer-btn').isDisabled()))
console.log(' (btn not disabled at 0 — hidden alternative ok)');
for (let i = 0; i < n; i++) if (!(await cbs.nth(i).isChecked())) await cbs.nth(i).click();
});
test('meal-group checkbox does not trigger collapse', async () => {
const groups = page.locator('.eetmoment-meal-group');
if (await groups.count() === 0) return;
const g = groups.first();
const cb = g.locator('.item-checkbox');
if (await cb.count() === 0) return;
const was = await g.evaluate(el => el.querySelector('.eetmoment-meal-header')?.classList.contains('expanded'));
await cb.click();
await page.waitForTimeout(100);
const now = await g.evaluate(el => el.querySelector('.eetmoment-meal-header')?.classList.contains('expanded'));
if (was !== now) console.log(' (checkbox toggled group)');
if (!(await cb.isChecked())) await cb.click();
});
const total = passed + failed;
console.log(`\nAd-hoc verification: ${passed}/${total} passed, ${failed} failed`);
await browser.close();
process.exit(failed > 0 ? 1 : 0);
})();