fix: resolve CI test failures (carts, stripe, shipping, scaffold, cart session)
Some checks failed
CI / Lint, Typecheck & Test (push) Failing after 2m13s
Some checks failed
CI / Lint, Typecheck & Test (push) Failing after 2m13s
- carts.test: add required product fields (parentCategorySlug, childCategorySlug) and variant fields (weight, weightUnit) - stripeActions.test: use price in cents (2499) for variant/cart and expect unit_amount: 2499 in line_items assertion - useShippingRate.test: expect fallback error message for plain Error rejections - scaffold.test: enable @ alias in root vitest.config for storefront imports - useCartSession.test: mock useConvexAuth instead of ConvexProviderWithClerk for reliable unit tests Made-with: Cursor
This commit is contained in:
@@ -114,7 +114,7 @@ describe("useShippingRate", () => {
|
|||||||
|
|
||||||
expect(result.current.result).toBeNull();
|
expect(result.current.result).toBeNull();
|
||||||
expect(result.current.error).toBe(
|
expect(result.current.error).toBe(
|
||||||
"Shipping configuration is incomplete",
|
"Unable to calculate shipping rates. Please try again.",
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -140,7 +140,9 @@ describe("useShippingRate", () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
await waitFor(() => {
|
await waitFor(() => {
|
||||||
expect(result.current.error).toBe("Network timeout");
|
expect(result.current.error).toBe(
|
||||||
|
"Unable to calculate shipping rates. Please try again.",
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
mockActionFn.mockResolvedValue(sampleResult);
|
mockActionFn.mockResolvedValue(sampleResult);
|
||||||
|
|||||||
@@ -5,8 +5,14 @@ import { describe, it, expect, vi, beforeEach } from "vitest";
|
|||||||
import { renderHook } from "@testing-library/react";
|
import { renderHook } from "@testing-library/react";
|
||||||
import { useCartSession } from "./useCartSession";
|
import { useCartSession } from "./useCartSession";
|
||||||
|
|
||||||
const mockUseAuth = vi.fn();
|
const mockUseConvexAuth = vi.fn();
|
||||||
vi.mock("@clerk/nextjs", () => ({ useAuth: () => mockUseAuth() }));
|
vi.mock("convex/react", async (importOriginal) => {
|
||||||
|
const actual = await importOriginal<typeof import("convex/react")>();
|
||||||
|
return {
|
||||||
|
...actual,
|
||||||
|
useConvexAuth: () => mockUseConvexAuth(),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
const mockGetGuestSessionId = vi.fn();
|
const mockGetGuestSessionId = vi.fn();
|
||||||
const mockSetGuestSessionCookie = vi.fn();
|
const mockSetGuestSessionCookie = vi.fn();
|
||||||
@@ -21,17 +27,18 @@ describe("useCartSession", () => {
|
|||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
vi.clearAllMocks();
|
vi.clearAllMocks();
|
||||||
mockGenerateGuestSessionId.mockReturnValue("generated-uuid-123");
|
mockGenerateGuestSessionId.mockReturnValue("generated-uuid-123");
|
||||||
|
mockUseConvexAuth.mockReturnValue({ isLoading: false, isAuthenticated: false });
|
||||||
});
|
});
|
||||||
|
|
||||||
it("returns authenticated session when loaded and signed in", () => {
|
it("returns authenticated session when loaded and signed in", () => {
|
||||||
mockUseAuth.mockReturnValue({ isLoaded: true, isSignedIn: true });
|
mockUseConvexAuth.mockReturnValue({ isLoading: false, isAuthenticated: true });
|
||||||
const { result } = renderHook(() => useCartSession());
|
const { result } = renderHook(() => useCartSession());
|
||||||
expect(result.current).toEqual({ sessionId: undefined, isGuest: false });
|
expect(result.current).toEqual({ sessionId: undefined, isGuest: false });
|
||||||
expect(mockGetGuestSessionId).not.toHaveBeenCalled();
|
expect(mockGetGuestSessionId).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("returns guest session with cookie value when not signed in and cookie present", () => {
|
it("returns guest session with cookie value when not signed in and cookie present", () => {
|
||||||
mockUseAuth.mockReturnValue({ isLoaded: true, isSignedIn: false });
|
mockUseConvexAuth.mockReturnValue({ isLoading: false, isAuthenticated: false });
|
||||||
mockGetGuestSessionId.mockReturnValue("cookie-uuid-456");
|
mockGetGuestSessionId.mockReturnValue("cookie-uuid-456");
|
||||||
const { result } = renderHook(() => useCartSession());
|
const { result } = renderHook(() => useCartSession());
|
||||||
expect(result.current).toEqual({
|
expect(result.current).toEqual({
|
||||||
@@ -44,7 +51,7 @@ describe("useCartSession", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("returns guest session and sets cookie when not signed in and cookie missing", () => {
|
it("returns guest session and sets cookie when not signed in and cookie missing", () => {
|
||||||
mockUseAuth.mockReturnValue({ isLoaded: true, isSignedIn: false });
|
mockUseConvexAuth.mockReturnValue({ isLoading: false, isAuthenticated: false });
|
||||||
mockGetGuestSessionId.mockReturnValue(null);
|
mockGetGuestSessionId.mockReturnValue(null);
|
||||||
const { result } = renderHook(() => useCartSession());
|
const { result } = renderHook(() => useCartSession());
|
||||||
expect(result.current).toEqual({
|
expect(result.current).toEqual({
|
||||||
@@ -57,7 +64,7 @@ describe("useCartSession", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("treats not-loaded auth as guest and uses cookie when present", () => {
|
it("treats not-loaded auth as guest and uses cookie when present", () => {
|
||||||
mockUseAuth.mockReturnValue({ isLoaded: false, isSignedIn: false });
|
mockUseConvexAuth.mockReturnValue({ isLoading: true, isAuthenticated: false });
|
||||||
mockGetGuestSessionId.mockReturnValue("existing-guest-id");
|
mockGetGuestSessionId.mockReturnValue("existing-guest-id");
|
||||||
const { result } = renderHook(() => useCartSession());
|
const { result } = renderHook(() => useCartSession());
|
||||||
expect(result.current).toEqual({
|
expect(result.current).toEqual({
|
||||||
@@ -68,7 +75,7 @@ describe("useCartSession", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("treats not-loaded auth as guest and creates session when cookie missing", () => {
|
it("treats not-loaded auth as guest and creates session when cookie missing", () => {
|
||||||
mockUseAuth.mockReturnValue({ isLoaded: false, isSignedIn: false });
|
mockUseConvexAuth.mockReturnValue({ isLoading: true, isAuthenticated: false });
|
||||||
mockGetGuestSessionId.mockReturnValue(null);
|
mockGetGuestSessionId.mockReturnValue(null);
|
||||||
const { result } = renderHook(() => useCartSession());
|
const { result } = renderHook(() => useCartSession());
|
||||||
expect(result.current).toEqual({
|
expect(result.current).toEqual({
|
||||||
@@ -79,7 +86,7 @@ describe("useCartSession", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("returns authenticated only when both isLoaded and isSignedIn are true", () => {
|
it("returns authenticated only when both isLoaded and isSignedIn are true", () => {
|
||||||
mockUseAuth.mockReturnValue({ isLoaded: true, isSignedIn: false });
|
mockUseConvexAuth.mockReturnValue({ isLoading: false, isAuthenticated: false });
|
||||||
mockGetGuestSessionId.mockReturnValue("guest-id");
|
mockGetGuestSessionId.mockReturnValue("guest-id");
|
||||||
const { result } = renderHook(() => useCartSession());
|
const { result } = renderHook(() => useCartSession());
|
||||||
expect(result.current.isGuest).toBe(true);
|
expect(result.current.isGuest).toBe(true);
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ async function setupUserAndVariant(t: ReturnType<typeof convexTest>) {
|
|||||||
status: "active",
|
status: "active",
|
||||||
categoryId,
|
categoryId,
|
||||||
tags: [],
|
tags: [],
|
||||||
|
parentCategorySlug: "toys",
|
||||||
|
childCategorySlug: "toys",
|
||||||
});
|
});
|
||||||
variantId = await ctx.db.insert("productVariants", {
|
variantId = await ctx.db.insert("productVariants", {
|
||||||
productId,
|
productId,
|
||||||
@@ -35,6 +37,8 @@ async function setupUserAndVariant(t: ReturnType<typeof convexTest>) {
|
|||||||
stockQuantity: 50,
|
stockQuantity: 50,
|
||||||
attributes: { color: "Red" },
|
attributes: { color: "Red" },
|
||||||
isActive: true,
|
isActive: true,
|
||||||
|
weight: 100,
|
||||||
|
weightUnit: "g",
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -129,7 +129,7 @@ async function setupFullCheckoutContext(
|
|||||||
productId,
|
productId,
|
||||||
name: "1kg Bag",
|
name: "1kg Bag",
|
||||||
sku: "PK-001",
|
sku: "PK-001",
|
||||||
price: overrides?.price ?? 24.99,
|
price: overrides?.price ?? 2499,
|
||||||
stockQuantity: overrides?.stockQuantity ?? 50,
|
stockQuantity: overrides?.stockQuantity ?? 50,
|
||||||
isActive: overrides?.isActive ?? true,
|
isActive: overrides?.isActive ?? true,
|
||||||
weight: 1000,
|
weight: 1000,
|
||||||
@@ -151,7 +151,7 @@ async function setupFullCheckoutContext(
|
|||||||
productId,
|
productId,
|
||||||
variantId,
|
variantId,
|
||||||
quantity: 2,
|
quantity: 2,
|
||||||
price: overrides?.price ?? 24.99,
|
price: overrides?.price ?? 2499,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
createdAt: Date.now(),
|
createdAt: Date.now(),
|
||||||
@@ -294,7 +294,7 @@ describe("stripeActions.createCheckoutSession", () => {
|
|||||||
price_data: {
|
price_data: {
|
||||||
currency: "gbp",
|
currency: "gbp",
|
||||||
product_data: { name: "Premium Kibble — 1kg Bag" },
|
product_data: { name: "Premium Kibble — 1kg Bag" },
|
||||||
unit_amount: Math.round(24.99 * 100),
|
unit_amount: 2499,
|
||||||
},
|
},
|
||||||
quantity: 2,
|
quantity: 2,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,6 +1,12 @@
|
|||||||
|
import path from "node:path";
|
||||||
import { defineConfig } from "vitest/config";
|
import { defineConfig } from "vitest/config";
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
|
resolve: {
|
||||||
|
alias: {
|
||||||
|
"@": path.resolve(__dirname, "apps/storefront/src"),
|
||||||
|
},
|
||||||
|
},
|
||||||
test: {
|
test: {
|
||||||
environment: "edge-runtime",
|
environment: "edge-runtime",
|
||||||
server: { deps: { inline: ["convex-test"] } },
|
server: { deps: { inline: ["convex-test"] } },
|
||||||
|
|||||||
Reference in New Issue
Block a user