Files
floci-ui/packages/api/src/cloud-spi/serviceCatalog.test.ts
T
2026-09-22 16:13:21 -04:00

98 lines
3.8 KiB
TypeScript

import {describe, expect, test} from 'bun:test'
import {
SERVICE_CATALOG,
SERVICE_CATALOG_ENTRIES,
SERVICE_GROUP_ORDER,
SERVICE_TYPES,
catalogEntry,
displayNameFor,
isServiceType,
routeFor,
} from './serviceCatalog'
describe('SERVICE_CATALOG', () => {
test('every entry carries the metadata the nav needs', () => {
for (const entry of SERVICE_CATALOG_ENTRIES) {
expect(entry.displayName.length).toBeGreaterThan(0)
expect(entry.iconKey.length).toBeGreaterThan(0)
expect(SERVICE_GROUP_ORDER).toContain(entry.group)
expect(Number.isFinite(entry.order)).toBe(true)
expect(routeFor(entry, 'aws').length).toBeGreaterThan(0)
}
})
test('exposes one entry per catalog key', () => {
expect(SERVICE_CATALOG_ENTRIES).toHaveLength(Object.keys(SERVICE_CATALOG).length)
expect(new Set(SERVICE_TYPES).size).toBe(SERVICE_TYPES.length)
})
test('registers the iac category under the Provisioning group', () => {
expect(SERVICE_GROUP_ORDER).toContain('Provisioning')
const iac = catalogEntry('iac')!
expect(iac.group).toBe('Provisioning')
expect(isServiceType('iac')).toBe(true)
expect(displayNameFor(iac, 'aws')).toBe('CloudFormation')
})
test('orders entries by group then in-group order', () => {
const positions = SERVICE_CATALOG_ENTRIES.map((entry) => [
SERVICE_GROUP_ORDER.indexOf(entry.group),
entry.order,
])
for (let i = 1; i < positions.length; i += 1) {
const [prevGroup, prevOrder] = positions[i - 1]!
const [group, order] = positions[i]!
expect(prevGroup < group || (prevGroup === group && prevOrder <= order)).toBe(true)
}
})
test('routes default to the slug', () => {
expect(routeFor(catalogEntry('storage')!, 'aws')).toBe('storage')
expect(routeFor(catalogEntry('storage')!, 'gcp')).toBe('storage')
})
test('a per-cloud override routes one provider to its bespoke page', () => {
// AWS Secrets Manager keeps its dedicated page until value reveal exists
// as a row action; GCP goes through the generic explorer today.
const secrets = catalogEntry('secrets')!
expect(routeFor(secrets, 'aws')).toBe('/secretsmanager')
expect(routeFor(secrets, 'gcp')).toBe('secrets')
})
test('resolves per-cloud routes so one category can span a legacy page and the explorer', () => {
const secrets = catalogEntry('secrets')!
expect(routeFor(secrets, 'aws')).toBe('/secretsmanager')
expect(routeFor(secrets, 'azure')).toBe('secrets')
// A category with no per-cloud override is unaffected by the cloud argument.
expect(routeFor(catalogEntry('storage')!, 'azure')).toBe('storage')
})
test('resolves per-cloud display names', () => {
const k8s = catalogEntry('k8s')!
expect(displayNameFor(k8s, 'aws')).toBe('EKS')
expect(displayNameFor(k8s, 'azure')).toBe('AKS')
expect(displayNameFor(k8s, 'gcp')).toBe('GKE')
// No override -> the shared display name.
expect(displayNameFor(catalogEntry('storage')!, 'gcp')).toBe('Storage')
})
})
describe('isServiceType', () => {
test('accepts every catalog key', () => {
for (const service of SERVICE_TYPES) {
expect(isServiceType(service)).toBe(true)
}
})
test('rejects unknown slugs so routes 404 instead of failing later', () => {
for (const slug of ['queue', 'stroage', '', 'constructor', '__proto__', 'toString']) {
expect(isServiceType(slug)).toBe(false)
}
})
test('catalogEntry returns undefined for an unknown slug', () => {
expect(catalogEntry('queue')).toBeUndefined()
})
})