Skip to content

Add registry provider to UI components #1705

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 26 commits into
base: main
Choose a base branch
from

Conversation

hardingjam
Copy link
Contributor

@hardingjam hardingjam commented Apr 28, 2025

Motivation

  • Moves the handling of custom registry URLs into a Provider which wraps the deployment route.
  • The provider handles the setting and getting of registry URLs from localstorage.

Solution

Checks

By submitting this for review, I'm confirming I've done the following:

  • made this PR as small as possible
  • unit-tested any new functionality
  • linked any relevant issues or PRs
  • included screenshots (if this involves a front-end change)

Summary by CodeRabbit

  • New Features
    • Introduced centralized registry management via a new provider and manager, allowing dynamic switching and resetting of registries within the UI.
    • Added the ability to load custom registries and display warnings when a custom registry is active.
    • Enhanced the deploy page to support advanced mode toggling and improved registry input handling.
  • Improvements
    • Updated UI components to use the new registry provider, improving consistency and state management.
    • Enhanced error handling and user feedback when loading registries or strategies fails.
    • Improved testability and test coverage for registry-related features.
  • Bug Fixes
    • Fixed issues related to registry state persistence and synchronization between URL, localStorage, and UI.
  • Tests
    • Added comprehensive tests for registry management, registry loading, and page behaviors.
    • Refactored and expanded tests for input and service components.
  • Chores
    • Removed obsolete mocks and test code, streamlining the codebase.

Copy link
Contributor

coderabbitai bot commented Apr 28, 2025

Walkthrough

This set of changes introduces a centralized registry management system via a new RegistryManager class and associated context/provider utilities within the UI components package. The registry URL is now managed through a context-based provider (RegistryProvider) and accessed via the useRegistry hook, replacing previous direct localStorage and URL parameter manipulations. A new service function, loadRegistryUrl, handles loading and updating the registry, including error handling and page reloads. Svelte components in the webapp and UI packages are refactored to use these abstractions, removing legacy props and logic. Comprehensive unit and integration tests are added for the new registry management, service, and component behaviors, while obsolete test code and mocks are removed.

Changes

File(s) Change Summary
src/lib/providers/registry/RegistryManager.ts, context.ts, RegistryProvider.svelte, useRegistry.ts Introduced new registry management system: RegistryManager class, context utilities, provider component, and hook for accessing registry state.
src/lib/components/input/InputRegistryUrl.svelte, src/lib/components/deployment/DeploymentSteps.svelte Refactored to use registry context/hook instead of localStorage and direct prop passing; updated UI and logic for registry input and deployment steps.
src/lib/services/loadRegistryUrl.ts, src/lib/services/index.ts Added new service function loadRegistryUrl for loading/updating registry; exported from services index.
src/__fixtures__/RegistryManager.ts Added fixture providing a mock RegistryManager for testing.
src/__tests__/InputRegistryUrl.test.ts, loadRegistryUrl.test.ts, RegistryManager.test.ts, registry.test.ts Added and refactored tests for registry input, registry manager, registry service, and registry loading logic using new abstractions and mocks.
src/lib/index.ts Exported new registry-related entities: RegistryProvider, useRegistry, RegistryManager.
src/lib/services/registry.ts Removed all inline unit tests for registry service functions.
src/routes/deploy/+layout.svelte, +layout.ts, [strategyName]/[deploymentKey]/+page.svelte, +page.svelte Refactored to use registry context/provider; removed legacy registry prop passing; updated data flow and conditional rendering for registry and strategies.
src/lib/components/CustomRegistryWarning.svelte, Sidebar.svelte Enhanced custom registry warning with context usage and event handling; added reload attribute to sidebar deploy link.
src/lib/__mocks__/stores.ts Updated mock store method to support partial updates and added reset method.
src/routes/deploy/page.test.ts Added new test suite for deploy page, mocking registry and page store state for various scenarios.
src/__tests__/handleGuiInitialization.test.ts, test-setup.ts Updated/removal of module mocks for improved test isolation and accuracy.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant InputRegistryUrl
    participant RegistryManager
    participant loadRegistryUrl
    participant Window

    User->>InputRegistryUrl: Enter registry URL and click "Load"
    InputRegistryUrl->>RegistryManager: getCurrentRegistry()
    InputRegistryUrl->>loadRegistryUrl: loadRegistryUrl(newURL, registryManager)
    loadRegistryUrl->>RegistryManager: setRegistry(newURL)
    loadRegistryUrl->>Window: reload()
Loading
sequenceDiagram
    participant RootLayout
    participant RegistryProvider
    participant RegistryManager
    participant ChildComponent

    RootLayout->>RegistryManager: new RegistryManager(defaultURL)
    RootLayout->>RegistryProvider: registryManager
    RegistryProvider->>ChildComponent: provide registry context
    ChildComponent->>RegistryManager: useRegistry() (via context)
Loading

Suggested labels

webapp

Suggested reviewers

  • hardyjosh
✨ Finishing Touches
  • 📝 Generate Docstrings

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@hardingjam hardingjam marked this pull request as ready for review April 28, 2025 13:04
@hardingjam hardingjam self-assigned this Apr 28, 2025
@hardingjam hardingjam added the enhancement New feature or request label Apr 28, 2025
Copy link
Contributor

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

🔭 Outside diff range comments (1)
packages/webapp/src/routes/deploy/+layout.ts (1)

16-40: 🧹 Nitpick (assertive)

Consider explicitly typing the load function return

The load function could benefit from an explicit return type using the newly defined LoadResult type.

-export const load: LayoutLoad = async ({ url }) => {
+export const load: LayoutLoad<LoadResult> = async ({ url }) => {
📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f460fc4 and 4b16b3b.

📒 Files selected for processing (21)
  • packages/ui-components/src/__tests__/InputRegistryUrl.test.ts (2 hunks)
  • packages/ui-components/src/lib/__mocks__/stores.ts (3 hunks)
  • packages/ui-components/src/lib/components/deployment/DeploymentSteps.svelte (3 hunks)
  • packages/ui-components/src/lib/components/input/InputRegistryUrl.svelte (1 hunks)
  • packages/ui-components/src/lib/index.ts (1 hunks)
  • packages/ui-components/src/lib/providers/registry/RegistryManager.ts (1 hunks)
  • packages/ui-components/src/lib/providers/registry/RegistryProvider.svelte (1 hunks)
  • packages/ui-components/src/lib/providers/registry/context.ts (1 hunks)
  • packages/ui-components/src/lib/providers/registry/useRegistry.ts (1 hunks)
  • packages/ui-components/src/lib/services/index.ts (1 hunks)
  • packages/ui-components/src/lib/services/loadRegistryUrl.test.ts (1 hunks)
  • packages/ui-components/src/lib/services/loadRegistryUrl.ts (1 hunks)
  • packages/ui-components/src/lib/types/registry.ts (1 hunks)
  • packages/ui-components/test-setup.ts (1 hunks)
  • packages/webapp/src/__tests__/DepositOrWithdrawModal.test.ts (1 hunks)
  • packages/webapp/src/__tests__/OrderRemoveModal.test.ts (1 hunks)
  • packages/webapp/src/__tests__/handleGuiInitialization.test.ts (1 hunks)
  • packages/webapp/src/routes/deploy/+layout.svelte (1 hunks)
  • packages/webapp/src/routes/deploy/+layout.ts (8 hunks)
  • packages/webapp/src/routes/deploy/+page.svelte (1 hunks)
  • packages/webapp/test-setup.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (2)
packages/ui-components/src/lib/services/index.ts (1)
Learnt from: hardingjam
PR: rainlanguage/rain.orderbook#1565
File: packages/webapp/src/lib/services/loadRegistryUrl.ts:21-95
Timestamp: 2025-04-09T12:57:52.799Z
Learning: In the loadRegistryUrl function, invalid URL format validation is handled by the fetchRegistryDotrains function rather than explicit URL format validation within loadRegistryUrl itself. The error handling in the catch block will handle any failures from the fetch operation.
packages/ui-components/src/lib/services/loadRegistryUrl.ts (1)
Learnt from: hardingjam
PR: rainlanguage/rain.orderbook#1565
File: packages/webapp/src/lib/services/loadRegistryUrl.ts:21-95
Timestamp: 2025-04-09T12:57:52.799Z
Learning: In the loadRegistryUrl function, invalid URL format validation is handled by the fetchRegistryDotrains function rather than explicit URL format validation within loadRegistryUrl itself. The error handling in the catch block will handle any failures from the fetch operation.
🧬 Code Graph Analysis (8)
packages/ui-components/test-setup.ts (1)
packages/ui-components/src/lib/__mocks__/stores.ts (1)
  • mockRegistryStore (166-170)
packages/ui-components/src/lib/services/loadRegistryUrl.ts (2)
packages/ui-components/src/lib/services/index.ts (2)
  • loadRegistryUrl (2-2)
  • fetchRegistryDotrains (1-1)
packages/ui-components/src/lib/providers/registry/RegistryManager.ts (1)
  • RegistryManager (4-148)
packages/ui-components/src/lib/providers/registry/useRegistry.ts (2)
packages/ui-components/src/lib/providers/registry/context.ts (1)
  • getRegistryContext (15-23)
packages/ui-components/src/lib/types/registry.ts (1)
  • RegistryStore (4-4)
packages/ui-components/src/lib/types/registry.ts (1)
packages/ui-components/src/lib/providers/registry/RegistryManager.ts (1)
  • RegistryManager (4-148)
packages/ui-components/src/lib/__mocks__/stores.ts (2)
packages/ui-components/src/lib/index.ts (1)
  • RegistryManager (136-136)
packages/ui-components/src/lib/providers/registry/RegistryManager.ts (1)
  • RegistryManager (4-148)
packages/ui-components/src/lib/providers/registry/context.ts (2)
packages/ui-components/src/lib/index.ts (1)
  • RegistryManager (136-136)
packages/ui-components/src/lib/providers/registry/RegistryManager.ts (1)
  • RegistryManager (4-148)
packages/ui-components/src/__tests__/InputRegistryUrl.test.ts (2)
packages/ui-components/src/lib/__mocks__/stores.ts (2)
  • mockRegistryStore (166-170)
  • initialRegistry (13-23)
packages/ui-components/src/lib/services/loadRegistryUrl.ts (1)
  • loadRegistryUrl (4-24)
packages/webapp/src/routes/deploy/+layout.ts (3)
packages/ui-components/src/lib/services/registry.ts (3)
  • RegistryDotrain (10-13)
  • fetchRegistryDotrains (56-77)
  • validateStrategies (79-119)
packages/ui-components/src/lib/index.ts (2)
  • ValidStrategyDetail (87-87)
  • InvalidStrategyDetail (87-87)
packages/webapp/src/lib/constants.ts (1)
  • REGISTRY_URL (1-2)
🪛 Biome (1.9.4)
packages/ui-components/src/lib/providers/registry/RegistryManager.ts

[error] 46-47: Template literals are preferred over string concatenation.

Unsafe fix: Use a template literal.

(lint/style/useTemplate)


[error] 62-63: Template literals are preferred over string concatenation.

Unsafe fix: Use a template literal.

(lint/style/useTemplate)


[error] 79-79: Template literals are preferred over string concatenation.

Unsafe fix: Use a template literal.

(lint/style/useTemplate)


[error] 112-113: Template literals are preferred over string concatenation.

Unsafe fix: Use a template literal.

(lint/style/useTemplate)


[error] 135-136: Template literals are preferred over string concatenation.

Unsafe fix: Use a template literal.

(lint/style/useTemplate)

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: standard-tests (ubuntu-latest, rainix-rs-artifacts, true)
🔇 Additional comments (57)
packages/webapp/src/__tests__/OrderRemoveModal.test.ts (1)

7-13: Improved mocking strategy for orderbook module

The change from a static mock to an asynchronous mock that preserves original exports is a significant improvement. This approach ensures that only the necessary function (getRemoveOrderCalldata) is mocked while keeping the rest of the module's functionality intact.

packages/webapp/src/__tests__/DepositOrWithdrawModal.test.ts (1)

19-27: Good implementation of selective mocking

The updated mock correctly preserves all original exports while only overriding specific calldata-related functions. This approach maintains the integrity of the module's other functionality during testing.

packages/webapp/test-setup.ts (1)

10-10: Removal of global mock improves test isolation

Removing the global mock for @rainlanguage/orderbook is appropriate as it's been replaced with more specific, targeted mocks in individual test files. This change promotes better test isolation and more explicit dependencies.

packages/webapp/src/__tests__/handleGuiInitialization.test.ts (1)

6-13: Proper test-specific mocking of DotrainOrderGui

The explicit mocking of DotrainOrderGui and its prototype methods provides clear visibility into what's being tested and how the dependencies are controlled. This local mock definition is more maintainable than relying on global mocks.

packages/ui-components/src/lib/services/index.ts (1)

2-2: Good addition of registry service export.

This export provides access to the new registry URL loading functionality from other components, supporting the centralized registry URL management as described in the PR objectives.

packages/ui-components/src/lib/types/registry.ts (1)

1-4: Clean type definition for the registry store.

The RegistryStore type properly defines a Svelte Readable store containing a RegistryManager instance, facilitating type-safe access to the registry throughout the component tree.

packages/ui-components/src/lib/providers/registry/RegistryProvider.svelte (1)

1-10: Well-implemented registry context provider.

This Svelte component follows the provider pattern correctly, accepting a registry store and making it available to child components through Svelte's context API. The implementation is minimal and focused on its single responsibility.

packages/ui-components/test-setup.ts (1)

3-10: Good test setup for registry functionality.

The mock implementation for the registry hook is consistent with the existing mocking patterns in the file and will properly support testing components that use the registry system.

packages/ui-components/src/lib/components/deployment/DeploymentSteps.svelte (3)

30-30: Good integration of the registry provider system.

The import of useRegistry hook aligns with the new centralized registry management approach.


61-61: LGTM: Proper hook initialization.

The hook is correctly initialized and will make the registry available throughout the component.


154-156: Correctly implemented dynamic registry URL retrieval.

The component now properly gets the registry URL dynamically through the registry provider system instead of using a static URL. This is a good refactoring that centralizes registry URL management.

packages/ui-components/src/lib/providers/registry/useRegistry.ts (2)

4-12: Well-implemented registry hook.

The hook correctly retrieves the registry context from Svelte's context system. The function is simple, focused, and follows the hook pattern appropriately.


14-38: Good test coverage for the hook.

The tests properly mock the context and verify both the function call and returned value. This ensures the hook works as expected in isolation.

packages/ui-components/src/lib/services/loadRegistryUrl.ts (1)

4-24:

❌ Incorrect review comment

Consider a more controlled approach to page reloading.

The function correctly validates inputs, fetches registry data, and updates the registry manager. However, forcing a full page reload with window.location.reload() can be jarring for users and loses application state.

Based on the retrieved learning, I can see URL validation is handled by fetchRegistryDotrains, which is good.

Consider a more controlled approach:

export async function loadRegistryUrl(
	url: string,
	registryManager: RegistryManager
): Promise<void> {
	if (!url) {
		throw new Error('No URL provided');
	}

	if (!registryManager) {
		throw new Error('Registry manager is required');
	}

	try {
		await fetchRegistryDotrains(url);
		registryManager.setRegistry(url);
-		window.location.reload();
+		// Return success and let caller decide how to update UI
+		return;
	} catch (e) {
		const errorMessage = e instanceof Error ? e.message : 'Failed to update registry URL';
		throw new Error(errorMessage);
	}
}

Components using this function could then handle UI updates in a more controlled way, such as showing a success message before redirecting or refreshing only certain parts of the UI.

Are there components that expect the page to reload after registry changes? This would help determine if this change is feasible.


🏁 Script executed:

#!/bin/bash
# Find components that use loadRegistryUrl to understand how they handle registry changes
rg -A 10 "loadRegistryUrl" --type svelte

Length of output: 71


🏁 Script executed:

#!/bin/bash
# Search for all usages of loadRegistryUrl across the codebase without file-type filtering
rg -n "loadRegistryUrl" .

Length of output: 2875


🏁 Script executed:

#!/bin/bash
# Display the InputRegistryUrl.svelte component to review how it handles loadRegistryUrl calls
sed -n '1,100p' packages/ui-components/src/lib/components/input/InputRegistryUrl.svelte

Length of output: 1320


Keep the full-page reload for registry URL changes

The forced reload in loadRegistryUrl is intentional and required to reinitialize application state (per our existing behavior in +layout.svelte). Removing window.location.reload() would leave stale state in the app, since no other code triggers a fresh bootstrap after the registry URL is updated.

  • Leave the call to window.location.reload() in packages/ui-components/src/lib/services/loadRegistryUrl.ts as is.
  • Components (like InputRegistryUrl.svelte) rely on that reload to fully apply the new registry URL across the app.

Likely an incorrect or invalid review comment.

packages/ui-components/src/lib/index.ts (1)

128-128: Well-organized exports for the new registry system.

The exports are properly organized by category (Providers, Hooks, Classes) and make the registry management system available as part of the public API. This allows consumers to use the registry provider, access hook, and manager class when needed.

Also applies to: 133-136

packages/ui-components/src/lib/services/loadRegistryUrl.test.ts (8)

1-7: Good test setup with clear imports and dependencies.

The test suite has all the necessary imports and properly sets up the test environment for the loadRegistryUrl function. The inclusion of the initialRegistry mock from the stores file is particularly good as it helps isolate tests.


8-13: Well-structured dependency mocking.

The mock setup for the fetchRegistryDotrains function is clean and follows best practices by using vi.fn() to create spy functions that can be asserted against later in the tests.


14-23: Good test initialization with proper cleanup.

The test suite properly resets mocks and resets the global window.location object between tests, which prevents test pollution. The explicit type casting approach with comments acknowledging the explicit any is a reasonable approach for testing environment setup.


24-27: LGTM: Validation test for missing URL parameter.

This test correctly verifies that the function rejects with an appropriate error message when no URL is provided.


29-33: LGTM: Validation test for missing registry manager.

This test correctly verifies that the function rejects when the registry manager is not provided.


35-44: LGTM: Comprehensive success case testing.

This test covers the happy path thoroughly by verifying that:

  1. The fetch function is called with the correct URL
  2. The registry manager's setRegistry method is called with the correct URL
  3. The page reload is triggered after a successful update

46-59: LGTM: Good error handling test for Error objects.

This test properly verifies that:

  1. Errors from fetchRegistryDotrains are propagated
  2. The registry is not updated when an error occurs
  3. The page is not reloaded on error

61-75: LGTM: Thorough test for non-Error exception handling.

This test covers the important edge case of handling non-Error rejections (like strings), which can happen in JavaScript. The test verifies that:

  1. A generic error message is thrown
  2. The registry is not updated
  3. The page is not reloaded

This is essential for robust error handling.

packages/ui-components/src/lib/components/input/InputRegistryUrl.svelte (5)

3-4: LGTM: Good imports for the registry provider pattern.

Importing the useRegistry hook and loadRegistryUrl service follows good separation of concerns, replacing direct DOM/localStorage manipulation with a centralized registry management approach.


6-9: LGTM: Clean state initialization.

The component properly:

  1. Gets the registry store using the hook
  2. Initializes the input with the current registry URL
  3. Sets up state variables for error handling and loading indication

11-23: LGTM: Well-implemented async click handler with proper error handling.

The handleClick function follows best practices for async operations:

  1. Sets loading state at the beginning
  2. Clears previous errors
  3. Uses try/catch for error handling
  4. Handles both Error objects and unknown error types
  5. Resets loading state in all cases
  6. Verifies registry availability before proceeding

26-37: LGTM: Clean UI layout with proper feedback states.

The UI structure is well organized:

  1. Uses flex layout for proper alignment
  2. Includes a data-testid attribute for testing
  3. Provides a visual loading indicator in the button
  4. Disables the button during loading to prevent multiple submissions

38-42: LGTM: Good error message display.

The error display section is well implemented:

  1. Maintains consistent height with a fixed placeholder div
  2. Uses conditional rendering to show errors only when present
  3. Includes a data-testid attribute for testing the error state
  4. Uses appropriate color for error messages
packages/webapp/src/routes/deploy/+page.svelte (6)

3-3: LGTM: Import page store for data access.

Importing the Svelte page store aligns with Svelte's pattern for accessing page data and simplifies the component by removing the need for props.


5-5: LGTM: Clean data destructuring from page store.

Destructuring the required data from $page.data makes the code more readable and ensures that only the needed data is extracted.


10-17: LGTM: Improved information section placement.

Moving the information section outside the conditional blocks ensures it's always visible, which improves the user experience by providing consistent context about Raindex and Rainlang.


19-22: LGTM: Enhanced error message with test ID.

The error display now includes a data-testid attribute, which makes it easier to test the error state in automated tests.


23-24: LGTM: Added empty state messaging.

Adding a specific message for when no strategies are found (with no error) improves the user experience by providing clear feedback.


26-31: LGTM: Cleaner conditional rendering for strategy sections.

Using nested conditional blocks for each strategy section makes the code more maintainable and ensures that sections are only rendered when they have content.

packages/ui-components/src/lib/__mocks__/stores.ts (5)

7-9: LGTM: Added imports for registry mocking.

Adding the necessary imports for RegistryManager and Vitest's mocking utilities prepares the file for implementing registry mocks.


10-12: LGTM: Good mock state initialization.

Setting up mock constants for the default and current registry URLs creates a clear initial state for tests and makes the mock behavior predictable.


13-23: LGTM: Comprehensive mock implementation of RegistryManager.

The initialRegistry mock provides implementations for all the key methods of the RegistryManager class:

  1. getCurrentRegistry returns the current or default URL
  2. setRegistry updates the mock state
  3. resetToDefault resets to the default URL
  4. updateUrlWithRegistry is stubbed for verification
  5. isCustomRegistry provides realistic logic

This enables thorough testing of components that interact with the registry.


58-58: LGTM: Mock registry store setup.

Creating a Svelte writable store initialized with the mock registry manager follows the same pattern as the other stores in this file.


166-170: LGTM: Complete registry store mock API.

The mockRegistryStore exports the necessary methods for subscription, setting, and updating the mock registry store, making it easy to use in tests.

packages/ui-components/src/__tests__/InputRegistryUrl.test.ts (6)

7-9: Well-structured test setup using vi.hoisted

The hoisted import ensures the mocks are defined before tests run, making them available for vi.mock to use.


10-13: Clean mock implementation of loadRegistryUrl service

Good approach to mock the service function, making it easy to control its behavior in different test scenarios.


37-49: Test thoroughly verifies loadRegistryUrl interaction

Good test case that verifies both user interaction and the service call with the correct parameters.


51-58: Well-crafted test for initial registry value

The test properly mocks the getCurrentRegistry method and verifies the input is initialized with the correct value.


60-69: Good error handling test case

The error case appropriately tests both the error triggering and the subsequent UI feedback to the user.


71-96: Comprehensive loading state test

This test is thorough in verifying the component's loading state behavior, including:

  • Using fake timers to control timing
  • Checking loading message display
  • Verifying button disabled state
  • Confirming return to normal state after loading completes

Excellent attention to the complete user experience.

packages/webapp/src/routes/deploy/+layout.svelte (3)

3-8: Good organization of imports

Clean import structure with named imports properly grouped.


16-18: Registry manager initialization and reactive binding

The registry manager is properly created and wrapped in a store for reactivity.


21-47: Well-structured registry provider with conditional rendering

The RegistryProvider component is properly implemented with conditional rendering based on registry state and current page. The structure allows for:

  • Showing/hiding the custom registry warning based on registry state
  • Toggling advanced mode only on the deploy page
  • Displaying the InputRegistryUrl component with transitions when in advanced mode
packages/ui-components/src/lib/providers/registry/RegistryManager.ts (2)

1-21: Good class structure with clear documentation

The class is well-structured with appropriate private fields and JSDoc comments explaining the purpose of each method and property.


145-147: Robust custom registry check

Good implementation of the isCustomRegistry method with a proper null check and comparison.

packages/ui-components/src/lib/providers/registry/context.ts (3)

15-23: Well-implemented context getter with helpful error message

The getRegistryContext function appropriately checks for missing context and provides a clear error message that guides the developer on how to fix the issue.


28-30: Simple and effective context setter

The setRegistryContext function is properly implemented to store the registry in Svelte's context.


32-68: Comprehensive inline tests

Excellent use of Vitest's inline testing capabilities to test the context functions. The tests cover both success and error cases.

packages/webapp/src/routes/deploy/+layout.ts (4)

4-6: Good import organization

The separation of type imports from value imports improves code readability. This follows best practices for TypeScript organization.


16-17: Clear variable renaming improves code clarity

Renaming registry to registryFromUrl makes the code more explicit about what this variable represents - the registry URL from the query parameter or default value.


89-89: Consistent variable name updates in tests

All test expectations have been properly updated to use the new registryFromUrl naming, maintaining consistency throughout the file.

Also applies to: 105-105, 121-121, 140-140, 153-153, 177-177


55-61:

✅ Verification successful

New RegistryManager mock added for tests

Adding the mock for the RegistryManager service is good for test reliability. This appears to be part of the broader registry management refactoring mentioned in the PR summary.


🌐 Web query:

What is the purpose of the SvelteKit layout.ts load function?

💡 Result:

Purpose of the SvelteKit +layout.ts Load Function

The load function exported from a SvelteKit +layout.ts (or +layout.js) file serves as a centralized data-fetching mechanism for a layout component and all its descendant pages and layouts within the same routing branch.

Key purposes and behaviors:

  • Fetch Shared Data:
    The +layout.ts load function allows you to fetch and provide data that is needed by multiple child pages under the same layout. This avoids data duplication and ensures consistency across sections like user authentication info, navigation menus, or other shared resources[2][8].

  • Pre-Render Data Loading:
    The data returned by the load function is made available to the associated +layout.svelte component via the data prop before it or any of its children are rendered. This enables components to access necessary data upfront[5][8].

  • Data Availability to Descendants:
    All child pages and layouts under the same route branch can access the data returned from a parent layout's load function. This is particularly useful for initializing app-wide state, fetching API tokens, or setting up global site information[2][7][8].

  • Reactivity and Efficient Data Fetching:
    The load function only re-runs when necessary—such as when navigating outside the current layout's scope or when dependencies (e.g., route params) change. This ensures efficient data-fetching and avoids unnecessary reloads of shared data[4][8].

  • Access to Load Event Context:
    The function receives a LoadEvent object, giving access to route parameters, query strings, cookies, and more, allowing context-aware data loading for the layout and its children[5].

  • Types of Load Functions:

    • +layout.ts: Universal load function running on both server and client (depending on navigation).
    • +layout.server.ts: Runs exclusively on the server, useful for accessing server-only secrets or protected APIs[5][8].

Example Use Cases:

  • Providing user authentication status or preferences to all pages within a dashboard section.
  • Serving a shared navigation menu or site settings to a set of pages.
  • Preloading data that multiple child pages will consume, preventing duplicate network requests.

Summary Table

Aspect +layout.ts Load Function Purpose
Scope Parent layout and all descendant routes
When it runs Before layout/child pages render; re-runs on relevant navigation events
Common uses Shared data: user info, navigation, API tokens
Data access in children Via data prop in Svelte components
Universal/Server option Runs on client, server, or both depending on file naming and navigation type
Avoids Redundant data fetching in individual pages

In short, the +layout.ts load function is a powerful feature in SvelteKit for efficient, context-aware, and shared data provision across multiple routes, streamlining data needs for grouped sections of your app[2][8].

Citations:


Approve: Mocking RegistryManager for layout load tests is appropriate

The SvelteKit +layout.ts load function fetches shared registry data for this layout and all its child routes. By mocking RegistryManager here, you prevent real storage calls and ensure reliable, side-effect-free tests—exactly what’s needed given the registry-management refactor.

• File: packages/webapp/src/routes/deploy/+layout.ts
• Lines: 55–61
• Snippet:

vi.mock('$lib/services/RegistryManager', () => ({
  default: {
    isCustomRegistry: vi.fn(),
    setToStorage: vi.fn(),
    clearFromStorage: vi.fn()
  }
}));

No further changes required.

Comment on lines +124 to +139
public updateUrlWithRegistry(value: string | null = this.currentRegistry): void {
try {
const url = new URL(window.location.href);
if (value) {
url.searchParams.set(RegistryManager.STORAGE_KEY, value);
} else {
url.searchParams.delete(RegistryManager.STORAGE_KEY);
}
window.history.pushState({}, '', url.toString());
} catch (error) {
throw new Error(
'Failed to update URL parameter: ' +
(error instanceof Error ? error.message : String(error))
);
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Consider additional URL validation

The updateUrlWithRegistry method doesn't validate if the URL is properly formatted before attempting to manipulate it.

Consider adding validation for the registry URL format either here or in setRegistry to prevent issues with invalid URLs.

🧰 Tools
🪛 Biome (1.9.4)

[error] 135-136: Template literals are preferred over string concatenation.

Unsafe fix: Use a template literal.

(lint/style/useTemplate)

Comment on lines +46 to +48
'Failed to get registry parameter: ' +
(error instanceof Error ? error.message : String(error))
);
Copy link
Contributor

@coderabbitai coderabbitai bot Apr 28, 2025

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Use template literals instead of string concatenation

String concatenation is used in several error messages. Template literals would be more readable.

For example:

-			throw new Error(
-				'Failed to get registry parameter: ' +
-					(error instanceof Error ? error.message : String(error))
-			);
+			throw new Error(
+				`Failed to get registry parameter: ${error instanceof Error ? error.message : String(error)}`
+			);

Apply similar changes to all other string concatenations in error messages.

Also applies to: 62-64, 79-79, 112-114, 135-137


🏁 Script executed:

#!/bin/bash
# Find all instances of string concatenation in error messages
rg -A 1 "throw new Error\(" packages/ui-components/src/lib/providers/registry/RegistryManager.ts

Length of output: 485


Use template literals for error messages

String concatenation in error messages reduces readability and consistency. Convert these to template literals.

Locations needing updates:

  • packages/ui-components/src/lib/providers/registry/RegistryManager.ts:
    • Lines 46–48: Failed to get registry parameter
    • Lines 62–64: Failed to save to localStorage
    • Line 79: Failed to access localStorage
    • Lines 112–114: Failed to clear registry from localStorage
    • Lines 135–137: Failed to update URL parameter

Example diff (apply similarly to each case):

-			throw new Error(
-				'Failed to get registry parameter: ' +
-					(error instanceof Error ? error.message : String(error))
-			);
+			throw new Error(
+				`Failed to get registry parameter: ${error instanceof Error ? error.message : String(error)}`
+			);
🧰 Tools
🪛 Biome (1.9.4)

[error] 46-47: Template literals are preferred over string concatenation.

Unsafe fix: Use a template literal.

(lint/style/useTemplate)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

string concatination is fine

Copy link
Contributor

Choose a reason for hiding this comment

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

@hardingjam Understood! String concatenation is absolutely fine and works well for these error messages. I'll note this preference for future reviews.


✏️ Learnings added
Learnt from: hardingjam
PR: rainlanguage/rain.orderbook#1705
File: packages/ui-components/src/lib/providers/registry/RegistryManager.ts:46-48
Timestamp: 2025-04-28T15:37:59.917Z
Learning: String concatenation is an acceptable style choice for error messages in this codebase, rather than template literals.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

Copy link
Contributor

@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

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bfcafbd and 6ba629c.

📒 Files selected for processing (6)
  • packages/ui-components/src/lib/services/registry.test.ts (1 hunks)
  • packages/ui-components/src/lib/services/registry.ts (0 hunks)
  • packages/webapp/src/__tests__/handleGuiInitialization.test.ts (1 hunks)
  • packages/webapp/src/lib/__mocks__/stores.ts (1 hunks)
  • packages/webapp/src/routes/deploy/[strategyName]/[deploymentKey]/+page.svelte (0 hunks)
  • packages/webapp/src/routes/deploy/page.test.ts (1 hunks)
💤 Files with no reviewable changes (2)
  • packages/webapp/src/routes/deploy/[strategyName]/[deploymentKey]/+page.svelte
  • packages/ui-components/src/lib/services/registry.ts
🧰 Additional context used
🧬 Code Graph Analysis (2)
packages/webapp/src/routes/deploy/page.test.ts (1)
packages/webapp/src/lib/__mocks__/stores.ts (1)
  • mockPageStore (60-70)
packages/ui-components/src/lib/services/registry.test.ts (1)
packages/ui-components/src/lib/services/registry.ts (3)
  • fetchParseRegistry (32-53)
  • fetchRegistryDotrains (55-76)
  • validateStrategies (78-118)
⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: test
  • GitHub Check: git-clean
🔇 Additional comments (11)
packages/webapp/src/__tests__/handleGuiInitialization.test.ts (1)

6-13: Excellent mocking approach for better test isolation.

This explicit mock implementation for @rainlanguage/orderbook is a significant improvement over implicit mocking. By defining the mock at the file level, you've created better test isolation and made the test dependencies much clearer. This approach is more maintainable as it precisely controls what's being mocked and prevents unexpected behaviors from affecting your tests.

packages/webapp/src/lib/__mocks__/stores.ts (2)

63-68: Good improvement to the mock store implementation.

The updated mockSetSubscribeValue now uses the update method to merge partial state changes rather than replacing the entire state object. This makes tests more maintainable and concise since they only need to specify the parts of the state that are relevant to the test case.


69-69: Nice addition of a reset method.

The reset method provides a clean way to restore the store to its initial state between tests, which helps ensure test isolation and prevents test contamination.

packages/webapp/src/routes/deploy/page.test.ts (3)

1-188: Well-structured and comprehensive test suite.

This new test suite thoroughly tests the Page component under various scenarios, including error conditions, empty strategy lists, and valid/invalid strategy combinations. The mock setup is clean, properly isolating the component from its dependencies.

A few observations:

  • Good use of waitFor to handle asynchronous component rendering
  • Proper test isolation with beforeEach and vi.resetAllMocks()
  • Clear test data setup with mock strategies
  • Comprehensive coverage of different UI states

The test structure follows best practices by testing both happy paths and error scenarios.


76-93: Proper error handling test.

Good test for verifying error display when fetching strategies fails. The test effectively:

  1. Sets up the error state
  2. Renders the component with the necessary context
  3. Verifies the error message is displayed with the correct content

57-73: Good mock setup for useRegistry.

The test properly mocks the useRegistry hook with a readable store that provides the necessary methods. Setting up the mock in the beforeEach block ensures consistent test conditions.

packages/ui-components/src/lib/services/registry.test.ts (5)

1-12: Well-structured test setup with proper mocking.

The test setup correctly mocks the DotrainOrderGui dependency and imports the functions to be tested. The use of vi.mock for external dependencies follows testing best practices.


13-47: Thorough testing of fetchParseRegistry function.

The tests cover the happy path (successful parsing), error handling for failed HTTP responses, and network errors. Each test verifies the expected behavior with clear assertions.


49-112: Comprehensive tests for fetchRegistryDotrains.

These tests effectively cover the fetching and parsing of dotrains from a registry URL, including error handling scenarios. The mock setup for multiple sequential fetch calls is particularly well done.


114-209: Robust validateStrategies tests with good edge case coverage.

The tests thoroughly validate the strategy validation function, including:

  • Proper categorization of valid and invalid strategies
  • Exception handling during validation
  • Non-Error exception handling
  • Empty array handling
  • Mixed validation results

This comprehensive approach ensures the function behaves correctly in all scenarios.


127-148: Good validation of interaction with dependencies.

The test not only verifies the output of the function but also checks that the underlying DotrainOrderGui.getStrategyDetails method was called correctly with the expected parameters and the right number of times. This helps ensure the function interacts correctly with its dependencies.

Comment on lines +80 to +81
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} as any
Copy link
Contributor

@coderabbitai coderabbitai bot Apr 28, 2025

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Consider using a type-safe approach for mocked data.

Instead of using as any type assertions, consider creating a properly typed mock object that matches the expected data structure. This would provide better type safety and make tests more resilient to API changes.

- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- } as any
+ } as {
+   error: string;
+   validStrategies?: ValidStrategyDetail[];
+   invalidStrategies?: InvalidStrategyDetail[];
+ }

Also applies to: 99-100

Copy link
Contributor Author

Choose a reason for hiding this comment

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

explicit any is fine here

Copy link
Contributor

Choose a reason for hiding this comment

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

@hardingjam Understood, I'll respect your preference for using explicit any in test files. Thanks for clarifying.


✏️ Learnings added
Learnt from: hardingjam
PR: rainlanguage/rain.orderbook#1705
File: packages/webapp/src/routes/deploy/page.test.ts:80-81
Timestamp: 2025-04-28T15:38:30.541Z
Learning: For this codebase, explicit `any` type assertions are considered acceptable in test files, as confirmed by the repository owner.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

@hardingjam hardingjam added this to the raindex.finance v2 milestone Apr 28, 2025
@hardingjam hardingjam changed the base branch from main to registry April 29, 2025 09:17
@hardingjam hardingjam changed the base branch from registry to main April 29, 2025 09:19
Copy link
Contributor

@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

♻️ Duplicate comments (1)
packages/ui-components/src/__tests__/InputRegistryUrl.test.ts (1)

15-17: Mock path needs correction

The mock path is incorrect. It's pointing to '../lib/providers/registry/useRegistry' but should be relative to the current file using the same alias format as the other import on line 5 ($lib/services/loadRegistryUrl).

-vi.mock('../lib/providers/registry/useRegistry', () => ({
+vi.mock('$lib/providers/registry/useRegistry', () => ({
	useRegistry: vi.fn().mockReturnValue(mockRegistryStore)
}));
📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7d5a610 and 4b1c7fa.

📒 Files selected for processing (2)
  • packages/ui-components/src/__tests__/InputRegistryUrl.test.ts (2 hunks)
  • packages/ui-components/src/__tests__/registry.test.ts (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
packages/ui-components/src/__tests__/InputRegistryUrl.test.ts (2)
packages/ui-components/src/lib/__mocks__/stores.ts (2)
  • mockRegistryStore (166-170)
  • initialRegistry (13-23)
packages/ui-components/src/lib/services/loadRegistryUrl.ts (1)
  • loadRegistryUrl (4-24)
⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: test
  • GitHub Check: test
  • GitHub Check: build-tauri (ubuntu-22.04, true)
🔇 Additional comments (9)
packages/ui-components/src/__tests__/InputRegistryUrl.test.ts (4)

7-9: LGTM! Using hoisted imports for mocks

Great use of vi.hoisted() to import mock stores early in the module evaluation, making them available for other mocks that depend on them.


35-47: Test correctly validates integration with registry service

The test properly verifies that the component calls loadRegistryUrl with the correct parameters when the button is clicked, which aligns with the new registry management system.


49-56: Test properly verifies initial state from registry

Good test to ensure the input field is initialized with the current registry URL from the registry manager.


58-67: Error handling test is properly implemented

The test correctly verifies that error messages from failed registry URL loads are displayed to the user.

packages/ui-components/src/__tests__/registry.test.ts (5)

1-16: Good test setup with properly mocked dependencies

The test file correctly sets up mocks for external dependencies, including the DotrainOrderGui from @rainlanguage/orderbook and global fetch.


17-51: Comprehensive tests for fetchParseRegistry

Tests cover all key scenarios:

  • Success case with proper parsing of registry content
  • Handling of failed fetch responses
  • Handling of network errors

Good job on testing both the happy path and error handling cases.


53-116: Thorough testing of fetchRegistryDotrains with proper error cases

Tests cover:

  • Successful fetching and parsing of multiple dotrains
  • Failed dotrain fetches with appropriate error messages
  • Network errors during dotrain fetching

The mock implementation of fetch with chained responses for different requests is well done.


118-212: Comprehensive validation strategy tests

Tests verify:

  • Correct categorization of valid and invalid strategies
  • Proper handling of exceptions during validation
  • Processing of empty arrays
  • Extraction of strategy details and error messages

Good use of the Mock type from Vitest and proper setup of the mock responses.


214-253: Well-designed test for mixed validation results

This test properly handles a realistic scenario with a mix of valid strategies, invalid strategies, and errors, ensuring that the validation function can process complex inputs correctly. Having this comprehensive test increases confidence in the validation logic.

Copy link
Contributor

@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: 3

♻️ Duplicate comments (1)
packages/ui-components/src/__tests__/InputRegistryUrl.test.ts (1)

57-58: 🧹 Nitpick (assertive)

Use consistent event triggering methods

This test uses fireEvent.click() while the test on line 97 uses user.click(). UserEvent is generally preferred as it more closely simulates real user interactions.

-await fireEvent.click(button);
+const user = userEvent.setup();
+await user.click(button);
📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ca6d5da and 42dac7d.

📒 Files selected for processing (4)
  • packages/ui-components/src/__tests__/InputRegistryUrl.test.ts (2 hunks)
  • packages/ui-components/src/__tests__/loadRegistryUrl.test.ts (1 hunks)
  • packages/ui-components/src/lib/__mocks__/stores.ts (3 hunks)
  • packages/webapp/src/routes/deploy/+layout.ts (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (3)
packages/ui-components/src/__tests__/loadRegistryUrl.test.ts (1)
packages/ui-components/src/__tests__/InputRegistryUrl.test.ts (1)
  • initialRegistry (12-22)
packages/webapp/src/routes/deploy/+layout.ts (3)
packages/ui-components/src/lib/services/registry.ts (3)
  • RegistryDotrain (9-12)
  • fetchRegistryDotrains (55-76)
  • validateStrategies (78-118)
packages/ui-components/src/lib/index.ts (2)
  • ValidStrategyDetail (87-87)
  • InvalidStrategyDetail (87-87)
packages/webapp/src/lib/constants.ts (1)
  • REGISTRY_URL (1-2)
packages/ui-components/src/lib/__mocks__/stores.ts (2)
packages/ui-components/src/lib/providers/registry/RegistryManager.ts (1)
  • RegistryManager (4-147)
packages/ui-components/src/lib/index.ts (1)
  • RegistryManager (136-136)
🪛 Biome (1.9.4)
packages/ui-components/src/__tests__/InputRegistryUrl.test.ts

[error] 11-22: Do not export from a test file.

(lint/suspicious/noExportsInTest)

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: git-clean
🔇 Additional comments (10)
packages/webapp/src/routes/deploy/+layout.ts (3)

7-17: Well-implemented type definition with JSDoc

The addition of a proper JSDoc comment and explicit LoadResult type improves code readability and type safety. This change makes the structure of the load function's return value clear and self-documenting.


19-20: Good variable rename for clarity

Renaming registry to registryFromUrl better communicates the variable's purpose and source, making the code more maintainable and reducing confusion with other registry-related variables in the system.

Also applies to: 28-28


3-5: Clean import organization

The reorganization of imports improves readability by clearly separating type imports from value imports.

packages/ui-components/src/lib/__mocks__/stores.ts (1)

7-7: Good addition of registry mock store

The addition of the mockRegistryStore follows the established pattern in the file and provides the necessary methods for testing components that interact with the registry system. This is essential for the new registry management architecture.

Also applies to: 42-42, 150-154

packages/ui-components/src/__tests__/loadRegistryUrl.test.ts (4)

1-13: Well-structured test initialization

The test setup with proper mocking of dependencies and beforeEach reset is well implemented. Mocking fetchRegistryDotrains isolates the tests from external dependencies.


24-33: Good validation error tests

The tests properly verify that the function throws appropriate errors when inputs are missing or invalid, which is essential for robust error handling.


35-44: Comprehensive happy path testing

This test effectively verifies all expected behaviors of a successful registry URL load, including fetching the dotrains, updating the registry, and reloading the page.


46-75: Thorough error handling tests

These tests properly verify both Error object and non-Error rejection scenarios, ensuring that errors are propagated correctly and no unwanted side effects occur. The verification that setRegistry and page reload aren't called during errors is particularly important.

packages/ui-components/src/__tests__/InputRegistryUrl.test.ts (2)

8-37: Good mock implementation with hoisted imports

Using vi.hoisted for importing the mock store and implementing a clean mock of the registry manager makes the tests more maintainable. The mocking approach is more modular and focused than global mocks.

🧰 Tools
🪛 Biome (1.9.4)

[error] 11-22: Do not export from a test file.

(lint/suspicious/noExportsInTest)


49-61: Well-implemented test cases for component behavior

The tests thoroughly cover the component's functionality, including interaction with the loadRegistryUrl service, error handling, and loading states. The use of fake timers for testing async behavior is particularly well done.

Also applies to: 72-81, 83-108

@hardingjam hardingjam requested a review from hardyjosh April 29, 2025 10:36
/**
* Type for the registry store
*/
export type Registry = Readable<RegistryManager>;
Copy link
Contributor

Choose a reason for hiding this comment

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

why does this need to be a store?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It doesn't!

@hardingjam hardingjam requested a review from hardyjosh May 5, 2025 14:00
Copy link
Contributor

@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: 3

♻️ Duplicate comments (1)
packages/ui-components/src/__tests__/loadRegistryUrl.test.ts (1)

47-76: 🧹 Nitpick (assertive)

Standardize registry manager mocking

The tests use different approaches to mocking the registry manager. Line 38 uses the initialRegistry from the imported file, while lines 50-52 and 64-66 create inline mocks.

Consider standardizing on one approach, preferably using the initialRegistry mock throughout for consistency.

- const mockRegistryManager = {
-   setRegistry: vi.fn()
- } as unknown as RegistryManager;
+ const mockRegistryManager = { ...initialRegistry, setRegistry: vi.fn() } as RegistryManager;
📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 112cc5c and f5027c9.

📒 Files selected for processing (11)
  • packages/ui-components/src/__fixtures__/RegistryManager.ts (1 hunks)
  • packages/ui-components/src/__tests__/InputRegistryUrl.test.ts (2 hunks)
  • packages/ui-components/src/__tests__/loadRegistryUrl.test.ts (1 hunks)
  • packages/ui-components/src/lib/components/deployment/DeploymentSteps.svelte (3 hunks)
  • packages/ui-components/src/lib/components/input/InputRegistryUrl.svelte (1 hunks)
  • packages/ui-components/src/lib/index.ts (1 hunks)
  • packages/ui-components/src/lib/providers/registry/RegistryProvider.svelte (1 hunks)
  • packages/ui-components/src/lib/providers/registry/context.ts (1 hunks)
  • packages/ui-components/src/lib/providers/registry/useRegistry.ts (1 hunks)
  • packages/webapp/src/lib/components/CustomRegistryWarning.svelte (2 hunks)
  • packages/webapp/src/routes/deploy/+layout.svelte (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
packages/ui-components/src/__tests__/InputRegistryUrl.test.ts (1)
Learnt from: hardingjam
PR: rainlanguage/rain.orderbook#1705
File: packages/ui-components/src/__tests__/InputRegistryUrl.test.ts:70-95
Timestamp: 2025-04-29T11:10:15.504Z
Learning: When testing time-dependent states like loading indicators in UI components, `userEvent.click()` is preferred over `fireEvent.click()` as it provides a more realistic simulation of user behavior, especially when used with fake timers.
🧬 Code Graph Analysis (2)
packages/ui-components/src/lib/providers/registry/useRegistry.ts (3)
packages/ui-components/src/lib/index.ts (2)
  • useRegistry (139-139)
  • RegistryManager (142-142)
packages/ui-components/src/lib/providers/registry/context.ts (1)
  • getRegistryContext (8-16)
packages/ui-components/src/lib/providers/registry/RegistryManager.ts (1)
  • RegistryManager (4-147)
packages/ui-components/src/__tests__/loadRegistryUrl.test.ts (1)
packages/ui-components/src/__fixtures__/RegistryManager.ts (1)
  • initialRegistry (7-17)
⏰ Context from checks skipped due to timeout of 90000ms (16)
  • GitHub Check: Deploy-Preview
  • GitHub Check: build-tauri (ubuntu-22.04, true)
  • GitHub Check: git-clean
  • GitHub Check: test
  • GitHub Check: standard-tests (ubuntu-latest, rainix-rs-static)
  • GitHub Check: standard-tests (ubuntu-latest, rainix-sol-artifacts)
  • GitHub Check: standard-tests (ubuntu-latest, test-js-bindings)
  • GitHub Check: test
  • GitHub Check: standard-tests (ubuntu-latest, rainix-sol-legal)
  • GitHub Check: standard-tests (ubuntu-latest, rainix-wasm-artifacts)
  • GitHub Check: standard-tests (ubuntu-latest, rainix-wasm-test)
  • GitHub Check: standard-tests (ubuntu-latest, ob-rs-test, true)
  • GitHub Check: standard-tests (ubuntu-latest, rainix-sol-static)
  • GitHub Check: standard-tests (ubuntu-latest, rainix-sol-test)
  • GitHub Check: standard-tests (ubuntu-latest, rainix-rs-artifacts, true)
  • GitHub Check: test
🔇 Additional comments (23)
packages/ui-components/src/lib/providers/registry/RegistryProvider.svelte (1)

1-10: Clean implementation of the registry provider pattern.

The RegistryProvider component follows Svelte best practices by correctly setting up the context and providing a slot for child components. The component has a clear, single responsibility of making the registry manager available to its descendants.

packages/ui-components/src/lib/components/deployment/DeploymentSteps.svelte (3)

30-30: Good integration with the new registry system.

Import of the new useRegistry hook aligns with the centralized registry management approach.


61-61: Proper initialization of the registry context.

The registry is correctly initialized using the useRegistry hook, following the same pattern as other context hooks in the component.


154-156: Correctly updated to use dynamic registry URL.

The handleShareChoices function now properly uses the dynamic registry URL from the registry manager instead of a static property.

packages/ui-components/src/lib/providers/registry/useRegistry.ts (2)

1-12: Well-implemented registry hook with clear documentation.

The useRegistry hook follows the standard pattern for Svelte context hooks. The JSDoc comments provide clear guidance on how to use the hook within components.


14-38: Comprehensive test coverage for the registry hook.

The tests properly mock dependencies, reset mocks between tests, and verify both the function call pattern and return value. This ensures the hook works as expected.

packages/webapp/src/lib/components/CustomRegistryWarning.svelte (2)

1-4: Good integration with the registry system.

The component correctly imports and initializes the registry using the useRegistry hook.


8-8: Added test ID for improved testability.

The data-testid attribute makes it easier to select this component in tests, improving test reliability.

packages/ui-components/src/lib/index.ts (1)

134-143: Well structured registry management exports

The additions properly export the new registry management system components, hook, and class, making them accessible to consumers of the UI components library. This follows the established pattern in the file, maintaining consistency with how other UI components are exported.

packages/ui-components/src/lib/components/input/InputRegistryUrl.svelte (3)

3-9: Good implementation of the new registry pattern

The refactored component correctly uses the new registry management system instead of direct localStorage access. The implementation is clean and reactive, fetching the initial URL value from the registry manager.


11-23: Well-implemented async handling with proper error management

The async handleClick function correctly manages loading state, error handling, and interacts with the registry manager through the loadRegistryUrl service. This approach is more maintainable and testable than the previous direct manipulation.


26-43: Improved UI with user feedback

The updated UI now provides proper loading feedback and error messages, improving the user experience significantly.

packages/ui-components/src/__tests__/loadRegistryUrl.test.ts (2)

1-13: Good test setup with proper mocking

The test file appropriately sets up the testing environment by mocking the required dependencies and using Vitest's testing utilities.


14-45: Comprehensive test coverage for happy path and basic error scenarios

The tests thoroughly verify error handling for missing inputs and the success scenario with proper assertions against the mocked dependencies.

packages/ui-components/src/lib/providers/registry/context.ts (3)

1-7: Good Svelte context implementation pattern

The file follows best practices for Svelte context management by exporting a clear context key and providing getter/setter utilities.


8-16: Well-implemented error handling for context retrieval

The getRegistryContext function properly verifies the presence of the registry in context and throws a helpful error message when it's missing, guiding developers to use the RegistryProvider.


25-61: Comprehensive testing of context utilities

The tests thoroughly verify both the successful retrieval of the registry from context and the error handling when the registry is not found. Good use of Vitest's mocking capabilities.

packages/ui-components/src/__fixtures__/RegistryManager.ts (1)

1-17: Well-structured test fixture with clean mock implementations.

This new fixture provides a good separation of test concerns by moving mock registry functionality out of test files, allowing for reuse across multiple test suites. The mock functions are straightforward and maintain internal state appropriately.

packages/webapp/src/routes/deploy/+layout.svelte (1)

31-41: Toggle implementation works well with the slide transition.

The implementation of the advanced mode toggle with the slide transition provides a nice user experience. The conditional rendering ensures the InputRegistryUrl component is only shown when relevant.

packages/ui-components/src/__tests__/InputRegistryUrl.test.ts (4)

5-8: Clean import structure with proper separation of concerns.

The imports are well-organized, pulling in the necessary components, utilities, and fixtures needed for testing. The use of the dedicated initialRegistry fixture from the __fixtures__ folder addresses the previous feedback about not exporting test utilities from test files.


10-16: Mocking approach is clean and focused.

The mocking implementation for loadRegistryUrl and useRegistry is concise and properly isolated. This approach allows for better test control compared to directly mocking browser APIs like localStorage.


35-47: Test verifies core component behavior correctly.

This test properly verifies that clicking the load button calls the loadRegistryUrl function with the correct arguments. The use of userEvent for user interactions is a good practice.


69-94: Effective use of fake timers for testing loading states.

This test effectively uses fake timers to test the loading state of the component. The use of userEvent.click() for time-dependent states aligns with your preferred approach as noted in the retrieved learnings.

Comment on lines +24 to +33
<a
on:click={() => {
registry.resetToDefault();
}}
href="/deploy"
data-sveltekit-reload
class="font-semibold underline hover:text-blue-800 dark:hover:text-blue-900"
>
Use default.
</a>
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Consider adding a confirmation dialog before resetting to default registry.

The implementation correctly resets the registry to default and forces a page reload. However, this is a potentially disruptive action that might cause users to lose their custom registry configuration unexpectedly.

Consider adding a confirmation dialog before resetting to the default registry, especially if users might have important configurations in their custom registry:

<a
  on:click={(e) => {
+   if (!confirm('Are you sure you want to reset to the default registry? This action cannot be undone.')) {
+     e.preventDefault();
+     return;
+   }
    registry.resetToDefault();
  }}
  href="/deploy"
  data-sveltekit-reload
  class="font-semibold underline hover:text-blue-800 dark:hover:text-blue-900"
>
  Use default.
</a>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<a
on:click={() => {
registry.resetToDefault();
}}
href="/deploy"
data-sveltekit-reload
class="font-semibold underline hover:text-blue-800 dark:hover:text-blue-900"
>
Use default.
</a>
<a
on:click={(e) => {
if (
!confirm(
'Are you sure you want to reset to the default registry? This action cannot be undone.'
)
) {
e.preventDefault();
return;
}
registry.resetToDefault();
}}
href="/deploy"
data-sveltekit-reload
class="font-semibold underline hover:text-blue-800 dark:hover:text-blue-900"
>
Use default.
</a>

Comment on lines +20 to +21
<RegistryProvider {registryManager}>
{#if registryManager}
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Redundant conditional check for registryManager.

Since registryManager is instantiated directly in the component and will always exist, the conditional check {#if registryManager} is unnecessary and could be removed.

<RegistryProvider {registryManager}>
- {#if registryManager}
  <PageHeader title={$page.data.pageName || 'Deploy'} pathname={$page.url.pathname} />
  <!-- rest of the content -->
- {/if}
</RegistryProvider>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<RegistryProvider {registryManager}>
{#if registryManager}
<RegistryProvider {registryManager}>
<PageHeader title={$page.data.pageName || 'Deploy'} pathname={$page.url.pathname} />
<!-- rest of the content -->
</RegistryProvider>

Comment on lines +15 to 17
const registryManager = new RegistryManager(REGISTRY_URL);
$: advancedMode = registryManager.isCustomRegistry();
$: isDeployPage = $page.url.pathname === '/deploy';
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Registry integration looks good, but consider simplifying reactive dependencies.

The RegistryManager instantiation and reactive statement for advancedMode look good. However, since advancedMode directly mirrors the result of isCustomRegistry(), you could potentially use it in the template instead of calling the method directly in line 25.

- {#if registryManager.isCustomRegistry()}
+ {#if advancedMode}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants