first-commit
ci / Validate workspace (push) Has been cancelled
landing-page-ci / Validate landing page (push) Has been cancelled
landing-page-deploy / Deploy landing page (push) Has been cancelled
github-metrics / Generate repository metrics SVG (push) Has been cancelled
refresh-contributors-wall / Refresh contributors wall cache bust (push) Waiting to run

This commit is contained in:
Zakaria
2026-05-04 14:58:14 -04:00
commit a46764fb1b
1210 changed files with 233231 additions and 0 deletions
+112
View File
@@ -0,0 +1,112 @@
import { cleanup, fireEvent, render, screen, within } from '@testing-library/react';
import { afterEach, describe, expect, it, vi } from 'vitest';
import { AssistantMessage } from '../../apps/web/src/components/AssistantMessage';
import type { AgentEvent, ChatMessage } from '../../apps/web/src/types';
function messageWithEvents(events: AgentEvent[]): ChatMessage {
return {
id: 'assistant-1',
role: 'assistant',
content: '',
events,
startedAt: 1_000,
endedAt: 3_000,
};
}
describe('AssistantMessage unfinished todo state', () => {
afterEach(() => cleanup());
it('keeps Done for a completed latest TodoWrite fixture', () => {
render(
<AssistantMessage
message={messageWithEvents([
{
kind: 'tool_use',
id: 'todo-1',
name: 'TodoWrite',
input: { todos: [{ content: 'Ship layout', status: 'completed' }] },
},
])}
streaming={false}
projectId="project-1"
isLast
/>,
);
expect(screen.getByText('Done')).toBeTruthy();
expect(screen.queryByText('Stopped with unfinished work')).toBeNull();
expect(screen.queryByRole('button', { name: 'Continue remaining tasks' })).toBeNull();
});
it('shows unfinished state and passes unfinished todos to the continue callback', () => {
const onContinue = vi.fn();
render(
<AssistantMessage
message={messageWithEvents([
{
kind: 'tool_use',
id: 'todo-1',
name: 'TodoWrite',
input: {
todos: [
{ content: 'Draft layout', status: 'completed' },
{
content: 'Build components',
status: 'in_progress',
activeForm: 'Building components',
},
{ content: 'Run QA', status: 'pending' },
],
},
},
])}
streaming={false}
projectId="project-1"
isLast
onContinueRemainingTasks={onContinue}
/>,
);
expect(screen.getByText('Stopped with unfinished work')).toBeTruthy();
expect(screen.getByText('2 task(s) remain')).toBeTruthy();
const remainingList = screen.getByText('2 task(s) remain').closest('.unfinished-todos');
expect(remainingList).not.toBeNull();
expect(within(remainingList as HTMLElement).getByText('Building components')).toBeTruthy();
expect(within(remainingList as HTMLElement).getByText('Run QA')).toBeTruthy();
fireEvent.click(screen.getByRole('button', { name: 'Continue remaining tasks' }));
expect(onContinue).toHaveBeenCalledWith([
{
content: 'Build components',
status: 'in_progress',
activeForm: 'Building components',
},
{ content: 'Run QA', status: 'pending', activeForm: undefined },
]);
});
it('hides the continue button on older assistant turns', () => {
render(
<AssistantMessage
message={messageWithEvents([
{
kind: 'tool_use',
id: 'todo-1',
name: 'TodoWrite',
input: { todos: [{ content: 'Run QA', status: 'pending' }] },
},
])}
streaming={false}
projectId="project-1"
isLast={false}
onContinueRemainingTasks={vi.fn()}
/>,
);
expect(screen.getByText('Stopped with unfinished work')).toBeTruthy();
expect(screen.getByText('1 task(s) remain')).toBeTruthy();
expect(screen.queryByRole('button', { name: 'Continue remaining tasks' })).toBeNull();
});
});
@@ -0,0 +1,77 @@
import { cleanup, render, screen } from '@testing-library/react';
import { afterEach, describe, expect, it, vi } from 'vitest';
import { ChatPane } from '../../apps/web/src/components/ChatPane';
import type { ChatMessage } from '../../apps/web/src/types';
function renderChatPane(messages: ChatMessage[]) {
return render(
<ChatPane
messages={messages}
streaming={false}
error={null}
projectId="project-1"
projectFiles={[]}
onEnsureProject={async () => 'project-1'}
onSend={() => {}}
onStop={() => {}}
conversations={[]}
activeConversationId={null}
onSelectConversation={() => {}}
onDeleteConversation={() => {}}
/>,
);
}
describe('conversation timestamps', () => {
afterEach(() => {
cleanup();
vi.useRealTimers();
});
it('shows inline relative message times with exact hover text', () => {
vi.useFakeTimers();
vi.setSystemTime(new Date('2025-01-15T14:00:00Z'));
renderChatPane([
{
id: 'user-1',
role: 'user',
content: 'Create a landing page',
createdAt: Date.parse('2025-01-15T12:00:00Z'),
},
{
id: 'assistant-1',
role: 'assistant',
content: 'Done',
createdAt: Date.parse('2025-01-15T12:01:00Z'),
},
]);
const firstTime = screen.getByText('2h ago');
expect(firstTime.tagName).toBe('TIME');
expect(firstTime.getAttribute('title')).toContain('2025');
expect(screen.getByText('1h ago').tagName).toBe('TIME');
});
it('adds day separators when a conversation crosses days', () => {
vi.useFakeTimers();
vi.setSystemTime(new Date('2025-01-16T14:00:00Z'));
renderChatPane([
{
id: 'user-1',
role: 'user',
content: 'First request',
createdAt: Date.parse('2025-01-15T12:00:00Z'),
},
{
id: 'user-2',
role: 'user',
content: 'Follow-up',
createdAt: Date.parse('2025-01-16T12:00:00Z'),
},
]);
expect(screen.getAllByRole('separator')).toHaveLength(2);
});
});
+109
View File
@@ -0,0 +1,109 @@
import { act, cleanup, fireEvent, render } from '@testing-library/react';
import { afterEach, describe, expect, it, vi } from 'vitest';
import { PreviewModal } from '../../apps/web/src/components/PreviewModal';
// Regression coverage for nexu-io/open-design#141: pressing Esc in fullscreen
// used to require two presses because the browser exits its native fullscreen
// element on the first press without delivering a keydown to JS, leaving the
// React `fullscreen` state stuck on. The fix listens to fullscreenchange and
// mirrors the native state into React.
const baseProps = {
title: 'Sample',
views: [{ id: 'main', label: 'Main', html: '<p>hi</p>' }],
exportTitleFor: (id: string) => id,
};
function dispatchFullscreenChange() {
act(() => {
document.dispatchEvent(new Event('fullscreenchange'));
});
}
function setNativeFullscreenElement(el: Element | null) {
Object.defineProperty(document, 'fullscreenElement', {
configurable: true,
get: () => el,
});
}
describe('PreviewModal fullscreen exit', () => {
afterEach(() => {
cleanup();
setNativeFullscreenElement(null);
});
it('drops the fullscreen overlay when the browser exits native fullscreen', () => {
const onClose = vi.fn();
const { container } = render(
<PreviewModal {...baseProps} onClose={onClose} />,
);
// Click the Fullscreen button. jsdom does not implement requestFullscreen
// on plain elements, so PreviewModal's fallback path runs and just sets
// the React state — exactly matching what happens after a successful
// browser fullscreen request.
const fsButton = container.querySelector(
'button[title="Fullscreen"]',
) as HTMLButtonElement;
expect(fsButton).toBeTruthy();
fireEvent.click(fsButton);
const stage = container.querySelector('.ds-modal') as HTMLElement;
expect(stage.classList.contains('ds-modal-fullscreen')).toBe(true);
// Simulate the user pressing Esc in browser fullscreen: the browser
// exits its native fullscreen element and fires fullscreenchange, but
// (in browsers like Firefox) does not deliver the keydown to JS.
setNativeFullscreenElement(null);
dispatchFullscreenChange();
expect(stage.classList.contains('ds-modal-fullscreen')).toBe(false);
expect(onClose).not.toHaveBeenCalled();
});
it('keeps the modal mounted on Esc while fullscreen, and closes only on a second Esc', () => {
const onClose = vi.fn();
const { container } = render(
<PreviewModal {...baseProps} onClose={onClose} />,
);
const fsButton = container.querySelector(
'button[title="Fullscreen"]',
) as HTMLButtonElement;
fireEvent.click(fsButton);
const stage = container.querySelector('.ds-modal') as HTMLElement;
expect(stage.classList.contains('ds-modal-fullscreen')).toBe(true);
// First Esc — drops fullscreen, must not close the modal.
fireEvent.keyDown(document, { key: 'Escape' });
expect(stage.classList.contains('ds-modal-fullscreen')).toBe(false);
expect(onClose).not.toHaveBeenCalled();
// Second Esc — closes the modal.
fireEvent.keyDown(document, { key: 'Escape' });
expect(onClose).toHaveBeenCalledTimes(1);
});
it('ignores fullscreenchange when another element is still fullscreen', () => {
const onClose = vi.fn();
const { container } = render(
<PreviewModal {...baseProps} onClose={onClose} />,
);
const fsButton = container.querySelector(
'button[title="Fullscreen"]',
) as HTMLButtonElement;
fireEvent.click(fsButton);
const stage = container.querySelector('.ds-modal') as HTMLElement;
expect(stage.classList.contains('ds-modal-fullscreen')).toBe(true);
// Some other element is the active fullscreen target — our overlay must
// not collapse to non-fullscreen on transitions that leave a different
// element fullscreen.
const other = document.createElement('div');
document.body.appendChild(other);
setNativeFullscreenElement(other);
dispatchFullscreenChange();
expect(stage.classList.contains('ds-modal-fullscreen')).toBe(true);
document.body.removeChild(other);
});
});
+92
View File
@@ -0,0 +1,92 @@
import { describe, expect, it } from 'vitest';
import { createClaudeStreamHandler } from '../../apps/daemon/src/claude-stream.js';
import { createCopilotStreamHandler } from '../../apps/daemon/src/copilot-stream.js';
import { mapPiRpcEvent } from '../../apps/daemon/src/pi-rpc.js';
describe('structured agent stream fixtures', () => {
it('emits TodoWrite tool_use from Claude Code stream JSON', () => {
const events: unknown[] = [];
const handler = createClaudeStreamHandler((event: unknown) => events.push(event));
handler.feed(`${JSON.stringify({
type: 'assistant',
message: {
id: 'msg-1',
content: [
{
type: 'tool_use',
id: 'toolu-1',
name: 'TodoWrite',
input: {
todos: [{ content: 'Run QA', status: 'pending' }],
},
},
],
},
})}\n`);
handler.flush();
expect(events).toContainEqual({
type: 'tool_use',
id: 'toolu-1',
name: 'TodoWrite',
input: {
todos: [{ content: 'Run QA', status: 'pending' }],
},
});
});
it('emits TodoWrite tool_use from Pi RPC tool_execution events', () => {
const events: unknown[] = [];
const send = (_channel: string, payload: unknown) => { events.push(payload); };
const ctx = { runStartedAt: Date.now(), sentFirstToken: { value: false } };
mapPiRpcEvent(
{ type: 'tool_execution_start', toolCallId: 'pi-call-1', toolName: 'TodoWrite', args: { todos: [{ content: 'Run QA', status: 'pending' }] } },
send,
ctx,
);
mapPiRpcEvent(
{ type: 'tool_execution_end', toolCallId: 'pi-call-1', toolName: 'TodoWrite', result: { content: [{ type: 'text', text: 'written' }] }, isError: false },
send,
ctx,
);
expect(events).toContainEqual({
type: 'tool_use',
id: 'pi-call-1',
name: 'TodoWrite',
input: { todos: [{ content: 'Run QA', status: 'pending' }] },
});
expect(events).toContainEqual({
type: 'tool_result',
toolUseId: 'pi-call-1',
content: 'written',
isError: false,
});
});
it('emits TodoWrite tool_use from GitHub Copilot CLI JSON stream', () => {
const events: unknown[] = [];
const handler = createCopilotStreamHandler((event: unknown) => events.push(event));
handler.feed(`${JSON.stringify({
type: 'tool.execution_start',
data: {
toolCallId: 'call-1',
toolName: 'TodoWrite',
arguments: {
todos: [{ content: 'Run QA', status: 'pending' }],
},
},
})}\n`);
handler.flush();
expect(events).toContainEqual({
type: 'tool_use',
id: 'call-1',
name: 'TodoWrite',
input: {
todos: [{ content: 'Run QA', status: 'pending' }],
},
});
});
});
+84
View File
@@ -0,0 +1,84 @@
import { describe, expect, it } from 'vitest';
import {
latestTodosFromEvents,
parseTodoWriteInput,
unfinishedTodosFromEvents,
} from '../../apps/web/src/runtime/todos';
import type { AgentEvent } from '../../apps/web/src/types';
const firstTodoInput = {
todos: [
{ content: 'Draft layout', status: 'completed' },
{ content: 'Build components', status: 'in_progress', activeForm: 'Building components' },
{ content: 'Run QA', status: 'pending' },
{ content: '', status: 'pending' },
{ content: 'Unknown status defaults pending', status: 'blocked' },
null,
],
};
describe('todo event helpers', () => {
it('normalizes TodoWrite input and ignores malformed items', () => {
expect(parseTodoWriteInput(firstTodoInput)).toEqual([
{ content: 'Draft layout', status: 'completed', activeForm: undefined },
{
content: 'Build components',
status: 'in_progress',
activeForm: 'Building components',
},
{ content: 'Run QA', status: 'pending', activeForm: undefined },
{
content: 'Unknown status defaults pending',
status: 'pending',
activeForm: undefined,
},
]);
});
it('uses the latest TodoWrite event as the current todo truth', () => {
const events: AgentEvent[] = [
{ kind: 'tool_use', id: 'todo-1', name: 'TodoWrite', input: firstTodoInput },
{ kind: 'text', text: 'Working...' },
{ kind: 'tool_use', id: 'todo-empty', name: 'TodoWrite', input: { todos: [] } },
{
kind: 'tool_use',
id: 'todo-2',
name: 'TodoWrite',
input: { todos: [{ content: 'Final polish', status: 'pending' }] },
},
];
expect(latestTodosFromEvents(events)).toEqual([
{ content: 'Final polish', status: 'pending', activeForm: undefined },
]);
});
it('treats an empty latest TodoWrite event as authoritative', () => {
const events: AgentEvent[] = [
{ kind: 'tool_use', id: 'todo-1', name: 'TodoWrite', input: firstTodoInput },
{ kind: 'text', text: 'All done.' },
{ kind: 'tool_use', id: 'todo-empty', name: 'TodoWrite', input: { todos: [] } },
];
expect(latestTodosFromEvents(events)).toEqual([]);
expect(unfinishedTodosFromEvents(events)).toEqual([]);
});
it('returns only pending and in-progress todos as unfinished', () => {
expect(unfinishedTodosFromEvents([
{ kind: 'tool_use', id: 'todo-1', name: 'TodoWrite', input: firstTodoInput },
])).toEqual([
{
content: 'Build components',
status: 'in_progress',
activeForm: 'Building components',
},
{ content: 'Run QA', status: 'pending', activeForm: undefined },
{
content: 'Unknown status defaults pending',
status: 'pending',
activeForm: undefined,
},
]);
});
});