Skip to content

Conversation

@thomasyuill-livekit
Copy link
Contributor

@thomasyuill-livekit thomasyuill-livekit commented Jan 25, 2026

Implement comprehensive unit tests for shadcn components and hooks to ensure coverage of props, events, and HTML attributes.

This PR addresses Linear issue LK-3563 by setting up Vitest and @testing-library/react and adding tests for all components and hooks in packages/shadcn, covering explicit props, arguments, and general HTML attributes like styles, className, id, and basic event handlers.


Linear Issue: LK-3563

Open in Cursor Open in Web

Summary by CodeRabbit

Release Notes

  • New Features

    • Added inline style support to audio visualizer and chat indicator components for enhanced customization
    • Improved state handling in track toggle component with controlled and uncontrolled modes
  • Bug Fixes

    • Added safety check in disconnect button to prevent errors when ending sessions
  • Tests

    • Established comprehensive test infrastructure with Vitest configuration and test suites for core components and utilities

✏️ Tip: You can customize this high-level summary in your review settings.

cursoragent and others added 3 commits January 25, 2026 15:34
- Add vitest config and test setup
- Add tests for button, toggle, tooltip, separator, alert, button-group
- Add tests for agent-chat-indicator and start-audio-button
- Configure testing infrastructure with @testing-library/react

Co-authored-by: thomas.yuill <thomas.yuill@livekit.io>
- Add tests for agent-track-toggle and agent-audio-visualizer-bar
- Add tests for use-agent-audio-visualizer-aura hook
- Add tests for message components and utils
- Add comprehensive prop and event handler tests

Co-authored-by: thomas.yuill <thomas.yuill@livekit.io>
- Add tests for all UI components (button, toggle, tooltip, separator, alert, button-group)
- Add tests for agent UI components (chat indicator, track toggle, audio visualizer bar, start audio button)
- Add tests for agent hooks (use-agent-audio-visualizer-aura, use-agent-audio-visualizer-bar)
- Add tests for AI elements (message components)
- Add tests for utils (cn function)
- Configure vitest with React plugin and mocks for ResizeObserver/IntersectionObserver
- 248 tests passing with comprehensive prop, event handler, and attribute testing

Co-authored-by: thomas.yuill <thomas.yuill@livekit.io>
@cursor
Copy link

cursor bot commented Jan 25, 2026

Cursor Agent can help with this pull request. Just @cursor in comments and I'll start working on changes in this branch.
Learn more about Cursor Agents

@changeset-bot
Copy link

changeset-bot bot commented Jan 25, 2026

⚠️ No Changeset found

Latest commit: 9262b54

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@CLAassistant
Copy link

CLAassistant commented Jan 25, 2026

CLA assistant check
All committers have signed the CLA.

@coderabbitai
Copy link

coderabbitai bot commented Jan 25, 2026

📝 Walkthrough

Walkthrough

This PR adds style prop support to multiple agent UI components and establishes comprehensive testing infrastructure with Vitest, including test suites for components and hooks.

Changes

Cohort / File(s) Summary
Style prop forwarding
packages/shadcn/components/agents-ui/agent-audio-visualizer-bar.tsx, agent-audio-visualizer-radial.tsx, agent-audio-visualizer-wave.tsx, agent-chat-indicator.tsx, agent-disconnect-button.tsx, start-audio-button.tsx
Destructure and forward style prop to root/underlying DOM elements, enabling inline styling without altering logic or behavior.
AgentTrackToggle state management
packages/shadcn/components/agents-ui/agent-track-toggle.tsx
Add controlled vs uncontrolled state handling for pressed via internal uncontrolledPressed state; compute resolvedPressed using useMemo; introduce handlePressedChange for safe updates; conditionally pass pressed/defaultPressed to Toggle based on control status.
Testing infrastructure
packages/shadcn/vitest.config.ts, vitest.setup.ts, packages/shadcn/package.json
Add Vitest configuration with React plugin, jsdom test environment, setup file, coverage config (v8, text/json/html reporters); define test/test:watch/test:coverage scripts; add @testing-library/*, vitest, jsdom, @vitest/coverage-v8, @vitejs/plugin-react dev dependencies.
Component test suites
packages/shadcn/tests/agent-audio-visualizer-{aura,bar,grid,radial,wave}.test.tsx, agent-chat-{indicator,transcript}.test.tsx, agent-control-bar.test.tsx, agent-disconnect-button.test.tsx, agent-session-provider.test.tsx, agent-track-toggle.test.tsx, react-shader-toy.test.tsx, start-audio-button.test.tsx
Add comprehensive test suites covering rendering, prop variants, HTML attributes, event handling, state management, audio track integration, and combined prop interactions across agent UI components.
Hook test suites
packages/shadcn/tests/use-agent-audio-visualizer-{aura,bar,grid,radial,wave}.test.ts
Add extensive unit tests for audio visualizer hooks, validating state-based animation values, audio track integration, state transitions, return value correctness, and hook stability.
Utility tests
packages/shadcn/tests/utils.test.ts
Add comprehensive test suite for the cn utility function covering class merging, Tailwind conflicts, conditional classes, and edge cases.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant AgentTrackToggle
    participant InternalState as Internal State
    participant Toggle
    participant Callback

    alt Uncontrolled Mode (no pressed prop)
        User->>AgentTrackToggle: User interacts (click)
        AgentTrackToggle->>InternalState: handlePressedChange triggered
        InternalState->>InternalState: Update uncontrolledPressed state
        AgentTrackToggle->>Callback: Call onPressedChange (if provided)
        AgentTrackToggle->>Toggle: Pass defaultPressed + updated state
    else Controlled Mode (pressed prop provided)
        User->>AgentTrackToggle: User interacts (click)
        AgentTrackToggle->>Callback: Call onPressedChange (if provided)
        AgentTrackToggle->>Toggle: Pass controlled pressed prop
        Callback->>User: Parent updates pressed prop
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • livekit/components-js#1273: Makes overlapping code-level changes to agent UI components (Wave/WaveShader, AgentTrackToggle) with similar style prop and state management enhancements.
  • livekit/components-js#1266: Introduces agent audio visualizer components (wave, aura, radial, bar) that are now receiving style prop updates and test coverage in this PR.

Suggested reviewers

  • 1egoman
  • lukasIO
  • mattherzog

Poem

🐰 Hop, hop, the styles now flow,
Tests are written, watch them grow!
Props and states, controlled with grace,
Coverage blooming, tests embrace!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'Shadcn components unit tests' directly and accurately describes the primary change—adding comprehensive unit tests for shadcn components and hooks.
Docstring Coverage ✅ Passed Docstring coverage is 85.71% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Contributor

github-actions bot commented Jan 25, 2026

size-limit report 📦

Path Size
LiveKitRoom only 6 KB (0%)
LiveKitRoom with VideoConference 32.46 KB (0%)
All exports 43.37 KB (0%)

cursoragent and others added 2 commits January 25, 2026 15:57
- Remove tests for external dependencies (UI components, AI elements)
- Add tests for all agent audio visualizers (bar, wave, grid, radial, aura)
- Add tests for all agent UI components (chat indicator, disconnect button, session provider, track toggle, start audio button)
- Add tests for all agent hooks (use-agent-audio-visualizer-aura, bar, wave, grid, radial)
- Configure vitest with React plugin and proper mocks
- 138 total tests with 132 passing (95.7% pass rate)
- Comprehensive testing of props, events, HTML attributes, and state management

Co-authored-by: thomas.yuill <thomas.yuill@livekit.io>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 9

🤖 Fix all issues with AI agents
In `@packages/shadcn/components/agents-ui/agent-audio-visualizer-wave.test.tsx`:
- Around line 54-58: The test description is misleading: the default size for
AgentAudioVisualizerWave is lg, not md; update the test name in the it(...) call
in agent-audio-visualizer-wave.test.tsx (the test that renders
<AgentAudioVisualizerWave /> and asserts
expect(visualizer).toHaveClass('h-[224px]')) to reflect "lg" (e.g., change
"applies md size styles by default" to "applies lg size styles by default") so
the description matches the asserted class.

In `@packages/shadcn/components/agents-ui/agent-session-provider.test.tsx`:
- Around line 1-15: The tests currently reuse the mock call history
(roomAudioRendererMock and any vi mocks), which can cause cross-test leakage;
add a test setup hook (e.g., beforeEach) to clear mock state before each test by
calling vi.clearAllMocks() or explicitly roomAudioRendererMock.mockClear() so
each test starts with a fresh mock invocation state and assertions on
roomAudioRendererMock (and other vi mocks) reflect only the current test.

In `@packages/shadcn/components/agents-ui/react-shader-toy.test.tsx`:
- Around line 6-19: The test leaks mocked state and globals between tests:
afterEach should clear the getContextMock call history and restore any
overwritten globals. Add persistent variables to capture the originals for
requestAnimationFrame and cancelAnimationFrame (e.g.,
originalRequestAnimationFrame/originalCancelAnimationFrame), set the mocked
values in beforeEach as now, then in afterEach call getContextMock.mockClear()
(or vi.clearAllMocks()) and restore globalThis.requestAnimationFrame and
globalThis.cancelAnimationFrame back to the saved originals, while still calling
vi.restoreAllMocks() to remove spies.

In `@packages/shadcn/hooks/agents-ui/use-agent-audio-visualizer-aura.test.ts`:
- Around line 23-27: The mock for the animation control includes a then property
which makes the object thenable and can interfere with Promise/async behavior;
update the mock returned by the animate mock (the vi.fn() that returns { stop:
vi.fn(), then: vi.fn() }) to remove the then property (or rename it to a
non-then identifier if you need to assert on it), ensuring tests only mock the
actual animation API methods like stop.

In `@packages/shadcn/hooks/agents-ui/use-agent-audio-visualizer-bar.test.ts`:
- Around line 6-12: The tests call vi.useFakeTimers() in beforeEach but only
call vi.restoreAllMocks() in afterEach, which leaves fake timers active; update
the afterEach to call vi.useRealTimers() (e.g., invoke vi.useRealTimers() before
or alongside vi.restoreAllMocks()) so fake timers are reverted after each test;
reference the beforeEach/afterEach hooks and the vi.useFakeTimers,
vi.useRealTimers, and vi.restoreAllMocks calls in
use-agent-audio-visualizer-bar.test.ts to make the change.

In `@packages/shadcn/hooks/agents-ui/use-agent-audio-visualizer-grid.test.ts`:
- Around line 10-12: The test teardown currently calls vi.restoreAllMocks() in
the afterEach block but doesn't restore timers; add vi.useRealTimers() alongside
vi.restoreAllMocks() in the afterEach to undo the vi.useFakeTimers() set in
beforeEach (update the afterEach that contains vi.restoreAllMocks() to also call
vi.useRealTimers()).

In `@packages/shadcn/hooks/agents-ui/use-agent-audio-visualizer-radial.test.ts`:
- Around line 6-12: The test setup uses vi.useFakeTimers() in beforeEach but
only calls vi.restoreAllMocks() in afterEach, which doesn't restore timers;
update the afterEach to also call vi.useRealTimers() (or
vi.runOnlyPendingTimers() then vi.useRealTimers() if pending timers must be
flushed) so fake timers from useFakeTimers() are reverted; modify the afterEach
that currently calls vi.restoreAllMocks() to include vi.useRealTimers() and
optionally flush pending timers to avoid leaking fake timers into other tests.

In `@packages/shadcn/hooks/agents-ui/use-agent-audio-visualizer-wave.test.ts`:
- Around line 15-24: The animate mock currently returns an object with a then
property which triggers the lint rule; change the animate mock in the vi.mock
block (the animate vi.fn) to return a real Promise (e.g., a Promise that
resolves immediately) and attach a stop method to that Promise (e.g.,
promise.stop = vi.fn()) so callers can call stop and await then() without
triggering lint/suspicious/noThenProperty; update only the animate mock while
keeping useMotionValue and useMotionValueEvent mocks unchanged.

In `@packages/shadcn/package.json`:
- Around line 56-70: The dependency entry for `@vitest/coverage-v8` is pinned to
"^3.0.0" but vitest is "^3.2.4"; update the `@vitest/coverage-v8` version string
to "^3.2.4" in package.json (change the "@vitest/coverage-v8": "^3.0.0" entry to
"@vitest/coverage-v8": "^3.2.4") so the peer dependency range aligns with the
vitest version.
🧹 Nitpick comments (8)
packages/shadcn/components/agents-ui/agent-session-provider.test.tsx (1)

51-90: Assert prop propagation instead of only presence checks.

The “passes session prop” and “passes room prop” tests don’t actually validate the props. Consider spying on SessionProvider and inspecting the RoomAudioRenderer call args.

✅ Suggested approach
-const roomAudioRendererMock = vi.fn((props: any) => (
+const sessionProviderMock = vi.fn(({ children, ...props }: any) => (
+  <div data-testid="session-provider" {...props}>{children}</div>
+));
+const roomAudioRendererMock = vi.fn((props: any) => (
   <div data-testid="room-audio-renderer" {...props} />
 ));
@@
 vi.mock('@livekit/components-react', () => ({
-  SessionProvider: ({ children }: any) => <div data-testid="session-provider">{children}</div>,
+  SessionProvider: (props: any) => sessionProviderMock(props),
   RoomAudioRenderer: (props: any) => roomAudioRendererMock(props),
 }));
@@
     it('passes session prop to SessionProvider', () => {
       const session = { room: null, state: 'connected' } as any;
       render(
         <AgentSessionProvider session={session}>
           <div>Content</div>
         </AgentSessionProvider>
       );
-      expect(screen.getByTestId('session-provider')).toBeInTheDocument();
+      const lastCall = sessionProviderMock.mock.calls.at(-1)?.[0] ?? {};
+      expect(lastCall).toEqual(expect.objectContaining({ session }));
     });
@@
     it('passes room prop to RoomAudioRenderer', () => {
       const mockRoom = {} as any;
       render(
         <AgentSessionProvider session={mockSession} room={mockRoom}>
           <div>Content</div>
         </AgentSessionProvider>
       );
-      expect(screen.getByTestId('room-audio-renderer')).toBeInTheDocument();
+      const lastCall = roomAudioRendererMock.mock.calls.at(-1)?.[0] ?? {};
+      expect(lastCall).toEqual(expect.objectContaining({ room: mockRoom }));
     });
packages/shadcn/vitest.setup.ts (1)

2-2: Unused import.

The React import is not used in this setup file. It can be removed unless there's a specific reason to keep it (e.g., ensuring React is in scope for JSX transforms in other setup scenarios).

Suggested fix
 import '@testing-library/jest-dom/vitest';
-import React from 'react';
packages/shadcn/components/agents-ui/agent-control-bar.test.tsx (1)

130-141: Consider setting isConnected in the chat message test.

The test renders AgentControlBar with isChatOpen but without isConnected. While this works because the chat input is rendered based on isChatOpen, it may be worth explicitly setting isConnected={true} to better reflect a realistic usage scenario where a user would be connected when sending messages.

Suggested improvement
   it('sends chat messages when chat is open', async () => {
     const user = userEvent.setup();
-    render(<AgentControlBar isChatOpen />);
+    render(<AgentControlBar isChatOpen isConnected />);

     const input = screen.getByPlaceholderText('Type something...');
packages/shadcn/components/agents-ui/agent-chat-transcript.test.tsx (1)

64-67: Consider adding a negative test case for the thinking indicator.

The test verifies the indicator appears when agentState="thinking", but there's no test confirming it's absent for other states. This would strengthen confidence in the conditional rendering logic.

Suggested additional test
  it('does not show thinking indicator when agent is not thinking', () => {
    render(<AgentChatTranscript agentState="idle" />);
    expect(screen.queryByTestId('chat-indicator')).not.toBeInTheDocument();
  });
packages/shadcn/components/agents-ui/agent-chat-indicator.test.tsx (1)

59-63: Assert the style prop is applied, not just rendered.
The test currently only checks presence; it should validate that inline styles are forwarded to the DOM.

Proposed test tightening
-      expect(indicator).toBeInTheDocument();
+      expect(indicator).toHaveStyle({ backgroundColor: 'red' });
packages/shadcn/components/agents-ui/agent-disconnect-button.test.tsx (1)

129-133: Validate that style is applied, not just rendered.
This test should assert the inline style value to confirm forwarding.

Proposed test tightening
-      expect(button).toBeInTheDocument();
+      expect(button).toHaveStyle({ backgroundColor: 'blue' });
packages/shadcn/hooks/agents-ui/use-agent-audio-visualizer-grid.test.ts (1)

37-72: Consider adding tests that advance fake timers to verify sequence progression.

The hook uses setInterval to animate through sequences for non-speaking states. You could strengthen coverage by using vi.advanceTimersByTime() to verify coordinates change over time.

Example:

it('progresses through sequence over time for connecting state', () => {
  const { result } = renderHook(() =>
    useAgentAudioVisualizerGridAnimator('connecting', 5, 5, 100)
  );
  
  const initialCoord = { ...result.current };
  vi.advanceTimersByTime(100);
  // Verify coordinate changed or sequence progressed
});
packages/shadcn/components/agents-ui/agent-audio-visualizer-radial.tsx (1)

124-136: Nitpick: Unused dependency in useMemo.

_barCount is included in the dependency array but isn't used in the sequencerInterval computation. This is pre-existing code, but could be cleaned up.

Suggested fix
   const sequencerInterval = useMemo(() => {
     switch (state) {
       case 'connecting':
       case 'listening':
         return 500;
       case 'initializing':
         return 250;
       case 'thinking':
         return Infinity;
       default:
         return 1000;
     }
-  }, [state, _barCount]);
+  }, [state]);
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a0afe15 and 9b3ac1f.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (29)
  • packages/shadcn/components/agents-ui/agent-audio-visualizer-aura.test.tsx
  • packages/shadcn/components/agents-ui/agent-audio-visualizer-bar.test.tsx
  • packages/shadcn/components/agents-ui/agent-audio-visualizer-bar.tsx
  • packages/shadcn/components/agents-ui/agent-audio-visualizer-grid.test.tsx
  • packages/shadcn/components/agents-ui/agent-audio-visualizer-radial.test.tsx
  • packages/shadcn/components/agents-ui/agent-audio-visualizer-radial.tsx
  • packages/shadcn/components/agents-ui/agent-audio-visualizer-wave.test.tsx
  • packages/shadcn/components/agents-ui/agent-audio-visualizer-wave.tsx
  • packages/shadcn/components/agents-ui/agent-chat-indicator.test.tsx
  • packages/shadcn/components/agents-ui/agent-chat-indicator.tsx
  • packages/shadcn/components/agents-ui/agent-chat-transcript.test.tsx
  • packages/shadcn/components/agents-ui/agent-control-bar.test.tsx
  • packages/shadcn/components/agents-ui/agent-disconnect-button.test.tsx
  • packages/shadcn/components/agents-ui/agent-disconnect-button.tsx
  • packages/shadcn/components/agents-ui/agent-session-provider.test.tsx
  • packages/shadcn/components/agents-ui/agent-track-toggle.test.tsx
  • packages/shadcn/components/agents-ui/agent-track-toggle.tsx
  • packages/shadcn/components/agents-ui/react-shader-toy.test.tsx
  • packages/shadcn/components/agents-ui/start-audio-button.test.tsx
  • packages/shadcn/components/agents-ui/start-audio-button.tsx
  • packages/shadcn/hooks/agents-ui/use-agent-audio-visualizer-aura.test.ts
  • packages/shadcn/hooks/agents-ui/use-agent-audio-visualizer-bar.test.ts
  • packages/shadcn/hooks/agents-ui/use-agent-audio-visualizer-grid.test.ts
  • packages/shadcn/hooks/agents-ui/use-agent-audio-visualizer-radial.test.ts
  • packages/shadcn/hooks/agents-ui/use-agent-audio-visualizer-wave.test.ts
  • packages/shadcn/lib/utils.test.ts
  • packages/shadcn/package.json
  • packages/shadcn/vitest.config.ts
  • packages/shadcn/vitest.setup.ts
🧰 Additional context used
🧬 Code graph analysis (21)
packages/shadcn/components/agents-ui/agent-audio-visualizer-aura.test.tsx (1)
packages/shadcn/components/agents-ui/agent-audio-visualizer-aura.tsx (1)
  • AgentAudioVisualizerAura (411-449)
packages/shadcn/components/agents-ui/agent-audio-visualizer-grid.test.tsx (1)
packages/shadcn/components/agents-ui/agent-audio-visualizer-grid.tsx (1)
  • AgentAudioVisualizerGrid (239-290)
packages/shadcn/components/agents-ui/start-audio-button.test.tsx (1)
packages/shadcn/components/agents-ui/start-audio-button.tsx (1)
  • StartAudioButton (42-58)
packages/shadcn/lib/utils.test.ts (1)
packages/shadcn/lib/utils.ts (1)
  • cn (4-6)
packages/shadcn/vitest.config.ts (1)
docs/storybook/.storybook/main.js (1)
  • path (2-2)
packages/shadcn/components/agents-ui/agent-chat-transcript.test.tsx (1)
packages/shadcn/components/agents-ui/agent-chat-transcript.tsx (1)
  • AgentChatTranscript (47-78)
packages/shadcn/components/agents-ui/agent-disconnect-button.test.tsx (1)
packages/shadcn/components/agents-ui/agent-disconnect-button.tsx (1)
  • AgentDisconnectButton (51-72)
packages/shadcn/components/agents-ui/agent-chat-indicator.tsx (1)
packages/shadcn/lib/utils.ts (1)
  • cn (4-6)
packages/shadcn/hooks/agents-ui/use-agent-audio-visualizer-aura.test.ts (1)
packages/shadcn/hooks/agents-ui/use-agent-audio-visualizer-aura.ts (1)
  • useAgentAudioVisualizerAura (46-124)
packages/shadcn/components/agents-ui/react-shader-toy.test.tsx (1)
packages/shadcn/components/agents-ui/react-shader-toy.tsx (1)
  • ReactShaderToy (466-943)
packages/shadcn/components/agents-ui/agent-audio-visualizer-wave.test.tsx (1)
packages/shadcn/components/agents-ui/agent-audio-visualizer-wave.tsx (1)
  • AgentAudioVisualizerWave (279-330)
packages/shadcn/hooks/agents-ui/use-agent-audio-visualizer-radial.test.ts (1)
packages/shadcn/hooks/agents-ui/use-agent-audio-visualizer-radial.ts (1)
  • useAgentAudioVisualizerRadialAnimator (25-73)
packages/shadcn/components/agents-ui/agent-disconnect-button.tsx (1)
packages/shadcn/components/ui/button.tsx (1)
  • Button (57-57)
packages/shadcn/components/agents-ui/agent-track-toggle.test.tsx (1)
packages/shadcn/components/agents-ui/agent-track-toggle.tsx (1)
  • AgentTrackToggle (118-166)
packages/shadcn/hooks/agents-ui/use-agent-audio-visualizer-grid.test.ts (1)
packages/shadcn/hooks/agents-ui/use-agent-audio-visualizer-grid.ts (1)
  • useAgentAudioVisualizerGridAnimator (66-116)
packages/shadcn/components/agents-ui/agent-audio-visualizer-bar.test.tsx (1)
packages/shadcn/components/agents-ui/agent-audio-visualizer-bar.tsx (1)
  • AgentAudioVisualizerBar (118-201)
packages/shadcn/hooks/agents-ui/use-agent-audio-visualizer-wave.test.ts (1)
packages/shadcn/hooks/agents-ui/use-agent-audio-visualizer-wave.ts (1)
  • useAgentAudioVisualizerWave (43-110)
packages/shadcn/hooks/agents-ui/use-agent-audio-visualizer-bar.test.ts (1)
packages/shadcn/hooks/agents-ui/use-agent-audio-visualizer-bar.ts (1)
  • useAgentAudioVisualizerBarAnimator (21-70)
packages/shadcn/components/agents-ui/agent-chat-indicator.test.tsx (1)
packages/shadcn/components/agents-ui/agent-chat-indicator.tsx (1)
  • AgentChatIndicator (77-92)
packages/shadcn/components/agents-ui/agent-control-bar.test.tsx (1)
packages/shadcn/components/agents-ui/agent-control-bar.tsx (1)
  • AgentControlBar (243-407)
packages/shadcn/components/agents-ui/agent-audio-visualizer-bar.tsx (1)
packages/shadcn/lib/utils.ts (1)
  • cn (4-6)
🪛 Biome (2.1.2)
packages/shadcn/hooks/agents-ui/use-agent-audio-visualizer-aura.test.ts

[error] 25-25: Do not add then to an object.

(lint/suspicious/noThenProperty)

packages/shadcn/hooks/agents-ui/use-agent-audio-visualizer-wave.test.ts

[error] 23-23: Do not add then to an object.

(lint/suspicious/noThenProperty)

🔇 Additional comments (29)
packages/shadcn/components/agents-ui/react-shader-toy.test.tsx (3)

21-28: LGTM — solid render smoke test.


30-40: Good async assertion for WebGL initialization.


42-52: Nice coverage of style prop propagation.

packages/shadcn/vitest.setup.ts (1)

5-19: LGTM!

The browser API mocks for ResizeObserver and IntersectionObserver are appropriate for testing Radix UI components in a jsdom environment. The minimal implementations cover the standard observer interface methods.

packages/shadcn/components/agents-ui/agent-audio-visualizer-aura.test.tsx (1)

21-44: LGTM!

The test suite covers essential rendering scenarios: default props, size variants, and className merging. The mocking approach properly isolates the component under test from its dependencies.

packages/shadcn/vitest.config.ts (1)

5-27: LGTM!

The Vitest configuration is well-structured with appropriate settings for a React component library:

  • React plugin integration for JSX support
  • jsdom environment for DOM testing
  • Sensible coverage exclusions
  • Path alias matching the package structure
packages/shadcn/components/agents-ui/agent-control-bar.test.tsx (1)

84-128: LGTM!

The test suite effectively covers core behaviors:

  • Default control rendering with proper element counts
  • Disconnect button disabled state when not connected
  • Edge case handling (all controls false) with console warning verification

The mocking strategy properly isolates the component from its dependencies.

packages/shadcn/components/agents-ui/agent-chat-indicator.tsx (1)

77-91: LGTM!

The explicit style prop destructuring and forwarding aligns with the pattern used across other agent UI components in this PR. This ensures inline styles are reliably applied to the underlying motion.span element.

packages/shadcn/components/agents-ui/agent-chat-transcript.test.tsx (1)

35-72: LGTM!

The test suite effectively covers core transcript functionality:

  • Message rendering with correct origin attribution (user vs assistant)
  • Thinking indicator presence when appropriate
  • Scroll button rendering

The mocking approach properly isolates the component from its sub-components while maintaining testable interfaces via data-testid attributes.

packages/shadcn/components/agents-ui/agent-chat-indicator.test.tsx (1)

7-49: Solid baseline rendering and size-variant coverage.
This set of tests cleanly validates default render and size class mappings.

packages/shadcn/hooks/agents-ui/use-agent-audio-visualizer-bar.test.ts (1)

14-236: Comprehensive state/edge-case coverage looks strong.
The suite hits key states, transitions, and edge cases effectively.

packages/shadcn/hooks/agents-ui/use-agent-audio-visualizer-radial.test.ts (1)

14-188: Nice breadth across states, counts, and edge cases.
This provides strong behavioral coverage for the animator.

packages/shadcn/components/agents-ui/agent-disconnect-button.tsx (1)

51-68: Style prop forwarding is a clean API extension.
Nice consistency with other agents-ui components.

packages/shadcn/components/agents-ui/agent-disconnect-button.test.tsx (1)

159-203: Event-handler coverage is thorough.
Good validation of onClick + session end interactions and disabled behavior.

packages/shadcn/lib/utils.test.ts (1)

4-177: Great coverage of cn edge cases and Tailwind merges.
The scenarios are broad and practical.

packages/shadcn/hooks/agents-ui/use-agent-audio-visualizer-aura.test.ts (1)

29-227: Well-structured test suite with comprehensive coverage.

The tests thoroughly cover:

  • All agent states with correct expected speed values matching the implementation
  • Audio track integration with proper option verification
  • State transitions with appropriate async handling
  • Hook stability and return value validation
packages/shadcn/hooks/agents-ui/use-agent-audio-visualizer-grid.test.ts (1)

14-35: Good test coverage for grid animator hook.

The tests appropriately cover coordinate bounds validation, various grid sizes, the radius parameter, edge cases (1x1 and large grids), and speaking state center behavior.

Also applies to: 74-186

packages/shadcn/package.json (1)

12-15: Test infrastructure setup looks good.

The test scripts and testing library dependencies are appropriate for a Vitest + React Testing Library setup.

Also applies to: 48-50

packages/shadcn/components/agents-ui/agent-audio-visualizer-bar.tsx (1)

118-129: Style prop forwarding is correctly implemented.

The style prop is properly destructured and applied to the root div, inheriting its type from the ComponentProps<'div'> intersection. This aligns with the style propagation pattern applied to other visualizer components in this PR.

Also applies to: 175-180

packages/shadcn/components/agents-ui/start-audio-button.tsx (1)

51-54: Style merging implementation is correct.

The merged style properly prioritizes mergedProps.style over props.style, ensuring hook-controlled styles take precedence. Explicitly setting style={mergedStyle} after the spreads guarantees the intended merge behavior.

packages/shadcn/components/agents-ui/agent-audio-visualizer-radial.tsx (1)

100-104: Style prop forwarding is correctly implemented.

The style prop is properly destructured and applied to the root div, consistent with the pattern used in other visualizer components.

Also applies to: 176-179

packages/shadcn/components/agents-ui/agent-audio-visualizer-grid.test.tsx (1)

19-173: Solid coverage across grid props and attributes.

Tests exercise sizes, options, state, HTML attributes, children, audioTrack, and combined props in a balanced way.

packages/shadcn/components/agents-ui/agent-audio-visualizer-bar.test.tsx (1)

20-284: Comprehensive bar visualizer coverage.

The test matrix covers size/state variants, audioTrack paths, bar attributes, and custom children thoroughly.

packages/shadcn/components/agents-ui/agent-audio-visualizer-wave.tsx (1)

167-205: Style prop forwarding is correctly wired.

Applying style directly on the WaveShader root keeps API parity with other visualizers and is a safe extension.

packages/shadcn/components/agents-ui/agent-audio-visualizer-wave.test.tsx (1)

28-138: Wave visualizer tests look well-rounded.

Size mappings, prop handling, HTML attributes, and combined-prop scenarios are all covered cleanly.

packages/shadcn/components/agents-ui/start-audio-button.test.tsx (1)

22-237: Thorough StartAudioButton coverage.

Variant sizing, attributes, event handling, and room integration tests are comprehensive and clear.

packages/shadcn/components/agents-ui/agent-audio-visualizer-radial.test.tsx (1)

19-168: Radial visualizer tests are comprehensive.

Rendering, size/state variants, bar attributes, and combined props are all exercised appropriately.

packages/shadcn/components/agents-ui/agent-track-toggle.tsx (1)

130-159: Controlled/uncontrolled toggle handling looks solid.

resolvedPressed and handlePressedChange cleanly separate controlled vs. uncontrolled behavior, and the conditional pressed/defaultPressed forwarding prevents double-control. Style forwarding is a nice addition.

packages/shadcn/components/agents-ui/agent-track-toggle.test.tsx (1)

81-254: Test coverage is thorough and aligned with the new behavior.

Good coverage for controlled/uncontrolled states, pending visuals, HTML attribute forwarding, and event handling.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

@thomasyuill-livekit thomasyuill-livekit marked this pull request as ready for review January 27, 2026 01:04
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Fix all issues with AI agents
In `@packages/shadcn/components/agents-ui/agent-disconnect-button.test.tsx`:
- Around line 230-236: The test falsely asserts safety on render only; update
the component and test: in AgentDisconnectButton's handleClick (where it calls
end from LiveKitComponents.useSessionContext) guard the call (e.g., check typeof
end === 'function' or use end?.()) so clicking with a missing session context
doesn't throw, and update the test (agent-disconnect-button.test.tsx) to
actually simulate a click on the rendered <AgentDisconnectButton /> and assert
no throw/that it handles the missing end gracefully.

In `@packages/shadcn/components/agents-ui/agent-session-provider.test.tsx`:
- Around line 56-64: The test for AgentSessionProvider currently only checks
presence and doesn't assert the session prop is forwarded to SessionProvider;
modify the test (agent-session-provider.test.tsx) so the mocked SessionProvider
captures props (e.g., via a jest.mock implementation or a dummy wrapper
component used in the test) and assert that the session passed into
AgentSessionProvider equals the captured prop value; update the test that
defines session = { room: null, state: 'connected' } and add an expectation that
the mocked SessionProvider received that session prop (similar to how the room
prop is verified).
- Around line 86-94: The test currently only checks the presence of the
RoomAudioRenderer element but doesn't assert the room prop is forwarded; update
the test for AgentSessionProvider to assert RoomAudioRenderer was invoked with
the room prop by mocking the RoomAudioRenderer component (same approach used for
volume/muted tests) and using an assertion like
expect(mockedRoomAudioRenderer).toHaveBeenCalledWith(expect.objectContaining({
room: mockRoom }), expect.anything()) so the forwarded prop is verified; locate
the test in agent-session-provider.test.tsx and replace the simple DOM existence
check with this mock-call assertion referencing AgentSessionProvider and
RoomAudioRenderer.
🧹 Nitpick comments (20)
packages/shadcn/components/agents-ui/agent-chat-transcript.test.tsx (2)

35-72: Good test coverage for core rendering scenarios.

The tests verify:

  • Message rendering with correct user/assistant origin based on isLocal
  • Thinking indicator conditional rendering
  • Scroll button presence

Consider adding beforeEach(() => vi.clearAllMocks()) for consistency with other test files in this PR, though it's less critical here since the tests don't assert on mock invocation counts.


64-67: Consider adding a complementary test for when the indicator should NOT render.

The test verifies the indicator renders when agentState="thinking", but doesn't verify it's absent for other states (e.g., "speaking" or undefined).

💡 Optional enhancement
it('hides thinking indicator when agent is not thinking', () => {
  render(<AgentChatTranscript agentState="speaking" />);
  expect(screen.queryByTestId('chat-indicator')).not.toBeInTheDocument();
});
packages/shadcn/components/agents-ui/agent-control-bar.test.tsx (2)

102-128: Reset mock return value after test to prevent state leakage.

The usePublishPermissions mock is modified with mockReturnValue on line 104, but it's not reset to the original value after the test. While vi.clearAllMocks() in beforeEach clears call history, it doesn't reset mockReturnValue. This could cause flaky tests if test order changes.

Suggested fix
  it('renders null and warns when all controls are false', () => {
    const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
    vi.mocked(controlBarHooks.usePublishPermissions).mockReturnValue({
      camera: false,
      microphone: false,
      screenShare: false,
      data: false,
    });

    const { container } = render(
      <AgentControlBar
        controls={{
          leave: false,
          microphone: false,
          screenShare: false,
          camera: false,
          chat: false,
        }}
      />,
    );

    expect(container.firstChild).toBeNull();
    expect(warnSpy).toHaveBeenCalledWith(
      'AgentControlBar: `visibleControls` contains only false values.',
    );
    warnSpy.mockRestore();
+   vi.mocked(controlBarHooks.usePublishPermissions).mockReturnValue({
+     camera: true,
+     microphone: true,
+     screenShare: true,
+     data: true,
+   });
  });

130-141: Consider adding error handling test for chat send failure.

The test verifies the happy path where send is called successfully. Consider adding a test case for when send rejects to ensure proper error handling.

packages/shadcn/components/agents-ui/agent-track-toggle.tsx (1)

132-135: useMemo is unnecessary for a simple boolean derivation.

This computation is trivial (a boolean check and fallback) and doesn't benefit from memoization. React's reconciliation is faster than the overhead of useMemo for such simple expressions.

Suggested simplification
  const [uncontrolledPressed, setUncontrolledPressed] = useState(defaultPressed ?? false);
  const isControlled = pressed !== undefined;
- const resolvedPressed = useMemo(
-   () => (isControlled ? pressed : uncontrolledPressed) ?? false,
-   [isControlled, pressed, uncontrolledPressed],
- );
+ const resolvedPressed = (isControlled ? pressed : uncontrolledPressed) ?? false;
  const IconComponent = getSourceIcon(source as Track.Source, resolvedPressed, pending);
packages/shadcn/vitest.setup.ts (2)

2-2: Remove unused React import.

The React import is not used in this setup file - there's no JSX or React API usage.

Suggested fix
 import '@testing-library/jest-dom/vitest';
-import React from 'react';

11-19: Consider adding missing IntersectionObserver properties for type completeness.

The mock uses as any to bypass TypeScript. For better type safety, consider adding the missing readonly properties (root, rootMargin, thresholds).

Suggested improvement
 // Mock IntersectionObserver
 global.IntersectionObserver = class IntersectionObserver {
+  readonly root: Element | Document | null = null;
+  readonly rootMargin: string = '';
+  readonly thresholds: ReadonlyArray<number> = [];
   constructor() {}
   observe() {}
   unobserve() {}
   disconnect() {}
   takeRecords() {
     return [];
   }
-} as any;
+};
packages/shadcn/components/agents-ui/agent-audio-visualizer-radial.tsx (1)

124-136: Remove unused _barCount from dependency array.

The _barCount variable is included in the dependency array but is not used within the useMemo callback. This appears to be a copy-paste artifact from the bar visualizer where it's actually used.

Suggested fix
   const sequencerInterval = useMemo(() => {
     switch (state) {
       case 'connecting':
       case 'listening':
         return 500;
       case 'initializing':
         return 250;
       case 'thinking':
         return Infinity;
       default:
         return 1000;
     }
-  }, [state, _barCount]);
+  }, [state]);
packages/shadcn/components/agents-ui/agent-chat-indicator.test.tsx (1)

59-63: Consider asserting the actual style value.

The style prop test only verifies the element exists but doesn't confirm the style was actually applied. This weakens the test's effectiveness.

💡 Suggested improvement
     it('accepts and applies style prop', () => {
       render(<AgentChatIndicator style={{ backgroundColor: 'red' }} data-testid="indicator" />);
       const indicator = screen.getByTestId('indicator');
-      expect(indicator).toBeInTheDocument();
+      expect(indicator).toHaveStyle({ backgroundColor: 'red' });
     });
packages/shadcn/components/agents-ui/agent-audio-visualizer-radial.test.tsx (1)

103-108: Consider asserting the actual style value.

Same as other test files - only verifying element existence rather than the style being applied.

💡 Suggested improvement
     it('accepts and applies style prop', () => {
       const { container } = render(
         <AgentAudioVisualizerRadial style={{ backgroundColor: 'green' }} />
       );
-      expect(container.firstChild).toBeInTheDocument();
+      expect(container.firstChild).toHaveStyle({ backgroundColor: 'green' });
     });
packages/shadcn/components/agents-ui/start-audio-button.test.tsx (1)

124-128: Consider asserting the actual style value.

Consistent with other test files, this only verifies element presence rather than style application.

💡 Suggested improvement
     it('accepts and applies style prop', () => {
       render(<StartAudioButton label="Start" style={{ backgroundColor: 'blue' }} />);
       const button = screen.getByRole('button');
-      expect(button).toBeInTheDocument();
+      expect(button).toHaveStyle({ backgroundColor: 'blue' });
     });
packages/shadcn/components/agents-ui/agent-disconnect-button.test.tsx (1)

129-133: Consider asserting the actual style value.

Consistent pattern across test files - only verifying element presence.

💡 Suggested improvement
     it('accepts and applies style prop', () => {
       render(<AgentDisconnectButton style={{ backgroundColor: 'blue' }} />);
       const button = screen.getByRole('button');
-      expect(button).toBeInTheDocument();
+      expect(button).toHaveStyle({ backgroundColor: 'blue' });
     });
packages/shadcn/hooks/agents-ui/use-agent-audio-visualizer-wave.test.ts (1)

136-149: State transition test doesn't verify values actually changed.

The test captures initialSpeed but never uses it in an assertion to verify the value changed after rerender. The final assertion only checks the value is defined.

💡 Suggested improvement
     it('updates values when state changes', async () => {
       const { result, rerender } = renderHook(
         ({ state }) => useAgentAudioVisualizerWave({ state }),
         { initialProps: { state: 'listening' as const } }
       );
       
       const initialSpeed = result.current.speed;
       
       rerender({ state: 'speaking' as const });
       
       await waitFor(() => {
-        expect(result.current.speed).toBeDefined();
+        // Verify the hook responds to state changes
+        // Note: With mocked motion values, actual value change may not occur,
+        // but we can verify the hook doesn't crash on state transition
+        expect(result.current).toHaveProperty('speed');
+        expect(result.current).toHaveProperty('amplitude');
       });
     });

If the intent is to verify actual value changes, the motion mocks would need to be enhanced to track state-driven updates.

packages/shadcn/components/agents-ui/agent-track-toggle.test.tsx (2)

27-58: Remove unused container destructuring.

Multiple tests destructure container but only use screen.getByRole('button'). This adds unnecessary noise.

✨ Suggested cleanup
   it('shows microphone icon when source is microphone and pressed', () => {
-    const { container } = render(
+    render(
       <AgentTrackToggle source="microphone" pressed={true} />
     );
     const button = screen.getByRole('button');
-    // The icon is rendered inside the button
     expect(button.querySelector('svg')).toBeInTheDocument();
   });

   it('shows microphone-off icon when source is microphone and not pressed', () => {
-    const { container } = render(
+    render(
       <AgentTrackToggle source="microphone" pressed={false} />
     );
     const button = screen.getByRole('button');
     expect(button.querySelector('svg')).toBeInTheDocument();
   });

   it('shows camera icon when source is camera and pressed', () => {
-    const { container } = render(
+    render(
       <AgentTrackToggle source="camera" pressed={true} />
     );
     const button = screen.getByRole('button');
     expect(button.querySelector('svg')).toBeInTheDocument();
   });

   it('shows monitor icon when source is screen_share', () => {
-    const { container } = render(
+    render(
       <AgentTrackToggle source="screen_share" pressed={true} />
     );
     const button = screen.getByRole('button');
     expect(button.querySelector('svg')).toBeInTheDocument();
   });

Apply similar cleanup to lines 63, 72-73, and 240 where container is also unused.


142-148: Strengthen style prop assertion.

The test only checks that the element exists, not that the style was actually applied.

✨ Suggested fix
   it('accepts and applies style prop', () => {
     render(
       <AgentTrackToggle source="microphone" style={{ backgroundColor: 'red' }} />
     );
     const toggle = screen.getByRole('button');
-    expect(toggle).toBeInTheDocument();
+    expect(toggle).toHaveStyle({ backgroundColor: 'red' });
   });
packages/shadcn/components/agents-ui/agent-audio-visualizer-bar.test.tsx (2)

117-148: State tests only verify rendering, not state-specific behavior.

These tests confirm the component renders without error for each state value, but don't verify any state-specific visual or behavioral differences. While this provides basic smoke testing, consider adding assertions for state-specific outcomes if the component behaves differently per state.


190-196: Strengthen style prop assertion.

Same issue as in the track toggle test - verify the style was actually applied.

✨ Suggested fix
   it('accepts and applies style prop', () => {
     const { container } = render(
       <AgentAudioVisualizerBar style={{ backgroundColor: 'red' }} />
     );
     const visualizer = container.querySelector('.relative.flex');
-    expect(visualizer).toBeInTheDocument();
+    expect(visualizer).toHaveStyle({ backgroundColor: 'red' });
   });
packages/shadcn/components/agents-ui/agent-audio-visualizer-wave.test.tsx (2)

6-15: Mock returns properties not used by the component.

Per the component code at agent-audio-visualizer-wave.tsx:305-308, the hook returns { speed, amplitude, frequency, opacity }. The mock includes unused properties (lineWidth, smoothing, brightness).

✨ Suggested cleanup
 vi.mock('@/hooks/agents-ui/use-agent-audio-visualizer-wave', () => ({
   useAgentAudioVisualizerWave: vi.fn(() => ({
     frequency: 1.0,
     amplitude: 0.5,
     speed: 1.0,
-    lineWidth: 2.0,
-    smoothing: 1.0,
-    brightness: 1.0,
+    opacity: 1.0,
   })),
 }));

99-104: Strengthen style prop assertion.

Consistent with other test files, verify the style was actually applied.

✨ Suggested fix
   it('accepts and applies style prop', () => {
     const { container } = render(
       <AgentAudioVisualizerWave style={{ backgroundColor: 'red' }} />
     );
-    expect(container.firstChild).toBeInTheDocument();
+    expect(container.firstChild).toHaveStyle({ backgroundColor: 'red' });
   });
packages/shadcn/hooks/agents-ui/use-agent-audio-visualizer-radial.test.ts (1)

158-172: State transition test doesn't verify the reset.

The test is named "resets index when state changes" but only checks that result.current is defined after rerender. The initial variable is captured but never used in an assertion.

✨ Suggested improvement
   it('resets index when state changes', async () => {
     const { result, rerender } = renderHook(
       ({ state, barCount, interval }) =>
         useAgentAudioVisualizerRadialAnimator(state, barCount, interval),
       { initialProps: { state: 'connecting' as const, barCount: 12, interval: 100 } }
     );

     const initial = result.current;
     
     rerender({ state: 'listening' as const, barCount: 12, interval: 100 });
     
-    expect(result.current).toBeDefined();
+    // After state change, the sequence resets - verify it changed or is at start
+    expect(result.current).toBeDefined();
+    expect(Array.isArray(result.current)).toBe(true);
+    // Note: For a stronger test, verify the sequence changed based on state
   });

Consider adding a more meaningful assertion that verifies the actual reset behavior, such as comparing sequence content before and after the state change.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a0afe15 and ad697d1.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (29)
  • packages/shadcn/components/agents-ui/agent-audio-visualizer-aura.test.tsx
  • packages/shadcn/components/agents-ui/agent-audio-visualizer-bar.test.tsx
  • packages/shadcn/components/agents-ui/agent-audio-visualizer-bar.tsx
  • packages/shadcn/components/agents-ui/agent-audio-visualizer-grid.test.tsx
  • packages/shadcn/components/agents-ui/agent-audio-visualizer-radial.test.tsx
  • packages/shadcn/components/agents-ui/agent-audio-visualizer-radial.tsx
  • packages/shadcn/components/agents-ui/agent-audio-visualizer-wave.test.tsx
  • packages/shadcn/components/agents-ui/agent-audio-visualizer-wave.tsx
  • packages/shadcn/components/agents-ui/agent-chat-indicator.test.tsx
  • packages/shadcn/components/agents-ui/agent-chat-indicator.tsx
  • packages/shadcn/components/agents-ui/agent-chat-transcript.test.tsx
  • packages/shadcn/components/agents-ui/agent-control-bar.test.tsx
  • packages/shadcn/components/agents-ui/agent-disconnect-button.test.tsx
  • packages/shadcn/components/agents-ui/agent-disconnect-button.tsx
  • packages/shadcn/components/agents-ui/agent-session-provider.test.tsx
  • packages/shadcn/components/agents-ui/agent-track-toggle.test.tsx
  • packages/shadcn/components/agents-ui/agent-track-toggle.tsx
  • packages/shadcn/components/agents-ui/react-shader-toy.test.tsx
  • packages/shadcn/components/agents-ui/start-audio-button.test.tsx
  • packages/shadcn/components/agents-ui/start-audio-button.tsx
  • packages/shadcn/hooks/agents-ui/use-agent-audio-visualizer-aura.test.ts
  • packages/shadcn/hooks/agents-ui/use-agent-audio-visualizer-bar.test.ts
  • packages/shadcn/hooks/agents-ui/use-agent-audio-visualizer-grid.test.ts
  • packages/shadcn/hooks/agents-ui/use-agent-audio-visualizer-radial.test.ts
  • packages/shadcn/hooks/agents-ui/use-agent-audio-visualizer-wave.test.ts
  • packages/shadcn/lib/utils.test.ts
  • packages/shadcn/package.json
  • packages/shadcn/vitest.config.ts
  • packages/shadcn/vitest.setup.ts
🧰 Additional context used
🧬 Code graph analysis (19)
packages/shadcn/components/agents-ui/agent-disconnect-button.test.tsx (1)
packages/shadcn/components/agents-ui/agent-disconnect-button.tsx (1)
  • AgentDisconnectButton (51-72)
packages/shadcn/components/agents-ui/agent-chat-indicator.test.tsx (1)
packages/shadcn/components/agents-ui/agent-chat-indicator.tsx (1)
  • AgentChatIndicator (77-92)
packages/shadcn/components/agents-ui/agent-chat-transcript.test.tsx (1)
packages/shadcn/components/agents-ui/agent-chat-transcript.tsx (1)
  • AgentChatTranscript (47-78)
packages/shadcn/hooks/agents-ui/use-agent-audio-visualizer-bar.test.ts (1)
packages/shadcn/hooks/agents-ui/use-agent-audio-visualizer-bar.ts (1)
  • useAgentAudioVisualizerBarAnimator (21-70)
packages/shadcn/components/agents-ui/start-audio-button.test.tsx (1)
packages/shadcn/components/agents-ui/start-audio-button.tsx (1)
  • StartAudioButton (42-58)
packages/shadcn/components/agents-ui/agent-audio-visualizer-aura.test.tsx (1)
packages/shadcn/components/agents-ui/agent-audio-visualizer-aura.tsx (1)
  • AgentAudioVisualizerAura (411-449)
packages/shadcn/hooks/agents-ui/use-agent-audio-visualizer-wave.test.ts (1)
packages/shadcn/hooks/agents-ui/use-agent-audio-visualizer-wave.ts (1)
  • useAgentAudioVisualizerWave (43-110)
packages/shadcn/lib/utils.test.ts (1)
packages/shadcn/lib/utils.ts (1)
  • cn (4-6)
packages/shadcn/hooks/agents-ui/use-agent-audio-visualizer-grid.test.ts (1)
packages/shadcn/hooks/agents-ui/use-agent-audio-visualizer-grid.ts (1)
  • useAgentAudioVisualizerGridAnimator (66-116)
packages/shadcn/components/agents-ui/agent-control-bar.test.tsx (1)
packages/shadcn/components/agents-ui/agent-control-bar.tsx (1)
  • AgentControlBar (243-407)
packages/shadcn/components/agents-ui/agent-audio-visualizer-wave.test.tsx (1)
packages/shadcn/components/agents-ui/agent-audio-visualizer-wave.tsx (1)
  • AgentAudioVisualizerWave (279-330)
packages/shadcn/vitest.config.ts (1)
docs/storybook/.storybook/main.js (1)
  • path (2-2)
packages/shadcn/components/agents-ui/agent-audio-visualizer-radial.test.tsx (1)
packages/shadcn/components/agents-ui/agent-audio-visualizer-radial.tsx (1)
  • AgentAudioVisualizerRadial (93-208)
packages/shadcn/hooks/agents-ui/use-agent-audio-visualizer-radial.test.ts (1)
packages/shadcn/hooks/agents-ui/use-agent-audio-visualizer-radial.ts (1)
  • useAgentAudioVisualizerRadialAnimator (25-73)
packages/shadcn/hooks/agents-ui/use-agent-audio-visualizer-aura.test.ts (1)
packages/shadcn/hooks/agents-ui/use-agent-audio-visualizer-aura.ts (1)
  • useAgentAudioVisualizerAura (46-124)
packages/shadcn/components/agents-ui/agent-audio-visualizer-bar.tsx (1)
packages/shadcn/lib/utils.ts (1)
  • cn (4-6)
packages/shadcn/components/agents-ui/react-shader-toy.test.tsx (1)
packages/shadcn/components/agents-ui/react-shader-toy.tsx (1)
  • ReactShaderToy (466-943)
packages/shadcn/components/agents-ui/agent-disconnect-button.tsx (1)
packages/shadcn/components/ui/button.tsx (1)
  • Button (57-57)
packages/shadcn/components/agents-ui/agent-chat-indicator.tsx (1)
packages/shadcn/lib/utils.ts (1)
  • cn (4-6)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: test
🔇 Additional comments (38)
packages/shadcn/components/agents-ui/start-audio-button.tsx (1)

51-55: Merged style handling looks solid.

Clear precedence and a single style prop prevent ambiguity.

packages/shadcn/lib/utils.test.ts (1)

1-177: Comprehensive cn coverage.

The test matrix is thorough across functional, Tailwind-merge, and edge scenarios.

packages/shadcn/components/agents-ui/agent-disconnect-button.tsx (1)

51-68: Style prop forwarding looks good.

No behavior changes beyond styling flexibility.

packages/shadcn/hooks/agents-ui/use-agent-audio-visualizer-grid.test.ts (1)

1-188: Solid hook test coverage and cleanup.

The suite is comprehensive and timer handling is clean.

packages/shadcn/components/agents-ui/agent-audio-visualizer-grid.test.tsx (1)

1-173: Nice breadth of component coverage.

Props, attributes, and combinations are all exercised well.

packages/shadcn/components/agents-ui/agent-audio-visualizer-aura.test.tsx (1)

15-18: The mock is correct and aligns with the component's imports. AgentAudioVisualizerAura imports ReactShaderToy from react-shader-toy, and the mock properly exports that symbol.

Likely an incorrect or invalid review comment.

packages/shadcn/components/agents-ui/react-shader-toy.test.tsx (2)

5-24: LGTM! Mock cleanup properly implemented.

The setup and teardown correctly addresses the mock state isolation concerns:

  • getContextMock.mockClear() resets call history between tests
  • Original requestAnimationFrame and cancelAnimationFrame globals are stored and restored
  • vi.restoreAllMocks() cleans up spies

26-57: Tests provide appropriate coverage for the component's core functionality.

The tests verify:

  • Canvas element rendering
  • WebGL context initialization on mount
  • Style prop forwarding to the canvas element
packages/shadcn/components/agents-ui/agent-session-provider.test.tsx (1)

22-24: Mock state properly cleared between tests.

The beforeEach hook with vi.clearAllMocks() addresses the concern about mock call history leaking between tests.

packages/shadcn/components/agents-ui/agent-chat-indicator.tsx (1)

77-91: LGTM! Style prop forwarding correctly implemented.

The style prop is properly destructured and forwarded to the underlying motion.span element, consistent with the pattern applied to other components in this PR (AgentDisconnectButton, AgentTrackToggle, etc.).

packages/shadcn/hooks/agents-ui/use-agent-audio-visualizer-aura.test.ts (3)

15-26: LGTM! Mock properly structured without thenable property.

The animate mock now correctly returns only { stop: vi.fn() } without the then property that could cause unexpected Promise-like behavior.


28-31: Proper mock cleanup between tests.

vi.clearAllMocks() in beforeEach ensures test isolation.


33-226: Comprehensive test coverage for the hook.

The test suite thoroughly covers:

  • Basic hook behavior and return value structure
  • State-based speed values for all agent states
  • Audio track integration and volume handling
  • State transitions with re-renders
  • Return value validation (defined, numeric, non-NaN)
  • Hook stability to prevent infinite re-renders
packages/shadcn/hooks/agents-ui/use-agent-audio-visualizer-bar.test.ts (3)

10-13: LGTM! Timer cleanup properly implemented.

The afterEach now correctly calls vi.useRealTimers() before vi.restoreAllMocks(), ensuring fake timers don't leak between tests.


15-236: Comprehensive test coverage for the bar animator hook.

The tests cover:

  • Basic return type and array length validation
  • State-specific sequence generation
  • Animation index reset on state/column changes
  • Sequence index bounds validation
  • Edge cases (single column, large column counts, zero interval)
  • Hook stability

141-151: The test correctly assumes the listening state sequence structure.

The assumption is accurate. generateListeningSequenceBar returns [[center], [noIndex]] where center = Math.floor(columns / 2). The hook initializes with index = 0 when the state changes, so result.current returns sequence[0], which is [center]. Therefore, result.current[0] correctly equals the center index. The test is valid and needs no changes.

packages/shadcn/components/agents-ui/agent-audio-visualizer-bar.tsx (2)

125-129: LGTM!

The style prop is correctly destructured and will be forwarded to the root element, enabling inline style customization. This aligns with the consistent pattern across other visualizer components in this PR.


176-180: LGTM!

The style prop is properly applied to the root <div>, maintaining consistency with the existing className forwarding pattern.

packages/shadcn/components/agents-ui/agent-track-toggle.tsx (1)

118-142: LGTM on controlled/uncontrolled pattern implementation.

The dual-mode state handling is correctly implemented - internal state is only updated when uncontrolled, and onPressedChange is always called when provided. The conditional prop passing to Toggle (lines 148-149) correctly delegates state management.

packages/shadcn/package.json (2)

12-15: LGTM!

Test scripts are well-structured with separate commands for single run, watch mode, and coverage.


48-70: LGTM!

Testing dependencies are appropriately versioned. The @vitest/coverage-v8 version now aligns with vitest at ^3.2.4, addressing the previous peer dependency concern.

packages/shadcn/components/agents-ui/agent-audio-visualizer-radial.tsx (1)

100-101: LGTM!

The style prop is correctly destructured and forwarded to the root element, consistent with the pattern in AgentAudioVisualizerBar.

packages/shadcn/components/agents-ui/agent-chat-indicator.test.tsx (1)

1-126: Well-structured test suite for AgentChatIndicator.

The tests comprehensively cover the component's API including sizes, HTML attributes, animation props, and combined scenarios. The organization with nested describe blocks is clean and readable.

packages/shadcn/components/agents-ui/agent-audio-visualizer-wave.tsx (1)

177-183: LGTM!

The style prop is correctly destructured and forwarded to the root div element, enabling inline style customization while maintaining proper ref forwarding.

packages/shadcn/components/agents-ui/agent-audio-visualizer-radial.test.tsx (2)

1-36: Good mock setup and rendering tests.

The mocks properly isolate the component from LiveKit dependencies and the internal animator hook. The rendering tests verify the expected structure.


38-68: Size tests are comprehensive and correct.

All five size variants (icon, sm, md, lg, xl) are tested with appropriate height class assertions matching the component's variant definitions.

packages/shadcn/components/agents-ui/start-audio-button.test.tsx (2)

1-39: Well-structured test suite with proper mock setup.

The tests effectively mock the LiveKit hooks and cover the component's rendering behavior. Using userEvent for click interactions is the correct approach.


192-216: Room integration tests are thorough.

Good verification of hook call patterns with proper mock setup and assertions for both provided and undefined room scenarios.

packages/shadcn/components/agents-ui/agent-disconnect-button.test.tsx (2)

1-56: Comprehensive rendering tests with proper mock setup.

Good coverage of default rendering, custom children, and icon customization scenarios.


159-203: Event handler tests are well-designed.

Good coverage of click behavior including verification that both onClick and end are called, and proper disabled state handling using userEvent.

packages/shadcn/hooks/agents-ui/use-agent-audio-visualizer-wave.test.ts (2)

15-26: Mock implementation correctly addresses the Biome lint issue.

The animate mock now returns a real Promise with the stop method attached, avoiding the noThenProperty lint rule violation from the previous review.


152-173: Good defensive tests for return value validation.

Testing for NaN values and ensuring speed is always positive across different states are valuable safeguards against regression.

packages/shadcn/components/agents-ui/agent-track-toggle.test.tsx (1)

168-220: Well-structured event handler tests.

Good use of userEvent.setup() with async/await pattern and proper verification that disabled state prevents handler invocation.

packages/shadcn/vitest.config.ts (1)

1-28: Well-configured Vitest setup.

The configuration properly sets up:

  • React plugin for JSX transform
  • jsdom environment for DOM testing
  • Path alias for module resolution
  • Coverage with sensible exclusions
packages/shadcn/components/agents-ui/agent-audio-visualizer-bar.test.tsx (1)

162-178: Good hook integration test.

Properly verifies that useMultibandTrackVolume is called with the correct track and options when in "speaking" state with an audio track.

packages/shadcn/components/agents-ui/agent-audio-visualizer-wave.test.tsx (1)

54-58: Previous feedback addressed.

The test description now correctly says "lg size" to match the default size.

packages/shadcn/hooks/agents-ui/use-agent-audio-visualizer-radial.test.ts (2)

10-13: Previous feedback addressed.

The afterEach now properly restores real timers with vi.useRealTimers() before vi.restoreAllMocks(), preventing timer leaks between test files.


92-99: Good assertion for speaking state behavior.

This test properly verifies that the speaking state returns all bar indices in order, which aligns with the hook implementation.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🤖 Fix all issues with AI agents
In `@packages/shadcn/tests/agent-disconnect-button.test.tsx`:
- Around line 127-131: The test for AgentDisconnectButton currently only asserts
the button exists; update the spec in agent-disconnect-button.test.tsx to assert
the passed style is applied by using Jest DOM's toHaveStyle on the retrieved
element (e.g., expect(button).toHaveStyle('background-color: blue') or
equivalent) so the test actually verifies the inline style prop is applied to
AgentDisconnectButton.

In `@packages/shadcn/tests/use-agent-audio-visualizer-aura.test.ts`:
- Around line 28-32: The test's beforeEach only calls vi.clearAllMocks(), but
you must also reset the mocked implementation of useTrackVolume to avoid
return-value leakage between tests; update the beforeEach in the
useAgentAudioVisualizerAura suite to reset or restore the useTrackVolume mock
(e.g., call mockReset/mockRestore or reassign its implementation) so the
mockReturnValue(0.8) set later does not persist across tests and affect scale
calculations in useAgentAudioVisualizerAura.

In `@packages/shadcn/tests/use-agent-audio-visualizer-bar.test.ts`:
- Around line 74-87: The test saves an unused variable `initial` and only
asserts that `result.current` is defined, so update the test for
useAgentAudioVisualizerBarAnimator to verify reset behavior: capture the
pre-rerender index or sequence value from result.current (e.g., const
initialIndex = result.current.index or the relevant field returned by
useAgentAudioVisualizerBarAnimator), then call rerender(...) and assert that
result.current.index (or the sequence/value) has been reset (for example to 0 or
to a known initial sequence), removing the unused `initial` variable if you
don't need it; ensure you reference the hook name
useAgentAudioVisualizerBarAnimator and the returned property (index/sequence)
when making the assertion.

In `@packages/shadcn/tests/use-agent-audio-visualizer-radial.test.ts`:
- Around line 156-170: The test "resets index when state changes" currently only
checks that result.current is defined and never uses the captured initial value;
update the test to either assert the actual index reset behavior or rename it.
If the hook useAgentAudioVisualizerRadialAnimator exposes an index or state
field (e.g., result.current.index or result.current.getCurrentIndex), assert
that after rerendering with state 'listening' the index equals the reset value
(likely 0) and that it differs from the initial captured index; alternatively,
if no index is exposed, remove the unused initial variable and rename the test
to reflect that it only verifies the hook still returns a value after state
change.

In `@packages/shadcn/tests/use-agent-audio-visualizer-wave.test.ts`:
- Around line 117-132: The test captures initialSpeed but never uses it and only
asserts speed is defined; update the State Transitions test for
useAgentAudioVisualizerWave to assert a real state change by storing
initialSpeed from result.current.speed, then after rerender({ state: 'speaking'
}) use waitFor to assert that result.current.speed is defined and not equal to
initialSpeed (or remove initialSpeed and change the test to assert a specific
expected value change), ensuring the assertion verifies the value changed rather
than merely being defined.
🧹 Nitpick comments (15)
packages/shadcn/tests/use-agent-audio-visualizer-wave.test.ts (2)

53-88: State-based tests could verify distinct behavior per state.

These tests only confirm that speed is defined or positive, but don't verify the state-specific multipliers from the implementation (e.g., thinking/connecting/initializing use DEFAULT_SPEED * 4, speaking uses DEFAULT_SPEED * 2). Since speed is set via setSpeed, these values should be deterministically testable.

Example for stronger assertions
     it('handles thinking state', () => {
       const { result } = renderHook(() => useAgentAudioVisualizerWave({ state: 'thinking' }));
-      expect(result.current.speed).toBeGreaterThan(0);
+      // Thinking state uses 4x speed multiplier
+      const { result: listeningResult } = renderHook(() => 
+        useAgentAudioVisualizerWave({ state: 'listening' })
+      );
+      expect(result.current.speed).toBe(listeningResult.current.speed * 4);
     });

105-114: Test doesn't verify volume actually affects output.

The test sets useTrackVolume to return 0.7 but only asserts that result.current is defined. Since the hook uses volume to calculate amplitude and frequency in speaking state, consider verifying those values change based on volume.

packages/shadcn/tests/use-agent-audio-visualizer-radial.test.ts (1)

5-13: Consider adding tests for animation progression.

The hook uses requestAnimationFrame for animation, but current tests only verify initial render state. Testing that the index advances over time would improve coverage of the core animation logic. This would require mocking requestAnimationFrame since Vitest's fake timers don't automatically intercept it.

Example approach for testing animation
it('advances index over time', async () => {
  // Mock requestAnimationFrame to use fake timers
  let rafCallback: FrameRequestCallback | null = null;
  vi.spyOn(window, 'requestAnimationFrame').mockImplementation((cb) => {
    rafCallback = cb;
    return 1;
  });
  vi.spyOn(window, 'cancelAnimationFrame').mockImplementation(() => {});

  const { result } = renderHook(() =>
    useAgentAudioVisualizerRadialAnimator('connecting', 12, 100),
  );

  const initialResult = [...result.current];

  // Simulate animation frame with elapsed time > interval
  if (rafCallback) {
    rafCallback(150); // time elapsed > 100ms interval
  }

  // Verify index advanced (sequence changed)
  // ... assertions based on expected behavior
});
packages/shadcn/tests/use-agent-audio-visualizer-bar.test.ts (1)

193-197: Test doesn't verify what its name claims.

This test only checks that result.current is defined, which doesn't actually verify that infinite re-renders don't occur. Consider renaming to reflect actual behavior (e.g., "renders without throwing") or implementing actual render count verification.

Option: Track render count to verify stability
     it('does not cause infinite re-renders', () => {
+      let renderCount = 0;
-      const { result } = renderHook(() => useAgentAudioVisualizerBarAnimator('speaking', 5, 100));
+      const { result } = renderHook(() => {
+        renderCount++;
+        return useAgentAudioVisualizerBarAnimator('speaking', 5, 100);
+      });
 
       expect(result.current).toBeDefined();
+      // Initial render should be minimal
+      expect(renderCount).toBeLessThan(10);
     });
packages/shadcn/tests/start-audio-button.test.tsx (2)

124-128: Style prop assertion should verify the style was actually applied.

The test only checks that the button exists (toBeInTheDocument()), but doesn't verify that the backgroundColor: 'blue' style was actually applied to the element. This makes the test less meaningful.

♻️ Proposed fix
     it('accepts and applies style prop', () => {
       render(<StartAudioButton label="Start" style={{ backgroundColor: 'blue' }} />);
       const button = screen.getByRole('button');
-      expect(button).toBeInTheDocument();
+      expect(button).toHaveStyle({ backgroundColor: 'blue' });
     });

161-174: Consider verifying handleClick is called exactly once.

While toHaveBeenCalled() is valid, using toHaveBeenCalledTimes(1) provides a stronger assertion that the handler is invoked exactly once per click.

♻️ Proposed fix
       await user.click(button);

-      expect(handleClick).toHaveBeenCalled();
+      expect(handleClick).toHaveBeenCalledTimes(1);
     });
packages/shadcn/tests/agent-audio-visualizer-radial.test.tsx (2)

83-92: Consider adding meaningful assertions for radius and audioTrack props.

Both tests only verify the element exists without validating that the props have any effect. For radius, consider checking the computed transform styles. For audioTrack, consider verifying that useMultibandTrackVolume was called with the track.

♻️ Proposed fix for audioTrack test
+import * as LiveKitComponents from '@livekit/components-react';
+
     it('accepts audioTrack prop', () => {
       const mockTrack = {} as any;
       const { container } = render(<AgentAudioVisualizerRadial audioTrack={mockTrack} />);
-      expect(container.querySelector('.relative.flex')).toBeInTheDocument();
+      expect(container.querySelector('.relative.flex')).toBeInTheDocument();
+      expect(LiveKitComponents.useMultibandTrackVolume).toHaveBeenCalledWith(
+        mockTrack,
+        expect.any(Object),
+      );
     });

101-106: Style prop test should verify the style was applied.

Same issue as in start-audio-button tests - the assertion doesn't validate the style was actually applied.

♻️ Proposed fix
     it('accepts and applies style prop', () => {
       const { container } = render(
         <AgentAudioVisualizerRadial style={{ backgroundColor: 'green' }} />,
       );
-      expect(container.firstChild).toBeInTheDocument();
+      expect(container.firstChild).toHaveStyle({ backgroundColor: 'green' });
     });
packages/shadcn/tests/agent-audio-visualizer-grid.test.tsx (3)

69-89: Grid option tests should verify the props have an effect.

These tests only check that the element exists after passing props, but don't verify the props actually affect the component. Consider verifying:

  • rowCount/columnCount: Assert the number of cells matches expected grid dimensions
  • interval: Verify the animator hook received the interval value
♻️ Proposed fix for rowCount test
+import * as GridAnimator from '@/hooks/agents-ui/use-agent-audio-visualizer-grid';
+
     it('accepts rowCount option', () => {
-      const { container } = render(<AgentAudioVisualizerGrid rowCount={3} />);
-      expect(container.querySelector('.grid')).toBeInTheDocument();
+      const { container } = render(<AgentAudioVisualizerGrid rowCount={3} columnCount={3} />);
+      const cells = container.querySelectorAll('[data-lk-index]');
+      // 3x3 grid = 9 cells
+      expect(cells).toHaveLength(9);
     });

109-114: Style prop test should verify the style was applied.

Consistent with other test files, this assertion only checks element presence.

♻️ Proposed fix
     it('accepts and applies style prop', () => {
       const { container } = render(
         <AgentAudioVisualizerGrid style={{ backgroundColor: 'blue' }} />,
       );
-      expect(container.firstChild).toBeInTheDocument();
+      expect(container.firstChild).toHaveStyle({ backgroundColor: 'blue' });
     });

127-136: Custom children test should verify children are rendered.

The test passes custom children but only asserts the grid exists, not that the custom child content appears.

♻️ Proposed fix
     it('renders with custom children', () => {
       const { container } = render(
         <AgentAudioVisualizerGrid>
           <div className="custom-cell">Cell</div>
         </AgentAudioVisualizerGrid>,
       );
-      expect(container.querySelector('.grid')).toBeInTheDocument();
+      expect(container.querySelector('.grid')).toBeInTheDocument();
+      const customCells = container.querySelectorAll('.custom-cell');
+      expect(customCells.length).toBeGreaterThan(0);
     });
packages/shadcn/tests/agent-audio-visualizer-bar.test.tsx (2)

117-148: State tests only verify rendering, not state-specific behavior.

These tests confirm the component renders for each state but don't verify state-specific effects like different animation intervals or visual styling. Consider at minimum checking the animator hook is called with expected interval values based on state.


190-194: Style prop test should verify the style was applied.

Consistent pattern across test files - the assertion should validate the style is actually applied.

♻️ Proposed fix
     it('accepts and applies style prop', () => {
       const { container } = render(<AgentAudioVisualizerBar style={{ backgroundColor: 'red' }} />);
       const visualizer = container.querySelector('.relative.flex');
-      expect(visualizer).toBeInTheDocument();
+      expect(visualizer).toHaveStyle({ backgroundColor: 'red' });
     });
packages/shadcn/tests/agent-audio-visualizer-wave.test.tsx (2)

97-100: Assert the style prop is applied.

This test currently only checks rendering. It would better validate the style-forwarding change if it also checks the applied style.

Suggested change
-    it('accepts and applies style prop', () => {
-      const { container } = render(<AgentAudioVisualizerWave style={{ backgroundColor: 'red' }} />);
-      expect(container.firstChild).toBeInTheDocument();
-    });
+    it('accepts and applies style prop', () => {
+      const { container } = render(<AgentAudioVisualizerWave style={{ backgroundColor: 'red' }} />);
+      const visualizer = container.firstChild as HTMLElement;
+      expect(visualizer).toBeInTheDocument();
+      expect(visualizer.style.backgroundColor).toBe('red');
+    });

73-83: Assert hook calls to validate prop wiring.

These cases only assert DOM presence. Since the hook is mocked, import it and assert its call arguments so prop → hook wiring regressions are caught.

Suggested change
-import { describe, it, expect, vi, beforeEach } from 'vitest';
-import { render, screen } from '@testing-library/react';
+import { describe, it, expect, vi, beforeEach } from 'vitest';
+import { render, screen } from '@testing-library/react';
+import { useAgentAudioVisualizerWave } from '@/hooks/agents-ui/use-agent-audio-visualizer-wave';
@@
-    it('accepts state prop', () => {
-      const { container } = render(<AgentAudioVisualizerWave state="speaking" />);
-      expect(container.firstChild).toBeInTheDocument();
-    });
+    it('accepts state prop', () => {
+      render(<AgentAudioVisualizerWave state="speaking" />);
+      expect(useAgentAudioVisualizerWave).toHaveBeenCalledWith(
+        expect.objectContaining({ state: 'speaking' }),
+      );
+    });
@@
-    it('accepts audioTrack prop', () => {
-      const mockTrack = {} as any;
-      const { container } = render(<AgentAudioVisualizerWave audioTrack={mockTrack} />);
-      expect(container.firstChild).toBeInTheDocument();
-    });
+    it('accepts audioTrack prop', () => {
+      const mockTrack = {} as any;
+      render(<AgentAudioVisualizerWave audioTrack={mockTrack} />);
+      expect(useAgentAudioVisualizerWave).toHaveBeenCalledWith(
+        expect.objectContaining({ audioTrack: mockTrack }),
+      );
+    });
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 52a67ca and 9262b54.

📒 Files selected for processing (20)
  • packages/shadcn/tests/agent-audio-visualizer-aura.test.tsx
  • packages/shadcn/tests/agent-audio-visualizer-bar.test.tsx
  • packages/shadcn/tests/agent-audio-visualizer-grid.test.tsx
  • packages/shadcn/tests/agent-audio-visualizer-radial.test.tsx
  • packages/shadcn/tests/agent-audio-visualizer-wave.test.tsx
  • packages/shadcn/tests/agent-chat-indicator.test.tsx
  • packages/shadcn/tests/agent-chat-transcript.test.tsx
  • packages/shadcn/tests/agent-control-bar.test.tsx
  • packages/shadcn/tests/agent-disconnect-button.test.tsx
  • packages/shadcn/tests/agent-session-provider.test.tsx
  • packages/shadcn/tests/agent-track-toggle.test.tsx
  • packages/shadcn/tests/react-shader-toy.test.tsx
  • packages/shadcn/tests/start-audio-button.test.tsx
  • packages/shadcn/tests/use-agent-audio-visualizer-aura.test.ts
  • packages/shadcn/tests/use-agent-audio-visualizer-bar.test.ts
  • packages/shadcn/tests/use-agent-audio-visualizer-grid.test.ts
  • packages/shadcn/tests/use-agent-audio-visualizer-radial.test.ts
  • packages/shadcn/tests/use-agent-audio-visualizer-wave.test.ts
  • packages/shadcn/tests/utils.test.ts
  • packages/shadcn/vitest.config.ts
🧰 Additional context used
🧬 Code graph analysis (18)
packages/shadcn/tests/agent-chat-indicator.test.tsx (1)
packages/shadcn/components/agents-ui/agent-chat-indicator.tsx (1)
  • AgentChatIndicator (77-92)
packages/shadcn/tests/utils.test.ts (1)
packages/shadcn/lib/utils.ts (1)
  • cn (4-6)
packages/shadcn/tests/agent-chat-transcript.test.tsx (1)
packages/shadcn/components/agents-ui/agent-chat-transcript.tsx (1)
  • AgentChatTranscript (47-78)
packages/shadcn/tests/use-agent-audio-visualizer-aura.test.ts (1)
packages/shadcn/hooks/agents-ui/use-agent-audio-visualizer-aura.ts (1)
  • useAgentAudioVisualizerAura (46-124)
packages/shadcn/tests/agent-control-bar.test.tsx (1)
packages/shadcn/components/agents-ui/agent-control-bar.tsx (1)
  • AgentControlBar (243-407)
packages/shadcn/tests/use-agent-audio-visualizer-wave.test.ts (1)
packages/shadcn/hooks/agents-ui/use-agent-audio-visualizer-wave.ts (1)
  • useAgentAudioVisualizerWave (43-110)
packages/shadcn/tests/react-shader-toy.test.tsx (1)
packages/shadcn/components/agents-ui/react-shader-toy.tsx (1)
  • ReactShaderToy (466-943)
packages/shadcn/tests/agent-disconnect-button.test.tsx (1)
packages/shadcn/components/agents-ui/agent-disconnect-button.tsx (1)
  • AgentDisconnectButton (51-74)
packages/shadcn/tests/use-agent-audio-visualizer-grid.test.ts (1)
packages/shadcn/hooks/agents-ui/use-agent-audio-visualizer-grid.ts (1)
  • useAgentAudioVisualizerGridAnimator (66-116)
packages/shadcn/tests/agent-audio-visualizer-aura.test.tsx (1)
packages/shadcn/components/agents-ui/agent-audio-visualizer-aura.tsx (1)
  • AgentAudioVisualizerAura (411-449)
packages/shadcn/tests/agent-audio-visualizer-radial.test.tsx (1)
packages/shadcn/components/agents-ui/agent-audio-visualizer-radial.tsx (1)
  • AgentAudioVisualizerRadial (93-208)
packages/shadcn/tests/agent-audio-visualizer-grid.test.tsx (1)
packages/shadcn/components/agents-ui/agent-audio-visualizer-grid.tsx (1)
  • AgentAudioVisualizerGrid (239-290)
packages/shadcn/tests/use-agent-audio-visualizer-radial.test.ts (1)
packages/shadcn/hooks/agents-ui/use-agent-audio-visualizer-radial.ts (1)
  • useAgentAudioVisualizerRadialAnimator (25-73)
packages/shadcn/tests/agent-audio-visualizer-bar.test.tsx (1)
packages/shadcn/components/agents-ui/agent-audio-visualizer-bar.tsx (1)
  • AgentAudioVisualizerBar (118-201)
packages/shadcn/tests/use-agent-audio-visualizer-bar.test.ts (1)
packages/shadcn/hooks/agents-ui/use-agent-audio-visualizer-bar.ts (1)
  • useAgentAudioVisualizerBarAnimator (21-70)
packages/shadcn/tests/start-audio-button.test.tsx (1)
packages/shadcn/components/agents-ui/start-audio-button.tsx (1)
  • StartAudioButton (42-58)
packages/shadcn/tests/agent-track-toggle.test.tsx (1)
packages/shadcn/components/agents-ui/agent-track-toggle.tsx (1)
  • AgentTrackToggle (118-166)
packages/shadcn/tests/agent-audio-visualizer-wave.test.tsx (1)
packages/shadcn/components/agents-ui/agent-audio-visualizer-wave.tsx (1)
  • AgentAudioVisualizerWave (279-330)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: test
🔇 Additional comments (50)
packages/shadcn/tests/use-agent-audio-visualizer-wave.test.ts (4)

1-31: Mocks are well-structured for hook isolation.

The mocking strategy properly isolates the hook from external dependencies. The motion/react mock correctly provides the stop method on the animate promise, matching the library's API.


33-51: Basic functionality tests appropriately validate the hook contract.

Good coverage of the hook's return shape and type guarantees.


154-166: Good stability test for detecting unnecessary recalculations.

This test correctly validates that the hook maintains stable values across re-renders with unchanged inputs.


134-152: NaN and boundary validation tests are good defensive measures.

Testing that animation values are never NaN is particularly valuable for shader/visualization code where invalid values can cause visual artifacts.

packages/shadcn/tests/use-agent-audio-visualizer-radial.test.ts (6)

10-13: Timer cleanup issue has been addressed.

The afterEach block now correctly calls vi.useRealTimers() before vi.restoreAllMocks(), which resolves the previously flagged issue about fake timers leaking into other test files.

[duplicate_comment, approve_code_changes]


15-34: LGTM!

Basic functionality tests correctly verify the hook returns an array with valid indices within the expected range.


36-81: LGTM!

State-based tests cover all relevant agent states. The tests for speaking and undefined states appropriately verify the array length matches barCount, which aligns with the hook implementation that returns all bar indices for these states.


83-131: LGTM!

Good coverage for bar count variations and return value validation. The test for disconnected state returning an empty array correctly validates the else branch in the hook's state handling logic.


133-154: LGTM!

Edge case tests appropriately cover boundary conditions including single bar, large bar counts, and zero interval scenarios.


172-186: LGTM!

The stability tests provide reasonable assurance - an infinite re-render would cause the test to timeout rather than complete successfully. The array structure test ensures consistent return type.

packages/shadcn/tests/agent-disconnect-button.test.tsx (8)

7-14: Well-structured mock setup.

The partial mock pattern using vi.importActual ensures other exports from @livekit/components-react remain functional while only overriding useSessionContext. This approach keeps the tests isolated without breaking potential internal dependencies.


16-24: LGTM!

Good setup pattern—mockEnd at describe scope allows individual tests to assert on the mock, and clearAllMocks in beforeEach ensures test isolation.


26-54: LGTM!

Rendering tests comprehensively cover default props, custom children, and icon customization scenarios.


56-86: LGTM!

Good coverage of size variants. The sr-only accessibility test at line 81-85 is a nice addition ensuring screen readers still receive the text when using icon-only size.


88-118: LGTM!

Variant tests correctly verify the default destructive variant and all alternative variants.


157-202: LGTM!

Thorough event handler coverage. The test at lines 191-201 correctly validates that disabled buttons don't trigger end() or custom onClick handlers.


204-216: LGTM!

Good integration test verifying that multiple props work together without conflicts.


218-235: LGTM!

Good edge case coverage. The test at lines 224-234 validates the safety check in the implementation that guards against end being undefined, ensuring the component doesn't throw when the session context lacks an end function.

packages/shadcn/tests/use-agent-audio-visualizer-bar.test.ts (4)

10-13: Timer cleanup is now correctly implemented.

The afterEach block properly restores real timers with vi.useRealTimers() before restoring mocks, addressing the previous review feedback.


15-33: Good foundational test coverage.

Basic functionality tests properly verify array return type and correct column count mapping for the speaking state.


140-169: Solid return value validation.

Good coverage for edge cases including NaN detection, disconnected state handling, and index bounds validation.


127-137: No action needed. The test is correct and not brittle. It validates that the listening state displays the center column index (which is Math.floor(columns / 2)), and this is the intended behavior—not an internal implementation detail. The hook directly returns this value at index 0 of the sequence.

Likely an incorrect or invalid review comment.

packages/shadcn/tests/utils.test.ts (2)

1-173: Comprehensive and well-structured test suite.

The test file provides excellent coverage of the cn utility function across multiple dimensions: basic functionality, conditional classes, Tailwind merge behavior, complex input scenarios, practical use cases, and edge cases. The organization into logical describe blocks makes the tests easy to understand and maintain.


157-161: The test is correct as-is. The review's concern overlooks that twMerge (the final step in the cn function) normalizes all whitespace by trimming and splitting on any whitespace run. While clsx passes string input as-is without trimming, the final output from cn(' text-red-500 ', ' bg-blue-500 ') will always be normalized by twMerge to 'text-red-500 bg-blue-500'. The toContain() assertions properly verify that the classes are present in the final normalized output, making the test valid and the suggested refactor unnecessary.

Likely an incorrect or invalid review comment.

packages/shadcn/tests/use-agent-audio-visualizer-aura.test.ts (7)

1-26: Mocks are well-scoped and keep external hooks isolated.


33-53: Nice baseline coverage for default and numeric outputs.


55-100: Speed mappings per state are covered clearly.


102-132: Audio-track integration paths are covered (with/without track).


134-168: State transition tests look solid.


170-199: Sanity checks for positivity/NaN are useful.


201-219: Stability checks are concise and effective.

packages/shadcn/tests/agent-track-toggle.test.tsx (1)

1-230: Comprehensive coverage of AgentTrackToggle behaviors.
The suite exercises core states, variants, attributes, and handlers thoroughly.

packages/shadcn/tests/agent-control-bar.test.tsx (1)

1-142: Well-isolated tests for AgentControlBar core flows.
Mocks and assertions cleanly validate rendering, warnings, and chat send behavior.

packages/shadcn/tests/use-agent-audio-visualizer-grid.test.ts (1)

1-188: Solid coverage for grid animator states and edge cases.
The tests validate coordinates across state changes and grid dimensions effectively.

packages/shadcn/tests/agent-chat-indicator.test.tsx (1)

1-110: Clear validation of size variants and prop passthrough.
Coverage looks complete and consistent with component API.

packages/shadcn/tests/agent-chat-transcript.test.tsx (1)

1-73: Nice coverage for transcript rendering and thinking state.
Mocks keep the tests focused and the assertions are aligned with expected behavior.

packages/shadcn/tests/agent-audio-visualizer-aura.test.tsx (1)

1-45: Concise, targeted checks for the aura visualizer.
Defaults, size variants, and className merging are covered well.

packages/shadcn/tests/start-audio-button.test.tsx (2)

1-15: LGTM! Clean mock setup.

The mock configuration properly spreads the actual module and overrides only the necessary hooks, allowing other exports to remain functional while isolating the component under test.


192-216: LGTM! Good room integration tests.

The tests properly verify hook invocations with the expected arguments, including the mock return value setup for useEnsureRoom.

packages/shadcn/tests/agent-audio-visualizer-radial.test.tsx (1)

1-17: LGTM! Proper mock setup for hooks.

The mocks correctly isolate the component from LiveKit dependencies and the internal animator hook.

packages/shadcn/tests/agent-session-provider.test.tsx (4)

6-19: LGTM! Well-structured mock setup.

The mocks capture props via vi.fn() wrappers, enabling verification of prop forwarding to SessionProvider and RoomAudioRenderer.


61-70: Previous review concern addressed.

The test now properly verifies that the session prop is forwarded to SessionProvider by inspecting the mock's call arguments.
[approve_code_changes, duplicate_comment]


92-103: Previous review concern addressed.

The test now uses toHaveBeenCalledWith to verify the room prop is correctly passed to RoomAudioRenderer.
[approve_code_changes, duplicate_comment]


165-180: LGTM! Good edge case coverage.

Testing null session and empty children helps ensure the component handles edge cases gracefully without crashing.

packages/shadcn/vitest.config.ts (1)

1-29: LGTM! Well-configured Vitest setup.

The configuration properly sets up React testing with jsdom, includes sensible coverage exclusions, and establishes the @ path alias for clean imports in test files.

packages/shadcn/tests/agent-audio-visualizer-grid.test.tsx (1)

1-16: LGTM! Proper mock setup.

The mocks correctly isolate the component from external dependencies.

packages/shadcn/tests/agent-audio-visualizer-bar.test.tsx (3)

1-18: LGTM! Well-structured mock setup.

The mocks properly isolate both the LiveKit hook and the custom animator hook.


162-180: LGTM! Good hook verification.

This test properly verifies that useMultibandTrackVolume is called with the expected track and configuration, validating the audio track integration.


233-259: LGTM! Good custom children tests.

These tests properly verify that custom children are cloned with the expected data attributes and that original classNames are preserved during cloning.

packages/shadcn/tests/react-shader-toy.test.tsx (1)

10-24: Cleanup is solid and keeps tests isolated.

Restoring globals and clearing mock history here should prevent cross‑test leakage.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Comment on lines +127 to +131
it('accepts and applies style prop', () => {
render(<AgentDisconnectButton style={{ backgroundColor: 'blue' }} />);
const button = screen.getByRole('button');
expect(button).toBeInTheDocument();
});
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Weak assertion—test doesn't verify style is actually applied.

The test claims to verify the style prop is applied but only checks that the button exists. Use toHaveStyle() to actually validate the inline style.

Proposed fix
     it('accepts and applies style prop', () => {
       render(<AgentDisconnectButton style={{ backgroundColor: 'blue' }} />);
       const button = screen.getByRole('button');
-      expect(button).toBeInTheDocument();
+      expect(button).toHaveStyle({ backgroundColor: 'blue' });
     });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
it('accepts and applies style prop', () => {
render(<AgentDisconnectButton style={{ backgroundColor: 'blue' }} />);
const button = screen.getByRole('button');
expect(button).toBeInTheDocument();
});
it('accepts and applies style prop', () => {
render(<AgentDisconnectButton style={{ backgroundColor: 'blue' }} />);
const button = screen.getByRole('button');
expect(button).toHaveStyle({ backgroundColor: 'blue' });
});
🤖 Prompt for AI Agents
In `@packages/shadcn/tests/agent-disconnect-button.test.tsx` around lines 127 -
131, The test for AgentDisconnectButton currently only asserts the button
exists; update the spec in agent-disconnect-button.test.tsx to assert the passed
style is applied by using Jest DOM's toHaveStyle on the retrieved element (e.g.,
expect(button).toHaveStyle('background-color: blue') or equivalent) so the test
actually verifies the inline style prop is applied to AgentDisconnectButton.

Comment on lines +28 to +32
describe('useAgentAudioVisualizerAura', () => {
beforeEach(() => {
vi.clearAllMocks();
});

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

cat -n packages/shadcn/tests/use-agent-audio-visualizer-aura.test.ts

Repository: livekit/components-js

Length of output: 9145


🌐 Web query:

Vitest vi.clearAllMocks vs vi.resetAllMocks behavior mock implementations

💡 Result:

vi.clearAllMocks()

  • Internally calls .mockClear() on every spy/mock.
  • Clears call history only (calls, instances, results), does not change the current implementation (e.g. mockReturnValue, mockImplementation, queued mockImplementationOnce, etc. stay in effect). (vitest.dev)

vi.resetAllMocks()

  • Internally calls .mockReset() on every spy/mock.
  • Clears call history and resets implementation:
    • For vi.fn(...): removes custom implementations and returns to its default behavior (what it was created with, or undefined if none). (vitest.dev)
    • For vi.spyOn(obj, 'method'): resets the spy’s mock implementation back to the original behavior (i.e., no custom implementation), while still keeping it as a spy. (v3.vitest.dev)

Quick example (behavioral)

const spy = vi.spyOn(api, 'get').mockReturnValue('mocked')

vi.clearAllMocks()
api.get() // still returns 'mocked' (impl kept)

vi.resetAllMocks()
api.get() // returns original behavior again (impl reset)

(First line matches “clear without affecting implementations”; second matches “reset implementation”.) (vitest.dev)

Related (often confused): vi.restoreAllMocks()

  • Restores original implementations for spies created with vi.spyOn (and in newer Vitest versions, it no longer resets spy state the same way it used to). (vitest.dev)

Citations:


🏁 Script executed:

# Check the hook implementation to see if it uses track volume value
find . -type f -name "use-agent-audio-visualizer-aura.ts*" -o -name "*use-agent-audio-visualizer*"

Repository: livekit/components-js

Length of output: 731


🏁 Script executed:

cat -n ./packages/shadcn/hooks/agents-ui/use-agent-audio-visualizer-aura.ts

Repository: livekit/components-js

Length of output: 4874


Reset useTrackVolume's return value in beforeEach to prevent mock leakage across tests.

vi.clearAllMocks() only clears call history and does not reset mock implementations. The mockReturnValue(0.8) called in the test at line 125 will persist across test runs, and because the hook uses volume to calculate the scale value (line 104-106 in the implementation), this could cause order-dependent behavior if future tests verify volume-dependent properties.

🛠️ Proposed fix
 beforeEach(() => {
   vi.clearAllMocks();
+  vi.mocked(LiveKitComponents.useTrackVolume).mockReturnValue(0);
 });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
describe('useAgentAudioVisualizerAura', () => {
beforeEach(() => {
vi.clearAllMocks();
});
describe('useAgentAudioVisualizerAura', () => {
beforeEach(() => {
vi.clearAllMocks();
vi.mocked(LiveKitComponents.useTrackVolume).mockReturnValue(0);
});
🤖 Prompt for AI Agents
In `@packages/shadcn/tests/use-agent-audio-visualizer-aura.test.ts` around lines
28 - 32, The test's beforeEach only calls vi.clearAllMocks(), but you must also
reset the mocked implementation of useTrackVolume to avoid return-value leakage
between tests; update the beforeEach in the useAgentAudioVisualizerAura suite to
reset or restore the useTrackVolume mock (e.g., call mockReset/mockRestore or
reassign its implementation) so the mockReturnValue(0.8) set later does not
persist across tests and affect scale calculations in
useAgentAudioVisualizerAura.

Comment on lines +74 to +87
it('resets index when state changes', () => {
const { result, rerender } = renderHook(
({ state, columns, interval }) =>
useAgentAudioVisualizerBarAnimator(state, columns, interval),
{ initialProps: { state: 'connecting' as const, columns: 5, interval: 100 } },
);

const initial = result.current;

rerender({ state: 'listening' as const, columns: 5, interval: 100 });

// After state change, should reset
expect(result.current).toBeDefined();
});
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Unused variable and weak assertion for reset behavior.

The test captures initial on line 81 but never uses it. The assertion only checks result.current is defined, which doesn't verify that the index actually reset. Consider comparing pre/post state change values or asserting on the sequence content.

Suggested improvement
      const initial = result.current;

      rerender({ state: 'listening' as const, columns: 5, interval: 100 });

-     // After state change, should reset
-     expect(result.current).toBeDefined();
+     // After state change, sequence should reflect the new state
+     // and may differ from the initial sequence
+     expect(result.current).toBeDefined();
+     expect(Array.isArray(result.current)).toBe(true);
+     // Verify listening state produces different sequence than connecting
+     expect(result.current).not.toEqual(initial);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
it('resets index when state changes', () => {
const { result, rerender } = renderHook(
({ state, columns, interval }) =>
useAgentAudioVisualizerBarAnimator(state, columns, interval),
{ initialProps: { state: 'connecting' as const, columns: 5, interval: 100 } },
);
const initial = result.current;
rerender({ state: 'listening' as const, columns: 5, interval: 100 });
// After state change, should reset
expect(result.current).toBeDefined();
});
it('resets index when state changes', () => {
const { result, rerender } = renderHook(
({ state, columns, interval }) =>
useAgentAudioVisualizerBarAnimator(state, columns, interval),
{ initialProps: { state: 'connecting' as const, columns: 5, interval: 100 } },
);
const initial = result.current;
rerender({ state: 'listening' as const, columns: 5, interval: 100 });
// After state change, sequence should reflect the new state
// and may differ from the initial sequence
expect(result.current).toBeDefined();
expect(Array.isArray(result.current)).toBe(true);
// Verify listening state produces different sequence than connecting
expect(result.current).not.toEqual(initial);
});
🤖 Prompt for AI Agents
In `@packages/shadcn/tests/use-agent-audio-visualizer-bar.test.ts` around lines 74
- 87, The test saves an unused variable `initial` and only asserts that
`result.current` is defined, so update the test for
useAgentAudioVisualizerBarAnimator to verify reset behavior: capture the
pre-rerender index or sequence value from result.current (e.g., const
initialIndex = result.current.index or the relevant field returned by
useAgentAudioVisualizerBarAnimator), then call rerender(...) and assert that
result.current.index (or the sequence/value) has been reset (for example to 0 or
to a known initial sequence), removing the unused `initial` variable if you
don't need it; ensure you reference the hook name
useAgentAudioVisualizerBarAnimator and the returned property (index/sequence)
when making the assertion.

Comment on lines +156 to +170
describe('State Transitions', () => {
it('resets index when state changes', async () => {
const { result, rerender } = renderHook(
({ state, barCount, interval }) =>
useAgentAudioVisualizerRadialAnimator(state, barCount, interval),
{ initialProps: { state: 'connecting' as const, barCount: 12, interval: 100 } },
);

const initial = result.current;

rerender({ state: 'listening' as const, barCount: 12, interval: 100 });

expect(result.current).toBeDefined();
});
});
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Test does not verify the behavior its name describes.

The test is named "resets index when state changes" but only asserts that result.current is defined after rerender. The captured initial variable on line 164 is never used in any assertion. Consider either strengthening the test to verify actual index reset behavior or renaming it to reflect what it actually tests.

Suggested improvement
  describe('State Transitions', () => {
-   it('resets index when state changes', async () => {
+   it('produces valid output after state change', async () => {
      const { result, rerender } = renderHook(
        ({ state, barCount, interval }) =>
          useAgentAudioVisualizerRadialAnimator(state, barCount, interval),
        { initialProps: { state: 'connecting' as const, barCount: 12, interval: 100 } },
      );

-     const initial = result.current;
-
      rerender({ state: 'listening' as const, barCount: 12, interval: 100 });

      expect(result.current).toBeDefined();
+     expect(Array.isArray(result.current)).toBe(true);
    });
  });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
describe('State Transitions', () => {
it('resets index when state changes', async () => {
const { result, rerender } = renderHook(
({ state, barCount, interval }) =>
useAgentAudioVisualizerRadialAnimator(state, barCount, interval),
{ initialProps: { state: 'connecting' as const, barCount: 12, interval: 100 } },
);
const initial = result.current;
rerender({ state: 'listening' as const, barCount: 12, interval: 100 });
expect(result.current).toBeDefined();
});
});
describe('State Transitions', () => {
it('produces valid output after state change', async () => {
const { result, rerender } = renderHook(
({ state, barCount, interval }) =>
useAgentAudioVisualizerRadialAnimator(state, barCount, interval),
{ initialProps: { state: 'connecting' as const, barCount: 12, interval: 100 } },
);
rerender({ state: 'listening' as const, barCount: 12, interval: 100 });
expect(result.current).toBeDefined();
expect(Array.isArray(result.current)).toBe(true);
});
});
🤖 Prompt for AI Agents
In `@packages/shadcn/tests/use-agent-audio-visualizer-radial.test.ts` around lines
156 - 170, The test "resets index when state changes" currently only checks that
result.current is defined and never uses the captured initial value; update the
test to either assert the actual index reset behavior or rename it. If the hook
useAgentAudioVisualizerRadialAnimator exposes an index or state field (e.g.,
result.current.index or result.current.getCurrentIndex), assert that after
rerendering with state 'listening' the index equals the reset value (likely 0)
and that it differs from the initial captured index; alternatively, if no index
is exposed, remove the unused initial variable and rename the test to reflect
that it only verifies the hook still returns a value after state change.

Comment on lines +117 to +132
describe('State Transitions', () => {
it('updates values when state changes', async () => {
const { result, rerender } = renderHook(
({ state }) => useAgentAudioVisualizerWave({ state }),
{ initialProps: { state: 'listening' as const } },
);

const initialSpeed = result.current.speed;

rerender({ state: 'speaking' as const });

await waitFor(() => {
expect(result.current.speed).toBeDefined();
});
});
});
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Unused variable and weak assertion in state transition test.

initialSpeed is captured but never used. The test name suggests verifying that values change, but the assertion only checks that speed is defined. Consider comparing values before and after the transition.

Suggested fix
     it('updates values when state changes', async () => {
       const { result, rerender } = renderHook(
         ({ state }) => useAgentAudioVisualizerWave({ state }),
         { initialProps: { state: 'listening' as const } },
       );

       const initialSpeed = result.current.speed;

       rerender({ state: 'speaking' as const });

       await waitFor(() => {
-        expect(result.current.speed).toBeDefined();
+        // Speaking state should have different speed than listening
+        expect(result.current.speed).not.toBe(initialSpeed);
       });
     });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
describe('State Transitions', () => {
it('updates values when state changes', async () => {
const { result, rerender } = renderHook(
({ state }) => useAgentAudioVisualizerWave({ state }),
{ initialProps: { state: 'listening' as const } },
);
const initialSpeed = result.current.speed;
rerender({ state: 'speaking' as const });
await waitFor(() => {
expect(result.current.speed).toBeDefined();
});
});
});
describe('State Transitions', () => {
it('updates values when state changes', async () => {
const { result, rerender } = renderHook(
({ state }) => useAgentAudioVisualizerWave({ state }),
{ initialProps: { state: 'listening' as const } },
);
const initialSpeed = result.current.speed;
rerender({ state: 'speaking' as const });
await waitFor(() => {
// Speaking state should have different speed than listening
expect(result.current.speed).not.toBe(initialSpeed);
});
});
});
🤖 Prompt for AI Agents
In `@packages/shadcn/tests/use-agent-audio-visualizer-wave.test.ts` around lines
117 - 132, The test captures initialSpeed but never uses it and only asserts
speed is defined; update the State Transitions test for
useAgentAudioVisualizerWave to assert a real state change by storing
initialSpeed from result.current.speed, then after rerender({ state: 'speaking'
}) use waitFor to assert that result.current.speed is defined and not equal to
initialSpeed (or remove initialSpeed and change the test to assert a specific
expected value change), ensuring the assertion verifies the value changed rather
than merely being defined.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants