// Verifies "Other" asset type gets a sensible suggestion (Hibah) instead of the // previous bug: a nonsensical "EPF / Takaful nomination" suggestion pointing at a // channel value ('nomination') that didn't even exist in the Nomination Registry. const { chromium } = require('playwright'); const { signInFreshFamily } = require('./e2e-auth-helper.cjs'); const BASE = 'https://moslem04.falahos.my/'; const results = []; const consoleErrors = []; function record(name, pass, detail = '') { results.push({ name, pass, detail }); console.log(`${pass ? 'PASS' : 'FAIL'} ${name}${detail ? ' — ' + detail : ''}`); } async function main() { const browser = await chromium.launch(); const page = await browser.newPage({ viewport: { width: 390, height: 844 } }); page.on('console', m => { if (m.type() === 'error') consoleErrors.push(m.text()); }); page.on('pageerror', e => consoleErrors.push(e.message)); await signInFreshFamily(page, BASE, 'e2e-other'); const clickTab = async label => { await page.locator('nav button.tab', { hasText: label }).click(); await page.waitForTimeout(500); }; const selectByText = async (locator, text) => { // Options load async from Supabase now — poll until the matching one shows up. let val; for (let i = 0; i < 20; i++) { val = await locator.evaluate((el, t) => Array.from(el.options).find(o => o.textContent.includes(t))?.value, text); if (val) break; await new Promise(r => setTimeout(r, 300)); } await locator.selectOption(val); }; await clickTab('Assets'); await page.locator('.field:has-text("Description") input').fill('Rare stamp collection'); await page.locator('.field:has-text("Estimated value") input').fill('20000'); await page.locator('.form-card select').first().selectOption('Other'); await page.locator('button.btn-primary', { hasText: 'Add asset' }).click(); await page.waitForTimeout(500); await clickTab('Coverage'); const rowBefore = await page.locator('.asset-row', { hasText: 'stamp collection' }).textContent(); record('Coverage: "Other" asset suggests Hibah, not the old nonsense EPF/Takaful suggestion', rowBefore.includes('Hibah') && !rowBefore.includes('EPF'), rowBefore.trim().slice(0, 200)); await clickTab('Nominate'); await selectByText(page.locator('select').first(), 'stamp collection'); await page.waitForTimeout(500); const suggestionText = await page.locator('.suggestion').textContent(); record('Nomination: suggestion for "Other" points to Hibah with sensible reasoning', suggestionText.includes('Hibah') && suggestionText.includes('safest general'), suggestionText.trim().slice(0, 200)); // Cover it via Hibah (the suggested path) await clickTab('Hibah'); await page.locator('.field:has-text("Recipient") input').fill('My Daughter'); await page.locator('.field:has-text("Relation to you") input').fill('daughter'); await page.locator('.field:has-text("Asset / gift description") input').fill('Stamp collection gift'); await selectByText(page.locator('select').first(), 'stamp collection'); await page.locator('button.btn-primary', { hasText: 'Log this hibah' }).click(); await page.waitForTimeout(500); await page.locator('.guard-buttons button.btn-secondary', { hasText: 'No' }).click(); await page.waitForTimeout(500); await page.locator('button.btn-primary', { hasText: 'Confirm and save' }).click(); await page.waitForTimeout(600); await clickTab('Coverage'); const pct = await page.locator('.big-percent').textContent(); record('Coverage: "Other" asset covered after following the Hibah suggestion', pct.trim() === '100%', pct); record('No uncaught JS console errors', consoleErrors.length === 0, consoleErrors.join(' || ')); await browser.close(); const passCount = results.filter(r => r.pass).length; const failCount = results.length - passCount; console.log(`\n${passCount} passed, ${failCount} failed, ${results.length} total`); if (failCount > 0) results.filter(r => !r.pass).forEach(r => console.log(` - ${r.name}: ${r.detail}`)); process.exit(failCount > 0 ? 1 : 0); } main().catch(e => { console.error('SCRIPT ERROR:', e); process.exit(2); });