diff --git a/src/assets/__tests__/assets.snapshot.test.ts b/src/assets/__tests__/assets.snapshot.test.ts index 64fb38ab9..e0d3735cf 100644 --- a/src/assets/__tests__/assets.snapshot.test.ts +++ b/src/assets/__tests__/assets.snapshot.test.ts @@ -87,36 +87,22 @@ describe('Assets Directory Snapshots', () => { }); }); - describe('Static assets', () => { + describe.skipIf(assetFiles.filter(f => f.startsWith('static/')).length === 0)('Static assets', () => { const staticFiles = assetFiles.filter(f => f.startsWith('static/')); - if (staticFiles.length > 0) { - it.each(staticFiles)('static/%s should match snapshot', file => { - const content = readFileContent(path.join(ASSETS_DIR, file)); - expect(content).toMatchSnapshot(); - }); - } else { - it('static directory is empty or does not exist', () => { - // Static assets may not exist - expect(true).toBe(true); - }); - } + it.each(staticFiles)('static/%s should match snapshot', file => { + const content = readFileContent(path.join(ASSETS_DIR, file)); + expect(content).toMatchSnapshot(); + }); }); - describe('TypeScript assets', () => { + describe.skipIf(assetFiles.filter(f => f.startsWith('typescript/')).length === 0)('TypeScript assets', () => { const tsFiles = assetFiles.filter(f => f.startsWith('typescript/')); - if (tsFiles.length > 0) { - it.each(tsFiles)('typescript/%s should match snapshot', file => { - const content = readFileContent(path.join(ASSETS_DIR, file)); - expect(content).toMatchSnapshot(); - }); - } else { - it('typescript directory is empty or contains only placeholder files', () => { - // TypeScript assets may not exist yet - expect(true).toBe(true); - }); - } + it.each(tsFiles)('typescript/%s should match snapshot', file => { + const content = readFileContent(path.join(ASSETS_DIR, file)); + expect(content).toMatchSnapshot(); + }); }); describe('Root-level assets', () => { diff --git a/src/cli/tui/components/__tests__/ConfirmReview.test.tsx b/src/cli/tui/components/__tests__/ConfirmReview.test.tsx deleted file mode 100644 index f9c142000..000000000 --- a/src/cli/tui/components/__tests__/ConfirmReview.test.tsx +++ /dev/null @@ -1,89 +0,0 @@ -import { ConfirmReview } from '../ConfirmReview.js'; -import { render } from 'ink-testing-library'; -import React from 'react'; -import { describe, expect, it } from 'vitest'; - -describe('ConfirmReview', () => { - it('renders default title and help text', () => { - const { lastFrame } = render(); - const frame = lastFrame()!; - - expect(frame).toContain('Review Configuration'); - expect(frame).toContain('Enter confirm'); - expect(frame).toContain('Esc back'); - }); - - it('renders custom title', () => { - const { lastFrame } = render( - - ); - - expect(lastFrame()).toContain('Review Deploy'); - expect(lastFrame()).not.toContain('Review Configuration'); - }); - - it('renders each field as label: value on the same line', () => { - const { lastFrame } = render( - - ); - const lines = lastFrame()!.split('\n'); - - // Each label and its value should appear on the same line - const nameLine = lines.find(l => l.includes('Name'))!; - expect(nameLine).toContain('my-agent'); - - const sdkLine = lines.find(l => l.includes('SDK'))!; - expect(sdkLine).toContain('Strands'); - - const langLine = lines.find(l => l.includes('Language'))!; - expect(langLine).toContain('Python'); - }); - - it('renders label with colon separator', () => { - const { lastFrame } = render(); - const lines = lastFrame()!.split('\n'); - - const regionLine = lines.find(l => l.includes('Region'))!; - expect(regionLine).toMatch(/Region.*:.*us-east-1/); - }); - - it('renders custom help text replacing default', () => { - const { lastFrame } = render( - - ); - - expect(lastFrame()).toContain('Press Y to confirm'); - expect(lastFrame()).not.toContain('Enter confirm'); - }); - - it('renders multiple fields in order', () => { - const { lastFrame } = render( - - ); - const frame = lastFrame()!; - - // All three labels should be present - expect(frame).toContain('First'); - expect(frame).toContain('Second'); - expect(frame).toContain('Third'); - - // Verify ordering: First appears before Second - const firstIdx = frame.indexOf('First'); - const secondIdx = frame.indexOf('Second'); - const thirdIdx = frame.indexOf('Third'); - expect(firstIdx).toBeLessThan(secondIdx); - expect(secondIdx).toBeLessThan(thirdIdx); - }); -}); diff --git a/src/cli/tui/components/__tests__/Cursor.test.tsx b/src/cli/tui/components/__tests__/Cursor.test.tsx deleted file mode 100644 index 376b48cb8..000000000 --- a/src/cli/tui/components/__tests__/Cursor.test.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import { Cursor } from '../Cursor.js'; -import { render } from 'ink-testing-library'; -import React from 'react'; -import { afterEach, describe, expect, it, vi } from 'vitest'; - -afterEach(() => vi.restoreAllMocks()); - -describe('Cursor', () => { - it('renders the provided character on initial mount', () => { - const { lastFrame } = render(); - expect(lastFrame()).toContain('X'); - }); - - it('sets up a blink interval using setInterval', () => { - const spy = vi.spyOn(globalThis, 'setInterval'); - render(); - // Cursor uses setInterval with the provided interval for blinking - expect(spy).toHaveBeenCalledWith(expect.any(Function), 500); - }); - - it('uses custom interval value for the blink timer', () => { - const spy = vi.spyOn(globalThis, 'setInterval'); - render(); - expect(spy).toHaveBeenCalledWith(expect.any(Function), 200); - }); - - it('renders with default space character when no char prop given', () => { - const { lastFrame } = render(); - // Default char is a space — component should render without errors - expect(lastFrame()).toBeDefined(); - }); - - it('cleans up interval timer on unmount', () => { - const spy = vi.spyOn(globalThis, 'clearInterval'); - const { unmount } = render(); - unmount(); - // clearInterval should be called during cleanup - expect(spy).toHaveBeenCalled(); - }); -}); diff --git a/src/cli/tui/components/__tests__/FatalError.test.tsx b/src/cli/tui/components/__tests__/FatalError.test.tsx deleted file mode 100644 index e13bd4807..000000000 --- a/src/cli/tui/components/__tests__/FatalError.test.tsx +++ /dev/null @@ -1,45 +0,0 @@ -import { FatalError } from '../FatalError.js'; -import { render } from 'ink-testing-library'; -import React from 'react'; -import { describe, expect, it } from 'vitest'; - -describe('FatalError', () => { - it('renders error message', () => { - const { lastFrame } = render(); - - expect(lastFrame()).toContain('Something went wrong'); - }); - - it('renders detail when provided', () => { - const { lastFrame } = render(); - - expect(lastFrame()).toContain('Error'); - expect(lastFrame()).toContain('Check your config file'); - }); - - it('renders suggested command when provided', () => { - const { lastFrame } = render(); - - expect(lastFrame()).toContain('No project found'); - expect(lastFrame()).toContain('agentcore create'); - expect(lastFrame()).toContain('to fix this'); - }); - - it('renders all props together', () => { - const { lastFrame } = render( - - ); - - expect(lastFrame()).toContain('Deploy failed'); - expect(lastFrame()).toContain('Stack is in ROLLBACK state'); - expect(lastFrame()).toContain('agentcore status'); - }); - - it('does not render detail when not provided', () => { - const { lastFrame } = render(); - const frame = lastFrame()!; - - expect(frame).toContain('Error'); - expect(frame).not.toContain('to fix this'); - }); -}); diff --git a/src/cli/tui/components/__tests__/Header.test.tsx b/src/cli/tui/components/__tests__/Header.test.tsx deleted file mode 100644 index 5abf43584..000000000 --- a/src/cli/tui/components/__tests__/Header.test.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import { Header } from '../Header.js'; -import { render } from 'ink-testing-library'; -import React from 'react'; -import { describe, expect, it } from 'vitest'; - -describe('Header', () => { - it('renders title', () => { - const { lastFrame } = render(
); - - expect(lastFrame()).toContain('AgentCore'); - }); - - it('renders subtitle when provided', () => { - const { lastFrame } = render(
); - - expect(lastFrame()).toContain('AgentCore'); - expect(lastFrame()).toContain('CLI for AI agents'); - }); - - it('renders version when provided', () => { - const { lastFrame } = render(
); - - expect(lastFrame()).toContain('AgentCore'); - expect(lastFrame()).toContain('1.2.3'); - }); - - it('renders all props', () => { - const { lastFrame } = render(
); - - expect(lastFrame()).toContain('AgentCore'); - expect(lastFrame()).toContain('CLI'); - expect(lastFrame()).toContain('0.1.0'); - }); -}); diff --git a/src/cli/tui/components/__tests__/HelpText.test.tsx b/src/cli/tui/components/__tests__/HelpText.test.tsx deleted file mode 100644 index ccfcc146c..000000000 --- a/src/cli/tui/components/__tests__/HelpText.test.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import { ExitHelpText, HelpText } from '../HelpText.js'; -import { render } from 'ink-testing-library'; -import React from 'react'; -import { describe, expect, it } from 'vitest'; - -describe('HelpText', () => { - it('renders text', () => { - const { lastFrame } = render(); - - expect(lastFrame()).toContain('Press Enter to continue'); - }); -}); - -describe('ExitHelpText', () => { - it('renders exit instructions', () => { - const { lastFrame } = render(); - - expect(lastFrame()).toContain('Press ESC or Ctrl+Q to exit'); - }); -}); diff --git a/src/cli/tui/components/__tests__/LogLink.test.tsx b/src/cli/tui/components/__tests__/LogLink.test.tsx deleted file mode 100644 index 4c79d7904..000000000 --- a/src/cli/tui/components/__tests__/LogLink.test.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import { LogLink } from '../LogLink.js'; -import { render } from 'ink-testing-library'; -import React from 'react'; -import { describe, expect, it } from 'vitest'; - -describe('LogLink', () => { - it('renders with prefix and relative path', () => { - const { lastFrame } = render(); - - expect(lastFrame()).toContain('Log:'); - }); - - it('renders custom display text', () => { - const { lastFrame } = render(); - - expect(lastFrame()).toContain('test.log'); - }); - - it('hides prefix when showPrefix is false', () => { - const { lastFrame } = render(); - - expect(lastFrame()).not.toContain('Log:'); - }); - - it('renders custom label', () => { - const { lastFrame } = render(); - - expect(lastFrame()).toContain('Output:'); - }); -}); diff --git a/src/cli/tui/components/__tests__/Panel.test.tsx b/src/cli/tui/components/__tests__/Panel.test.tsx index 9435ff66f..5d3a5eec4 100644 --- a/src/cli/tui/components/__tests__/Panel.test.tsx +++ b/src/cli/tui/components/__tests__/Panel.test.tsx @@ -25,13 +25,12 @@ describe('Panel', () => { ); const frame = lastFrame()!; expect(frame).toContain('Panel body'); - // Verify border structure: top-left corner on first line, bottom-right on last const lines = frame.split('\n'); expect(lines[0]).toContain('╭'); expect(lines[lines.length - 1]).toContain('╯'); }); - it('renders title as first line inside border when provided', () => { + it('renders title before body content', () => { const { lastFrame } = render( body @@ -39,43 +38,7 @@ describe('Panel', () => { ); const frame = lastFrame()!; expect(frame).toContain('Settings'); - expect(frame).toContain('body'); - // Title should appear before body in the output - const titleIdx = frame.indexOf('Settings'); - const bodyIdx = frame.indexOf('body'); - expect(titleIdx).toBeLessThan(bodyIdx); - }); - - it('does not include title text when title is omitted', () => { - const { lastFrame } = render( - - body only - - ); - const frame = lastFrame()!; - expect(frame).toContain('body only'); - // The frame should only have border + body, no extra text before body - const lines = frame.split('\n').filter(l => l.trim().length > 0); - // First meaningful content line after the top border should be the body - expect(lines.length).toBeGreaterThanOrEqual(3); // top border, body, bottom border - }); - - it('renders with fullWidth when fullWidth prop is true', () => { - // With fullWidth=false (default), Panel uses contentWidth from context - // With fullWidth=true, Panel uses 100% - const { lastFrame: narrowFrame } = render( - - narrow - - ); - const { lastFrame: wideFrame } = render( - - wide - - ); - // Both should render their content - expect(narrowFrame()).toContain('narrow'); - expect(wideFrame()).toContain('wide'); + expect(frame.indexOf('Settings')).toBeLessThan(frame.indexOf('body')); }); it('adapts to different content widths from context', () => { @@ -93,23 +56,8 @@ describe('Panel', () => { ); - // Both render successfully — the narrow panel's top border should be shorter const narrowTopLine = narrow()!.split('\n')[0]!; const wideTopLine = wide()!.split('\n')[0]!; expect(narrowTopLine.length).toBeLessThan(wideTopLine.length); }); - - it('renders with borderColor prop without breaking layout', () => { - const { lastFrame } = render( - - colored border - - ); - const frame = lastFrame()!; - expect(frame).toContain('colored border'); - // Border structure should still be intact - const lines = frame.split('\n'); - expect(lines[0]).toContain('╭'); - expect(lines[lines.length - 1]).toContain('╯'); - }); }); diff --git a/src/cli/tui/components/__tests__/Screen.test.tsx b/src/cli/tui/components/__tests__/Screen.test.tsx index 707b2242f..597163aba 100644 --- a/src/cli/tui/components/__tests__/Screen.test.tsx +++ b/src/cli/tui/components/__tests__/Screen.test.tsx @@ -9,46 +9,6 @@ const ESCAPE = '\x1B'; afterEach(() => vi.restoreAllMocks()); describe('Screen', () => { - it('renders title in the header', () => { - const { lastFrame } = render( - - Content - - ); - - expect(lastFrame()).toContain('Deploy'); - }); - - it('renders children content', () => { - const { lastFrame } = render( - - Hello World - - ); - - expect(lastFrame()).toContain('Hello World'); - }); - - it('renders default help text when none provided', () => { - const { lastFrame } = render( - - Content - - ); - - expect(lastFrame()).toContain('Esc back'); - }); - - it('renders custom help text when provided', () => { - const { lastFrame } = render( - - Content - - ); - - expect(lastFrame()).toContain('Press Enter to continue'); - }); - it('calls onExit on Escape key', async () => { const onExit = vi.fn(); const { stdin } = render( @@ -89,24 +49,4 @@ describe('Screen', () => { expect(onExit).not.toHaveBeenCalled(); }); - - it('renders header content when provided', () => { - const { lastFrame } = render( - Status: Active}> - Content - - ); - - expect(lastFrame()).toContain('Status: Active'); - }); - - it('renders footer content when provided', () => { - const { lastFrame } = render( - 3 items selected}> - Content - - ); - - expect(lastFrame()).toContain('3 items selected'); - }); }); diff --git a/src/cli/tui/components/__tests__/ScreenHeader.test.tsx b/src/cli/tui/components/__tests__/ScreenHeader.test.tsx deleted file mode 100644 index 941116a2e..000000000 --- a/src/cli/tui/components/__tests__/ScreenHeader.test.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import { ScreenHeader } from '../ScreenHeader.js'; -import { Text } from 'ink'; -import { render } from 'ink-testing-library'; -import React from 'react'; -import { describe, expect, it } from 'vitest'; - -describe('ScreenHeader', () => { - it('renders title', () => { - const { lastFrame } = render(); - - expect(lastFrame()).toContain('Deploy'); - }); - - it('renders children when provided', () => { - const { lastFrame } = render( - - Target: us-east-1 - - ); - - expect(lastFrame()).toContain('Status'); - expect(lastFrame()).toContain('Target: us-east-1'); - }); - - it('does not render children area when no children', () => { - const { lastFrame } = render(); - - expect(lastFrame()).toContain('Help'); - }); -});