checkpoint: pre-split branch cleanup
This commit is contained in:
parent
4c2ae2e5b7
commit
b5db7a7753
276 changed files with 35912 additions and 60119 deletions
|
|
@ -0,0 +1,12 @@
|
|||
import test from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import fs from 'node:fs/promises';
|
||||
import path from 'node:path';
|
||||
|
||||
test('dependency graph uses hide-closed filtered epics for epic chip strip', async () => {
|
||||
const file = await fs.readFile(path.join(process.cwd(), 'src/components/graph/dependency-graph-page.tsx'), 'utf8');
|
||||
|
||||
assert.ok(file.includes('const selectableEpics = useMemo'), 'expected selectableEpics memoized list');
|
||||
assert.ok(file.includes('epics={selectableEpics}'), 'expected EpicChipStrip to receive selectableEpics');
|
||||
assert.ok(file.includes('selectableEpics.some((epic) => epic.id === requestedEpicId)'), 'expected requested epic validation against selectable epics');
|
||||
});
|
||||
84
tests/components/shared/left-panel-filtering.test.ts
Normal file
84
tests/components/shared/left-panel-filtering.test.ts
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
import test from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
|
||||
import { shouldHideEpicEntry, type LeftPanelFilters } from '../../../src/components/shared/left-panel';
|
||||
|
||||
const defaultFilters: LeftPanelFilters = {
|
||||
query: '',
|
||||
status: 'all',
|
||||
priority: 'all',
|
||||
preset: 'all',
|
||||
hideClosed: true,
|
||||
};
|
||||
|
||||
test('does not hide epics with no children when hideClosed is the only active toggle', () => {
|
||||
const hidden = shouldHideEpicEntry({
|
||||
epicStatus: 'open',
|
||||
matchedChildrenCount: 0,
|
||||
totalChildrenCount: 0,
|
||||
isSelected: false,
|
||||
filters: defaultFilters,
|
||||
});
|
||||
|
||||
assert.equal(hidden, false);
|
||||
});
|
||||
|
||||
test('hides epics with only closed children when hideClosed is enabled', () => {
|
||||
const hidden = shouldHideEpicEntry({
|
||||
epicStatus: 'open',
|
||||
matchedChildrenCount: 0,
|
||||
totalChildrenCount: 4,
|
||||
isSelected: false,
|
||||
filters: defaultFilters,
|
||||
});
|
||||
|
||||
assert.equal(hidden, true);
|
||||
});
|
||||
|
||||
test('hides epic with children when query filter excludes all children', () => {
|
||||
const hidden = shouldHideEpicEntry({
|
||||
epicStatus: 'open',
|
||||
matchedChildrenCount: 0,
|
||||
totalChildrenCount: 3,
|
||||
isSelected: false,
|
||||
filters: { ...defaultFilters, query: 'nonexistent' },
|
||||
});
|
||||
|
||||
assert.equal(hidden, true);
|
||||
});
|
||||
|
||||
test('keeps selected epic visible even when no children match filters', () => {
|
||||
const hidden = shouldHideEpicEntry({
|
||||
epicStatus: 'open',
|
||||
matchedChildrenCount: 0,
|
||||
totalChildrenCount: 5,
|
||||
isSelected: true,
|
||||
filters: { ...defaultFilters, status: 'blocked' },
|
||||
});
|
||||
|
||||
assert.equal(hidden, false);
|
||||
});
|
||||
|
||||
test('hides closed epic even when it has no children', () => {
|
||||
const hidden = shouldHideEpicEntry({
|
||||
epicStatus: 'closed',
|
||||
matchedChildrenCount: 0,
|
||||
totalChildrenCount: 0,
|
||||
isSelected: false,
|
||||
filters: defaultFilters,
|
||||
});
|
||||
|
||||
assert.equal(hidden, true);
|
||||
});
|
||||
|
||||
test('hides closed selected epic when hideClosed is enabled', () => {
|
||||
const hidden = shouldHideEpicEntry({
|
||||
epicStatus: 'closed',
|
||||
matchedChildrenCount: 2,
|
||||
totalChildrenCount: 2,
|
||||
isSelected: true,
|
||||
filters: defaultFilters,
|
||||
});
|
||||
|
||||
assert.equal(hidden, true);
|
||||
});
|
||||
|
|
@ -1,66 +1,66 @@
|
|||
import { describe, it } from 'node:test';
|
||||
import assert from 'node:assert';
|
||||
|
||||
describe('LeftPanel Component Contract', () => {
|
||||
it('exports LeftPanel component', async () => {
|
||||
try {
|
||||
const mod = await import('../../../src/components/shared/left-panel');
|
||||
assert.ok(mod.LeftPanel, 'LeftPanel should be exported');
|
||||
assert.equal(typeof mod.LeftPanel, 'function', 'LeftPanel should be a function/component');
|
||||
} catch (err: any) {
|
||||
assert.fail(`LeftPanel module should exist: ${err.message}`);
|
||||
}
|
||||
});
|
||||
|
||||
it('LeftPanel accepts issues and onEpicSelect props', async () => {
|
||||
try {
|
||||
const mod = await import('../../../src/components/shared/left-panel');
|
||||
const LeftPanel = mod.LeftPanel;
|
||||
assert.ok(LeftPanel, 'Component should be callable');
|
||||
} catch (err: any) {
|
||||
assert.fail(`Component import failed: ${err.message}`);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('LeftPanel Tree Structure', () => {
|
||||
it('renders epics as expandable tree items', async () => {
|
||||
try {
|
||||
const mod = await import('../../../src/components/shared/left-panel');
|
||||
assert.ok(mod.LeftPanel, 'LeftPanel should exist');
|
||||
} catch (err: any) {
|
||||
assert.fail(`LeftPanel should render epic tree: ${err.message}`);
|
||||
}
|
||||
});
|
||||
|
||||
it('groups beads under their parent epic', async () => {
|
||||
try {
|
||||
const mod = await import('../../../src/components/shared/left-panel');
|
||||
assert.ok(mod.LeftPanel, 'LeftPanel should exist');
|
||||
} catch (err: any) {
|
||||
assert.fail(`LeftPanel should group beads under epics: ${err.message}`);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('LeftPanel Responsive Behavior', () => {
|
||||
it('applies responsive classes for desktop, tablet, and mobile', async () => {
|
||||
try {
|
||||
const mod = await import('../../../src/components/shared/left-panel');
|
||||
assert.ok(mod.LeftPanel, 'LeftPanel should exist');
|
||||
} catch (err: any) {
|
||||
assert.fail(`LeftPanel should have responsive classes: ${err.message}`);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('LeftPanel Scope Controls', () => {
|
||||
it('renders scope section', async () => {
|
||||
try {
|
||||
const mod = await import('../../../src/components/shared/left-panel');
|
||||
assert.ok(mod.LeftPanel, 'LeftPanel should exist');
|
||||
} catch (err: any) {
|
||||
assert.fail(`LeftPanel should render scope section: ${err.message}`);
|
||||
}
|
||||
});
|
||||
});
|
||||
import { describe, it } from 'node:test';
|
||||
import assert from 'node:assert';
|
||||
|
||||
describe('LeftPanel Component Contract', () => {
|
||||
it('exports LeftPanel component', async () => {
|
||||
try {
|
||||
const mod = await import('../../../src/components/shared/left-panel');
|
||||
assert.ok(mod.LeftPanel, 'LeftPanel should be exported');
|
||||
assert.equal(typeof mod.LeftPanel, 'function', 'LeftPanel should be a function/component');
|
||||
} catch (err: any) {
|
||||
assert.fail(`LeftPanel module should exist: ${err.message}`);
|
||||
}
|
||||
});
|
||||
|
||||
it('LeftPanel accepts issues and onEpicSelect props', async () => {
|
||||
try {
|
||||
const mod = await import('../../../src/components/shared/left-panel');
|
||||
const LeftPanel = mod.LeftPanel;
|
||||
assert.ok(LeftPanel, 'Component should be callable');
|
||||
} catch (err: any) {
|
||||
assert.fail(`Component import failed: ${err.message}`);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('LeftPanel Tree Structure', () => {
|
||||
it('renders epics as expandable tree items', async () => {
|
||||
try {
|
||||
const mod = await import('../../../src/components/shared/left-panel');
|
||||
assert.ok(mod.LeftPanel, 'LeftPanel should exist');
|
||||
} catch (err: any) {
|
||||
assert.fail(`LeftPanel should render epic tree: ${err.message}`);
|
||||
}
|
||||
});
|
||||
|
||||
it('groups beads under their parent epic', async () => {
|
||||
try {
|
||||
const mod = await import('../../../src/components/shared/left-panel');
|
||||
assert.ok(mod.LeftPanel, 'LeftPanel should exist');
|
||||
} catch (err: any) {
|
||||
assert.fail(`LeftPanel should group beads under epics: ${err.message}`);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('LeftPanel Responsive Behavior', () => {
|
||||
it('applies responsive classes for desktop, tablet, and mobile', async () => {
|
||||
try {
|
||||
const mod = await import('../../../src/components/shared/left-panel');
|
||||
assert.ok(mod.LeftPanel, 'LeftPanel should exist');
|
||||
} catch (err: any) {
|
||||
assert.fail(`LeftPanel should have responsive classes: ${err.message}`);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('LeftPanel Scope Controls', () => {
|
||||
it('renders scope section', async () => {
|
||||
try {
|
||||
const mod = await import('../../../src/components/shared/left-panel');
|
||||
assert.ok(mod.LeftPanel, 'LeftPanel should exist');
|
||||
} catch (err: any) {
|
||||
assert.fail(`LeftPanel should render scope section: ${err.message}`);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
import test from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import fs from 'node:fs/promises';
|
||||
import path from 'node:path';
|
||||
|
||||
test('UnifiedShell clears selected closed epic when hideClosed is enabled', async () => {
|
||||
const file = await fs.readFile(path.join(process.cwd(), 'src/components/shared/unified-shell.tsx'), 'utf8');
|
||||
|
||||
assert.ok(file.includes('if (epic.status === \'closed\' || epic.status === \'tombstone\')'), 'expected closed epic guard');
|
||||
assert.ok(file.includes('setEpicId(null);'), 'expected selected epic reset');
|
||||
});
|
||||
|
|
@ -1,16 +1,16 @@
|
|||
// @ts-ignore
|
||||
import { expect, test, describe, mock } from 'bun:test';
|
||||
|
||||
// Mock the hook that the component tries to import
|
||||
mock.module('@/hooks/use-url-state', () => ({
|
||||
useUrlState: () => ({ setUrlState: () => { }, swarmId: '1' })
|
||||
}));
|
||||
|
||||
describe('SwarmMissionPicker Component', () => {
|
||||
test('exports SwarmMissionPicker component that is a function', async () => {
|
||||
// @ts-ignore
|
||||
const mod = await import('../../../src/components/swarm/swarm-mission-picker');
|
||||
expect(mod.SwarmMissionPicker).toBeDefined();
|
||||
expect(typeof mod.SwarmMissionPicker).toBe('function');
|
||||
});
|
||||
});
|
||||
// @ts-ignore
|
||||
import { expect, test, describe, mock } from 'bun:test';
|
||||
|
||||
// Mock the hook that the component tries to import
|
||||
mock.module('@/hooks/use-url-state', () => ({
|
||||
useUrlState: () => ({ setUrlState: () => { }, swarmId: '1' })
|
||||
}));
|
||||
|
||||
describe('SwarmMissionPicker Component', () => {
|
||||
test('exports SwarmMissionPicker component that is a function', async () => {
|
||||
// @ts-ignore
|
||||
const mod = await import('../../../src/components/swarm/swarm-mission-picker');
|
||||
expect(mod.SwarmMissionPicker).toBeDefined();
|
||||
expect(typeof mod.SwarmMissionPicker).toBe('function');
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
// @ts-ignore
|
||||
import { expect, test, describe } from 'bun:test';
|
||||
|
||||
describe('SwarmWorkspace Component', () => {
|
||||
test('exports SwarmWorkspace component that is a function', async () => {
|
||||
// @ts-ignore
|
||||
const mod = await import('../../../src/components/swarm/swarm-workspace');
|
||||
expect(mod.SwarmWorkspace).toBeDefined();
|
||||
expect(typeof mod.SwarmWorkspace).toBe('function');
|
||||
});
|
||||
});
|
||||
// @ts-ignore
|
||||
import { expect, test, describe } from 'bun:test';
|
||||
|
||||
describe('SwarmWorkspace Component', () => {
|
||||
test('exports SwarmWorkspace component that is a function', async () => {
|
||||
// @ts-ignore
|
||||
const mod = await import('../../../src/components/swarm/swarm-workspace');
|
||||
expect(mod.SwarmWorkspace).toBeDefined();
|
||||
expect(typeof mod.SwarmWorkspace).toBe('function');
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,66 +1,66 @@
|
|||
import test from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import fs from 'fs/promises';
|
||||
import path from 'path';
|
||||
|
||||
// Test that the UnifiedShell component exists and exports correctly
|
||||
test('UnifiedShell - file exists and exports', async () => {
|
||||
const fileContent = await fs.readFile(path.join(process.cwd(), 'src/components/shared/unified-shell.tsx'), 'utf-8');
|
||||
assert.ok(fileContent.includes('export function UnifiedShell'), 'Should export UnifiedShell function');
|
||||
assert.ok(fileContent.includes('export interface UnifiedShellProps'), 'Should export UnifiedShellProps interface');
|
||||
});
|
||||
|
||||
// Test that UnifiedShell has assignMode state
|
||||
test('UnifiedShell - has assignMode state', async () => {
|
||||
const fileContent = await fs.readFile(path.join(process.cwd(), 'src/components/shared/unified-shell.tsx'), 'utf-8');
|
||||
assert.ok(fileContent.includes('assignMode'), 'Should have assignMode state');
|
||||
});
|
||||
|
||||
// Test that UnifiedShell has selectedAssignIssue state
|
||||
test('UnifiedShell - has selectedAssignIssue state', async () => {
|
||||
const fileContent = await fs.readFile(path.join(process.cwd(), 'src/components/shared/unified-shell.tsx'), 'utf-8');
|
||||
assert.ok(fileContent.includes('selectedAssignIssue'), 'Should have selectedAssignIssue state');
|
||||
});
|
||||
|
||||
// Test that SmartDag receives onAssignModeChange callback
|
||||
test('UnifiedShell - passes onAssignModeChange to SmartDag', async () => {
|
||||
const fileContent = await fs.readFile(path.join(process.cwd(), 'src/components/shared/unified-shell.tsx'), 'utf-8');
|
||||
assert.ok(fileContent.includes('onAssignModeChange'), 'Should pass onAssignModeChange to SmartDag');
|
||||
});
|
||||
|
||||
// Test that SmartDag receives onSelectedIssueChange callback
|
||||
test('UnifiedShell - passes onSelectedIssueChange to SmartDag', async () => {
|
||||
const fileContent = await fs.readFile(path.join(process.cwd(), 'src/components/shared/unified-shell.tsx'), 'utf-8');
|
||||
assert.ok(fileContent.includes('onSelectedIssueChange'), 'Should pass onSelectedIssueChange to SmartDag');
|
||||
});
|
||||
|
||||
// Test that AssignmentPanel is imported
|
||||
test('UnifiedShell - imports AssignmentPanel', async () => {
|
||||
const fileContent = await fs.readFile(path.join(process.cwd(), 'src/components/shared/unified-shell.tsx'), 'utf-8');
|
||||
assert.ok(fileContent.includes('AssignmentPanel'), 'Should import AssignmentPanel');
|
||||
});
|
||||
|
||||
test('UnifiedShell - checks bd health and renders setup warning', async () => {
|
||||
const fileContent = await fs.readFile(path.join(process.cwd(), 'src/components/shared/unified-shell.tsx'), 'utf-8');
|
||||
assert.ok(fileContent.includes('useBdHealth'), 'Should use bd health hook');
|
||||
assert.ok(fileContent.includes('BD setup issue:'), 'Should show bd setup warning text');
|
||||
});
|
||||
|
||||
// Test that AssignmentPanel is rendered conditionally based on view and assignMode
|
||||
test('UnifiedShell - renders AssignmentPanel conditionally', async () => {
|
||||
const fileContent = await fs.readFile(path.join(process.cwd(), 'src/components/shared/unified-shell.tsx'), 'utf-8');
|
||||
// Check for the condition: view === 'graph' && assignMode
|
||||
assert.ok(fileContent.includes("view === 'graph' && assignMode"), 'Should check view === graph && assignMode condition for AssignmentPanel');
|
||||
});
|
||||
|
||||
// Test that SwarmWorkspace import is removed (deprecated)
|
||||
test('UnifiedShell - does not import SwarmWorkspace', async () => {
|
||||
const fileContent = await fs.readFile(path.join(process.cwd(), 'src/components/shared/unified-shell.tsx'), 'utf-8');
|
||||
assert.ok(!fileContent.includes('SwarmWorkspace'), 'Should NOT import SwarmWorkspace (deprecated)');
|
||||
});
|
||||
|
||||
// Test that SwarmMissionPicker import is removed (deprecated)
|
||||
test('UnifiedShell - does not import SwarmMissionPicker', async () => {
|
||||
const fileContent = await fs.readFile(path.join(process.cwd(), 'src/components/shared/unified-shell.tsx'), 'utf-8');
|
||||
assert.ok(!fileContent.includes('SwarmMissionPicker'), 'Should NOT import SwarmMissionPicker (deprecated)');
|
||||
});
|
||||
import test from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import fs from 'fs/promises';
|
||||
import path from 'path';
|
||||
|
||||
// Test that the UnifiedShell component exists and exports correctly
|
||||
test('UnifiedShell - file exists and exports', async () => {
|
||||
const fileContent = await fs.readFile(path.join(process.cwd(), 'src/components/shared/unified-shell.tsx'), 'utf-8');
|
||||
assert.ok(fileContent.includes('export function UnifiedShell'), 'Should export UnifiedShell function');
|
||||
assert.ok(fileContent.includes('export interface UnifiedShellProps'), 'Should export UnifiedShellProps interface');
|
||||
});
|
||||
|
||||
// Test that UnifiedShell has assignMode state
|
||||
test('UnifiedShell - has assignMode state', async () => {
|
||||
const fileContent = await fs.readFile(path.join(process.cwd(), 'src/components/shared/unified-shell.tsx'), 'utf-8');
|
||||
assert.ok(fileContent.includes('assignMode'), 'Should have assignMode state');
|
||||
});
|
||||
|
||||
// Test that UnifiedShell has selectedAssignIssue state
|
||||
test('UnifiedShell - has selectedAssignIssue state', async () => {
|
||||
const fileContent = await fs.readFile(path.join(process.cwd(), 'src/components/shared/unified-shell.tsx'), 'utf-8');
|
||||
assert.ok(fileContent.includes('selectedAssignIssue'), 'Should have selectedAssignIssue state');
|
||||
});
|
||||
|
||||
// Test that SmartDag receives onAssignModeChange callback
|
||||
test('UnifiedShell - passes onAssignModeChange to SmartDag', async () => {
|
||||
const fileContent = await fs.readFile(path.join(process.cwd(), 'src/components/shared/unified-shell.tsx'), 'utf-8');
|
||||
assert.ok(fileContent.includes('onAssignModeChange'), 'Should pass onAssignModeChange to SmartDag');
|
||||
});
|
||||
|
||||
// Test that SmartDag receives onSelectedIssueChange callback
|
||||
test('UnifiedShell - passes onSelectedIssueChange to SmartDag', async () => {
|
||||
const fileContent = await fs.readFile(path.join(process.cwd(), 'src/components/shared/unified-shell.tsx'), 'utf-8');
|
||||
assert.ok(fileContent.includes('onSelectedIssueChange'), 'Should pass onSelectedIssueChange to SmartDag');
|
||||
});
|
||||
|
||||
// Test that AssignmentPanel is imported
|
||||
test('UnifiedShell - imports AssignmentPanel', async () => {
|
||||
const fileContent = await fs.readFile(path.join(process.cwd(), 'src/components/shared/unified-shell.tsx'), 'utf-8');
|
||||
assert.ok(fileContent.includes('AssignmentPanel'), 'Should import AssignmentPanel');
|
||||
});
|
||||
|
||||
test('UnifiedShell - checks bd health and renders setup warning', async () => {
|
||||
const fileContent = await fs.readFile(path.join(process.cwd(), 'src/components/shared/unified-shell.tsx'), 'utf-8');
|
||||
assert.ok(fileContent.includes('useBdHealth'), 'Should use bd health hook');
|
||||
assert.ok(fileContent.includes('BD setup issue:'), 'Should show bd setup warning text');
|
||||
});
|
||||
|
||||
// Test that AssignmentPanel is rendered conditionally based on view and assignMode
|
||||
test('UnifiedShell - renders AssignmentPanel conditionally', async () => {
|
||||
const fileContent = await fs.readFile(path.join(process.cwd(), 'src/components/shared/unified-shell.tsx'), 'utf-8');
|
||||
// Check for the condition: assignMode && !taskId
|
||||
assert.ok(fileContent.includes("assignMode && !taskId"), 'Should check assignMode && !taskId condition for AssignmentPanel');
|
||||
});
|
||||
|
||||
// Test that SwarmWorkspace import is removed (deprecated)
|
||||
test('UnifiedShell - does not import SwarmWorkspace', async () => {
|
||||
const fileContent = await fs.readFile(path.join(process.cwd(), 'src/components/shared/unified-shell.tsx'), 'utf-8');
|
||||
assert.ok(!fileContent.includes('SwarmWorkspace'), 'Should NOT import SwarmWorkspace (deprecated)');
|
||||
});
|
||||
|
||||
// Test that SwarmMissionPicker import is removed (deprecated)
|
||||
test('UnifiedShell - does not import SwarmMissionPicker', async () => {
|
||||
const fileContent = await fs.readFile(path.join(process.cwd(), 'src/components/shared/unified-shell.tsx'), 'utf-8');
|
||||
assert.ok(!fileContent.includes('SwarmMissionPicker'), 'Should NOT import SwarmMissionPicker (deprecated)');
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue