mirror of
https://github.com/stablyai/orca.git
synced 2026-11-14 01:47:24 +00:00
157 lines
6.2 KiB
TypeScript
157 lines
6.2 KiB
TypeScript
import { describe, expect, it } from 'vitest'
|
|
import { isPluginThemeRegistration, parsePluginAppThemeArtifact } from './plugin-theme-artifact'
|
|
import {
|
|
isPluginTerminalThemeRegistration,
|
|
parsePluginTerminalThemeArtifact
|
|
} from './plugin-terminal-theme-artifact'
|
|
|
|
const parseApp = (value: unknown) => () =>
|
|
parsePluginAppThemeArtifact(JSON.stringify(value), 'strict')
|
|
|
|
describe('plugin app theme artifacts', () => {
|
|
it.each([
|
|
['a private token', { base: 'dark', tokens: { '--internal-gap': '#000' } }],
|
|
['a URL', { base: 'dark', tokens: { '--background': 'url(x)' } }],
|
|
['a var() chain', { base: 'dark', tokens: { '--background': 'var(--a)' } }],
|
|
['declaration syntax', { base: 'dark', tokens: { '--background': '#000; color: red' } }],
|
|
['no tokens', { base: 'dark', tokens: {} }],
|
|
[
|
|
'transparent',
|
|
{ base: 'dark', tokens: { '--background': 'transparent', '--foreground': '#fff' } }
|
|
],
|
|
['an unknown key', { base: 'dark', tokens: { '--border': '#000' }, extra: 1 }]
|
|
])('rejects %s', (_label, value) => {
|
|
expect(parseApp(value)).toThrow()
|
|
})
|
|
|
|
it('skips unknown tokens and keys at runtime so newer themes still load', () => {
|
|
const theme = parsePluginAppThemeArtifact(
|
|
JSON.stringify({
|
|
schemaVersion: 1,
|
|
base: 'dark',
|
|
tokens: { '--background': '#000', '--foreground': '#fff', '--future': '#123' },
|
|
future: true
|
|
})
|
|
)
|
|
expect(theme.tokens).not.toHaveProperty('--future')
|
|
expect(parseApp({ schemaVersion: 2, base: 'dark', tokens: {} })).toThrow()
|
|
})
|
|
|
|
it('reads a background image, strict for authors and never fatal at runtime', () => {
|
|
const base = { base: 'dark', tokens: { '--background': '#000', '--foreground': '#fff' } }
|
|
const background = { path: 'images/dusk.webp', opacity: 0.35, size: 'tile' }
|
|
const runtime = (value: unknown) =>
|
|
parsePluginAppThemeArtifact(JSON.stringify({ ...base, background: value })).background
|
|
expect(parseApp({ ...base, background })().background).toEqual(background)
|
|
expect(parseApp({ ...base, background: { path: 'a.png', blur: 4 } })).toThrow()
|
|
expect(runtime({ path: 'a.png', blur: 4 })).toEqual({ path: 'a.png' })
|
|
// A newer or out-of-range style value falls back to its default; only a bad path drops the image.
|
|
expect(parseApp({ ...base, background: { path: 'a.png', size: 'stretch' } })).toThrow()
|
|
expect(runtime({ path: 'a.png', size: 'stretch', opacity: 2 })).toMatchObject({ path: 'a.png' })
|
|
expect(parseApp({ ...base, background: { path: '../escape.png' } })).toThrow()
|
|
expect(runtime({ path: '../escape.png' })).toBeUndefined()
|
|
})
|
|
|
|
it('reads VS Code-shaped tokenColors, strict for authors and tolerant at runtime', () => {
|
|
const base = { base: 'dark', tokens: { '--background': '#000', '--foreground': '#fff' } }
|
|
const keyword = { name: 'Keywords', scope: ['keyword'], settings: { foreground: '#ff79c6' } }
|
|
expect(parseApp({ ...base, tokenColors: [keyword] })().tokenColors).toEqual([keyword])
|
|
expect(
|
|
parseApp({ ...base, tokenColors: [{ scope: 'x', settings: { foreground: 'red' } }] })
|
|
).toThrow()
|
|
expect(
|
|
parseApp({ ...base, tokenColors: [{ scope: 'x', settings: { fontStyle: 'wavy' } }] })
|
|
).toThrow()
|
|
expect(
|
|
parsePluginAppThemeArtifact(
|
|
JSON.stringify({
|
|
...base,
|
|
tokenColors: [
|
|
{ ...keyword, settings: { ...keyword.settings, background: '#000' } },
|
|
{ scope: 'x', settings: { foreground: 'red' } },
|
|
'junk'
|
|
]
|
|
})
|
|
).tokenColors
|
|
).toEqual([{ scope: ['keyword'], settings: { foreground: '#ff79c6' } }])
|
|
})
|
|
|
|
it('validates registrations crossing IPC', () => {
|
|
const registration = {
|
|
id: 'plugin:samples.midnight/midnight',
|
|
revision: 'r1',
|
|
pluginKey: 'samples.midnight',
|
|
pluginName: 'Midnight',
|
|
label: 'Midnight',
|
|
base: 'dark',
|
|
tokens: { '--background': '#000000', '--foreground': '#ffffff' }
|
|
}
|
|
expect(isPluginThemeRegistration(registration)).toBe(true)
|
|
expect(isPluginThemeRegistration({ ...registration, id: 'midnight' })).toBe(false)
|
|
expect(isPluginThemeRegistration({ ...registration, tokens: { '--x': '#000' } })).toBe(false)
|
|
})
|
|
})
|
|
|
|
describe('plugin terminal theme artifacts', () => {
|
|
const terminal = { background: '#000000', foreground: '#ffffff', green: '#00ff00' }
|
|
|
|
it('skips unknown slots at runtime', () => {
|
|
expect(
|
|
parsePluginTerminalThemeArtifact(
|
|
JSON.stringify({ schemaVersion: 1, terminal: { ...terminal, glow: '#000000' } })
|
|
)
|
|
).toEqual({ mode: 'unknown', terminal })
|
|
})
|
|
|
|
it.each([
|
|
['an unknown slot', { ...terminal, glow: '#000000' }],
|
|
['an invalid color', { ...terminal, red: 'red; x' }],
|
|
['no ANSI color', { background: '#000000', foreground: '#ffffff' }]
|
|
])('rejects %s', (_label, colors) => {
|
|
expect(() =>
|
|
parsePluginTerminalThemeArtifact(
|
|
JSON.stringify({ schemaVersion: 1, terminal: colors }),
|
|
'strict'
|
|
)
|
|
).toThrow()
|
|
})
|
|
|
|
it('validates registrations crossing IPC', () => {
|
|
const registration = {
|
|
id: 'plugin:samples.midnight/midnight',
|
|
pluginKey: 'samples.midnight',
|
|
pluginName: 'Midnight',
|
|
label: 'Midnight',
|
|
mode: 'dark',
|
|
terminal
|
|
}
|
|
expect(isPluginTerminalThemeRegistration(registration)).toBe(true)
|
|
expect(isPluginTerminalThemeRegistration({ ...registration, terminal: {} })).toBe(false)
|
|
})
|
|
})
|
|
|
|
describe('plugin app theme completion', () => {
|
|
it('requires a background and foreground', () => {
|
|
expect(parseApp({ base: 'dark', tokens: { '--background': '#000' } })).toThrow('--foreground')
|
|
})
|
|
|
|
it.each(['transparent', 'inherit', 'currentColor', '100px', 'calc(1px + 2px)', 'env(x)'])(
|
|
'rejects the non-color value %s',
|
|
(value) => {
|
|
expect(
|
|
parseApp({ base: 'dark', tokens: { '--background': value, '--foreground': '#fff' } })
|
|
).toThrow()
|
|
}
|
|
)
|
|
|
|
it('keeps a sidebar the theme sets', () => {
|
|
const { tokens } = parsePluginAppThemeArtifact(
|
|
JSON.stringify({
|
|
base: 'dark',
|
|
tokens: { '--background': '#1d1533', '--foreground': '#e8e0ff', '--sidebar': '#271d45' }
|
|
})
|
|
)
|
|
expect(tokens['--worktree-sidebar']).toBe('#271d45')
|
|
})
|
|
})
|