test(foundation): coverage matrix + strategy + gap-fill batch (#773) (#980)

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
oxoxDev
2026-04-28 16:13:48 +05:30
committed by GitHub
co-authored by Claude Opus 4.7
parent f9c15bd1ee
commit 4f9da9eb8d
14 changed files with 1673 additions and 2 deletions
@@ -0,0 +1,183 @@
import { afterAll, beforeAll, describe, expect, it, vi } from 'vitest';
import type { ActionableItem } from '../../../types/intelligence';
import { filterItems, getItemStats, groupItemsByTime } from '../utils';
// Pin the wall clock so day-boundary buckets are stable across the day and on CI.
const FIXED_NOW = new Date('2026-04-27T12:00:00.000Z');
beforeAll(() => {
vi.useFakeTimers();
vi.setSystemTime(FIXED_NOW);
});
afterAll(() => {
vi.useRealTimers();
});
function makeItem(
partial: Partial<ActionableItem> & { id: string; createdAt: Date }
): ActionableItem {
return {
title: partial.title ?? 'Untitled',
description: partial.description,
source: partial.source ?? 'system',
priority: partial.priority ?? 'normal',
status: partial.status ?? 'active',
updatedAt: partial.updatedAt ?? partial.createdAt,
actionable: partial.actionable ?? false,
sourceLabel: partial.sourceLabel,
expiresAt: partial.expiresAt,
...partial,
} as ActionableItem;
}
const HOUR = 60 * 60 * 1000;
const DAY = 24 * HOUR;
function daysAgo(n: number): Date {
return new Date(Date.now() - n * DAY);
}
describe('intelligence/utils — actionable item helpers (11.1.2)', () => {
describe('groupItemsByTime', () => {
it('buckets items into Today / Yesterday / This Week / Older', () => {
const items = [
makeItem({ id: 'today', createdAt: new Date() }),
makeItem({ id: 'yest', createdAt: daysAgo(1) }),
makeItem({ id: 'wk', createdAt: daysAgo(3) }),
makeItem({ id: 'old', createdAt: daysAgo(30) }),
];
const groups = groupItemsByTime(items);
const labels = groups.map(g => g.label);
expect(labels).toEqual(['Today', 'Yesterday', 'This Week', 'Older']);
const find = (label: string) => groups.find(g => g.label === label);
expect(find('Today')?.items.map(i => i.id)).toEqual(['today']);
expect(find('Yesterday')?.items.map(i => i.id)).toEqual(['yest']);
expect(find('This Week')?.items.map(i => i.id)).toEqual(['wk']);
expect(find('Older')?.items.map(i => i.id)).toEqual(['old']);
});
it('omits empty buckets and orders within a bucket by priority then recency', () => {
const items = [
makeItem({ id: 'a', createdAt: new Date(), priority: 'normal' }),
makeItem({ id: 'b', createdAt: new Date(Date.now() - 2 * HOUR), priority: 'critical' }),
makeItem({ id: 'c', createdAt: new Date(Date.now() - HOUR), priority: 'critical' }),
];
const groups = groupItemsByTime(items);
expect(groups).toHaveLength(1);
const today = groups[0];
expect(today.label).toBe('Today');
// Critical first; within critical, newer first; normal last.
expect(today.items.map(i => i.id)).toEqual(['c', 'b', 'a']);
expect(today.count).toBe(3);
});
it('handles an empty input as an empty group list', () => {
expect(groupItemsByTime([])).toEqual([]);
});
});
describe('filterItems', () => {
const items = [
makeItem({
id: '1',
createdAt: new Date(),
title: 'Reply to Alice',
source: 'email',
priority: 'critical',
status: 'active',
sourceLabel: 'Gmail',
}),
makeItem({
id: '2',
createdAt: new Date(),
title: 'Standup',
source: 'calendar',
priority: 'normal',
status: 'active',
sourceLabel: 'Calendar',
}),
makeItem({
id: '3',
createdAt: new Date(),
title: 'Reply to Bob',
source: 'email',
priority: 'important',
status: 'completed',
sourceLabel: 'Gmail',
description: 'Follow-up on the canary deployment',
}),
];
it('filters by source', () => {
const out = filterItems(items, { source: 'email' });
expect(out.map(i => i.id)).toEqual(['1', '3']);
});
it('filters by priority', () => {
const out = filterItems(items, { priority: 'critical' });
expect(out.map(i => i.id)).toEqual(['1']);
});
it('filters by status', () => {
const out = filterItems(items, { status: 'completed' });
expect(out.map(i => i.id)).toEqual(['3']);
});
it('filters by searchTerm across title, description, and sourceLabel', () => {
expect(filterItems(items, { searchTerm: 'reply' }).map(i => i.id)).toEqual(['1', '3']);
expect(filterItems(items, { searchTerm: 'canary' }).map(i => i.id)).toEqual(['3']);
expect(filterItems(items, { searchTerm: 'gmail' }).map(i => i.id)).toEqual(['1', '3']);
});
it('treats "all" as a no-op for source/priority/status', () => {
const out = filterItems(items, { source: 'all', priority: 'all', status: 'all' });
expect(out.map(i => i.id)).toEqual(['1', '2', '3']);
});
it('returns no items when searchTerm matches nothing (failure path)', () => {
const out = filterItems(items, { searchTerm: 'definitely-not-present' });
expect(out).toEqual([]);
});
});
describe('getItemStats', () => {
it('counts totals, priorities, and sources, and flags new + expiringSoon', () => {
const items = [
makeItem({
id: 'fresh',
createdAt: new Date(Date.now() - 60 * 1000), // 1 minute ago
priority: 'critical',
source: 'email',
}),
makeItem({
id: 'old',
createdAt: new Date(Date.now() - 10 * DAY),
priority: 'normal',
source: 'calendar',
}),
makeItem({
id: 'expSoon',
createdAt: new Date(Date.now() - 2 * HOUR),
priority: 'important',
source: 'email',
expiresAt: new Date(Date.now() + 6 * HOUR),
}),
];
const stats = getItemStats(items);
expect(stats.total).toBe(3);
expect(stats.byPriority.critical).toBe(1);
expect(stats.byPriority.important).toBe(1);
expect(stats.byPriority.normal).toBe(1);
expect(stats.bySource.email).toBe(2);
expect(stats.bySource.calendar).toBe(1);
expect(stats.newItems).toBe(1);
expect(stats.expiringSoon).toBe(1);
});
});
});
@@ -0,0 +1,84 @@
import { renderHook } from '@testing-library/react';
import { describe, expect, it, vi } from 'vitest';
import { useCoreState } from '../../../providers/CoreStateProvider';
import { useAutocompleteSkillStatus } from '../useAutocompleteSkillStatus';
vi.mock('../../../providers/CoreStateProvider', () => ({ useCoreState: vi.fn() }));
type AutocompleteRuntime = {
platform_supported: boolean;
running: boolean;
enabled: boolean;
last_error?: string | null;
};
function mockSnapshot(autocomplete: AutocompleteRuntime | null): void {
vi.mocked(useCoreState).mockReturnValue({ snapshot: { runtime: { autocomplete } } } as ReturnType<
typeof useCoreState
>);
}
describe('useAutocompleteSkillStatus (5.2 — autocomplete settings status)', () => {
it('returns offline + Enable CTA when no runtime status is available yet', () => {
mockSnapshot(null);
const { result } = renderHook(() => useAutocompleteSkillStatus());
expect(result.current.connectionStatus).toBe('offline');
expect(result.current.statusLabel).toBe('Offline');
expect(result.current.ctaLabel).toBe('Enable');
expect(result.current.platformUnsupported).toBe(false);
});
it('returns Unsupported when the platform reports the runtime is unsupported', () => {
mockSnapshot({ platform_supported: false, running: false, enabled: false });
const { result } = renderHook(() => useAutocompleteSkillStatus());
expect(result.current.connectionStatus).toBe('offline');
expect(result.current.statusLabel).toBe('Unsupported');
expect(result.current.ctaLabel).toBe('Details');
expect(result.current.platformUnsupported).toBe(true);
});
it('returns Active + Manage CTA when the runtime is running (overrides stale errors)', () => {
mockSnapshot({
platform_supported: true,
running: true,
enabled: true,
last_error: 'stale: should not surface',
});
const { result } = renderHook(() => useAutocompleteSkillStatus());
expect(result.current.connectionStatus).toBe('connected');
expect(result.current.statusLabel).toBe('Active');
expect(result.current.ctaLabel).toBe('Manage');
});
it('returns Error + Retry CTA when not running and an error is present', () => {
mockSnapshot({
platform_supported: true,
running: false,
enabled: true,
last_error: 'permission denied',
});
const { result } = renderHook(() => useAutocompleteSkillStatus());
expect(result.current.connectionStatus).toBe('error');
expect(result.current.statusLabel).toBe('Error');
expect(result.current.ctaLabel).toBe('Retry');
expect(result.current.ctaVariant).toBe('amber');
});
it('returns Enabled (disconnected) + Manage when enabled but not running and no error', () => {
mockSnapshot({ platform_supported: true, running: false, enabled: true, last_error: null });
const { result } = renderHook(() => useAutocompleteSkillStatus());
expect(result.current.connectionStatus).toBe('disconnected');
expect(result.current.statusLabel).toBe('Enabled');
expect(result.current.ctaLabel).toBe('Manage');
});
it('returns Disabled + Enable CTA when not enabled and not running', () => {
mockSnapshot({ platform_supported: true, running: false, enabled: false, last_error: null });
const { result } = renderHook(() => useAutocompleteSkillStatus());
expect(result.current.connectionStatus).toBe('offline');
expect(result.current.statusLabel).toBe('Disabled');
expect(result.current.ctaLabel).toBe('Enable');
expect(result.current.ctaVariant).toBe('sage');
});
});
+8
View File
@@ -72,5 +72,13 @@ export const store = configureStore({
export const persistor = persistStore(store);
// Expose the store on `window` so WDIO E2E specs can read Redux state directly
// to assert backing-state changes (see app/test/e2e/specs/*.spec.ts). The store
// holds no secrets that aren't already in the renderer's memory; this only
// surfaces the existing handle under a stable, namespaced key.
if (typeof window !== 'undefined') {
(window as unknown as { __OPENHUMAN_STORE__?: typeof store }).__OPENHUMAN_STORE__ = store;
}
export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;