Files
orca/src/shared/plugins/declarative/plugin-declarative-relative-time.test.ts
T
Neil 8503ecda71 plugins: check runs the worker and scenarios; RelativeTime (#37047)
- orca plugin check mounts the plugin's worker (main) on the same mock host
  as each panel, so plugin.request reaches its orca.panels.handle handlers
  as in Orca; a worker that fails to activate or deactivate is an issue
  named after its file. In orca/testing, a worker mounted on a host answers
  that host's panel requests unless `requests` stubs the name.
- Check scenarios: <entry>.check.ts (e.g. src/panel.check.ts) exports
  defineCheck({ name: { ...mockHost options, persisted, theme, events } });
  check renders the panel once per scenario and labels each result.
- RelativeTime (catalog 3, since 1.4.247) and { type: 'relative', at } Table
  cells: Orca ticks them (each second under a minute, then less often), so
  plugins never poll. Inline inside Text; test kit reads them as drawn.
- Typings, docs, skill guide, generated references; gallery shows it.
2026-11-01 06:56:19 -08:00

59 lines
2.1 KiB
TypeScript

import { describe, expect, it } from 'vitest'
import { parsePluginDeclarativeTree } from './plugin-declarative-tree'
import {
formatPluginRelativeTime,
pluginRelativeTimeParts,
pluginRelativeTimeTickMs
} from './plugin-declarative-relative-time'
const NOW = Date.UTC(2026, 10, 1, 12)
describe('relative time', () => {
it('picks the largest whole unit and words it in each format', () => {
expect(pluginRelativeTimeParts(-45_000)).toEqual({ value: -45, unit: 'second' })
expect(pluginRelativeTimeParts(-5 * 60_000 - 10)).toEqual({ value: -5, unit: 'minute' })
expect(pluginRelativeTimeParts(3 * 86_400_000)).toEqual({ value: 3, unit: 'day' })
const at = NOW - 5 * 60_000
expect(formatPluginRelativeTime(at, NOW, 'short', 'en')).toBe('5m ago')
expect(formatPluginRelativeTime(at, NOW, 'long', 'en')).toBe('5 minutes ago')
expect(formatPluginRelativeTime(at, NOW, 'duration', 'en')).toBe('5m')
expect(formatPluginRelativeTime(NOW + 2 * 3_600_000, NOW, 'long', 'en')).toBe('in 2 hours')
})
it('ticks often only while the words change often', () => {
expect(pluginRelativeTimeTickMs(-10_000)).toBe(1000)
expect(pluginRelativeTimeTickMs(-10 * 60_000)).toBe(15_000)
expect(pluginRelativeTimeTickMs(-5 * 3_600_000)).toBe(300_000)
})
it('accepts RelativeTime inside Text and relative Table cells', () => {
const parsed = parsePluginDeclarativeTree({
type: 'Stack',
props: {},
children: [
{
type: 'Text',
props: {},
children: ['Started ', { type: 'RelativeTime', props: { at: NOW, format: 'long' } }]
},
{
type: 'Table',
props: {
label: 'Agents',
columns: [{ key: 'since', label: 'Since' }],
rows: [
{ key: 'a', cells: { since: { type: 'relative', at: NOW, format: 'duration' } } }
]
}
}
]
})
expect(parsed).toMatchObject({ ok: true, warnings: [] })
const bad = parsePluginDeclarativeTree({
type: 'RelativeTime',
props: { at: Number.POSITIVE_INFINITY }
})
expect(bad.ok && bad.tree?.type).toBe('Unsupported')
})
})