import { readFileSync } from 'node:fs' import { describe, expect, it } from 'vitest' const source = readFileSync( new URL('./BillingApp.vue', import.meta.url), 'utf8', ) describe('Billing app Sky UI migration', () => { it('uses Sky UI instead of Konsta components', () => { expect(source).not.toContain("from 'konsta/vue'") expect(source).not.toMatch(/<\/?k[A-Z-]/) expect(source).not.toContain('--k-') for (const component of [ 'SkyAppPage', 'SkyNavbar', 'SkyNavbarBackLink', 'SkyGlass', 'SkyCard', 'SkyBadge', 'SkyButton', 'SkyLink', 'SkySearchbar', 'SkySegmented', 'SkySegmentedButton', 'SkySpinner', 'SkyTabBar', 'SkyTabButton', 'SkySheet', 'SkyNotification', ]) { expect(source).toContain(`<${component}`) } }) it('uses the Sky sheet focus and escape behavior for payment', () => { expect(source).toContain('@escape="paymentOpen = false"') expect(source).toContain(':ariaLabelledby=') }) it('shows the Billing icon and localized name as one navbar brand', () => { expect(source).toContain('') expect(source).toContain('') expect(source).toContain("{{ t('name') }}") }) it('blends every navbar into dark and light page backgrounds', () => { expect(source).toMatch( /\.billing-navbar::after\s*\{[^}]*bottom:\s*-18px;[^}]*height:\s*18px;[^}]*linear-gradient\(to bottom, rgb\(7 9 12 \/ 88%\), transparent\);/s, ) expect(source).toMatch( /\.billing-app--light \.billing-navbar::after\s*\{[^}]*linear-gradient\(to bottom, rgb\(245 247 250 \/ 88%\), transparent\);/s, ) }) it('keeps every overview box icon white', () => { expect(source).toMatch( /\.billing-summary__item svg\s*\{[^}]*color:\s*#fff;/s, ) expect(source).not.toContain('.billing-summary__item--open svg') expect(source).not.toContain('.billing-summary__item--due svg') expect(source).not.toContain('.billing-summary__item--overdue svg') }) it('aligns invoice information and note with the detail hero edges', () => { expect(source).toMatch( /\.billing-panel,\s*\.billing-note\s*\{[^}]*margin-right:\s*0;[^}]*margin-left:\s*0;/s, ) }) it('presents pay and dispute as a matched action pair', () => { expect(source).toContain('class="billing-action billing-action--pay"') expect(source).toContain('class="billing-action billing-action--dispute"') expect(source).toContain('variant="secondary"') expect(source).toMatch( /\.billing-detail__actions\s*\{[^}]*grid-template-columns:\s*repeat\(2, minmax\(0, 1fr\)\);/s, ) expect(source).toMatch( /\.billing-detail__actions :deep\(\.sky-button\)\s*\{[^}]*height:\s*44px;[^}]*border-radius:\s*14px;/s, ) expect(source).toMatch( /@media \(hover: hover\)\s*\{[^}]*\.billing-detail__actions :deep\(\.billing-action:hover\)\s*\{[^}]*transform:\s*translateY\(-2px\);/s, ) expect(source).toContain( ':deep(.billing-action:hover .billing-action-chevron)', ) }) it('keeps the invoice and payment information heading readable', () => { expect(source).toMatch( /\.billing-detail__section-title\s*\{[^}]*font-size:\s*11px;/s, ) }) it('keeps the Overview brand in main and detail headers', () => { expect(source).toContain('