Skip to content

Test Infrastructure with Bun Test Runner#97

Open
prakharsingh-74 wants to merge 3 commits intoStabilityNexus:mainfrom
prakharsingh-74:main
Open

Test Infrastructure with Bun Test Runner#97
prakharsingh-74 wants to merge 3 commits intoStabilityNexus:mainfrom
prakharsingh-74:main

Conversation

@prakharsingh-74
Copy link
Copy Markdown
Contributor

@prakharsingh-74 prakharsingh-74 commented Nov 26, 2025

fixes - #79

Implemented comprehensive test infrastructure for the Gluon-Ergo-UI frontend using Bun's native test runner. This PR adds 168 passing tests covering utility functions and business logic, establishing a solid foundation for code quality and reliability.

Changes

Test Infrastructure

  • Created /tests directory structure mirroring source code
  • Added global test setup with browser API mocks (tests/setup.ts)
  • Configured Bun test runner with TypeScript support

Test Coverage (168 tests, 100% passing)

Utility Functions (src/lib/utils):

  • utils.ts - className merging (8 tests)
  • erg-converter.ts - ERG conversion & formatting (60 tests)
  • error-handler.ts - Error classification & handling (36 tests)
  • node-service.ts - Blockchain API service (15 tests)
  • transaction-listener.ts - Transaction monitoring (12 tests)

Business Logic (src/lib/functions/reactor):

  • utils.ts - Token validation & swap actions (37 tests)

Configuration Updates

  • Updated package.json with test scripts (test, test:watch, test:coverage)
  • Added @types/bun dependency for TypeScript support
  • Updated tsconfig.json to include Bun types
  • Updated README.md with Testing section and accurate directory structure

Summary by CodeRabbit

  • Documentation

    • Updated README with testing section and expanded folder structure details
  • Tests

    • Added comprehensive test coverage for utility functions, error handling, and core services
    • Migrated test infrastructure to Bun test runner with watch mode and coverage reporting
  • Chores

    • Added Bun type definitions to development dependencies
    • Updated TypeScript configuration for Bun compatibility

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

…nsaction listening, and reactor functions, and update project configuration.
… directories, detailing `src/lib` components and functions, and listing specific page files.
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Nov 26, 2025

Walkthrough

This pull request introduces comprehensive test coverage for utility functions and business logic modules by migrating from Vitest to Bun's test runner. Configuration files are updated to support Bun testing, documentation is extended with testing details, and test suites are added for reactor utilities, error handling, node service, transaction listeners, and erg conversion functions.

Changes

Cohort / File(s) Summary
Configuration & Tooling
package.json, tsconfig.json
Updated test scripts to use Bun test runner (replacing vitest); added watch and coverage modes; added @types/bun dev dependency; reformatted configuration arrays for readability
Documentation
README.md
Added Testing section with Bun test suite commands and coverage breakdown; extended Folder Structure documentation with detailed src/ layout hierarchy, including public/ directory and new component/reactor organization
Test Infrastructure
tests/setup.ts
Introduced global test setup file for Bun runner with browser globals mocking, localStorage implementation, and Web Storage API support
Test Suites
tests/lib/functions/reactor/utils.test.ts, tests/lib/utils/erg-converter.test.ts, tests/lib/utils/error-handler.test.ts, tests/lib/utils/node-service.test.ts, tests/lib/utils/transaction-listener.test.ts, tests/lib/utils/utils.test.ts
Added comprehensive test coverage for reactor utilities (VALID_PAIRS, defaultTokens, action type and description functions), erg conversion and formatting, error classification and handling, NodeService HTTP methods and blockchain API helpers, TransactionListener persistence and state management, and className utility function

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Multiple new test files with varying logic density — Each test suite covers different domains (reactor, erg conversion, error handling, node service, transaction listener, utilities) requiring separate reasoning for correctness and edge case coverage
  • Test setup and configuration changes are straightforward — Bun migration involves simple script updates and type annotation additions
  • Mocking strategies — NodeService and localStorage mocking patterns should be verified for consistency and correctness
  • Edge case coverage — Particular attention to error handling tests and transaction listener state management scenarios

Possibly related PRs

Suggested reviewers

  • Zahnentferner

Poem

🐰 Hop, hop, hooray! Tests multiply today,
Coverage blooms in Bun's swift way,
From vitest's nest, we've come to stay,
Where errors fall and utilities play! 🧪✨

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Test Infrastructure with Bun Test Runner' accurately summarizes the main change: implementing a test infrastructure using Bun's test runner, which is the primary focus of the PR.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Tip

📝 Customizable high-level summaries are now available in beta!

You can now customize how CodeRabbit generates the high-level summary in your pull requests — including its content, structure, tone, and formatting.

  • Provide your own instructions using the high_level_summary_instructions setting.
  • Format the summary however you like (bullet lists, tables, multi-section layouts, contributor stats, etc.).
  • Use high_level_summary_in_walkthrough to move the summary from the description to the walkthrough section.

Example instruction:

"Divide the high-level summary into five sections:

  1. 📝 Description — Summarize the main change in 50–60 words, explaining what was done.
  2. 📓 References — List relevant issues, discussions, documentation, or related PRs.
  3. 📦 Dependencies & Requirements — Mention any new/updated dependencies, environment variable changes, or configuration updates.
  4. 📊 Contributor Summary — Include a Markdown table showing contributions:
    | Contributor | Lines Added | Lines Removed | Files Changed |
  5. ✔️ Additional Notes — Add any extra reviewer context.
    Keep each section concise (under 200 words) and use bullet or numbered lists for clarity."

Note: This feature is currently in beta for Pro-tier users, and pricing will be announced later.


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
Copy Markdown

@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 (7)
tests/setup.ts (1)

7-9: Consider a more complete window mock.

The empty object cast to any may cause issues if tests inadvertently access window properties. Consider either:

  1. Defining only the properties your tests need
  2. Using a more comprehensive mock if window interactions are expected

Apply this diff if window properties are needed:

-if (typeof window === 'undefined') {
-    global.window = {} as any;
-}
+if (typeof window === 'undefined') {
+    global.window = {
+        location: { href: 'http://localhost' },
+        navigator: { userAgent: 'test' },
+    } as any;
+}
tests/lib/utils/transaction-listener.test.ts (6)

2-2: Simplify the import path.

The import path "../../../tests/setup" goes up to the project root and back down into tests/. This can be simplified to "../../setup" since the current file is already in tests/lib/utils/.

Apply this diff:

-import "../../../tests/setup"; // Import setup to ensure localStorage mock is available
+import "../../setup"; // Import setup to ensure localStorage mock is available

88-90: Extract inline objects into variables for readability.

These lines exceed 200 characters with complex nested object literals, making them difficult to read and maintain. Consider extracting the state and changes objects into named variables.

Apply this diff:

         test("should handle multiple transactions", () => {
-            listener.saveUpTransaction("tx1", "fission", { erg: "1000000000", gau: "0", gauc: "0", timestamp: Date.now() }, { erg: "-500000000", gau: "250000000", gauc: "250000000", fees: "-1000000" });
-            listener.saveUpTransaction("tx2", "fusion", { erg: "1000000000", gau: "500000000", gauc: "500000000", timestamp: Date.now() }, { erg: "1000000000", gau: "-500000000", gauc: "-500000000", fees: "-1000000" });
+            const tx1State: WalletState = { erg: "1000000000", gau: "0", gauc: "0", timestamp: Date.now() };
+            const tx1Changes: ExpectedChanges = { erg: "-500000000", gau: "250000000", gauc: "250000000", fees: "-1000000" };
+            listener.saveUpTransaction("tx1", "fission", tx1State, tx1Changes);
+            
+            const tx2State: WalletState = { erg: "1000000000", gau: "500000000", gauc: "500000000", timestamp: Date.now() };
+            const tx2Changes: ExpectedChanges = { erg: "1000000000", gau: "-500000000", gauc: "-500000000", fees: "-1000000" };
+            listener.saveUpTransaction("tx2", "fusion", tx2State, tx2Changes);
 
             const stored = localStorage.getItem("gluon_pending_transactions");

105-106: Extract inline objects for better readability.

Similar to the issue on lines 88-90, these setup lines are excessively long. Extract the objects into variables.

Apply this diff:

         beforeEach(() => {
             // Add some test transactions
-            listener.saveUpTransaction("tx1", "fission", { erg: "1000000000", gau: "0", gauc: "0", timestamp: Date.now() }, { erg: "-500000000", gau: "250000000", gauc: "250000000", fees: "-1000000" });
-            listener.saveUpTransaction("tx2", "fusion", { erg: "1000000000", gau: "500000000", gauc: "500000000", timestamp: Date.now() }, { erg: "1000000000", gau: "-500000000", gauc: "-500000000", fees: "-1000000" });
+            const tx1State: WalletState = { erg: "1000000000", gau: "0", gauc: "0", timestamp: Date.now() };
+            const tx1Changes: ExpectedChanges = { erg: "-500000000", gau: "250000000", gauc: "250000000", fees: "-1000000" };
+            listener.saveUpTransaction("tx1", "fission", tx1State, tx1Changes);
+            
+            const tx2State: WalletState = { erg: "1000000000", gau: "500000000", gauc: "500000000", timestamp: Date.now() };
+            const tx2Changes: ExpectedChanges = { erg: "1000000000", gau: "-500000000", gauc: "-500000000", fees: "-1000000" };
+            listener.saveUpTransaction("tx2", "fusion", tx2State, tx2Changes);
         });

158-158: Extract inline objects for consistency.

For consistency with the refactoring suggested elsewhere, extract the inline objects here as well.

Apply this diff:

         test("should return true when pending transactions exist", () => {
-            listener.saveUpTransaction("tx1", "fission", { erg: "1000000000", gau: "0", gauc: "0", timestamp: Date.now() }, { erg: "-500000000", gau: "250000000", gauc: "250000000", fees: "-1000000" });
+            const state: WalletState = { erg: "1000000000", gau: "0", gauc: "0", timestamp: Date.now() };
+            const changes: ExpectedChanges = { erg: "-500000000", gau: "250000000", gauc: "250000000", fees: "-1000000" };
+            listener.saveUpTransaction("tx1", "fission", state, changes);
             expect(listener.hasPendingTransactions()).toBe(true);
         });

170-171: Extract inline objects for consistency.

Apply the same refactoring pattern used in other tests.

Apply this diff:

         test("should return array of pending transactions", () => {
-            listener.saveUpTransaction("tx1", "fission", { erg: "1000000000", gau: "0", gauc: "0", timestamp: Date.now() }, { erg: "-500000000", gau: "250000000", gauc: "250000000", fees: "-1000000" });
-            listener.saveUpTransaction("tx2", "fusion", { erg: "1000000000", gau: "500000000", gauc: "500000000", timestamp: Date.now() }, { erg: "1000000000", gau: "-500000000", gauc: "-500000000", fees: "-1000000" });
+            const tx1State: WalletState = { erg: "1000000000", gau: "0", gauc: "0", timestamp: Date.now() };
+            const tx1Changes: ExpectedChanges = { erg: "-500000000", gau: "250000000", gauc: "250000000", fees: "-1000000" };
+            listener.saveUpTransaction("tx1", "fission", tx1State, tx1Changes);
+            
+            const tx2State: WalletState = { erg: "1000000000", gau: "500000000", gauc: "500000000", timestamp: Date.now() };
+            const tx2Changes: ExpectedChanges = { erg: "1000000000", gau: "-500000000", gauc: "-500000000", fees: "-1000000" };
+            listener.saveUpTransaction("tx2", "fusion", tx2State, tx2Changes);
 
             const list = listener.getPendingTransactionsList();

187-187: Extract inline objects for consistency.

Apply the same refactoring for the last occurrence of inline objects.

Apply this diff:

         test("should start listening when pending transactions exist", () => {
-            listener.saveUpTransaction("tx1", "fission", { erg: "1000000000", gau: "0", gauc: "0", timestamp: Date.now() }, { erg: "-500000000", gau: "250000000", gauc: "250000000", fees: "-1000000" });
+            const state: WalletState = { erg: "1000000000", gau: "0", gauc: "0", timestamp: Date.now() };
+            const changes: ExpectedChanges = { erg: "-500000000", gau: "250000000", gauc: "250000000", fees: "-1000000" };
+            listener.saveUpTransaction("tx1", "fission", state, changes);
 
             // Create new listener to test initialization
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9565760 and 0657a86.

⛔ Files ignored due to path filters (1)
  • bun.lockb is excluded by !**/bun.lockb
📒 Files selected for processing (10)
  • README.md (1 hunks)
  • package.json (3 hunks)
  • tests/lib/functions/reactor/utils.test.ts (1 hunks)
  • tests/lib/utils/erg-converter.test.ts (1 hunks)
  • tests/lib/utils/error-handler.test.ts (1 hunks)
  • tests/lib/utils/node-service.test.ts (1 hunks)
  • tests/lib/utils/transaction-listener.test.ts (1 hunks)
  • tests/lib/utils/utils.test.ts (1 hunks)
  • tests/setup.ts (1 hunks)
  • tsconfig.json (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (4)
tests/lib/functions/reactor/utils.test.ts (2)
src/lib/functions/reactor/utils.ts (8)
  • VALID_PAIRS (5-10)
  • defaultTokens (12-45)
  • getValidToTokens (47-61)
  • getActionType (63-69)
  • getDescription (71-84)
  • getTitle (86-98)
  • validateAmount (100-106)
  • formatValue (108-112)
src/lib/functions/reactor/types.ts (1)
  • TokenSymbol (3-3)
tests/lib/utils/utils.test.ts (1)
src/lib/utils/utils.ts (1)
  • cn (4-6)
tests/lib/utils/erg-converter.test.ts (1)
src/lib/utils/erg-converter.ts (11)
  • convertFromDecimals (30-33)
  • convertToDecimals (40-47)
  • formatMacroNumber (54-82)
  • formatMicroNumber (89-114)
  • formatApprox (116-118)
  • format (120-122)
  • formatNumber (129-131)
  • nanoErgsToErgs (133-135)
  • ergsToNanoErgs (137-141)
  • UIFriendlyValue (143-146)
  • APIFriendlyValue (148-152)
tests/lib/utils/error-handler.test.ts (1)
src/lib/utils/error-handler.ts (3)
  • handleTransactionError (175-240)
  • handleCalculationError (275-318)
  • handleInitializationError (323-336)
🪛 markdownlint-cli2 (0.18.1)
README.md

155-155: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🔇 Additional comments (20)
tests/setup.ts (2)

12-39: LGTM! LocalStorageMock implementation is solid.

The mock correctly implements the core Web Storage API methods (getItem, setItem, removeItem, clear, length, key). This is sufficient for most test scenarios involving localStorage.


41-41: Global localStorage assignment looks good.

The assignment properly makes the LocalStorageMock available globally for all tests. The as any cast is necessary for Node.js global augmentation.

tsconfig.json (1)

9-11: Good addition of Bun type support.

Adding "@types/bun" to the types array properly enables TypeScript IntelliSense and type checking for Bun's test runner APIs and globals.

tests/lib/utils/utils.test.ts (1)

1-52: Comprehensive test coverage for cn utility.

The test suite thoroughly covers the className merging utility with:

  • Basic merging and conditional classes
  • Tailwind CSS conflict resolution
  • Multiple input types (arrays, objects, strings)
  • Edge cases (empty, undefined, null)

All assertions look correct and align with the expected behavior of clsx and tailwind-merge.

package.json (3)

13-15: Test scripts updated correctly for Bun.

The migration from Vitest to Bun's test runner is properly configured with appropriate scripts for running tests, watch mode, and coverage.


83-83: I'll help you verify whether the Vitest dependency is truly unused before confirming the review comment. Let me search the codebase for any Vitest references.
<function_calls>

#!/bin/bash

Search for vitest imports and references in the codebase

rg -n "from ['"]vitest|import.*vitest|vitest" --type ts --type tsx --type js --type jsx -g '!node_modules' -g '!dist' -g '!build'


</function_calls>

#!/bin/bash

Check for vitest configuration files

fd -e vitest.config.ts -e vitest.config.js -e .vitest.config.ts -e .vitest.config.js -e vitest.config.mjs


</function_calls>
<function_calls>

#!/bin/bash

Check package.json for vitest references in scripts and other sections

cat package.json | head -150


</function_calls>
<function_calls>

#!/bin/bash

Search for test files and check what test runner they use

fd -e ".test." -e ".spec." | head -20


</function_calls>


65-65: Version ^1.3.3 is current. Confirmed as the latest available version of @types/bun on npm as of November 2025.

tests/lib/utils/node-service.test.ts (4)

1-24: Axios mocking setup looks good.

The mock structure correctly uses Bun's mock.module to intercept axios and provide a mocked instance. The mock axios instance includes get, post, head methods and defaults object.


30-37: Good use of beforeEach for test isolation.

Clearing mocks before each test ensures test isolation and prevents state leakage between tests. Creating a fresh NodeService instance for each test is the correct pattern.


135-258: Comprehensive blockchain API method coverage.

The test suite thoroughly validates all NodeService methods including:

  • Node info and height queries
  • Token and box lookups
  • Transaction operations
  • Error handling for network failures

All assertions properly verify both method invocation and response handling.


94-103: Based on my verification of the codebase, I have examined the actual NodeService implementation and can now provide the rewritten review comment.


The test correctly reflects the current implementation, but the POST method has a design flaw with shared state mutation.

The test assertion is accurate—the post() method at lines 48-51 of src/lib/utils/node-service.ts explicitly mutates this.backend.defaults.headers with the passed headers. However, this design is problematic:

  1. State leakage: Headers persist on the axios instance defaults across subsequent requests, potentially affecting unrelated calls.
  2. Inconsistency: The get() method passes headers per-request (lines 29-32) rather than mutating defaults, creating inconsistent behavior.
  3. Race conditions: In concurrent async scenarios, mutating shared defaults can cause unintended header collisions.

Consider refactoring post() to match the get() pattern by passing headers in the request config object instead of mutating defaults.

README.md (1)

98-148: Excellent testing documentation.

The Testing section provides clear, comprehensive documentation covering:

  • Running tests with various modes (watch, coverage, specific files)
  • Current test coverage breakdown by module
  • Guidance on writing tests
  • Clear statement of what's not yet tested

This will help contributors understand the testing setup and expectations.

tests/lib/utils/erg-converter.test.ts (3)

17-91: Thorough conversion function testing.

The tests for convertFromDecimals and convertToDecimals comprehensively cover:

  • Different input types (number, bigint, string)
  • Edge cases (zero, empty string, null, undefined, NaN)
  • Custom decimal precision
  • Rounding behavior

All assertions correctly validate the conversion logic.


93-187: Excellent formatting function coverage.

The formatting tests thoroughly validate macro and micro number formatting including:

  • Suffix generation (K, M, B, T)
  • Decimal place handling
  • Trailing zero removal
  • Tooltip formatting
  • Multiple input types

The test expectations align with the implementation details shown in the relevant code snippets.


215-291: Comprehensive coverage of conversion utilities.

Tests for ERG/nanoERG conversions and UI/API helper functions cover all necessary scenarios including type variations, edge cases, and custom divisors. The test suite validates the complete public API surface.

tests/lib/functions/reactor/utils.test.ts (4)

15-57: Solid test coverage for data structures.

Tests properly validate the VALID_PAIRS configuration and defaultTokens array, ensuring:

  • Correct number of pairs and tokens
  • All expected tokens are present
  • Token properties (name, decimals) are correct

59-120: Comprehensive token swap logic validation.

Tests thoroughly validate the swap pair resolution and action type determination, including:

  • All valid token pair combinations
  • Invalid pairs returning appropriate values
  • Edge cases (same token, invalid symbols)

The tests ensure the reactor business logic correctly handles all scenarios.


122-184: Excellent description and title tests.

Tests validate that UI messaging correctly maps to swap actions for all operation types (FISSION, FUSION, TRANSMUTATION), including proper fallback behavior for null actions.


186-268: Thorough input validation testing.

Tests for validateAmount and formatValue cover:

  • All validation error cases (empty, invalid, zero, negative)
  • Valid inputs (positive numbers, decimals, small/large values)
  • Formatting edge cases (undefined, NaN, various number types)

The validation logic is well-tested for robustness.

tests/lib/utils/error-handler.test.ts (1)

1-236: Comprehensive test coverage with well-organized structure.

The test suite provides excellent coverage of the error-handler module with 38 tests across all major functions. The tests are well-structured, properly disable toast notifications for unit testing, and cover various error shapes and edge cases.

Optional suggestions for future enhancement:

  • Line 233 tests null errors; consider also explicitly testing undefined for completeness
  • Lines 59, 161: Exact error message strings in tests may require maintenance if error messages change in implementation

Comment thread README.md
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