// Verifies land parcels specifically get covered via a trust setup in 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-trust'); const clickTab = async label => { await page.locator('nav button.tab', { hasText: label }).click(); await page.waitForTimeout(500); }; // Add a Property-type asset (land parcel) await clickTab('Assets'); await page.locator('.field:has-text("Description") input').fill('Land Parcel, Perak'); await page.locator('.field:has-text("Estimated value") input').fill('500000'); // type defaults to Property await page.locator('button.btn-primary', { hasText: 'Add asset' }).click(); await page.waitForTimeout(500); // Coverage should show this asset as exposed initially, with a trust suggestion await clickTab('Coverage'); const rowText = await page.locator('.asset-row', { hasText: 'Land Parcel' }).textContent(); record('Coverage: land parcel initially shown exposed with trust suggestion', rowText.includes('Not covered') && /trust/i.test(rowText), rowText.trim().slice(0, 200)); // Go to Nomination Registry, select trust channel await clickTab('Nominate'); const assetSelect = page.locator('select').first(); const targetValue = await assetSelect.evaluate(el => { const opt = Array.from(el.options).find(o => o.textContent.includes('Land Parcel')); return opt ? opt.value : null; }); await assetSelect.selectOption(targetValue); await page.waitForTimeout(500); const suggestionVisible = await page.locator('.suggestion').isVisible(); record('Nomination: trust suggestion shown for property-type asset', suggestionVisible); const typeSelect = page.locator('.form-card select').nth(1); await typeSelect.selectOption('trust'); await page.waitForTimeout(500); const trustFieldsVisible = await page.locator('.trust-fields').isVisible(); record('Nomination: trust-specific fields (trustee/successor/beneficiaries) appear', trustFieldsVisible); const trustInputs = page.locator('.trust-fields .field input'); await trustInputs.nth(0).fill('Ahmad bin Ismail'); await trustInputs.nth(1).fill('Faridah binti Omar'); await trustInputs.nth(2).fill('Equal split among 3 children'); await page.locator('button.btn-primary', { hasText: 'Add trust setup' }).click(); await page.waitForTimeout(600); const trustRowVisible = await page.locator('.nomination-row', { hasText: 'Land Parcel' }).isVisible(); record('Nomination: trust setup row created for land parcel', trustRowVisible); const exportBtnVisible = await page.locator('.nomination-row', { hasText: 'Land Parcel' }).locator('.export-btn').isVisible(); record('Nomination: trust deed export button present', exportBtnVisible); const [download] = await Promise.all([ page.waitForEvent('download'), page.locator('.nomination-row', { hasText: 'Land Parcel' }).locator('.export-btn').click() ]); record('Nomination: trust deed downloads correctly', download.suggestedFilename() === 'trust-setup-draft.txt', download.suggestedFilename()); // Coverage should now show land parcel as fast/covered await clickTab('Coverage'); const pct = await page.locator('.big-percent').textContent(); record('Coverage: land parcel now covered (100%)', pct.trim() === '100%', pct); const rowAfter = await page.locator('.asset-row', { hasText: 'Land Parcel' }).textContent(); record('Coverage: land parcel row shows trust channel, no longer "Not covered"', !rowAfter.includes('Not covered') && /trust/i.test(rowAfter), rowAfter.trim().slice(0, 200)); const statusDotOn = await page.locator('.asset-row', { hasText: 'Land Parcel' }).locator('.status-dot').evaluate(el => el.classList.contains('on')); record('Coverage: land parcel status dot is green (on)', statusDotOn); // Death Trigger should generate a packet for the land parcel via trust channel await clickTab('Trigger'); const inputs = page.locator('.attestor-row input'); await inputs.nth(0).fill('Executor A'); await page.locator('.attestor-row .confirm-btn').nth(0).click(); await inputs.nth(1).fill('Witness B'); await page.locator('.attestor-row .confirm-btn').nth(1).click(); await page.locator('.field:has-text("Date of death") input').fill('2026-08-13'); await page.locator('.field:has-text("Death certificate reference") input').fill('DC-TEST-001'); await page.waitForTimeout(500); await page.locator('button.btn-danger-solid').click(); await page.waitForTimeout(600); const packetForLand = await page.locator('.packet-row', { hasText: 'Land Parcel' }).isVisible(); record('Death Trigger: execution packet generated for land parcel via trust', packetForLand); const [pdl] = await Promise.all([ page.waitForEvent('download'), page.locator('.packet-row', { hasText: 'Land Parcel' }).locator('.btn-small').click() ]); record('Death Trigger: land parcel packet download works', pdl.suggestedFilename().includes('execution-packet'), pdl.suggestedFilename()); 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); });