84 lines
2.4 KiB
TypeScript
84 lines
2.4 KiB
TypeScript
import assert from 'node:assert/strict'
|
|
import { describe, it } from 'node:test'
|
|
import {
|
|
OA_APP_ICON_COLOR_PAIRS,
|
|
OA_APP_EP_ICON_NAMES,
|
|
buildEpIconUrl,
|
|
parseEpIconUrl,
|
|
resolveOaAppIcon,
|
|
pickRandomOaAppIconUrl,
|
|
iconFgFromBg,
|
|
isEpIconUrl
|
|
} from './oa-app-icons'
|
|
|
|
describe('oa-app-icons palette', () => {
|
|
it('has exactly 8 pairs and no gray/slate', () => {
|
|
assert.equal(OA_APP_ICON_COLOR_PAIRS.length, 8)
|
|
for (const p of OA_APP_ICON_COLOR_PAIRS) {
|
|
assert.notEqual(p.bg.toLowerCase(), '#e2e8f0')
|
|
assert.notEqual(p.fg.toLowerCase(), '#475569')
|
|
}
|
|
})
|
|
})
|
|
|
|
describe('build/parse ep url', () => {
|
|
it('round-trips', () => {
|
|
const raw = buildEpIconUrl('Calendar', '#dbeafe')
|
|
assert.equal(raw, 'ep:Calendar|#dbeafe')
|
|
const parsed = parseEpIconUrl(raw)
|
|
assert.deepEqual(parsed, { icon: 'Calendar', bg: '#dbeafe', fg: '#2563eb' })
|
|
})
|
|
|
|
it('falls back on unknown icon and illegal bg', () => {
|
|
const a = parseEpIconUrl('ep:NotARealIcon|#d1fae5')
|
|
assert.equal(a.icon, 'Document')
|
|
const b = parseEpIconUrl('ep:Document|#ffffff')
|
|
assert.equal(b.bg, '#d1fae5')
|
|
assert.equal(b.fg, '#059669')
|
|
})
|
|
|
|
it('falls back on malformed ep string', () => {
|
|
const p = parseEpIconUrl('ep:broken')
|
|
assert.equal(p.icon, 'Document')
|
|
assert.equal(p.bg, '#d1fae5')
|
|
})
|
|
})
|
|
|
|
describe('resolveOaAppIcon', () => {
|
|
it('resolves ep kind', () => {
|
|
const r = resolveOaAppIcon('ep:Document|#d1fae5')
|
|
assert.equal(r.kind, 'ep')
|
|
if (r.kind === 'ep') {
|
|
assert.equal(r.icon, 'Document')
|
|
assert.equal(r.bg, '#d1fae5')
|
|
assert.equal(r.fg, '#059669')
|
|
}
|
|
})
|
|
|
|
it('resolves image kind for legacy path', () => {
|
|
const r = resolveOaAppIcon('/oa-app-icons/doc-orange.svg')
|
|
assert.equal(r.kind, 'image')
|
|
if (r.kind === 'image') {
|
|
assert.equal(r.src, '/oa-app-icons/doc-orange.svg')
|
|
}
|
|
})
|
|
|
|
it('empty becomes fallback ep', () => {
|
|
const r = resolveOaAppIcon('')
|
|
assert.equal(r.kind, 'ep')
|
|
})
|
|
})
|
|
|
|
describe('random', () => {
|
|
it('pickRandomOaAppIconUrl returns valid ep in palette and icon list', () => {
|
|
for (let i = 0; i < 30; i++) {
|
|
const u = pickRandomOaAppIconUrl()
|
|
assert.equal(isEpIconUrl(u), true)
|
|
const p = parseEpIconUrl(u)
|
|
assert.ok(OA_APP_EP_ICON_NAMES.includes(p.icon as (typeof OA_APP_EP_ICON_NAMES)[number]))
|
|
assert.ok(OA_APP_ICON_COLOR_PAIRS.some((c) => c.bg === p.bg))
|
|
assert.equal(iconFgFromBg(p.bg), p.fg)
|
|
}
|
|
})
|
|
})
|