learning_ai_common_plat/packages/quick-actions/src/client.test.ts
saravanakumardb1 be03efa111 feat(shared-packages): add 9 @bytelyst/* client packages with 100% API coverage
Packages added:
- @bytelyst/referral-client — referral API client + share helpers
- @bytelyst/subscription-client — subscription/plan API client + cache
- @bytelyst/celebrations — milestone triggers, confetti, positive messages
- @bytelyst/gentle-notifications — ND-friendly messaging, forbidden phrases
- @bytelyst/accessibility — VoiceOver/TalkBack label generators
- @bytelyst/quick-actions — progressive disclosure, smart defaults
- @bytelyst/time-references — familiar duration references
- @bytelyst/org-client — org/workspace/membership/license API client
- @bytelyst/marketplace-client — listing/review/install API client

All packages: pure TS, ESM, globalThis.fetch, no Node.js deps.
99 Vitest tests across 9 packages, 79/79 public methods covered.

Review fixes applied:
- time-references: fix module-level mutable state leak + add clearCustomReferences()
- accessibility: fix parameter reassignment in formatDurationForA11y/numberToWords
- subscription-client: fix flaky daysRemaining test (ms boundary race)
2026-03-19 13:10:09 -07:00

118 lines
3.6 KiB
TypeScript

import { describe, it, expect } from 'vitest';
import {
getVisibleSections,
getAvailableActions,
pickSmartDefault,
MAX_VISIBLE_ITEMS,
MAX_VISIBLE_LIST,
} from './client.js';
import type { ProgressiveSection, QuickAction, SmartDefault } from './types.js';
describe('getVisibleSections', () => {
const sections: ProgressiveSection[] = [
{ id: 'main', title: 'Main', defaultExpanded: true, priority: 'primary' },
{ id: 'stats', title: 'Stats', defaultExpanded: false, priority: 'secondary' },
{ id: 'details', title: 'Details', defaultExpanded: false, priority: 'detail' },
{ id: 'advanced', title: 'Advanced', defaultExpanded: false, priority: 'primary' },
];
it('should show primary and defaultExpanded sections', () => {
const visible = getVisibleSections(sections, new Set());
expect(visible.map(s => s.id)).toEqual(['main', 'advanced']);
});
it('should include explicitly expanded sections', () => {
const visible = getVisibleSections(sections, new Set(['stats']));
expect(visible.map(s => s.id)).toEqual(['main', 'stats', 'advanced']);
});
it('should return empty for no sections', () => {
expect(getVisibleSections([], new Set())).toHaveLength(0);
});
});
describe('getAvailableActions', () => {
const actions: QuickAction[] = [
{
id: 'start',
label: 'Start',
icon: 'play',
shortLabel: 'Start',
action: 'start',
requiresAuth: false,
},
{
id: 'share',
label: 'Share',
icon: 'share',
shortLabel: 'Share',
action: 'share',
requiresAuth: true,
},
{
id: 'stop',
label: 'Stop',
icon: 'stop',
shortLabel: 'Stop',
action: 'stop',
requiresAuth: false,
},
];
it('should filter out auth-required actions when not authenticated', () => {
const available = getAvailableActions(actions, { isAuthenticated: false });
expect(available.map(a => a.id)).toEqual(['start', 'stop']);
});
it('should include all when authenticated', () => {
const available = getAvailableActions(actions, { isAuthenticated: true });
expect(available).toHaveLength(3);
});
it('should include non-auth actions by default', () => {
const available = getAvailableActions(actions, {});
expect(available.map(a => a.id)).toEqual(['start', 'stop']);
});
});
describe('pickSmartDefault', () => {
it('should prefer last_used over others', () => {
const candidates: SmartDefault[] = [
{ key: 'protocol', value: 'OMAD', source: 'most_common' },
{ key: 'protocol', value: '16:8', source: 'last_used' },
{ key: 'protocol', value: '18:6', source: 'recommendation' },
];
const result = pickSmartDefault(candidates);
expect(result?.value).toBe('16:8');
});
it('should fall back to most_common', () => {
const candidates: SmartDefault[] = [
{ key: 'protocol', value: 'OMAD', source: 'most_common' },
{ key: 'protocol', value: '18:6', source: 'system' },
];
const result = pickSmartDefault(candidates);
expect(result?.value).toBe('OMAD');
});
it('should return null for empty array', () => {
expect(pickSmartDefault([])).toBeNull();
});
it('should return first if no priority match', () => {
const candidates: SmartDefault[] = [{ key: 'x', value: 'a', source: 'system' }];
const result = pickSmartDefault(candidates);
expect(result?.value).toBe('a');
});
});
describe('constants', () => {
it('should export MAX_VISIBLE_ITEMS', () => {
expect(MAX_VISIBLE_ITEMS).toBe(3);
});
it('should export MAX_VISIBLE_LIST', () => {
expect(MAX_VISIBLE_LIST).toBe(5);
});
});