Skip to content

Animation tests#7255

Merged
PavelVanecek merged 2 commits into
mainfrom
animation-tests
Apr 18, 2026
Merged

Animation tests#7255
PavelVanecek merged 2 commits into
mainfrom
animation-tests

Conversation

@PavelVanecek

@PavelVanecek PavelVanecek commented Apr 18, 2026

Copy link
Copy Markdown
Collaborator

Tests only. I'm extracting changes from the huge animations branch that we can merge independently to make the huge branch a bit smaller.

Summary by CodeRabbit

  • Tests
    • Added test coverage for d3 scale positioning behavior and LineChart point position computation during data window changes (both categorical and numerical scales).
    • Added test coverage for clipping behavior validation and SVG/DOM rendering under various axis configurations and overflow settings.

PavelVanecek and others added 2 commits April 18, 2026 12:02
Document that useNeedsClip is purely driven by the allowDataOverflow prop,
not by axis type (category vs number) or domain configuration.

Key findings:
- Neither categorical nor numerical axes enable clipPath by default
- Only explicit allowDataOverflow={true} triggers GraphicalItemClipPath rendering
- There is always a global chart-level clipPath from ClipPathProvider
- The visual difference with type='number' is about pixel position computation
  (scaleLinear keeps points in bounds), not about SVG clipping

Co-authored-by: Copilot <[email protected]>
@coderabbitai

coderabbitai Bot commented Apr 18, 2026

Copy link
Copy Markdown
Contributor

Walkthrough

Adds two comprehensive test suites for GraphicalItemClipPath behavior: one verifying d3 scale positioning with sliding data windows across categorical and numerical axes, and another validating clip-path rendering and axis overflow settings in LineChart scenarios.

Changes

Cohort / File(s) Summary
GraphicalItemClipPath Test Suite
test/cartesian/GraphicalItemClipPath.spec.tsx, test/cartesian/GraphicalItemClipPath.scale-behavior.spec.tsx
New test files validating clip-path rendering, useNeedsClip hook behavior under various axis configurations, and d3 scale positioning during domain shifts in LineChart; verifies categorical vs. numerical axis behavior and allowDataOverflow impact on clipping.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • ckifer
🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description is minimal and lacks required template sections including Related Issue, Motivation and Context, How Has This Been Tested, and Types of changes checklist. Complete the PR description template by adding Related Issue link, explaining the motivation, documenting test coverage, and checking appropriate change type boxes.
Title check ❓ Inconclusive The title 'Animation tests' is vague and does not adequately describe the specific changes; the PR adds tests for GraphicalItemClipPath behavior and d3 scale positioning, which are implementation details beyond generic 'animation tests'. Use a more specific title such as 'Add GraphicalItemClipPath and scale positioning tests' or 'Add tests for clipping behavior and d3 scale animations'.
✅ Passed checks (1 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch animation-tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (2)
test/cartesian/GraphicalItemClipPath.spec.tsx (1)

65-69: Add call-count assertions for selector spies.

These createSelectorTestCase usages inspect the selector output but do not verify how many times the selector ran. Adding expect(spy).toHaveBeenCalledTimes(...) keeps these tests aligned with the render-performance guardrail.

As per coding guidelines, Verify the number of selector calls using the spy object from createSelectorTestCase to spot unnecessary re-renders and improve performance.

Also applies to: 101-105, 134-138, 290-301, 304-315, 365-376

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/cartesian/GraphicalItemClipPath.spec.tsx` around lines 65 - 69, Add an
assertion that verifies how many times the selector spy was invoked: after
rendering the test case that uses renderTestCase(state =>
selectXAxisSettings(state, 0)) and before inspecting spy.mock.lastCall, add
expect(spy).toHaveBeenCalledTimes(1) so the test ensures selectXAxisSettings was
executed exactly once and catches unintended extra selector runs.
test/cartesian/GraphicalItemClipPath.scale-behavior.spec.tsx (1)

284-285: Assert selector call counts for these selector test cases.

These tests consume createSelectorTestCase spies but only inspect the last result. Add explicit toHaveBeenCalledTimes(...) checks around the initial render and post-slide update to catch unexpected extra selector runs.

As per coding guidelines, Verify the number of selector calls using the spy object from createSelectorTestCase to spot unnecessary re-renders and improve performance.

Also applies to: 372-373, 441-442, 492-515

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/cartesian/GraphicalItemClipPath.scale-behavior.spec.tsx` around lines
284 - 285, Add explicit call-count assertions for the selector spy returned by
createSelectorTestCase: after the initial render of renderTestCase (using
selectLinePoints) assert expect(spy).toHaveBeenCalledTimes(1), then after the
slide/update action assert expect(spy).toHaveBeenCalledTimes(2) to ensure no
extra selector runs; apply the same pattern to the other selector test cases
that use createSelectorTestCase (the other renderTestCase/selector usages
referenced in the review) so each test verifies initial and post-update call
counts via the spy.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@test/cartesian/GraphicalItemClipPath.scale-behavior.spec.tsx`:
- Around line 475-530: The test renders static categorical (catChart) and
numerical (numChart) charts but never exercises the "slide" transition; update
the test to perform a Slide state transition for both charts via
createSelectorTestCase so you capture pre- and post-slide positions using
selectLinePoints (e.g., call the selector once before the slide and once after
applying the Slide transition/update), then compute spacing delta (catSpacing
and numSpacing) from the before→after positions and assert that the shifts
match; keep isAnimationActive={false} and reuse the existing id="line" selector
to locate points.
- Around line 294-300: Import vi from 'vitest' at the top of the test file and
ensure each simulated button click is followed by flushing pending timers so
selector updates scheduled via requestAnimationFrame are applied before reading
spy.mock.calls; specifically, around the act(() => { button.click(); }) blocks
(the ones using spy and reading spy.mock.calls[…]) call vi.runAllTimers() (or
vi.advanceTimersByTime(...)) inside act or immediately after to flush RAF
timers, and apply this pattern to the click blocks referenced (the blocks around
act(() => { button.click(); }) that are read into afterPoints and similar
variables), i.e., add the import and wrap/append vi.runAllTimers() for the click
code at the three locations mentioned.

---

Nitpick comments:
In `@test/cartesian/GraphicalItemClipPath.scale-behavior.spec.tsx`:
- Around line 284-285: Add explicit call-count assertions for the selector spy
returned by createSelectorTestCase: after the initial render of renderTestCase
(using selectLinePoints) assert expect(spy).toHaveBeenCalledTimes(1), then after
the slide/update action assert expect(spy).toHaveBeenCalledTimes(2) to ensure no
extra selector runs; apply the same pattern to the other selector test cases
that use createSelectorTestCase (the other renderTestCase/selector usages
referenced in the review) so each test verifies initial and post-update call
counts via the spy.

In `@test/cartesian/GraphicalItemClipPath.spec.tsx`:
- Around line 65-69: Add an assertion that verifies how many times the selector
spy was invoked: after rendering the test case that uses renderTestCase(state =>
selectXAxisSettings(state, 0)) and before inspecting spy.mock.lastCall, add
expect(spy).toHaveBeenCalledTimes(1) so the test ensures selectXAxisSettings was
executed exactly once and catches unintended extra selector runs.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: a5bbaeb4-a9d4-456c-b1c3-85d9c3fe806e

📥 Commits

Reviewing files that changed from the base of the PR and between 46f1a5b and 83e124c.

📒 Files selected for processing (2)
  • test/cartesian/GraphicalItemClipPath.scale-behavior.spec.tsx
  • test/cartesian/GraphicalItemClipPath.spec.tsx

Comment on lines +294 to +300
// Slide the data
const button = container.querySelector('button')!;
act(() => {
button.click();
});

const afterPoints: ReadonlyArray<LinePointItem> | undefined = spy.mock.calls[spy.mock.calls.length - 1]?.[0];

Copy link
Copy Markdown
Contributor

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:

#!/bin/bash
# Verify click-driven selector assertions flush pending timers before reading the spy.
rg -n -C4 'button\.click\(\)|runOnlyPendingTimers|spy\.mock\.calls\[spy\.mock\.calls\.length - 1\]' test/cartesian/GraphicalItemClipPath.scale-behavior.spec.tsx

Repository: recharts/recharts

Length of output: 3126


🏁 Script executed:

#!/bin/bash
# Check imports and timer handling in the test file
head -30 test/cartesian/GraphicalItemClipPath.scale-behavior.spec.tsx

Repository: recharts/recharts

Length of output: 1649


🏁 Script executed:

#!/bin/bash
# Check if vi is imported and search for any timer-related calls
rg -n "import.*vi|vi\.useFakeTimers|vi\.runOnlyPendingTimers" test/cartesian/GraphicalItemClipPath.scale-behavior.spec.tsx | head -20

Repository: recharts/recharts

Length of output: 190


🏁 Script executed:

#!/bin/bash
# Find all button click instances in the file to understand full scope
rg -n "button\.click\(\)" test/cartesian/GraphicalItemClipPath.scale-behavior.spec.tsx

Repository: recharts/recharts

Length of output: 144


🏁 Script executed:

#!/bin/bash
# Check the createSelectorTestCase helper to see if it handles timers
head -50 test/helper/createSelectorTestCase.ts

Repository: recharts/recharts

Length of output: 157


🏁 Script executed:

#!/bin/bash
# Search for similar patterns in other test files to see if they flush timers after clicks
rg -l "button\.click\(\)" test --type ts --type tsx | head -5

Repository: recharts/recharts

Length of output: 88


🏁 Script executed:

#!/bin/bash
# Look for patterns where clicks are followed by timer flushes in other test files
rg -B2 -A2 "button\.click\(\).*\n.*vi\.runOnlyPendingTimers" test --type ts --type tsx | head -30

Repository: recharts/recharts

Length of output: 252


🏁 Script executed:

#!/bin/bash
# Find the createSelectorTestCase helper file
find test -name "*createSelectorTestCase*" -type f

Repository: recharts/recharts

Length of output: 99


🏁 Script executed:

#!/bin/bash
# Search for button clicks followed by timer flushes
rg -U "button\.click\(\).*\n.*runOnlyPendingTimers" test

Repository: recharts/recharts

Length of output: 43


🏁 Script executed:

#!/bin/bash
# Look for tests that use runOnlyPendingTimers after click events
rg -B3 -A3 "runOnlyPendingTimers" test --type ts | head -50

Repository: recharts/recharts

Length of output: 2999


🏁 Script executed:

#!/bin/bash
# Check the createSelectorTestCase helper
cat test/helper/createSelectorTestCase.tsx

Repository: recharts/recharts

Length of output: 8431


🏁 Script executed:

#!/bin/bash
# Check the DynamicZIndex.spec.tsx file to see the full pattern
rg -B5 -A5 "button\.click" test/zIndex/DynamicZIndex.spec.tsx | head -40

Repository: recharts/recharts

Length of output: 481


🏁 Script executed:

#!/bin/bash
# Check if vi is imported in DynamicZIndex.spec.tsx
head -10 test/zIndex/DynamicZIndex.spec.tsx

Repository: recharts/recharts

Length of output: 446


Add vi import and flush pending timers after each button click.

These click-driven updates trigger Redux auto-batched state changes that are deferred to requestAnimationFrame. Reading spy.mock.calls[...] immediately after the click can capture stale selector output. The createSelectorTestCase helper already flushes timers during initial render, but additional timer flushes are required after user interactions.

Required changes
-import { describe, it, expect, beforeEach } from 'vitest';
+import { describe, it, expect, beforeEach, vi } from 'vitest';

Then wrap each button click with timer flush:

-      act(() => {
+      act(() => {
         button.click();
+        vi.runOnlyPendingTimers();
       });

       const afterPoints: ReadonlyArray<LinePointItem> | undefined = spy.mock.calls[spy.mock.calls.length - 1]?.[0];

Apply to lines 294–300, 381–387, and 451–456.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/cartesian/GraphicalItemClipPath.scale-behavior.spec.tsx` around lines
294 - 300, Import vi from 'vitest' at the top of the test file and ensure each
simulated button click is followed by flushing pending timers so selector
updates scheduled via requestAnimationFrame are applied before reading
spy.mock.calls; specifically, around the act(() => { button.click(); }) blocks
(the ones using spy and reading spy.mock.calls[…]) call vi.runAllTimers() (or
vi.advanceTimersByTime(...)) inside act or immediately after to flush RAF
timers, and apply this pattern to the click blocks referenced (the blocks around
act(() => { button.click(); }) that are read into afterPoints and similar
variables), i.e., add the import and wrap/append vi.runAllTimers() for the click
code at the three locations mentioned.

Comment on lines +475 to +530
it('both axis types produce the same shift magnitude when item count stays constant', () => {
// Categorical
const catChart = ({ children }: { children: ReactNode }) => (
<LineChart
width={500}
height={300}
data={[
{ name: 'A', value: 10 },
{ name: 'B', value: 20 },
{ name: 'C', value: 30 },
]}
>
<XAxis dataKey="name" />
<Line isAnimationActive={false} dataKey="value" id="line" />
{children}
</LineChart>
);
const catRender = createSelectorTestCase(catChart);
const { spy: catSpy } = catRender(state => selectLinePoints(state, 0, 0, false, 'line'));
const catPoints: ReadonlyArray<LinePointItem> | undefined = catSpy.mock.calls[catSpy.mock.calls.length - 1]?.[0];
assertNotNull(catPoints);

// Numerical
const numChart = ({ children }: { children: ReactNode }) => (
<LineChart
width={500}
height={300}
data={[
{ x: 1, value: 10 },
{ x: 2, value: 20 },
{ x: 3, value: 30 },
]}
>
<XAxis dataKey="x" type="number" domain={['dataMin', 'dataMax']} />
<Line isAnimationActive={false} dataKey="value" id="line" />
{children}
</LineChart>
);
const numRender = createSelectorTestCase(numChart);
const { spy: numSpy } = numRender(state => selectLinePoints(state, 0, 0, false, 'line'));
const numPoints: ReadonlyArray<LinePointItem> | undefined = numSpy.mock.calls[numSpy.mock.calls.length - 1]?.[0];
assertNotNull(numPoints);

// Both should have same number of points
expect(catPoints).toHaveLength(3);
expect(numPoints).toHaveLength(3);

// Both should use the same range, so the first and last point positions
// should be similar (they both map to the edges of the plot area)
// Note: exact values may differ due to YAxis presence and padding
const catSpacing = catPoints[1]!.x! - catPoints[0]!.x!;
const numSpacing = numPoints[1]!.x! - numPoints[0]!.x!;

// Both spacings should be equal because both have the same number of points
// across the same plot width
expect(catSpacing).toBeCloseTo(numSpacing, 0);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Make this test exercise the slide it describes.

The test title says “during identical data slide”, but it renders one static categorical chart and one static numerical chart. This can pass even if the slide/update behavior regresses; consider giving both charts a Slide state transition and comparing before/after shifts.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/cartesian/GraphicalItemClipPath.scale-behavior.spec.tsx` around lines
475 - 530, The test renders static categorical (catChart) and numerical
(numChart) charts but never exercises the "slide" transition; update the test to
perform a Slide state transition for both charts via createSelectorTestCase so
you capture pre- and post-slide positions using selectLinePoints (e.g., call the
selector once before the slide and once after applying the Slide
transition/update), then compute spacing delta (catSpacing and numSpacing) from
the before→after positions and assert that the shifts match; keep
isAnimationActive={false} and reuse the existing id="line" selector to locate
points.

@codecov

codecov Bot commented Apr 18, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 89.07%. Comparing base (d99d8dc) to head (83e124c).
⚠️ Report is 6 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #7255   +/-   ##
=======================================
  Coverage   89.07%   89.07%           
=======================================
  Files         539      539           
  Lines       41010    41010           
  Branches     5557     5558    +1     
=======================================
  Hits        36528    36528           
  Misses       4474     4474           
  Partials        8        8           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@github-actions

Copy link
Copy Markdown
Contributor

Staging Deployment Details

These deployments will remain available for 30 days.

To update snapshots: Comment /update-snapshots on this PR to automatically update the baseline screenshots.

@PavelVanecek
PavelVanecek merged commit ce3f5fd into main Apr 18, 2026
58 checks passed
@PavelVanecek
PavelVanecek deleted the animation-tests branch April 18, 2026 03:45
@codecov

codecov Bot commented Apr 18, 2026

Copy link
Copy Markdown

Bundle Report

Bundle size has no change ✅

@coderabbitai coderabbitai Bot mentioned this pull request Jun 25, 2026
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.

1 participant