Skip to content

Comments

fix: added tests for FreakyEffects#32

Merged
FreakyAli merged 2 commits intomasterfrom
r-1/gh/add-tests
Feb 24, 2026
Merged

fix: added tests for FreakyEffects#32
FreakyAli merged 2 commits intomasterfrom
r-1/gh/add-tests

Conversation

@FreakyAli
Copy link
Owner

@FreakyAli FreakyAli commented Feb 21, 2026

Summary by CodeRabbit

  • Bug Fixes

    • Updated animation methods (fade, beat, shake) to use asynchronous operations for improved responsiveness.
    • Fixed property initialization in touch tracking rectangle that was causing incorrect coordinate assignment.
  • Tests

    • Added comprehensive test suite covering animation constructors, touch event arguments, gesture recognition, and touch tracking functionality to enhance code reliability.

@coderabbitai
Copy link

coderabbitai bot commented Feb 21, 2026

📝 Walkthrough

Walkthrough

The PR introduces a comprehensive test suite for the Maui.FreakyEffects library by adding a new net10.0 test project with unit tests covering animations, event arguments, gesture recognition, and utility classes. Additionally, animation classes are refactored to use asynchronous method variants, and a parameter ordering bug in TouchTrackingRect is corrected.

Changes

Cohort / File(s) Summary
Test Project Setup
Maui.FreakyEffects.Tests/Maui.FreakyEffects.Tests.csproj, Maui.FreakyEffects.sln
New test project targeting net10.0 with xUnit, SkiaSharp, and code coverage dependencies; solution file updated with project references and build configurations.
Skeleton Animation Tests
Maui.FreakyEffects.Tests/Skeleton/AnimationConstructorTests.cs
Tests for FadeAnimation and BeatAnimation constructor behavior, parameter defaults, and AnimationTypes enum validation (10 test methods).
SkiaScene Event Argument Tests
Maui.FreakyEffects.Tests/SkiaScene/PanEventArgsTests.cs, PinchEventArgsTests.cs, TapEventArgsTests.cs
Tests verifying property initialization in event argument constructors including PreviousPoint, NewPoint, PivotPoint, TouchActionType, and ViewPoint with boundary/negative value handling.
SkiaScene Utility Tests
Maui.FreakyEffects.Tests/SkiaScene/SKPointExtensionsTests.cs, TouchGestureRecognizerTests.cs
Tests for SKPoint.GetMagnitude extension across edge cases (origin, triangles, unit vectors, negative coordinates) and comprehensive TouchGestureRecognizer event firing (pan, pinch, tap with 11 test scenarios).
TouchTracking Tests
Maui.FreakyEffects.Tests/TouchTracking/TouchActionEventArgsTests.cs, TouchTrackingPointTests.cs, TouchTrackingRectTests.cs
Tests for event argument initialization, coordinate storage with zero/negative values, property mutability, and boundary-aware containment logic with exclusive right/bottom boundaries.
Animation Async Refactoring
Maui.FreakyEffects/Shared/Skeleton/BeatAnimation.cs, FadeAnimation.cs, HorizontalShakeAnimation.cs, VerticalShakeAnimation.cs
Updated animation methods to use async variants (ScaleToAsync, FadeToAsync, TranslateToAsync) replacing synchronous calls.
Bug Fix
Maui.FreakyEffects/Shared/TouchTracking/TouchTrackingRect.cs
Corrected constructor parameter assignments where Top and Right parameters were swapped; now assigned to correct properties.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly related PRs

  • Chore: .NET 10 Support #30: Coordinates .NET 10 platform upgrades across the repository by adding net10.0 test infrastructure while the other PR bumps existing projects and CI pipelines to net10.

Poem

A rabbit hops with tests so grand, 🐰✨
Async animations, now they're planned!
TouchTracking fixed with swapped repair,
Quality checks beyond compare!

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Title check ⚠️ Warning The title indicates tests were added, but the PR includes multiple bug fixes (async API migrations, constructor assignment fix) beyond test additions. Update the title to reflect all significant changes, such as 'fix: migrate animations to async APIs and add comprehensive test suite' or split into separate PRs.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

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

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch r-1/gh/add-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.

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: 1

🧹 Nitpick comments (4)
Maui.FreakyEffects/Maui.FreakyEffects/Shared/Skeleton/BeatAnimation.cs (1)

19-23: StopAnimation uses an unsafe direct cast inconsistent with other animation classes.

HorizontalShakeAnimation and VerticalShakeAnimation both guard with if (bindable is View self) in StopAnimation, but BeatAnimation (and FadeAnimation) perform a direct (View)bindable cast without a type guard, which would throw an InvalidCastException if ever called with a non-View bindable. Consider aligning with the safer pattern used elsewhere.

♻️ Suggested fix
 protected override async Task StopAnimation(BindableObject bindable)
 {
-    var self = (View)bindable;
-    await self.ScaleToAsync(1, 100);
+    if (bindable is View self)
+        await self.ScaleToAsync(1, 100);
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Maui.FreakyEffects/Maui.FreakyEffects/Shared/Skeleton/BeatAnimation.cs`
around lines 19 - 23, BeatAnimation.StopAnimation currently does a direct cast
(var self = (View)bindable) which can throw; change it to match the safe pattern
used in HorizontalShakeAnimation/VerticalShakeAnimation by using an "if
(bindable is View self)" guard and only call self.ScaleToAsync(1, 100) inside
that block (no cast or exception). Also mirror the same guard pattern in
FadeAnimation.StopAnimation if present to keep consistency across animation
classes.
Maui.FreakyEffects/Maui.FreakyEffects.Tests/Skeleton/AnimationConstructorTests.cs (1)

74-80: AnimationTypes_HasFiveMembers will break on any future enum addition.

If this is intentionally guarding the public API surface, add a comment explaining that. Otherwise, consider removing it since AnimationTypes_HasExpectedValues (lines 65-72) already validates all five named members.

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

In
`@Maui.FreakyEffects/Maui.FreakyEffects.Tests/Skeleton/AnimationConstructorTests.cs`
around lines 74 - 80, The test AnimationTypes_HasFiveMembers is brittle because
it asserts a hardcoded enum count; either remove this test or convert it to an
explicit API-guard with a clear comment. Update the test file by either deleting
the AnimationTypes_HasFiveMembers method (since AnimationTypes_HasExpectedValues
already checks the named members) or keep it but add a comment above the
AnimationTypes_HasFiveMembers test explaining it intentionally guards the public
API surface and must be updated when enum members are added; ensure references
to the test name AnimationTypes_HasFiveMembers and the complementary test
AnimationTypes_HasExpectedValues are preserved so reviewers can see which
approach you chose.
Maui.FreakyEffects/Maui.FreakyEffects.Tests/TouchTracking/TouchTrackingRectTests.cs (1)

8-38: Consider consolidating the four constructor-property tests.

All four tests construct the same TouchTrackingRect(10f, 20f, 30f, 40f) and each assert a single property. A single test with four assertions (or a [Theory] with [MemberData]) avoids the repeated construction and keeps the constructor contract in one place.

♻️ Proposed consolidation
-    [Fact]
-    public void Constructor_SetsLeft()
-    {
-        var rect = new TouchTrackingRect(10f, 20f, 30f, 40f);
-        Assert.Equal(10f, rect.Left);
-    }
-
-    [Fact]
-    public void Constructor_SetsTop()
-    {
-        var rect = new TouchTrackingRect(10f, 20f, 30f, 40f);
-        Assert.Equal(20f, rect.Top);
-    }
-
-    [Fact]
-    public void Constructor_SetsRight()
-    {
-        var rect = new TouchTrackingRect(10f, 20f, 30f, 40f);
-        Assert.Equal(30f, rect.Right);
-    }
-
-    [Fact]
-    public void Constructor_SetsBottom()
-    {
-        var rect = new TouchTrackingRect(10f, 20f, 30f, 40f);
-        Assert.Equal(40f, rect.Bottom);
-    }
+    [Fact]
+    public void Constructor_SetsAllProperties()
+    {
+        var rect = new TouchTrackingRect(10f, 20f, 30f, 40f);
+
+        Assert.Equal(10f, rect.Left);
+        Assert.Equal(20f, rect.Top);
+        Assert.Equal(30f, rect.Right);
+        Assert.Equal(40f, rect.Bottom);
+    }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@Maui.FreakyEffects/Maui.FreakyEffects.Tests/TouchTracking/TouchTrackingRectTests.cs`
around lines 8 - 38, Replace the four separate Fact tests (Constructor_SetsLeft,
Constructor_SetsTop, Constructor_SetsRight, Constructor_SetsBottom) with a
single consolidated test that constructs TouchTrackingRect(10f, 20f, 30f, 40f)
once and asserts all four properties (Left, Top, Right, Bottom) in that test
(e.g., a new Fact named Constructor_InitializesAllProperties or use a
Theory+MemberData if preferred); update or remove the four original test methods
so there’s one test validating the constructor initializes all properties.
Maui.FreakyEffects/Maui.FreakyEffects.sln (1)

10-11: LGTM — test project correctly wired into the solution.

The project entry and all four configuration mappings (Debug/Release × ActiveCfg/Build.0) are in order.

Nit: the project GUID {A1B2C3D4-E5F6-7890-ABCD-EF1234567890} is clearly hand-crafted rather than auto-generated. This is functionally fine but could collide with another hand-crafted GUID in a different branch. Consider letting Visual Studio or dotnet sln add generate a proper random GUID.

Also applies to: 26-29

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

In `@Maui.FreakyEffects/Maui.FreakyEffects.sln` around lines 10 - 11, The solution
contains a hand-crafted project GUID ({A1B2C3D4-E5F6-7890-ABCD-EF1234567890}) in
the Project(...) entry which risks collisions; replace that GUID with a proper
randomly-generated GUID by removing and re-adding the test project (or using
Visual Studio/dotnet sln add to re-add it) so the Project(...) line for
"Maui.FreakyEffects.Tests" receives an auto-generated GUID; ensure the same
change is applied to the duplicate entries referenced on lines 26-29.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@Maui.FreakyEffects/Maui.FreakyEffects.Tests/SkiaScene/TouchGestureRecognizerTests.cs`:
- Around line 69-83: The test fails because
TouchGestureRecognizer.ProcessTouchEvent calls DetectPinchAndPanGestures(type)
before removing the touch, so OnPan is fired during the Released event; update
the test in
TouchGestureRecognizerTests.ProcessTouchEvent_Released_RemovesTouchFromTracking
to expect OnPan to have fired by changing the assertion to Assert.Equal(1,
panCount) and adjust the comment to state "Pan fires on Released (1 touch)" (or
alternatively remove the final Moved event and reword the comment) so the test
reflects that DetectPinchAndPanGestures triggers OnPan on Released.

---

Duplicate comments:
In `@Maui.FreakyEffects/Maui.FreakyEffects/Shared/Skeleton/FadeAnimation.cs`:
- Around line 19-23: StopAnimation currently does an unsafe direct cast
((View)bindable) which can throw; update StopAnimation in FadeAnimation to use
safe pattern matching (e.g., if (bindable is View self) { await
self.FadeToAsync(1, 100); } else return) similar to the change suggested for
BeatAnimation.StopAnimation so the method returns early when bindable is not a
View.

---

Nitpick comments:
In `@Maui.FreakyEffects/Maui.FreakyEffects.sln`:
- Around line 10-11: The solution contains a hand-crafted project GUID
({A1B2C3D4-E5F6-7890-ABCD-EF1234567890}) in the Project(...) entry which risks
collisions; replace that GUID with a proper randomly-generated GUID by removing
and re-adding the test project (or using Visual Studio/dotnet sln add to re-add
it) so the Project(...) line for "Maui.FreakyEffects.Tests" receives an
auto-generated GUID; ensure the same change is applied to the duplicate entries
referenced on lines 26-29.

In
`@Maui.FreakyEffects/Maui.FreakyEffects.Tests/Skeleton/AnimationConstructorTests.cs`:
- Around line 74-80: The test AnimationTypes_HasFiveMembers is brittle because
it asserts a hardcoded enum count; either remove this test or convert it to an
explicit API-guard with a clear comment. Update the test file by either deleting
the AnimationTypes_HasFiveMembers method (since AnimationTypes_HasExpectedValues
already checks the named members) or keep it but add a comment above the
AnimationTypes_HasFiveMembers test explaining it intentionally guards the public
API surface and must be updated when enum members are added; ensure references
to the test name AnimationTypes_HasFiveMembers and the complementary test
AnimationTypes_HasExpectedValues are preserved so reviewers can see which
approach you chose.

In
`@Maui.FreakyEffects/Maui.FreakyEffects.Tests/TouchTracking/TouchTrackingRectTests.cs`:
- Around line 8-38: Replace the four separate Fact tests (Constructor_SetsLeft,
Constructor_SetsTop, Constructor_SetsRight, Constructor_SetsBottom) with a
single consolidated test that constructs TouchTrackingRect(10f, 20f, 30f, 40f)
once and asserts all four properties (Left, Top, Right, Bottom) in that test
(e.g., a new Fact named Constructor_InitializesAllProperties or use a
Theory+MemberData if preferred); update or remove the four original test methods
so there’s one test validating the constructor initializes all properties.

In `@Maui.FreakyEffects/Maui.FreakyEffects/Shared/Skeleton/BeatAnimation.cs`:
- Around line 19-23: BeatAnimation.StopAnimation currently does a direct cast
(var self = (View)bindable) which can throw; change it to match the safe pattern
used in HorizontalShakeAnimation/VerticalShakeAnimation by using an "if
(bindable is View self)" guard and only call self.ScaleToAsync(1, 100) inside
that block (no cast or exception). Also mirror the same guard pattern in
FadeAnimation.StopAnimation if present to keep consistency across animation
classes.

Comment on lines +69 to +83
[Fact]
public void ProcessTouchEvent_Released_RemovesTouchFromTracking()
{
var recognizer = new TouchGestureRecognizer();
int panCount = 0;
recognizer.OnPan += (_, _) => panCount++;

recognizer.ProcessTouchEvent(1, TouchActionType.Pressed, new SKPoint(0, 0));
recognizer.ProcessTouchEvent(1, TouchActionType.Released, new SKPoint(5, 5));

// After release, a move with the same id should do nothing
recognizer.ProcessTouchEvent(1, TouchActionType.Moved, new SKPoint(10, 10));

Assert.Equal(0, panCount); // Pan fires on Released (1 touch), but not on Move after release
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

fd "TouchGestureRecognizer.cs" --exclude "*Tests*" -type f

Repository: FreakyAli/Maui.FreakyEffects

Length of output: 242


🏁 Script executed:

fd "TouchGestureRecognizer.cs" --exclude "*Tests*"

Repository: FreakyAli/Maui.FreakyEffects

Length of output: 290


🏁 Script executed:

cat "Maui.FreakyEffects/Maui.FreakyEffects/Shared/SkiaScene/SkiaScene.TouchManipulation/TouchGestureRecognizer.cs"

Repository: FreakyAli/Maui.FreakyEffects

Length of output: 4889


Test will fail — OnPan fires on Released with 1 touch.

The implementation calls DetectPinchAndPanGestures(type) on line 72 (in TouchGestureRecognizer.cs) before removing the touch from the dictionary. When exactly 1 touch remains, this invokes OnPan (line 120).

In this test, the Released event triggers OnPan, incrementing panCount to 1. The assertion Assert.Equal(0, panCount) will fail.

Either update the assertion to Assert.Equal(1, panCount), or remove the final Moved event (lines 80–81) and reword the comment to clarify that OnPan fires on Released.

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

In
`@Maui.FreakyEffects/Maui.FreakyEffects.Tests/SkiaScene/TouchGestureRecognizerTests.cs`
around lines 69 - 83, The test fails because
TouchGestureRecognizer.ProcessTouchEvent calls DetectPinchAndPanGestures(type)
before removing the touch, so OnPan is fired during the Released event; update
the test in
TouchGestureRecognizerTests.ProcessTouchEvent_Released_RemovesTouchFromTracking
to expect OnPan to have fired by changing the assertion to Assert.Equal(1,
panCount) and adjust the comment to state "Pan fires on Released (1 touch)" (or
alternatively remove the final Moved event and reword the comment) so the test
reflects that DetectPinchAndPanGestures triggers OnPan on Released.

@FreakyAli FreakyAli merged commit e623556 into master Feb 24, 2026
4 checks passed
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.

2 participants