import { readFileSync } from 'node:fs' import { describe, expect, it } from 'vitest' const source = readFileSync(new URL('./CryptoApp.vue', import.meta.url), 'utf8') const logoSource = readFileSync( new URL('../../components/crypto/CryptoLogo.vue', import.meta.url), 'utf8', ) const server = readFileSync( new URL('../../../../sky_phone/source/server/crypto.lua', import.meta.url), 'utf8', ) const passwordProvider = readFileSync( new URL( '../../../../sky_phone/source/server/crypto_password.js', import.meta.url, ), 'utf8', ) const config = readFileSync( new URL('../../../../sky_phone/config/config.lua', import.meta.url), 'utf8', ) const testServer = readFileSync( new URL('../../../testserver/index.cjs', import.meta.url), 'utf8', ) describe('VaultX crypto app contracts', () => { it('uses Sky UI without introducing Konsta components', () => { expect(source).not.toContain("from 'konsta/vue'") for (const component of [ 'SkyAppPage', 'SkyNavbar', 'SkyScrollArea', 'SkyField', 'SkyButton', 'SkySheet', 'SkyPillNavigation', 'SkySegmented', ]) { expect(source).toContain(`<${component}`) } }) it('shows distinct icons in every primary navigation item', () => { expect(source).toContain(' { expect(source).toContain('selected.priceHistory') expect(source).toContain('const detailChart = computed') expect(source).toContain('CHART_PERIOD_CONFIG[period.value]') expect(source).toContain('class="detail-chart__marker"') expect(source).toContain('v-for="tick in detailChart.yTicks"') expect(source).toContain('v-for="value in CHART_PERIODS"') expect(source).toContain(':aria-pressed="period === value"') expect(source).toContain("t('marketDetail.statistics')") expect(source).toContain('class="detail-trade-dock"') expect(source).toContain('class="vault-view vault-detail-scroll"') expect(source).toContain('class="trade-side-selector"') expect(source).toContain('class="trade-entry-card"') expect(source).toContain('class="trade-protection"') expect(source).toContain('crypto.pendingQuote = null') expect(source).toContain(' { expect(source).toContain('class="profile-signout"') expect(source).toContain("{{ t('logout') }}") expect(source).not.toMatch(/icon-only\s+class="profile-signout"/) expect(source).toContain('class="profile-edit-button"') expect(source).toContain("sheet.value = 'profile'") expect(source).toContain('v-model="profileCurrentPassword"') expect(source).toContain('v-model="profileNewPassword"') expect(server).toContain( 'verify_password(profile.id, data.currentPassword)', ) expect(server).toContain('CryptoHashPassword(new_password)') }) it('provides detailed registration and server-authoritative crypto-key transfers', () => { const transferServer = server.slice( server.indexOf('local function execute_transfer'), server.indexOf('Bridge.Callbacks.Register("sky_phone:crypto:quote"'), ) expect(source).toContain('class="password-strength"') expect(source).toContain('v-model="confirmPassword"') expect(source).toContain(' { expect(source).toContain("import { copyText } from '@/utils/clipboard'") expect(source).toContain( "import { useEasyShareStore } from '@/stores/easyshare'", ) expect(source).toContain('class="wallet-key-card__actions"') expect(source).toContain('@click="copyWalletKey"') expect(source).toContain('@click="shareWalletKey"') expect(source).toContain("appId: 'crypto'") expect(source).toContain("kind: 'text'") }) it('uses the premium dashboard hierarchy without manual refresh controls', () => { expect(source).toContain('class="portfolio-shell"') expect(source).toContain('class="featured-market"') expect(source).toContain('class="activity-status"') expect(source).toContain('class="profile-card"') expect(source).not.toContain('RefreshCw') expect(source).not.toContain(':aria-label="t(\'refresh\')"') }) it('keeps portfolio quick actions concise and interactive', () => { const quickActions = source.slice( source.indexOf('
'), source.indexOf(''), ) expect(quickActions).not.toContain('') expect(source).toContain('@media (hover: hover) and (pointer: fine)') expect(source).toContain('.quick button:hover') expect(source).toContain('.quick button:focus-visible') }) it('anchors portfolio performance history and forecast at the current position', () => { expect(source).toContain('const portfolioProfitLoss = computed') expect(source).toContain('class="portfolio-history"') expect(source).toContain('class="portfolio-forecast"') expect(source).toContain(':cx="portfolioChart.currentX"') expect(source).toContain(':cy="portfolioChart.currentY"') expect(source).toContain("t('portfolio.current')") expect(source).toContain('stroke-dasharray: 7 7') }) it('uses the compact Flare-style navigation and polished overlay transitions', () => { const navbarTag = source.match(//)?.[0] ?? '' expect(source).toContain('class="vault-navbar"') expect(source).toContain('class="vault-header-logo"') expect(source).toContain( '