Skip to content

🌈 improve(testing): consolidate test utilities#6

Merged
UniquePixels merged 3 commits intodevelopfrom
fix/sonarcloud-cleanup
Mar 8, 2026
Merged

🌈 improve(testing): consolidate test utilities#6
UniquePixels merged 3 commits intodevelopfrom
fix/sonarcloud-cleanup

Conversation

@UniquePixels
Copy link
Owner

@UniquePixels UniquePixels commented Mar 8, 2026

Summary by CodeRabbit

  • Refactor

    • Enhanced interaction routing logic for improved code organization and maintainability
  • Chores

    • Updated project dependencies including undici package
    • Improved GitHub Actions CI/CD workflow and build configuration
    • Consolidated test utilities across the codebase
    • Updated development environment configuration

Extract shared replyWithResult helper in interaction-router,
consolidate assertDefined and createMockCommand into test-helpers,
fix type casts, catch param naming, and redundant returns.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Brian L. <brian@uniquepixels.xyz>
@coderabbitai
Copy link

coderabbitai bot commented Mar 8, 2026

πŸ“ Walkthrough

Walkthrough

Pull request consolidates test utilities into a shared module, updates dependency versions and configuration settings, refactors error handling in core libraries, and introduces a common abstraction for interaction reply logic in the router.

Changes

Cohort / File(s) Summary
Configuration and Dependencies
.github/workflows/ci-release.yml, .vscode/settings.json, package.json, renovate.json
Updated GitHub Action version, SonarLint project key, undici dependency override to ^7.22.0, and reformatted Renovate configuration for consistency.
Test Helpers Extraction
src/core/lib/test-helpers/index.ts, src/core/lib/test-helpers/mock-interaction.ts
Added public exports for assertDefined assertion utility and createMockCommand factory function to centralize test helper logic.
Test Files Updated
src/core/guards/index.test.ts, src/core/lib/logger/index.test.ts, src/core/sparks/command-group.test.ts, src/core/sparks/command.test.ts, src/core/sparks/scheduled-event.test.ts, src/guards/built-in/has-channel.test.ts, src/guards/built-in/special-channels.test.ts
Refactored tests to import assertDefined and createMockCommand from shared test-helpers module instead of local definitions.
Core Logic Refactoring
src/core/configuration/schema-helpers.test.ts, src/core/lib/attempt/index.ts, src/core/sparks/interaction-router.ts
Updated conditional logic in schema helpers, renamed error variable in attempt handler, and extracted common reply-handling abstraction (replyWithResult) in interaction router.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

πŸš₯ Pre-merge checks | βœ… 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning No pull request description was provided; only the template with a @coderabbitai suggestion comment is present. Add a detailed description explaining the consolidation of test utilities, the benefits, and which test helpers were moved or created.
βœ… Passed checks (2 passed)
Check name Status Explanation
Title check βœ… Passed The title clearly describes the main objective: consolidating test utilities across the codebase by extracting shared helpers into a centralized test-helpers module.
Docstring Coverage βœ… Passed Docstring coverage is 100.00% 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 (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 fix/sonarcloud-cleanup

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 changed the title @coderabbitai 🌈 improve(testing): consolidate test utilities Mar 8, 2026
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: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/core/sparks/interaction-router.ts (1)

39-47: 🧹 Nitpick | πŸ”΅ Trivial

Consider simplifying the condition for readability.

The double-negation !(result.ok || interaction.replied) is semantically equivalent to !result.ok && !interaction.replied. The latter reads more directly as "failed AND not yet replied."

Suggested fix
-	if (!(result.ok || interaction.replied)) {
+	if (!result.ok && !interaction.replied) {
πŸ€– Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/core/sparks/interaction-router.ts` around lines 39 - 47, Replace the
negated OR condition with an explicit AND for clarity: change the conditional in
the interaction handling block that currently reads if (!(result.ok ||
interaction.replied)) to if (!result.ok && !interaction.replied) so the logic
reads "failed AND not yet replied"; keep the inner branches (checking
interaction.deferred and calling interaction.editReply or interaction.reply with
MessageFlags.Ephemeral and result.reason) unchanged so behavior remains
identical.
πŸ€– Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@package.json`:
- Around line 34-35: The override for undici currently uses an open-ended range
(">=7.22.0") which can allow undici v8+ to be injected; update the override
entry under "overrides" to pin undici to a specific, tested patched version
(e.g., replace the value for "undici" with "7.22.0") so the transitive graph
cannot silently drift to incompatible majors; locate the "overrides" object and
the "undici" key in package.json to make this change.

In `@src/core/lib/test-helpers/index.ts`:
- Around line 27-30: The file fails the formatter (Biome) because the exported
helper signature formatting changed; run Biome/your project's formatter on
src/core/lib/test-helpers/index.ts (or reformat the assertDefined<T>(val: T |
undefined | null): asserts val is NonNullable<T> function) to match the
project's style rules, then commit the formatted result; ensure the exported
symbol assertDefined retains the same generic and assertion signature but with
spacing/linebreaks corrected per Biome so the format check passes.

In `@src/core/lib/test-helpers/mock-interaction.ts`:
- Around line 239-240: The createMockCommand mock currently returns a bare
object cast to SlashCommandBuilder which lacks the builder methods used
elsewhere (e.g., toJSON, setIntegrationTypes, setContexts) and will fail at
runtime; update createMockCommand to return an object shaped like a
SlashCommandBuilder that implements the methods toJSON(),
setIntegrationTypes(...), and setContexts(...) (each returning the builder for
chaining) and includes the name property so code in register-commands that calls
toJSON() or chains setIntegrationTypes/setContexts will work correctly.

In `@src/core/sparks/component.ts`:
- Line 380: The function that currently ends with "return undefined;" should be
changed to a bare "return;" or simply allow the function to fall through, since
its declared return type is BaseComponentSpark | undefined; remove the explicit
undefined token at the end of the function (the statement returning undefined)
so the function implicitly returns undefined instead, ensuring compliance with
the Biome lint rule and preserving the same behavior for callers expecting
BaseComponentSpark | undefined.

---

Outside diff comments:
In `@src/core/sparks/interaction-router.ts`:
- Around line 39-47: Replace the negated OR condition with an explicit AND for
clarity: change the conditional in the interaction handling block that currently
reads if (!(result.ok || interaction.replied)) to if (!result.ok &&
!interaction.replied) so the logic reads "failed AND not yet replied"; keep the
inner branches (checking interaction.deferred and calling interaction.editReply
or interaction.reply with MessageFlags.Ephemeral and result.reason) unchanged so
behavior remains identical.

ℹ️ Review info
βš™οΈ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 05f0d22c-1ce2-4d9e-8afc-a5c980cf146c

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between 43f3f72 and a484dba.

β›” Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock
πŸ“’ Files selected for processing (17)
  • .github/workflows/ci-release.yml
  • .vscode/settings.json
  • package.json
  • renovate.json
  • src/core/configuration/schema-helpers.test.ts
  • src/core/guards/index.test.ts
  • src/core/lib/attempt/index.ts
  • src/core/lib/logger/index.test.ts
  • src/core/lib/test-helpers/index.ts
  • src/core/lib/test-helpers/mock-interaction.ts
  • src/core/sparks/command-group.test.ts
  • src/core/sparks/command.test.ts
  • src/core/sparks/component.ts
  • src/core/sparks/interaction-router.ts
  • src/core/sparks/scheduled-event.test.ts
  • src/guards/built-in/has-channel.test.ts
  • src/guards/built-in/special-channels.test.ts
πŸ“œ Review details
🧰 Additional context used
πŸ““ Path-based instructions (5)
**

βš™οΈ CodeRabbit configuration file

**: General project rules:

  • Runtime is Bun, not Node.js. Do not suggest node/npm/yarn patterns.
  • Zod v4 is used. z.enum() handles native TS enums directly;
    z.nativeEnum() is deprecated. Do not flag z.enum(SomeEnum) as incorrect.
  • attempt() is the project's Result-type wrapper. All fallible calls in
    sparks must use it β€” never raw try/catch or uncaught promises.
  • import type is required for type-only imports (verbatimModuleSyntax).
  • Biome enforces kebab-case filenames and organized imports.

Files:

  • src/core/sparks/component.ts
  • renovate.json
  • src/core/lib/test-helpers/mock-interaction.ts
  • src/core/lib/attempt/index.ts
  • src/core/configuration/schema-helpers.test.ts
  • src/guards/built-in/has-channel.test.ts
  • src/core/guards/index.test.ts
  • src/core/lib/logger/index.test.ts
  • src/core/lib/test-helpers/index.ts
  • src/core/sparks/interaction-router.ts
  • src/core/sparks/command.test.ts
  • src/core/sparks/command-group.test.ts
  • package.json
  • src/guards/built-in/special-channels.test.ts
  • src/core/sparks/scheduled-event.test.ts
src/core/**

βš™οΈ CodeRabbit configuration file

src/core/**: Core framework code. Focus on:

  • Type safety and proper TypeScript patterns
  • Error handling with attempt() β€” no raw try/catch in sparks
  • API design consistency and backward compatibility
  • Performance implications for hot paths (interaction routing, guard chains)

Files:

  • src/core/sparks/component.ts
  • src/core/lib/test-helpers/mock-interaction.ts
  • src/core/lib/attempt/index.ts
  • src/core/configuration/schema-helpers.test.ts
  • src/core/guards/index.test.ts
  • src/core/lib/logger/index.test.ts
  • src/core/lib/test-helpers/index.ts
  • src/core/sparks/interaction-router.ts
  • src/core/sparks/command.test.ts
  • src/core/sparks/command-group.test.ts
  • src/core/sparks/scheduled-event.test.ts
.github/**

βš™οΈ CodeRabbit configuration file

.github/**: CI/CD configuration. Check for:

  • Pinned action versions with hash comments
  • Harden Runner with egress blocking on all jobs
  • No credential or secret exposure risks
  • Correct branch targeting (main vs develop)

Files:

  • .github/workflows/ci-release.yml
**/*.test.ts

βš™οΈ CodeRabbit configuration file

**/*.test.ts: Test files use Bun's test runner. Verify:

  • Meaningful, descriptive test names
  • Edge cases and error paths covered
  • No flaky patterns (timers, network, race conditions)
  • DRY β€” shared setup extracted into file-local helpers
  • 100% coverage is the project threshold

Files:

  • src/core/configuration/schema-helpers.test.ts
  • src/guards/built-in/has-channel.test.ts
  • src/core/guards/index.test.ts
  • src/core/lib/logger/index.test.ts
  • src/core/sparks/command.test.ts
  • src/core/sparks/command-group.test.ts
  • src/guards/built-in/special-channels.test.ts
  • src/core/sparks/scheduled-event.test.ts
src/guards/**

βš™οΈ CodeRabbit configuration file

src/guards/**: Guards are composable validation functions. Ensure:

  • Proper TypeScript type narrowing via generics
  • Clear, actionable error messages in GuardResult
  • No side effects β€” guards must be pure predicates
  • Consistent pattern with existing built-in guards

Files:

  • src/guards/built-in/has-channel.test.ts
  • src/guards/built-in/special-channels.test.ts
πŸͺ› GitHub Check: Lint
src/core/sparks/component.ts

[notice] 380-380: lint/complexity/noUselessUndefined
Don't use unnecessary undefined.

src/core/lib/test-helpers/index.ts

[failure] 1-1: format
File content differs from formatting output

πŸͺ› GitHub Check: SonarCloud Code Analysis
src/core/guards/index.test.ts

[warning] 711-711: This assertion is unnecessary since it does not change the type of the expression.

See more on https://sonarcloud.io/project/issues?id=UniquePixels_unicorn&issues=AZzPW_bJC1LEfgiIivFg&open=AZzPW_bJC1LEfgiIivFg&pullRequest=6

πŸ”‡ Additional comments (10)
renovate.json (1)

8-9: Formatting-only cleanup looks good.

These edits keep the Renovate settings and match patterns unchanged while making the arrays more compact. No concerns here.

Also applies to: 15-15, 21-25, 30-30, 36-36, 42-42, 48-48, 53-53

src/core/lib/attempt/index.ts (1)

148-168: LGTM!

Clean refactor renaming the catch parameter to error_ to avoid shadowing the const error declaration on line 163. The error handling logic is sound:

  • Defensive JSON.stringify with fallback to String() for circular references
  • Properly preserves error chain via cause
src/core/sparks/interaction-router.ts (3)

15-24: LGTM!

Clean abstractions. RepliableInteraction captures the minimal required surface from discord.js interaction types. ExecuteResult is structurally compatible with GuardResult<T> (the extra value field on success is safely ignored).


71-99: LGTM!

Clean refactoring. The spark.execute() result (typed as GuardResult<TGuarded>) is structurally compatible with ExecuteResult, and the delegation to replyWithResult centralizes the post-execution reply logic cleanly.


157-165: LGTM!

Consistent refactoring pattern with handleCommand. The centralized reply handling via replyWithResult eliminates duplication and ensures uniform behavior for both commands and components.

src/guards/built-in/has-channel.test.ts (1)

4-4: LGTM!

The import consolidation from local helper to shared @/core/lib/test-helpers module aligns with the DRY principle and the PR's objective of centralizing test utilities.

src/core/sparks/scheduled-event.test.ts (1)

4-4: LGTM!

The consolidated import of assertDefined and createMockClient from the shared test-helpers module is correct. Both utilities are used appropriately throughout the test file.

src/guards/built-in/special-channels.test.ts (1)

5-5: LGTM!

The import consolidation is correct. The parameterized test pattern using guardTestCases is well-structured and aligns with the DRY principle.

src/core/sparks/command-group.test.ts (1)

9-13: LGTM!

The consolidated imports from @/core/lib/test-helpers are correct and all three utilities (assertDefined, createMockClient, createMockCommand) are used throughout this comprehensive test suite.

src/core/sparks/command.test.ts (1)

9-17: LGTM!

The consolidated imports from @/core/lib/test-helpers are well-organized. Both newly added imports (assertDefined, createMockCommand) along with the existing helpers (createMockAutocompleteInteraction, createMockChatInputInteraction, createMockClient, failGuard, passThroughGuard) are appropriately used throughout the test suite.

UniquePixels and others added 2 commits March 8, 2026 17:03
Revert to bare return per Biome preference, fix assertDefined
type narrowing to use NonNullable<T>.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Brian L. <brian@uniquepixels.xyz>
Prevent open-ended >=7.22.0 range from drifting to incompatible
major versions while discord.js still bundles vulnerable undici.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Brian L. <brian@uniquepixels.xyz>
@sonarqubecloud
Copy link

sonarqubecloud bot commented Mar 8, 2026

Quality Gate Passed Quality Gate passed

Issues
0 New issues
1 Accepted issue

Measures
0 Security Hotspots
No data about Coverage
0.0% Duplication on New Code

See analysis details on SonarQube Cloud

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.

♻️ Duplicate comments (1)
package.json (1)

35-35: ⚠️ Potential issue | 🟠 Major

The override still forces an unsupported undici major for the Discord stack.

^7.22.0 avoids v8 drift, but it still rewrites discord.js@14.25.1 / @discordjs/rest off their pinned undici@6.21.3. Unless those packages were upgraded to releases that officially support v7, this remains a compatibility risk; prefer the upstream-tested version or remove the override until that upgrade happens.

What undici version is declared by discord.js 14.25.1 and `@discordjs/rest` 2.6.0, and do those releases officially support being overridden to undici v7?
πŸ€– Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@package.json` at line 35, The package.json override forcing "undici":
"^7.22.0" conflicts with the versions pinned by discord.js@14.25.1 and
`@discordjs/rest` (which expect undici@6.21.3); either remove the override or
change it to the upstream-tested "6.21.3" until those libraries are upgraded to
officially support undici v7 β€” locate the "undici" entry in package.json and
update or delete the override, then run a fresh install and verify
discord.js/@discordjs/rest still resolve to compatible undici@6.21.3.
πŸ€– Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@package.json`:
- Line 35: The package.json override forcing "undici": "^7.22.0" conflicts with
the versions pinned by discord.js@14.25.1 and `@discordjs/rest` (which expect
undici@6.21.3); either remove the override or change it to the upstream-tested
"6.21.3" until those libraries are upgraded to officially support undici v7 β€”
locate the "undici" entry in package.json and update or delete the override,
then run a fresh install and verify discord.js/@discordjs/rest still resolve to
compatible undici@6.21.3.

ℹ️ Review info
βš™οΈ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 339ed8e9-1083-48ad-ab5c-3e9a8f38b945

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between a484dba and e35321d.

πŸ“’ Files selected for processing (2)
  • package.json
  • src/core/lib/test-helpers/index.ts
πŸ“œ Review details
🧰 Additional context used
πŸ““ Path-based instructions (2)
**

βš™οΈ CodeRabbit configuration file

**: General project rules:

  • Runtime is Bun, not Node.js. Do not suggest node/npm/yarn patterns.
  • Zod v4 is used. z.enum() handles native TS enums directly;
    z.nativeEnum() is deprecated. Do not flag z.enum(SomeEnum) as incorrect.
  • attempt() is the project's Result-type wrapper. All fallible calls in
    sparks must use it β€” never raw try/catch or uncaught promises.
  • import type is required for type-only imports (verbatimModuleSyntax).
  • Biome enforces kebab-case filenames and organized imports.

Files:

  • src/core/lib/test-helpers/index.ts
  • package.json
src/core/**

βš™οΈ CodeRabbit configuration file

src/core/**: Core framework code. Focus on:

  • Type safety and proper TypeScript patterns
  • Error handling with attempt() β€” no raw try/catch in sparks
  • API design consistency and backward compatibility
  • Performance implications for hot paths (interaction routing, guard chains)

Files:

  • src/core/lib/test-helpers/index.ts
πŸ”‡ Additional comments (2)
src/core/lib/test-helpers/index.ts (2)

1-2: Good shared assertion helper.

assertDefined gives callers proper NonNullable<T> narrowing, and using expect() here keeps failures readable while centralizing the null/undefined check in one reusable test utility.

Also applies to: 23-32


10-10: Nice barrel export.

Re-exporting createMockCommand here keeps the test-helper surface consistent across suites.

coderabbitai[bot]
coderabbitai bot previously approved these changes Mar 8, 2026
@UniquePixels UniquePixels changed the base branch from main to develop March 8, 2026 22:36
@UniquePixels UniquePixels dismissed coderabbitai[bot]’s stale review March 8, 2026 22:36

The base branch was changed.

@UniquePixels
Copy link
Owner Author

@coderabbitai had to change branch, please reapprove

@coderabbitai
Copy link

coderabbitai bot commented Mar 8, 2026

@UniquePixels Sure! Reapproving the PR now.

βœ… Actions performed

Comments resolved and changes approved.

@UniquePixels UniquePixels merged commit b4448fc into develop Mar 8, 2026
12 checks passed
@UniquePixels UniquePixels deleted the fix/sonarcloud-cleanup branch March 8, 2026 22:42
UniquePixels added a commit that referenced this pull request Mar 9, 2026
## Release v0.1.1

### 🌈 Improvements

- reduce cognitive complexity in health check handler (#9)
- detect all Biome finding severities as failures (#8)
- revamp badge row (#21)
- add Renovate commit format and squash strategy (#10)
- consolidate test utilities (#6)

### 🧺 Chores

- update undici to v7
- update install-action digest

---

**After merging**, the tag-release job will automatically:
- Tag this commit as `v0.1.1`
- Create a GitHub Release with the changelog
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