Test Infrastructure with Bun Test Runner#97
Test Infrastructure with Bun Test Runner#97prakharsingh-74 wants to merge 3 commits intoStabilityNexus:mainfrom
Conversation
…nsaction listening, and reactor functions, and update project configuration.
… directories, detailing `src/lib` components and functions, and listing specific page files.
WalkthroughThis 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
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes
Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
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.
Example instruction:
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (7)
tests/setup.ts (1)
7-9: Consider a more complete window mock.The empty object cast to
anymay cause issues if tests inadvertently accesswindowproperties. Consider either:
- Defining only the properties your tests need
- 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 intotests/. This can be simplified to"../../setup"since the current file is already intests/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
⛔ Files ignored due to path filters (1)
bun.lockbis 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 anycast 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
clsxandtailwind-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/bashSearch 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/bashCheck 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/bashCheck package.json for vitest references in scripts and other sections
cat package.json | head -150
</function_calls>
<function_calls>
#!/bin/bashSearch 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.moduleto 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 ofsrc/lib/utils/node-service.tsexplicitly mutatesthis.backend.defaults.headerswith the passed headers. However, this design is problematic:
- State leakage: Headers persist on the axios instance defaults across subsequent requests, potentially affecting unrelated calls.
- Inconsistency: The
get()method passes headers per-request (lines 29-32) rather than mutating defaults, creating inconsistent behavior.- Race conditions: In concurrent async scenarios, mutating shared defaults can cause unintended header collisions.
Consider refactoring
post()to match theget()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
convertFromDecimalsandconvertToDecimalscomprehensively 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
validateAmountandformatValuecover:
- 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
nullerrors; consider also explicitly testingundefinedfor completeness- Lines 59, 161: Exact error message strings in tests may require maintenance if error messages change in implementation
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
/testsdirectory structure mirroring source codetests/setup.ts)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
package.jsonwith test scripts (test,test:watch,test:coverage)@types/bundependency for TypeScript supporttsconfig.jsonto include Bun typesREADME.mdwith Testing section and accurate directory structureSummary by CodeRabbit
Documentation
Tests
Chores
✏️ Tip: You can customize this high-level summary in your review settings.