You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
svelte-kit-vice/src/arts/sium/test/errors.test.ts

88 lines
2.6 KiB

eidos: pilot wrapper pattern + doctrinal API conventions Toggle as the eidos pilot: subdirectory layout (recipe + Svelte wrapper + types + index + README) replacing the flat CSS-only form. Pattern is documented in eidos/components/README.md and the toggle README. Shared types live in eidos/lib/types.ts. First export is `Size` (8 values xxs..xxl + full); components narrow with `Extract<Size, ...>` per the per-component-subset doctrine. No `Eidos` prefix on types — module path already conveys the layer. API doctrine: - soma stays compound (Toggle.Provider) for symmetry with multi-part - eidos exports both default + Provider so single-part components accept both `<Toggle>` (ergonomic) and `<Toggle.Provider>` (compound-style consumers) SoundChannel eager-init fixes the autoplay race: AudioContext is created + resumed synchronously on the first user gesture (capture-phase listener registered in the constructor), avoiding the previous race where the first emit() scheduled the resume in a microtask outside the gesture window. Demo page (web/routes/toggle/+page.svelte) restructured so the live preview renders ALWAYS above the tablist — Sema-tab Play buttons can fire on the real toggle. Motion preview amplifies scale ×8 visually only; doctrinal values stay in the <dl>. Conventions 7-13 added to src/docs/sema-implementation-guide.md covering: directory structure, wrapper composition, no Eidos prefix, soma compound vs eidos flat, iconOnly sr-only body, sound eager-init, docs-preview amplification. CLAUDE.md gets a session hand-off block listing where things stand and next concrete steps (migrate switch/collapsible/dialog/drawer/popover/ toast/avatar; wire topbar sound mute to masterGain; rename theme tokens to drop the success/warning/danger fallback aliases). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
import { describe, expect, it } from 'vitest';
import {
isSiumAsyncSchemaError,
isSiumValidationError,
SiumAsyncSchemaError,
SiumValidationError,
type Issue
} from '../index.ts';
import {
SIUM_ERR,
SIUM_ERR_ASYNC_SCHEMA,
SIUM_ERR_VALIDATION
} from '../errors.ts';
import { CodeError, isCodeError, matches } from '$libs/errs';
const ISSUE: Issue = {
path: ['name'],
message: 'required',
code: 'invalid_type'
} as Issue;
describe('SiumValidationError', () => {
it('extends CodeError with the validation code', () => {
const err = new SiumValidationError([ISSUE]);
expect(err).toBeInstanceOf(CodeError);
expect(err.code).toBe(SIUM_ERR_VALIDATION);
expect(err.name).toBe(SIUM_ERR_VALIDATION);
});
it('carries issues alongside the code', () => {
const err = new SiumValidationError([ISSUE]);
expect(err.issues).toEqual([ISSUE]);
});
it('is detected by isSiumValidationError and isCodeError', () => {
const err = new SiumValidationError([ISSUE]);
expect(isSiumValidationError(err)).toBe(true);
expect(isCodeError(err)).toBe(true);
});
it('is matched by the SIUM_ERR module seed', () => {
const err = new SiumValidationError([ISSUE]);
expect(matches(err, SIUM_ERR)).toBe(true);
});
});
describe('SiumAsyncSchemaError', () => {
it('extends CodeError with the async-schema code', () => {
const err = new SiumAsyncSchemaError('object');
expect(err).toBeInstanceOf(CodeError);
expect(err.code).toBe(SIUM_ERR_ASYNC_SCHEMA);
expect(err.name).toBe(SIUM_ERR_ASYNC_SCHEMA);
});
it('carries the schema kind', () => {
const err = new SiumAsyncSchemaError('union');
expect(err.schemaKind).toBe('union');
});
it('is detected by isSiumAsyncSchemaError and isCodeError', () => {
const err = new SiumAsyncSchemaError();
expect(isSiumAsyncSchemaError(err)).toBe(true);
expect(isCodeError(err)).toBe(true);
});
it('does not match the validation code', () => {
const err = new SiumAsyncSchemaError();
expect(matches(err, SIUM_ERR_VALIDATION)).toBe(false);
expect(matches(err, SIUM_ERR_ASYNC_SCHEMA)).toBe(true);
});
it('is matched by the SIUM_ERR module seed', () => {
const err = new SiumAsyncSchemaError();
expect(matches(err, SIUM_ERR)).toBe(true);
});
});
describe('CodeError fluent decorators on sium errors', () => {
it('preserves the subclass-specific fields after withMessage', () => {
const err = new SiumValidationError([ISSUE]);
const decorated = err.withMessage('User-facing failure');
expect(decorated.userMessage).toBe('User-facing failure');
// Decoration returns plain CodeError; subclass fields stay on the
// original instance only.
expect(matches(decorated, SIUM_ERR_VALIDATION)).toBe(true);
});
});

Powered by TurnKey Linux.