/** * Node built-in test runner for pure GenerationReadinessPanel helpers. * Mirrors pure exports in GenerationReadinessPanel.tsx (kept isolated — no React). * Run: node --test src/components/project/GenerationReadinessPanel.node-test.mjs */ import { describe, it } from 'node:test'; import assert from 'node:assert/strict'; const MSP_LABELS = { mikro: 'Mikro', mala: 'Mała', srednia: 'Średnia', duza: 'Duża', unknown: 'Nieustalony', }; function formatMspLabel(status) { const key = String(status || 'unknown').toLowerCase().trim(); return MSP_LABELS[key] || MSP_LABELS.unknown; } function formatEur(value) { if (value === null || value === undefined || Number.isNaN(Number(value))) { return 'brak danych'; } return `${Number(value).toLocaleString('pl-PL', { maximumFractionDigits: 0 })} EUR`; } function shouldShowEligibilitySection(readiness) { if (!readiness) return false; if (readiness.eligibility && typeof readiness.eligibility === 'object') return true; const missing = readiness.missing_fields || []; return missing.some((m) => m.category === 'eligibility'); } function isEligibilitySpineEnforced(readiness) { if (!readiness) return true; const elig = readiness.eligibility; if (readiness.eligibility_spine_enforced === false) return false; if (elig && typeof elig === 'object' && elig.spine_enabled === false) return false; return true; } function isEligibilityBlocking(readiness) { if (!readiness) return true; const elig = readiness.eligibility; if (!elig || typeof elig !== 'object') { return (readiness.missing_fields || []).some((m) => m.category === 'eligibility'); } if (Array.isArray(elig.blockers) && elig.blockers.length > 0) return true; if (!isEligibilitySpineEnforced(readiness)) { return false; } if (elig.ready_for_full_autopilot === true) return false; if (elig.ready_for_full_autopilot === false) return true; const mspStatus = String(elig.msp?.status || 'unknown').toLowerCase().trim(); if (mspStatus === 'unknown' || Boolean(elig.msp?.is_large)) return true; if (Boolean(elig.de_minimis?.exhausted)) return true; if (elig.de_minimis?.used_eur === null || elig.de_minimis?.used_eur === undefined) { return true; } return false; } function eligibilityBannerMessage(readiness) { if (isEligibilityBlocking(readiness)) { return { tone: 'blocked', text: 'Full Autopilot zablokowany do czasu weryfikacji kwalifikowalności (fail-closed). ' + 'Brak wiarygodnego statusu MŚP lub de minimis nie jest traktowany jako „OK”.', }; } if (!isEligibilitySpineEnforced(readiness)) { return { tone: 'info', text: 'Spine kwalifikowalności w trybie informacyjnym (nie egzekwowany) — nie bramkuje Full Autopilot. ' + 'Status MŚP / de minimis poniżej tylko do wglądu.', }; } return { tone: 'ok', text: 'Spine kwalifikowalności OK — MŚP i de minimis nie blokują Full Autopilot.', }; } describe('formatMspLabel', () => { it('maps known statuses', () => { assert.equal(formatMspLabel('mikro'), 'Mikro'); assert.equal(formatMspLabel('duza'), 'Duża'); assert.equal(formatMspLabel('unknown'), 'Nieustalony'); }); it('fails closed on empty', () => { assert.equal(formatMspLabel(null), 'Nieustalony'); assert.equal(formatMspLabel(''), 'Nieustalony'); assert.equal(formatMspLabel('weird'), 'Nieustalony'); }); }); describe('formatEur', () => { it('formats numbers', () => { assert.match(formatEur(45000), /45\s?000/); assert.match(formatEur(0), /0/); }); it('fails closed on null/undefined/NaN', () => { assert.equal(formatEur(null), 'brak danych'); assert.equal(formatEur(undefined), 'brak danych'); assert.equal(formatEur(Number.NaN), 'brak danych'); }); }); describe('shouldShowEligibilitySection', () => { it('false when no readiness', () => { assert.equal(shouldShowEligibilitySection(null), false); assert.equal(shouldShowEligibilitySection({}), false); }); it('true when eligibility report present', () => { assert.equal( shouldShowEligibilitySection({ eligibility: { blockers: [] } }), true, ); }); it('true when missing_fields category eligibility', () => { assert.equal( shouldShowEligibilitySection({ missing_fields: [{ field: 'msp_status', label: 'MŚP', category: 'eligibility' }], }), true, ); }); it('false when only other missing categories', () => { assert.equal( shouldShowEligibilitySection({ missing_fields: [{ field: 'title', label: 'Tytuł', category: 'project' }], }), false, ); }); }); describe('isEligibilityBlocking (fail-closed)', () => { it('blocks when readiness null', () => { assert.equal(isEligibilityBlocking(null), true); }); it('blocks on eligibility missing_fields without report', () => { assert.equal( isEligibilityBlocking({ missing_fields: [{ field: 'nip', label: 'NIP', category: 'eligibility' }], }), true, ); }); it('does not block on unrelated missing fields without report', () => { assert.equal( isEligibilityBlocking({ missing_fields: [{ field: 'title', label: 'Tytuł', category: 'project' }], }), false, ); }); it('blocks on explicit blockers always', () => { assert.equal( isEligibilityBlocking({ eligibility_spine_enforced: false, eligibility: { spine_enabled: false, ready_for_full_autopilot: true, blockers: ['Status duża firma'], msp: { status: 'duza', is_large: true }, de_minimis: { used_eur: 0 }, }, }), true, ); }); it('does not claim FA blocked when spine not enforced (no blockers)', () => { assert.equal( isEligibilityBlocking({ eligibility_spine_enforced: false, eligibility: { spine_enabled: false, ready_for_full_autopilot: false, blockers: [], msp: { status: 'unknown' }, de_minimis: {}, }, }), false, ); }); it('honors ready_for_full_autopilot when enforced', () => { assert.equal( isEligibilityBlocking({ eligibility_spine_enforced: true, eligibility: { ready_for_full_autopilot: true, blockers: [], msp: { status: 'mikro' }, de_minimis: { used_eur: 10_000, exhausted: false }, }, }), false, ); assert.equal( isEligibilityBlocking({ eligibility_spine_enforced: true, eligibility: { ready_for_full_autopilot: false, blockers: [], msp: { status: 'mikro' }, de_minimis: { used_eur: 10_000 }, }, }), true, ); }); it('fail-closed heuristics when ready flag absent', () => { assert.equal( isEligibilityBlocking({ eligibility: { blockers: [], msp: { status: 'unknown' }, de_minimis: { used_eur: 0 }, }, }), true, ); assert.equal( isEligibilityBlocking({ eligibility: { blockers: [], msp: { status: 'mikro', is_large: true }, de_minimis: { used_eur: 0 }, }, }), true, ); assert.equal( isEligibilityBlocking({ eligibility: { blockers: [], msp: { status: 'mikro' }, de_minimis: { used_eur: 300_000, exhausted: true }, }, }), true, ); assert.equal( isEligibilityBlocking({ eligibility: { blockers: [], msp: { status: 'mikro' }, de_minimis: { used_eur: null }, }, }), true, ); }); it('treats used_eur 0 as known (not missing)', () => { assert.equal( isEligibilityBlocking({ eligibility: { blockers: [], msp: { status: 'srednia' }, de_minimis: { used_eur: 0, remaining_eur: 300_000, exhausted: false }, }, }), false, ); }); }); describe('eligibilityBannerMessage', () => { it('blocked tone on blockers', () => { const b = eligibilityBannerMessage({ eligibility: { blockers: ['x'], msp: { status: 'duza' } }, }); assert.equal(b.tone, 'blocked'); assert.match(b.text, /fail-closed/i); }); it('info tone when spine not enforced', () => { const b = eligibilityBannerMessage({ eligibility_spine_enforced: false, eligibility: { spine_enabled: false, blockers: [], msp: { status: 'unknown' }, }, }); assert.equal(b.tone, 'info'); assert.match(b.text, /informacyjnym/i); }); it('ok tone when ready', () => { const b = eligibilityBannerMessage({ eligibility_spine_enforced: true, eligibility: { ready_for_full_autopilot: true, blockers: [], msp: { status: 'mikro' }, de_minimis: { used_eur: 1 }, }, }); assert.equal(b.tone, 'ok'); }); });