import { describe, expect, it } from 'vitest' import { ref } from 'vue' import { PackageState, type PackageDataEntry } from '@/types/api' import { filterEntriesForTab, isServiceContainer, isServicePackage, resolveAppIcon, useCategoriesWithApps } from '../appsConfig' function makePkg(id: string, title: string, category: string): PackageDataEntry { return { state: PackageState.Running, manifest: { id, title, version: '1.0.0', description: { short: '', long: '' }, 'release-notes': '', license: '', 'wrapper-repo': '', 'upstream-repo': '', 'support-site': '', 'marketing-site': '', 'donation-url': null, category, } as unknown as PackageDataEntry['manifest'], 'static-files': { license: '', instructions: '', icon: '' }, } } describe('appsConfig service filtering', () => { it('treats bitcoin stack UI sidecars as services', () => { expect(isServiceContainer('bitcoin-ui')).toBe(true) expect(isServiceContainer('lnd-ui')).toBe(true) expect(isServiceContainer('electrs-ui')).toBe(true) }) it('treats container aliases as services even with non-service keys', () => { const aliasPkg = makePkg('bitcoin-ui', 'Bitcoin UI', 'money') expect(isServicePackage('core-lnd-ui', aliasPkg)).toBe(true) }) it('removes service-only categories from app category tabs', () => { const packages = ref>({ 'core-bitcoin-ui': makePkg('bitcoin-ui', 'Bitcoin UI', 'money'), 'filebrowser': makePkg('filebrowser', 'File Browser', 'data'), }) const allCategories = ref([ { id: 'all', name: 'All' }, { id: 'money', name: 'Money' }, { id: 'data', name: 'Data' }, ]) const visible = useCategoriesWithApps(packages, allCategories) expect(visible.value.map(c => c.id)).toEqual(['all', 'data']) }) it('filters apps tab by category using manifest-aware service checks', () => { const entries: Array<[string, PackageDataEntry]> = [ ['core-bitcoin-ui', makePkg('bitcoin-ui', 'Bitcoin UI', 'money')], ['filebrowser', makePkg('filebrowser', 'File Browser', 'data')], ['btcpay-server', makePkg('btcpay-server', 'BTCPay', 'commerce')], ] const appsAll = filterEntriesForTab(entries, 'apps', 'all') expect(appsAll.map(([id]) => id)).toEqual(['filebrowser', 'btcpay-server']) const appsData = filterEntriesForTab(entries, 'apps', 'data') expect(appsData.map(([id]) => id)).toEqual(['filebrowser']) }) it('routes service aliases into services tab and excludes user apps', () => { const entries: Array<[string, PackageDataEntry]> = [ ['core-lnd-ui', makePkg('lnd-ui', 'LND UI', 'money')], ['grafana', makePkg('grafana', 'Grafana', 'data')], ] const services = filterEntriesForTab(entries, 'services', 'all') expect(services.map(([id]) => id)).toEqual(['core-lnd-ui']) }) it('falls back to packaged app icon when static icon token is not a path', () => { const pkg = makePkg('gitea', 'Gitea', 'dev') pkg['static-files']!.icon = 'git-branch' expect(resolveAppIcon('gitea', pkg)).toBe('/assets/img/app-icons/gitea.svg') }) })