dreame-action/test/checkout-extension.test.ts

110 lines
3.5 KiB
TypeScript
Raw Normal View History

2026-06-19 19:35:50 +08:00
import { describe, expect, test, vi } from "vitest";
import { normalizeAppUrl, requestActivityCheck } from "../extensions/thank-you-activity/src/activity-api";
describe("checkout extension activity api", () => {
test("normalizes only HTTPS app URLs", () => {
expect(normalizeAppUrl("https://app.example.com/")).toBe("https://app.example.com");
expect(normalizeAppUrl(" https://app.example.com/path/ ")).toBe("https://app.example.com/path");
expect(normalizeAppUrl("http://localhost:3000")).toBeNull();
expect(normalizeAppUrl("")).toBeNull();
});
test("posts order context with a fresh checkout session token", async () => {
const fetchImpl = vi.fn(async () =>
new Response(
JSON.stringify({
success: true,
redirectUrl: "https://activity.example.com",
buttonText: "Claim",
}),
{ status: 200 },
),
);
const getSessionToken = vi.fn(async () => "checkout-token");
const result = await requestActivityCheck({
appUrl: "https://app.example.com/",
order: {
id: "gid://shopify/Order/123",
name: "#1001",
},
locale: "en",
getSessionToken,
fetchImpl,
timeoutMs: 100,
});
expect(result).toEqual({
success: true,
redirectUrl: "https://activity.example.com",
buttonText: "Claim",
});
expect(getSessionToken).toHaveBeenCalledOnce();
expect(fetchImpl).toHaveBeenCalledWith(
"https://app.example.com/api/action/activity/check",
expect.objectContaining({
method: "POST",
cache: "no-store",
headers: {
Authorization: "Bearer checkout-token",
"Content-Type": "application/json",
},
body: JSON.stringify({
orderId: "gid://shopify/Order/123",
orderNumber: "#1001",
locale: "en",
}),
signal: expect.any(AbortSignal),
}),
);
});
test("returns hidden state for non-2xx and invalid JSON responses", async () => {
const nonOk = await requestActivityCheck({
appUrl: "https://app.example.com",
order: { id: "gid://shopify/Order/123" },
locale: "en",
getSessionToken: async () => "checkout-token",
fetchImpl: async () => new Response(JSON.stringify({ success: true }), { status: 500 }),
timeoutMs: 100,
});
const invalidJson = await requestActivityCheck({
appUrl: "https://app.example.com",
order: { id: "gid://shopify/Order/123" },
locale: "en",
getSessionToken: async () => "checkout-token",
fetchImpl: async () => new Response("not json", { status: 200 }),
timeoutMs: 100,
});
expect(nonOk).toEqual({ success: false });
expect(invalidJson).toEqual({ success: false });
});
test("does not call the backend when app URL or order ID is unavailable", async () => {
const fetchImpl = vi.fn();
const invalidUrl = await requestActivityCheck({
appUrl: "http://localhost:3000",
order: { id: "gid://shopify/Order/123" },
locale: "en",
getSessionToken: async () => "checkout-token",
fetchImpl,
timeoutMs: 100,
});
const missingOrder = await requestActivityCheck({
appUrl: "https://app.example.com",
order: undefined,
locale: "en",
getSessionToken: async () => "checkout-token",
fetchImpl,
timeoutMs: 100,
});
expect(invalidUrl).toEqual({ success: false });
expect(missingOrder).toEqual({ success: false });
expect(fetchImpl).not.toHaveBeenCalled();
});
});