@frak-labs/core-sdk
Version:
Core SDK of the Frak wallet, low level library to interact directly with the frak ecosystem.
389 lines (336 loc) • 12.5 kB
text/typescript
/**
* Tests for displayModal action
* Tests modal display via RPC with various step configurations
*/
import type { Address } from "viem";
import { describe, expect, it, vi } from "../../tests/vitest-fixtures";
import type {
DisplayModalParamsType,
FrakClient,
ModalStepTypes,
} from "../types";
import { displayModal } from "./displayModal";
describe("displayModal", () => {
describe("basic modal display", () => {
it("should call client.request with correct method and params", async () => {
const mockResponse = {
login: {
wallet: "0x1234567890123456789012345678901234567890" as Address,
},
};
const mockClient = {
config: {
metadata: {
name: "Test App",
},
},
request: vi.fn().mockResolvedValue(mockResponse),
} as unknown as FrakClient;
const params: DisplayModalParamsType<ModalStepTypes[]> = {
steps: {
login: { allowSso: true },
},
};
await displayModal(mockClient, params);
expect(mockClient.request).toHaveBeenCalledWith({
method: "frak_displayModal",
params: [params.steps, params.metadata, { name: "Test App" }],
});
});
it("should return modal results", async () => {
const mockResponse = {
login: {
wallet: "0xabcdefabcdefabcdefabcdefabcdefabcdefabcd" as Address,
},
};
const mockClient = {
config: {
metadata: {
name: "Test App",
},
},
request: vi.fn().mockResolvedValue(mockResponse),
} as unknown as FrakClient;
const params: DisplayModalParamsType<ModalStepTypes[]> = {
steps: {
login: { allowSso: false },
},
};
const result = await displayModal(mockClient, params);
expect(result).toEqual(mockResponse);
});
});
describe("modal with multiple steps", () => {
it("should handle login + sendTransaction steps", async () => {
const mockResponse = {
login: {
wallet: "0x1234567890123456789012345678901234567890" as Address,
},
sendTransaction: {
hash: "0xtxhash" as `0x${string}`,
},
};
const mockClient = {
config: {
metadata: {
name: "Test App",
},
},
request: vi.fn().mockResolvedValue(mockResponse),
} as unknown as FrakClient;
const params: DisplayModalParamsType<ModalStepTypes[]> = {
steps: {
login: { allowSso: true },
sendTransaction: {
tx: [
{
to: "0xdeadbeef" as Address,
data: "0xdata" as `0x${string}`,
},
],
},
},
};
const result = await displayModal(mockClient, params);
expect(result).toEqual(mockResponse);
});
it("should handle full modal flow", async () => {
const mockResponse = {
login: {
wallet: "0x1234567890123456789012345678901234567890" as Address,
},
sendTransaction: {
hash: "0xtxhash" as `0x${string}`,
},
final: {},
};
const mockClient = {
config: {
metadata: {
name: "Test App",
logoUrl: "https://example.com/logo.png",
},
},
request: vi.fn().mockResolvedValue(mockResponse),
} as unknown as FrakClient;
const params: DisplayModalParamsType<ModalStepTypes[]> = {
steps: {
login: { allowSso: true },
sendTransaction: {
tx: [
{
to: "0xdeadbeef" as Address,
data: "0xdata" as `0x${string}`,
},
],
},
final: {
action: { key: "reward" },
},
},
};
const result = await displayModal(mockClient, params);
expect(result).toEqual(mockResponse);
});
});
describe("modal with metadata", () => {
it("should pass metadata to request", async () => {
const mockResponse = {
login: {
wallet: "0x1234567890123456789012345678901234567890" as Address,
},
};
const mockClient = {
config: {
metadata: {
name: "Test App",
},
},
request: vi.fn().mockResolvedValue(mockResponse),
} as unknown as FrakClient;
const params: DisplayModalParamsType<ModalStepTypes[]> = {
steps: {
login: { allowSso: true },
},
metadata: {
header: {
title: "My Custom Title",
icon: "https://example.com/icon.png",
},
},
};
await displayModal(mockClient, params);
expect(mockClient.request).toHaveBeenCalledWith({
method: "frak_displayModal",
params: [
params.steps,
{
header: {
title: "My Custom Title",
icon: "https://example.com/icon.png",
},
},
{ name: "Test App" },
],
});
});
it("should work without metadata", async () => {
const mockResponse = {
login: {
wallet: "0x1234567890123456789012345678901234567890" as Address,
},
};
const mockClient = {
config: {
metadata: {
name: "Test App",
},
},
request: vi.fn().mockResolvedValue(mockResponse),
} as unknown as FrakClient;
const params: DisplayModalParamsType<ModalStepTypes[]> = {
steps: {
login: { allowSso: true },
},
};
await displayModal(mockClient, params);
expect(mockClient.request).toHaveBeenCalledWith({
method: "frak_displayModal",
params: [params.steps, undefined, { name: "Test App" }],
});
});
});
describe("modal with SSO metadata", () => {
it("should handle SSO metadata in login step", async () => {
const mockResponse = {
login: {
wallet: "0x1234567890123456789012345678901234567890" as Address,
},
};
const mockClient = {
config: {
metadata: {
name: "Test App",
},
},
request: vi.fn().mockResolvedValue(mockResponse),
} as unknown as FrakClient;
const params: DisplayModalParamsType<ModalStepTypes[]> = {
steps: {
login: {
allowSso: true,
ssoMetadata: {
logoUrl: "https://example.com/logo.png",
homepageLink: "https://example.com",
},
},
},
};
await displayModal(mockClient, params);
expect(mockClient.request).toHaveBeenCalledWith({
method: "frak_displayModal",
params: [params.steps, undefined, { name: "Test App" }],
});
});
});
describe("modal with sharing action", () => {
it("should handle sharing final action", async () => {
const mockResponse = {
final: {},
};
const mockClient = {
config: {
metadata: {
name: "Test App",
},
},
request: vi.fn().mockResolvedValue(mockResponse),
} as unknown as FrakClient;
const params: DisplayModalParamsType<ModalStepTypes[]> = {
steps: {
final: {
action: {
key: "sharing",
options: {
popupTitle: "Share the app",
text: "Discover my app",
link: "https://example.com",
},
},
},
},
};
await displayModal(mockClient, params);
expect(mockClient.request).toHaveBeenCalledWith({
method: "frak_displayModal",
params: [params.steps, undefined, { name: "Test App" }],
});
});
it("should handle reward final action", async () => {
const mockResponse = {
final: {},
};
const mockClient = {
config: {
metadata: {
name: "Test App",
},
},
request: vi.fn().mockResolvedValue(mockResponse),
} as unknown as FrakClient;
const params: DisplayModalParamsType<ModalStepTypes[]> = {
steps: {
final: {
action: { key: "reward" },
autoSkip: true,
},
},
};
await displayModal(mockClient, params);
expect(mockClient.request).toHaveBeenCalledWith({
method: "frak_displayModal",
params: [params.steps, undefined, { name: "Test App" }],
});
});
});
describe("error handling", () => {
it("should propagate errors from client.request", async () => {
const error = new Error("Modal display failed");
const mockClient = {
config: {
metadata: {
name: "Test App",
},
},
request: vi.fn().mockRejectedValue(error),
} as unknown as FrakClient;
const params: DisplayModalParamsType<ModalStepTypes[]> = {
steps: {
login: { allowSso: true },
},
};
await expect(displayModal(mockClient, params)).rejects.toThrow(
"Modal display failed"
);
});
it("should handle network errors", async () => {
const error = new Error("Network timeout");
const mockClient = {
config: {
metadata: {
name: "Test App",
},
},
request: vi.fn().mockRejectedValue(error),
} as unknown as FrakClient;
const params: DisplayModalParamsType<ModalStepTypes[]> = {
steps: {
login: { allowSso: true },
},
};
await expect(displayModal(mockClient, params)).rejects.toThrow(
"Network timeout"
);
});
});
});