@frak-labs/react-sdk
Version:
React SDK of the Frak wallet, low level library to interact directly with the frak ecosystem.
185 lines (154 loc) • 6.03 kB
text/typescript
/**
* Tests for useFrakConfig hook
* Tests that the hook correctly retrieves the FrakConfig from context
* and throws error when used outside provider
*/
import { FrakRpcError } from "@frak-labs/frame-connector";
import { renderHook } from "@testing-library/react";
import React from "react";
import { describe, expect, test, vi } from "../../tests/vitest-fixtures";
import { FrakConfigProvider } from "../provider/FrakConfigProvider";
import { useFrakConfig } from "./useFrakConfig";
describe("useFrakConfig", () => {
test("should throw FrakRpcError when used outside provider", () => {
// Mock console.error to avoid noise in test output
const consoleErrorSpy = vi
.spyOn(console, "error")
.mockImplementation(() => {});
expect(() => {
renderHook(() => useFrakConfig());
}).toThrow(FrakRpcError);
try {
renderHook(() => useFrakConfig());
} catch (error) {
expect(error).toBeInstanceOf(FrakRpcError);
// FrakRpcError message contains the error code
expect((error as FrakRpcError).message).toContain("-32002");
}
consoleErrorSpy.mockRestore();
});
test("should return config when used inside provider", ({
mockFrakConfig,
}) => {
const wrapper = ({ children }: { children: React.ReactNode }) =>
React.createElement(
FrakConfigProvider,
{ config: mockFrakConfig },
children
);
const { result } = renderHook(() => useFrakConfig(), {
wrapper,
});
expect(result.current).toBeDefined();
expect(result.current.domain).toBe(mockFrakConfig.domain);
expect(result.current.metadata?.name).toBe(
mockFrakConfig.metadata?.name
);
});
test("should apply default walletUrl if not provided", () => {
const configWithoutWalletUrl = {
domain: "example.com",
metadata: {
name: "Test App",
},
};
const wrapper = ({ children }: { children: React.ReactNode }) =>
React.createElement(
FrakConfigProvider,
{ config: configWithoutWalletUrl },
children
);
const { result } = renderHook(() => useFrakConfig(), {
wrapper,
});
expect(result.current.walletUrl).toBe("https://wallet.frak.id");
});
test("should use provided walletUrl if specified", ({ mockFrakConfig }) => {
const wrapper = ({ children }: { children: React.ReactNode }) =>
React.createElement(
FrakConfigProvider,
{ config: mockFrakConfig },
children
);
const { result } = renderHook(() => useFrakConfig(), {
wrapper,
});
expect(result.current.walletUrl).toBe(mockFrakConfig.walletUrl);
});
test("should return stable config across re-renders", ({
mockFrakConfig,
}) => {
const wrapper = ({ children }: { children: React.ReactNode }) =>
React.createElement(
FrakConfigProvider,
{ config: mockFrakConfig },
children
);
const { result, rerender } = renderHook(() => useFrakConfig(), {
wrapper,
});
const firstConfig = result.current;
rerender();
const secondConfig = result.current;
// Config values should remain stable
expect(firstConfig.domain).toBe(secondConfig.domain);
expect(firstConfig.walletUrl).toBe(secondConfig.walletUrl);
expect(firstConfig.domain).toBe(mockFrakConfig.domain);
});
test("should include all config properties", ({ mockFrakConfig }) => {
const wrapper = ({ children }: { children: React.ReactNode }) =>
React.createElement(
FrakConfigProvider,
{ config: mockFrakConfig },
children
);
const { result } = renderHook(() => useFrakConfig(), {
wrapper,
});
expect(result.current.domain).toBe(mockFrakConfig.domain);
expect(result.current.walletUrl).toBe(mockFrakConfig.walletUrl);
expect(result.current.metadata).toEqual(mockFrakConfig.metadata);
expect(result.current.customizations).toEqual(
mockFrakConfig.customizations
);
});
test("should handle minimal config", () => {
const minimalConfig = {
domain: "minimal.com",
metadata: {
name: "Minimal Test App",
},
};
const wrapper = ({ children }: { children: React.ReactNode }) =>
React.createElement(
FrakConfigProvider,
{ config: minimalConfig },
children
);
const { result } = renderHook(() => useFrakConfig(), {
wrapper,
});
expect(result.current.domain).toBe("minimal.com");
expect(result.current.walletUrl).toBe("https://wallet.frak.id");
expect(result.current.metadata.name).toBe("Minimal Test App");
expect(result.current.customizations).toBeUndefined();
});
test("should fallback to window.location.host if domain not provided", () => {
const configWithoutDomain = {
metadata: {
name: "Test App",
},
};
const wrapper = ({ children }: { children: React.ReactNode }) =>
React.createElement(
FrakConfigProvider,
{ config: configWithoutDomain as any },
children
);
const { result } = renderHook(() => useFrakConfig(), {
wrapper,
});
// In test environment, window.location.host is "localhost:3000" (JSDOM default)
expect(result.current.domain).toBe(window.location.host);
});
});