docs: added tests for components in api-reference project (#14428)
* add tests (WIP) * added test for h2 * finished adding tests * fixes * fixes * fixes
This commit is contained in:
@@ -0,0 +1,182 @@
|
||||
import React from "react"
|
||||
import { beforeEach, describe, expect, test, vi } from "vitest"
|
||||
import { cleanup, fireEvent, render } from "@testing-library/react"
|
||||
import { usePathname } from "next/navigation"
|
||||
import AreaProvider, { useArea } from "../area"
|
||||
import { OpenAPI } from "types"
|
||||
|
||||
// Mock functions
|
||||
const mockSetActivePath = vi.fn()
|
||||
const mockUseSidebar = vi.fn(() => ({
|
||||
setActivePath: mockSetActivePath,
|
||||
}))
|
||||
const mockUsePathname = vi.fn(() => "/store/test")
|
||||
const mockCapitalize = vi.fn((str: string) => str.charAt(0).toUpperCase() + str.slice(1))
|
||||
// Track previous values for usePrevious mock
|
||||
// usePrevious returns the value from the previous render
|
||||
let previousValue: unknown = undefined
|
||||
const mockUsePrevious = vi.fn((value: unknown) => {
|
||||
const result = previousValue
|
||||
previousValue = value
|
||||
return result
|
||||
})
|
||||
|
||||
// Test component that uses the hook
|
||||
const TestComponent = () => {
|
||||
const { area, prevArea, displayedArea, setArea } = useArea()
|
||||
return (
|
||||
<div>
|
||||
<div data-testid="area">{area}</div>
|
||||
<div data-testid="prev-area">{prevArea || "undefined"}</div>
|
||||
<div data-testid="displayed-area">{displayedArea}</div>
|
||||
<button
|
||||
data-testid="set-area-store"
|
||||
onClick={() => setArea("store" as OpenAPI.Area)}
|
||||
>
|
||||
Set Store
|
||||
</button>
|
||||
<button
|
||||
data-testid="set-area-admin"
|
||||
onClick={() => setArea("admin" as OpenAPI.Area)}
|
||||
>
|
||||
Set Admin
|
||||
</button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
vi.mock("docs-ui", () => ({
|
||||
capitalize: (str: string) => mockCapitalize(str),
|
||||
usePrevious: (value: unknown) => mockUsePrevious(value),
|
||||
useSidebar: () => mockUseSidebar(),
|
||||
}))
|
||||
|
||||
vi.mock("next/navigation", () => ({
|
||||
usePathname: () => mockUsePathname(),
|
||||
}))
|
||||
|
||||
describe("AreaProvider", () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks()
|
||||
cleanup()
|
||||
previousValue = undefined
|
||||
mockUsePathname.mockReturnValue("/store/test")
|
||||
mockCapitalize.mockImplementation((str: string) => str.charAt(0).toUpperCase() + str.slice(1))
|
||||
})
|
||||
|
||||
describe("rendering", () => {
|
||||
test("renders children", () => {
|
||||
const { getByText } = render(
|
||||
<AreaProvider area="store">
|
||||
<div>Test Content</div>
|
||||
</AreaProvider>
|
||||
)
|
||||
expect(getByText("Test Content")).toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
|
||||
describe("initial state", () => {
|
||||
test("initializes with passed area", () => {
|
||||
const { getByTestId } = render(
|
||||
<AreaProvider area="store">
|
||||
<TestComponent />
|
||||
</AreaProvider>
|
||||
)
|
||||
expect(getByTestId("area")).toHaveTextContent("store")
|
||||
})
|
||||
|
||||
test("displays capitalized area", () => {
|
||||
const { getByTestId } = render(
|
||||
<AreaProvider area="store">
|
||||
<TestComponent />
|
||||
</AreaProvider>
|
||||
)
|
||||
expect(getByTestId("displayed-area")).toHaveTextContent("Store")
|
||||
expect(mockCapitalize).toHaveBeenCalledWith("store")
|
||||
})
|
||||
|
||||
test("prevArea is undefined initially", () => {
|
||||
const { getByTestId } = render(
|
||||
<AreaProvider area="store">
|
||||
<TestComponent />
|
||||
</AreaProvider>
|
||||
)
|
||||
expect(getByTestId("prev-area")).toHaveTextContent("undefined")
|
||||
})
|
||||
})
|
||||
|
||||
describe("setArea", () => {
|
||||
test("updates area when setArea is called", () => {
|
||||
const { getByTestId } = render(
|
||||
<AreaProvider area="store">
|
||||
<TestComponent />
|
||||
</AreaProvider>
|
||||
)
|
||||
const setAdminButton = getByTestId("set-area-admin")
|
||||
const areaElement = getByTestId("area")
|
||||
|
||||
expect(areaElement).toHaveTextContent("store")
|
||||
fireEvent.click(setAdminButton)
|
||||
expect(areaElement).toHaveTextContent("admin")
|
||||
})
|
||||
|
||||
test("updates displayedArea when area changes", () => {
|
||||
const { getByTestId } = render(
|
||||
<AreaProvider area="store">
|
||||
<TestComponent />
|
||||
</AreaProvider>
|
||||
)
|
||||
const setAdminButton = getByTestId("set-area-admin")
|
||||
const displayedAreaElement = getByTestId("displayed-area")
|
||||
|
||||
expect(displayedAreaElement).toHaveTextContent("Store")
|
||||
fireEvent.click(setAdminButton)
|
||||
expect(displayedAreaElement).toHaveTextContent("Admin")
|
||||
})
|
||||
})
|
||||
|
||||
describe("useEffect behavior", () => {
|
||||
test("calls setActivePath(null) when pathname changes", () => {
|
||||
const { rerender } = render(
|
||||
<AreaProvider area="store">
|
||||
<TestComponent />
|
||||
</AreaProvider>
|
||||
)
|
||||
|
||||
mockUsePathname.mockReturnValue("/admin/test")
|
||||
rerender(
|
||||
<AreaProvider area="store">
|
||||
<TestComponent />
|
||||
</AreaProvider>
|
||||
)
|
||||
|
||||
expect(mockSetActivePath).toHaveBeenCalledWith(null)
|
||||
})
|
||||
})
|
||||
|
||||
describe("useArea hook", () => {
|
||||
test("throws error when used outside provider", () => {
|
||||
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => {})
|
||||
|
||||
expect(() => {
|
||||
render(<TestComponent />)
|
||||
}).toThrow("useAreaProvider must be used inside an AreaProvider")
|
||||
|
||||
consoleSpy.mockRestore()
|
||||
})
|
||||
|
||||
test("returns area, prevArea, displayedArea, and setArea", () => {
|
||||
const { getByTestId } = render(
|
||||
<AreaProvider area="store">
|
||||
<TestComponent />
|
||||
</AreaProvider>
|
||||
)
|
||||
expect(getByTestId("area")).toBeInTheDocument()
|
||||
expect(getByTestId("prev-area")).toBeInTheDocument()
|
||||
expect(getByTestId("displayed-area")).toBeInTheDocument()
|
||||
expect(getByTestId("set-area-store")).toBeInTheDocument()
|
||||
expect(getByTestId("set-area-admin")).toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -0,0 +1,363 @@
|
||||
import React from "react"
|
||||
import { beforeEach, describe, expect, test, vi } from "vitest"
|
||||
import { cleanup, render, waitFor } from "@testing-library/react"
|
||||
import { OpenAPI, Sidebar } from "types"
|
||||
|
||||
// mock data
|
||||
const mockShownSidebar: Sidebar.Sidebar = {
|
||||
sidebar_id: "test-sidebar",
|
||||
title: "Test Sidebar",
|
||||
items: [],
|
||||
}
|
||||
|
||||
const mockBaseSpecs: OpenAPI.ExpandedDocument = {
|
||||
openapi: "3.0.0",
|
||||
info: {
|
||||
title: "Test API",
|
||||
version: "1.0.0",
|
||||
},
|
||||
tags: [
|
||||
{
|
||||
name: "TestTag",
|
||||
},
|
||||
],
|
||||
expandedTags: {
|
||||
"testtag": {
|
||||
"get": {
|
||||
summary: "Test Operation",
|
||||
description: "Test Operation Description",
|
||||
parameters: [],
|
||||
},
|
||||
},
|
||||
},
|
||||
paths: {
|
||||
"/test-path": {
|
||||
get: {
|
||||
operationId: "test-operation",
|
||||
summary: "Test Operation",
|
||||
description: "Test Operation Description",
|
||||
"x-authenticated": false,
|
||||
"x-codeSamples": [],
|
||||
parameters: [],
|
||||
responses: {
|
||||
"200": {
|
||||
description: "OK",
|
||||
content: {}
|
||||
}
|
||||
},
|
||||
requestBody: {
|
||||
content: {}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
components: {
|
||||
securitySchemes: {
|
||||
"test-security": {
|
||||
type: "http",
|
||||
scheme: "bearer",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// Mock functions
|
||||
const mockPush = vi.fn()
|
||||
const mockReplace = vi.fn()
|
||||
const mockUseRouter = vi.fn(() => ({
|
||||
push: mockPush,
|
||||
replace: mockReplace,
|
||||
}))
|
||||
const mockSetActivePath = vi.fn()
|
||||
const mockResetItems = vi.fn()
|
||||
const mockUpdateItems = vi.fn()
|
||||
const mockUseSidebar = vi.fn(() => ({
|
||||
activePath: "testtag",
|
||||
setActivePath: mockSetActivePath,
|
||||
resetItems: mockResetItems,
|
||||
updateItems: mockUpdateItems,
|
||||
shownSidebar: mockShownSidebar as Sidebar.Sidebar | Sidebar.SidebarItemSidebar | undefined,
|
||||
}))
|
||||
const mockGetSectionId = vi.fn((parts: string[]) => parts.join("-").toLowerCase())
|
||||
const mockGetTagChildSidebarItems = vi.fn(() => [] as Sidebar.SidebarItem[])
|
||||
|
||||
vi.mock("next/navigation", () => ({
|
||||
useRouter: () => mockUseRouter(),
|
||||
}))
|
||||
|
||||
vi.mock("docs-ui", () => ({
|
||||
useSidebar: () => mockUseSidebar(),
|
||||
}))
|
||||
|
||||
vi.mock("docs-utils", () => ({
|
||||
getSectionId: (parts: string[]) => mockGetSectionId(parts),
|
||||
}))
|
||||
|
||||
vi.mock("@/utils/get-tag-child-sidebar-items", () => ({
|
||||
default: () => mockGetTagChildSidebarItems(),
|
||||
}))
|
||||
|
||||
import BaseSpecsProvider, { useBaseSpecs } from "../base-specs"
|
||||
|
||||
// Test component that uses the hook
|
||||
const TestComponent = () => {
|
||||
const { baseSpecs, getSecuritySchema } = useBaseSpecs()
|
||||
return (
|
||||
<div>
|
||||
<div data-testid="base-specs">{baseSpecs ? "present" : "null"}</div>
|
||||
<div data-testid="security-schema">
|
||||
{getSecuritySchema("test-security") ? "found" : "null"}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
describe("BaseSpecsProvider", () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks()
|
||||
cleanup()
|
||||
window.location.hash = ""
|
||||
mockGetSectionId.mockImplementation((parts: string[]) => parts.join("-").toLowerCase())
|
||||
mockGetTagChildSidebarItems.mockReturnValue([])
|
||||
})
|
||||
|
||||
describe("rendering", () => {
|
||||
test("renders children", () => {
|
||||
const { getByText } = render(
|
||||
<BaseSpecsProvider baseSpecs={mockBaseSpecs}>
|
||||
<div>Test Content</div>
|
||||
</BaseSpecsProvider>
|
||||
)
|
||||
expect(getByText("Test Content")).toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
|
||||
describe("useBaseSpecs hook", () => {
|
||||
test("throws error when used outside provider", () => {
|
||||
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => {})
|
||||
|
||||
expect(() => {
|
||||
render(<TestComponent />)
|
||||
}).toThrow("useBaseSpecs must be used inside a BaseSpecsProvider")
|
||||
|
||||
consoleSpy.mockRestore()
|
||||
})
|
||||
|
||||
test("returns baseSpecs and getSecuritySchema", () => {
|
||||
const { getByTestId } = render(
|
||||
<BaseSpecsProvider baseSpecs={mockBaseSpecs}>
|
||||
<TestComponent />
|
||||
</BaseSpecsProvider>
|
||||
)
|
||||
expect(getByTestId("base-specs")).toHaveTextContent("present")
|
||||
expect(getByTestId("security-schema")).toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
|
||||
describe("getSecuritySchema", () => {
|
||||
test("returns security schema when it exists", () => {
|
||||
const { getByTestId } = render(
|
||||
<BaseSpecsProvider baseSpecs={mockBaseSpecs}>
|
||||
<TestComponent />
|
||||
</BaseSpecsProvider>
|
||||
)
|
||||
const securitySchema = getByTestId("security-schema")
|
||||
expect(securitySchema).toHaveTextContent("found")
|
||||
})
|
||||
|
||||
test("returns null when security schema does not exist", () => {
|
||||
const { getByTestId } = render(
|
||||
<BaseSpecsProvider baseSpecs={mockBaseSpecs}>
|
||||
<TestComponent />
|
||||
</BaseSpecsProvider>
|
||||
)
|
||||
const securitySchema = getByTestId("security-schema")
|
||||
// Change to a non-existent security name
|
||||
const TestComponent2 = () => {
|
||||
const { getSecuritySchema } = useBaseSpecs()
|
||||
return (
|
||||
<div data-testid="security-schema-2">
|
||||
{getSecuritySchema("non-existent") ? "found" : "null"}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
const { getByTestId: getByTestId2 } = render(
|
||||
<BaseSpecsProvider baseSpecs={mockBaseSpecs}>
|
||||
<TestComponent2 />
|
||||
</BaseSpecsProvider>
|
||||
)
|
||||
expect(getByTestId2("security-schema-2")).toHaveTextContent("null")
|
||||
})
|
||||
|
||||
test("returns null when security schema is a ref", () => {
|
||||
const baseSpecsWithRef: OpenAPI.ExpandedDocument = {
|
||||
...mockBaseSpecs,
|
||||
components: {
|
||||
securitySchemes: {
|
||||
"test-security": {
|
||||
$ref: "#/components/securitySchemes/OtherSecurity",
|
||||
},
|
||||
},
|
||||
},
|
||||
} as OpenAPI.ExpandedDocument
|
||||
|
||||
const TestComponent3 = () => {
|
||||
const { getSecuritySchema } = useBaseSpecs()
|
||||
return (
|
||||
<div data-testid="security-schema-3">
|
||||
{getSecuritySchema("test-security") ? "found" : "null"}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const { getByTestId } = render(
|
||||
<BaseSpecsProvider baseSpecs={baseSpecsWithRef}>
|
||||
<TestComponent3 />
|
||||
</BaseSpecsProvider>
|
||||
)
|
||||
expect(getByTestId("security-schema-3")).toHaveTextContent("null")
|
||||
})
|
||||
})
|
||||
|
||||
describe("itemsToUpdate", () => {
|
||||
test("generates itemsToUpdate from baseSpecs tags", async () => {
|
||||
const mockSidebar: Sidebar.Sidebar = {
|
||||
sidebar_id: "test-sidebar",
|
||||
title: "Test Sidebar",
|
||||
items: [],
|
||||
}
|
||||
mockUseSidebar.mockReturnValue({
|
||||
activePath: "testtag",
|
||||
setActivePath: mockSetActivePath,
|
||||
resetItems: mockResetItems,
|
||||
updateItems: mockUpdateItems,
|
||||
shownSidebar: mockSidebar,
|
||||
})
|
||||
mockGetTagChildSidebarItems.mockReturnValue([
|
||||
{
|
||||
type: "link",
|
||||
path: "/test-path",
|
||||
title: "Test Link",
|
||||
},
|
||||
])
|
||||
|
||||
render(
|
||||
<BaseSpecsProvider baseSpecs={mockBaseSpecs}>
|
||||
<div>Test</div>
|
||||
</BaseSpecsProvider>
|
||||
)
|
||||
|
||||
await waitFor(() => {
|
||||
expect(mockUpdateItems).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
const updateCall = mockUpdateItems.mock.calls[0][0]
|
||||
expect(updateCall.sidebar_id).toBe("test-sidebar")
|
||||
expect(updateCall.items).toBeDefined()
|
||||
expect(Array.isArray(updateCall.items)).toBe(true)
|
||||
expect(updateCall.items.length).toBeGreaterThan(0)
|
||||
})
|
||||
|
||||
test("does not update items when baseSpecs is undefined", () => {
|
||||
render(
|
||||
<BaseSpecsProvider baseSpecs={undefined}>
|
||||
<div>Test</div>
|
||||
</BaseSpecsProvider>
|
||||
)
|
||||
|
||||
expect(mockUpdateItems).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
test("does not update items when shownSidebar is null", () => {
|
||||
mockUseSidebar.mockReturnValue({
|
||||
activePath: "testtag",
|
||||
setActivePath: mockSetActivePath,
|
||||
resetItems: mockResetItems,
|
||||
updateItems: mockUpdateItems,
|
||||
shownSidebar: undefined,
|
||||
})
|
||||
render(
|
||||
<BaseSpecsProvider baseSpecs={mockBaseSpecs}>
|
||||
<div>Test</div>
|
||||
</BaseSpecsProvider>
|
||||
)
|
||||
|
||||
expect(mockUpdateItems).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
test("includes onOpen handler that updates hash and activePath", async () => {
|
||||
mockUseSidebar.mockReturnValue({
|
||||
activePath: "something-else",
|
||||
setActivePath: mockSetActivePath,
|
||||
resetItems: mockResetItems,
|
||||
updateItems: mockUpdateItems,
|
||||
shownSidebar: mockShownSidebar,
|
||||
})
|
||||
window.location.hash = ""
|
||||
|
||||
render(
|
||||
<BaseSpecsProvider baseSpecs={mockBaseSpecs}>
|
||||
<div>Test</div>
|
||||
</BaseSpecsProvider>
|
||||
)
|
||||
|
||||
await waitFor(() => {
|
||||
expect(mockUpdateItems).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
const updateCall = mockUpdateItems.mock.calls[0][0]
|
||||
const item = updateCall.items[0]
|
||||
expect(item.newItem.onOpen).toBeDefined()
|
||||
|
||||
// Call onOpen
|
||||
item.newItem.onOpen()
|
||||
expect(mockPush).toHaveBeenCalledWith("#testtag", { scroll: false })
|
||||
expect(mockSetActivePath).toHaveBeenCalledWith("testtag")
|
||||
})
|
||||
|
||||
test("onOpen does not update hash when it already matches", async () => {
|
||||
mockUseSidebar.mockReturnValue({
|
||||
activePath: "testtag",
|
||||
setActivePath: mockSetActivePath,
|
||||
resetItems: mockResetItems,
|
||||
updateItems: mockUpdateItems,
|
||||
shownSidebar: mockShownSidebar,
|
||||
})
|
||||
window.location.hash = "#testtag"
|
||||
|
||||
render(
|
||||
<BaseSpecsProvider baseSpecs={mockBaseSpecs}>
|
||||
<div>Test</div>
|
||||
</BaseSpecsProvider>
|
||||
)
|
||||
|
||||
await waitFor(() => {
|
||||
expect(mockUpdateItems).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
const updateCall = mockUpdateItems.mock.calls[0][0]
|
||||
const item = updateCall.items[0]
|
||||
mockPush.mockClear()
|
||||
mockSetActivePath.mockClear()
|
||||
|
||||
// Call onOpen
|
||||
item.newItem.onOpen()
|
||||
expect(mockPush).not.toHaveBeenCalled()
|
||||
expect(mockSetActivePath).not.toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
|
||||
describe("cleanup", () => {
|
||||
test("calls resetItems on unmount", () => {
|
||||
const { unmount } = render(
|
||||
<BaseSpecsProvider baseSpecs={mockBaseSpecs}>
|
||||
<div>Test</div>
|
||||
</BaseSpecsProvider>
|
||||
)
|
||||
|
||||
unmount()
|
||||
expect(mockResetItems).toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
import React from "react"
|
||||
import { beforeEach, describe, expect, test, vi } from "vitest"
|
||||
import { cleanup, fireEvent, render } from "@testing-library/react"
|
||||
import LoadingProvider, { useLoading } from "../loading"
|
||||
|
||||
// Test component that uses the hook
|
||||
const TestComponent = () => {
|
||||
const { loading, removeLoading } = useLoading()
|
||||
return (
|
||||
<div>
|
||||
<div data-testid="loading-state">{loading.toString()}</div>
|
||||
<button data-testid="remove-loading" onClick={removeLoading}>
|
||||
Remove Loading
|
||||
</button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
describe("LoadingProvider", () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks()
|
||||
cleanup()
|
||||
})
|
||||
|
||||
describe("rendering", () => {
|
||||
test("renders children", () => {
|
||||
const { getByText } = render(
|
||||
<LoadingProvider>
|
||||
<div>Test Content</div>
|
||||
</LoadingProvider>
|
||||
)
|
||||
expect(getByText("Test Content")).toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
|
||||
describe("initial loading state", () => {
|
||||
test("initializes with loading false by default", () => {
|
||||
const { getByTestId } = render(
|
||||
<LoadingProvider>
|
||||
<TestComponent />
|
||||
</LoadingProvider>
|
||||
)
|
||||
expect(getByTestId("loading-state")).toHaveTextContent("false")
|
||||
})
|
||||
|
||||
test("initializes with loading true when initialLoading is true", () => {
|
||||
const { getByTestId } = render(
|
||||
<LoadingProvider initialLoading={true}>
|
||||
<TestComponent />
|
||||
</LoadingProvider>
|
||||
)
|
||||
expect(getByTestId("loading-state")).toHaveTextContent("true")
|
||||
})
|
||||
})
|
||||
|
||||
describe("removeLoading", () => {
|
||||
test("sets loading to false when removeLoading is called", () => {
|
||||
const { getByTestId } = render(
|
||||
<LoadingProvider initialLoading={true}>
|
||||
<TestComponent />
|
||||
</LoadingProvider>
|
||||
)
|
||||
const removeLoadingButton = getByTestId("remove-loading")
|
||||
const loadingState = getByTestId("loading-state")
|
||||
|
||||
expect(loadingState).toHaveTextContent("true")
|
||||
fireEvent.click(removeLoadingButton)
|
||||
expect(loadingState).toHaveTextContent("false")
|
||||
})
|
||||
})
|
||||
|
||||
describe("useLoading hook", () => {
|
||||
test("throws error when used outside provider", () => {
|
||||
// Suppress console.error for this test
|
||||
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => {})
|
||||
|
||||
expect(() => {
|
||||
render(<TestComponent />)
|
||||
}).toThrow("useLoading must be used inside a LoadingProvider")
|
||||
|
||||
consoleSpy.mockRestore()
|
||||
})
|
||||
|
||||
test("returns loading state and removeLoading function", () => {
|
||||
const { getByTestId } = render(
|
||||
<LoadingProvider>
|
||||
<TestComponent />
|
||||
</LoadingProvider>
|
||||
)
|
||||
expect(getByTestId("loading-state")).toBeInTheDocument()
|
||||
expect(getByTestId("remove-loading")).toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
import React from "react"
|
||||
import { beforeEach, describe, expect, test, vi } from "vitest"
|
||||
import { cleanup, render } from "@testing-library/react"
|
||||
import { MainNavProvider } from "../main-nav"
|
||||
|
||||
// Mock functions
|
||||
const mockGetNavDropdownItems = vi.fn((options: unknown) => [
|
||||
{
|
||||
title: "Test Item",
|
||||
path: "/test",
|
||||
},
|
||||
])
|
||||
|
||||
vi.mock("docs-ui", () => ({
|
||||
getNavDropdownItems: (options: unknown) => mockGetNavDropdownItems(options),
|
||||
MainNavProvider: ({ children, navItems }: { children: React.ReactNode; navItems: unknown[] }) => (
|
||||
<div data-testid="ui-main-nav-provider" data-nav-items={JSON.stringify(navItems)}>
|
||||
{children}
|
||||
</div>
|
||||
),
|
||||
}))
|
||||
|
||||
vi.mock("@/config", () => ({
|
||||
config: {
|
||||
baseUrl: "https://test.com",
|
||||
},
|
||||
}))
|
||||
|
||||
describe("MainNavProvider", () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks()
|
||||
cleanup()
|
||||
})
|
||||
|
||||
describe("rendering", () => {
|
||||
test("renders children", () => {
|
||||
const { getByText } = render(
|
||||
<MainNavProvider>
|
||||
<div>Test Content</div>
|
||||
</MainNavProvider>
|
||||
)
|
||||
expect(getByText("Test Content")).toBeInTheDocument()
|
||||
})
|
||||
|
||||
test("renders UiMainNavProvider with navItems", () => {
|
||||
const { getByTestId } = render(
|
||||
<MainNavProvider>
|
||||
<div>Test</div>
|
||||
</MainNavProvider>
|
||||
)
|
||||
const uiProvider = getByTestId("ui-main-nav-provider")
|
||||
expect(uiProvider).toBeInTheDocument()
|
||||
expect(mockGetNavDropdownItems).toHaveBeenCalledWith({
|
||||
basePath: "https://test.com",
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("navigationDropdownItems", () => {
|
||||
test("memoizes navigationDropdownItems", () => {
|
||||
const { rerender } = render(
|
||||
<MainNavProvider>
|
||||
<div>Test</div>
|
||||
</MainNavProvider>
|
||||
)
|
||||
|
||||
const callCount = mockGetNavDropdownItems.mock.calls.length
|
||||
|
||||
rerender(
|
||||
<MainNavProvider>
|
||||
<div>Test</div>
|
||||
</MainNavProvider>
|
||||
)
|
||||
|
||||
// Should not call getNavDropdownItems again due to memoization
|
||||
expect(mockGetNavDropdownItems.mock.calls.length).toBe(callCount)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -0,0 +1,206 @@
|
||||
import React from "react"
|
||||
import { beforeEach, describe, expect, test, vi } from "vitest"
|
||||
import { cleanup, render } from "@testing-library/react"
|
||||
import PageTitleProvider from "../page-title"
|
||||
import { Sidebar } from "types"
|
||||
|
||||
// Mock functions
|
||||
const mockUseSidebar = vi.fn(() => ({
|
||||
activePath: "test-path" as string | null,
|
||||
activeItem: {
|
||||
type: "link",
|
||||
path: "test-path",
|
||||
title: "Test Item",
|
||||
},
|
||||
}))
|
||||
const mockUseArea = vi.fn(() => ({
|
||||
displayedArea: "Store",
|
||||
}))
|
||||
|
||||
vi.mock("docs-ui", () => ({
|
||||
useSidebar: () => mockUseSidebar(),
|
||||
}))
|
||||
|
||||
vi.mock("@/providers/area", () => ({
|
||||
useArea: () => mockUseArea(),
|
||||
}))
|
||||
|
||||
describe("PageTitleProvider", () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks()
|
||||
cleanup()
|
||||
document.title = ""
|
||||
mockUseSidebar.mockReturnValue({
|
||||
activePath: "test-path",
|
||||
activeItem: {
|
||||
type: "link",
|
||||
path: "test-path",
|
||||
title: "Test Item",
|
||||
},
|
||||
})
|
||||
mockUseArea.mockReturnValue({
|
||||
displayedArea: "Store",
|
||||
})
|
||||
})
|
||||
|
||||
describe("rendering", () => {
|
||||
test("renders children", () => {
|
||||
const { getByText } = render(
|
||||
<PageTitleProvider>
|
||||
<div>Test Content</div>
|
||||
</PageTitleProvider>
|
||||
)
|
||||
expect(getByText("Test Content")).toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
|
||||
describe("document title", () => {
|
||||
test("sets title to suffix when activePath is null", () => {
|
||||
mockUseSidebar.mockReturnValue({
|
||||
activePath: null,
|
||||
activeItem: {
|
||||
type: "link",
|
||||
path: "test-path",
|
||||
title: "Test Item",
|
||||
},
|
||||
})
|
||||
render(
|
||||
<PageTitleProvider>
|
||||
<div>Test</div>
|
||||
</PageTitleProvider>
|
||||
)
|
||||
expect(document.title).toBe("Medusa Store API Reference")
|
||||
})
|
||||
|
||||
test("sets title to suffix when activePath is empty string", () => {
|
||||
mockUseSidebar.mockReturnValue({
|
||||
activePath: "",
|
||||
activeItem: {
|
||||
type: "link",
|
||||
path: "test-path",
|
||||
title: "Test Item",
|
||||
},
|
||||
})
|
||||
render(
|
||||
<PageTitleProvider>
|
||||
<div>Test</div>
|
||||
</PageTitleProvider>
|
||||
)
|
||||
expect(document.title).toBe("Medusa Store API Reference")
|
||||
})
|
||||
|
||||
test("sets title with activeItem title when activeItem.path matches activePath", () => {
|
||||
const mockItem: Sidebar.SidebarItemLink = {
|
||||
type: "link",
|
||||
path: "/test-path",
|
||||
title: "Test Item",
|
||||
}
|
||||
mockUseSidebar.mockReturnValue({
|
||||
activePath: "/test-path",
|
||||
activeItem: mockItem,
|
||||
})
|
||||
|
||||
render(
|
||||
<PageTitleProvider>
|
||||
<div>Test</div>
|
||||
</PageTitleProvider>
|
||||
)
|
||||
|
||||
expect(document.title).toBe("Test Item - Medusa Store API Reference")
|
||||
})
|
||||
|
||||
test("sets title with child item title when activeItem has matching child", () => {
|
||||
const mockChildItem: Sidebar.SidebarItemLink = {
|
||||
type: "link",
|
||||
path: "/child-path",
|
||||
title: "Child Item",
|
||||
}
|
||||
const mockItem: Sidebar.SidebarItemLink = {
|
||||
type: "link",
|
||||
path: "/parent-path",
|
||||
title: "Parent Item",
|
||||
children: [mockChildItem],
|
||||
}
|
||||
mockUseSidebar.mockReturnValue({
|
||||
activePath: "/child-path",
|
||||
activeItem: mockItem,
|
||||
})
|
||||
|
||||
render(
|
||||
<PageTitleProvider>
|
||||
<div>Test</div>
|
||||
</PageTitleProvider>
|
||||
)
|
||||
|
||||
expect(document.title).toBe("Child Item - Medusa Store API Reference")
|
||||
})
|
||||
|
||||
test("sets title to suffix when activeItem has no matching child", () => {
|
||||
const mockItem: Sidebar.SidebarItemLink = {
|
||||
type: "link",
|
||||
path: "/parent-path",
|
||||
title: "Parent Item",
|
||||
children: [
|
||||
{
|
||||
type: "link",
|
||||
path: "/other-path",
|
||||
title: "Other Item",
|
||||
},
|
||||
],
|
||||
}
|
||||
mockUseSidebar.mockReturnValue({
|
||||
activePath: "/child-path",
|
||||
activeItem: mockItem,
|
||||
})
|
||||
|
||||
render(
|
||||
<PageTitleProvider>
|
||||
<div>Test</div>
|
||||
</PageTitleProvider>
|
||||
)
|
||||
|
||||
expect(document.title).toBe("Medusa Store API Reference")
|
||||
})
|
||||
|
||||
test("updates title when displayedArea changes", () => {
|
||||
mockUseArea.mockReturnValue({
|
||||
displayedArea: "Admin",
|
||||
})
|
||||
render(
|
||||
<PageTitleProvider>
|
||||
<div>Test</div>
|
||||
</PageTitleProvider>
|
||||
)
|
||||
expect(document.title).toBe("Test Item - Medusa Admin API Reference")
|
||||
})
|
||||
|
||||
test("updates title when activePath changes", () => {
|
||||
const { rerender } = render(
|
||||
<PageTitleProvider>
|
||||
<div>Test</div>
|
||||
</PageTitleProvider>
|
||||
)
|
||||
|
||||
expect(document.title).toBe("Test Item - Medusa Store API Reference")
|
||||
|
||||
const mockItem: Sidebar.SidebarItemLink = {
|
||||
type: "link",
|
||||
path: "/new-path",
|
||||
title: "New Item",
|
||||
}
|
||||
mockUseSidebar.mockReturnValue({
|
||||
activePath: "/new-path",
|
||||
activeItem: mockItem,
|
||||
})
|
||||
|
||||
rerender(
|
||||
<PageTitleProvider>
|
||||
<div>Test</div>
|
||||
</PageTitleProvider>
|
||||
)
|
||||
|
||||
expect(document.title).toBe("New Item - Medusa Store API Reference")
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -0,0 +1,162 @@
|
||||
import React from "react"
|
||||
import { beforeEach, describe, expect, test, vi } from "vitest"
|
||||
import { cleanup, render } from "@testing-library/react"
|
||||
import SearchProvider from "../search"
|
||||
|
||||
// Mock functions
|
||||
const mockIsLoading = vi.fn(() => false)
|
||||
const mockUsePageLoading = vi.fn(() => ({
|
||||
isLoading: mockIsLoading(),
|
||||
}))
|
||||
const mockBasePathUrl = vi.fn((url: string) => url)
|
||||
|
||||
vi.mock("docs-ui", () => ({
|
||||
usePageLoading: () => mockUsePageLoading(),
|
||||
SearchProvider: ({
|
||||
children,
|
||||
algolia,
|
||||
indices,
|
||||
defaultIndex,
|
||||
searchProps,
|
||||
}: {
|
||||
children: React.ReactNode
|
||||
algolia: unknown
|
||||
indices: unknown[]
|
||||
defaultIndex: string
|
||||
searchProps: unknown
|
||||
}) => (
|
||||
<div
|
||||
data-testid="ui-search-provider"
|
||||
data-algolia={JSON.stringify(algolia)}
|
||||
data-indices={JSON.stringify(indices)}
|
||||
data-default-index={defaultIndex}
|
||||
data-search-props={JSON.stringify(searchProps)}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
),
|
||||
}))
|
||||
|
||||
vi.mock("@/config", () => ({
|
||||
config: {
|
||||
baseUrl: "https://test.com",
|
||||
},
|
||||
}))
|
||||
|
||||
vi.mock("@/utils/base-path-url", () => ({
|
||||
default: (url: string) => mockBasePathUrl(url),
|
||||
}))
|
||||
|
||||
describe("SearchProvider", () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks()
|
||||
cleanup()
|
||||
// Set environment variables
|
||||
process.env.NEXT_PUBLIC_ALGOLIA_APP_ID = "test-app-id"
|
||||
process.env.NEXT_PUBLIC_ALGOLIA_API_KEY = "test-api-key"
|
||||
process.env.NEXT_PUBLIC_API_ALGOLIA_INDEX_NAME = "test-api-index"
|
||||
process.env.NEXT_PUBLIC_DOCS_ALGOLIA_INDEX_NAME = "test-docs-index"
|
||||
mockIsLoading.mockReturnValue(false)
|
||||
})
|
||||
|
||||
describe("rendering", () => {
|
||||
test("renders children", () => {
|
||||
const { getByText } = render(
|
||||
<SearchProvider>
|
||||
<div>Test Content</div>
|
||||
</SearchProvider>
|
||||
)
|
||||
expect(getByText("Test Content")).toBeInTheDocument()
|
||||
})
|
||||
|
||||
test("renders UiSearchProvider with correct props", () => {
|
||||
const { getByTestId } = render(
|
||||
<SearchProvider>
|
||||
<div>Test</div>
|
||||
</SearchProvider>
|
||||
)
|
||||
const uiProvider = getByTestId("ui-search-provider")
|
||||
expect(uiProvider).toBeInTheDocument()
|
||||
|
||||
const algolia = JSON.parse(uiProvider.getAttribute("data-algolia") || "{}")
|
||||
expect(algolia).toEqual({
|
||||
appId: "test-app-id",
|
||||
apiKey: "test-api-key",
|
||||
mainIndexName: "test-api-index",
|
||||
})
|
||||
|
||||
const indices = JSON.parse(uiProvider.getAttribute("data-indices") || "[]")
|
||||
expect(indices).toEqual([
|
||||
{
|
||||
value: "test-docs-index",
|
||||
title: "Docs",
|
||||
},
|
||||
{
|
||||
value: "test-api-index",
|
||||
title: "Store & Admin API",
|
||||
},
|
||||
])
|
||||
|
||||
expect(uiProvider.getAttribute("data-default-index")).toBe("test-api-index")
|
||||
})
|
||||
})
|
||||
|
||||
describe("environment variables", () => {
|
||||
test("uses default values when env vars are not set", () => {
|
||||
delete process.env.NEXT_PUBLIC_ALGOLIA_APP_ID
|
||||
delete process.env.NEXT_PUBLIC_ALGOLIA_API_KEY
|
||||
delete process.env.NEXT_PUBLIC_API_ALGOLIA_INDEX_NAME
|
||||
delete process.env.NEXT_PUBLIC_DOCS_ALGOLIA_INDEX_NAME
|
||||
|
||||
const { getByTestId } = render(
|
||||
<SearchProvider>
|
||||
<div>Test</div>
|
||||
</SearchProvider>
|
||||
)
|
||||
const uiProvider = getByTestId("ui-search-provider")
|
||||
const algolia = JSON.parse(uiProvider.getAttribute("data-algolia") || "{}")
|
||||
expect(algolia.appId).toBe("temp")
|
||||
expect(algolia.apiKey).toBe("temp")
|
||||
expect(algolia.mainIndexName).toBe("temp")
|
||||
})
|
||||
})
|
||||
|
||||
describe("searchProps", () => {
|
||||
test("passes isLoading from usePageLoading", () => {
|
||||
mockIsLoading.mockReturnValue(true)
|
||||
const { getByTestId } = render(
|
||||
<SearchProvider>
|
||||
<div>Test</div>
|
||||
</SearchProvider>
|
||||
)
|
||||
const uiProvider = getByTestId("ui-search-provider")
|
||||
const searchProps = JSON.parse(uiProvider.getAttribute("data-search-props") || "{}")
|
||||
expect(searchProps.isLoading).toBe(true)
|
||||
})
|
||||
|
||||
test("includes suggestions", () => {
|
||||
const { getByTestId } = render(
|
||||
<SearchProvider>
|
||||
<div>Test</div>
|
||||
</SearchProvider>
|
||||
)
|
||||
const uiProvider = getByTestId("ui-search-provider")
|
||||
const searchProps = JSON.parse(uiProvider.getAttribute("data-search-props") || "{}")
|
||||
expect(searchProps.suggestions).toBeDefined()
|
||||
expect(Array.isArray(searchProps.suggestions)).toBe(true)
|
||||
expect(searchProps.suggestions.length).toBeGreaterThan(0)
|
||||
})
|
||||
|
||||
test("includes checkInternalPattern regex", () => {
|
||||
const { getByTestId } = render(
|
||||
<SearchProvider>
|
||||
<div>Test</div>
|
||||
</SearchProvider>
|
||||
)
|
||||
const uiProvider = getByTestId("ui-search-provider")
|
||||
const searchProps = JSON.parse(uiProvider.getAttribute("data-search-props") || "{}")
|
||||
expect(searchProps.checkInternalPattern).toBeDefined()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -0,0 +1,237 @@
|
||||
import React from "react"
|
||||
import { beforeEach, describe, expect, test, vi } from "vitest"
|
||||
import { cleanup, render, waitFor } from "@testing-library/react"
|
||||
import SidebarProvider from "../sidebar"
|
||||
import { Sidebar } from "types"
|
||||
|
||||
// Mock functions
|
||||
const mockIsLoading = vi.fn(() => false)
|
||||
const mockSetIsLoading = vi.fn()
|
||||
const mockUsePageLoading = vi.fn(() => ({
|
||||
isLoading: mockIsLoading(),
|
||||
setIsLoading: mockSetIsLoading,
|
||||
}))
|
||||
const mockScrollableElement = vi.fn(() => null as HTMLElement | null)
|
||||
const mockUseScrollController = vi.fn(() => ({
|
||||
scrollableElement: mockScrollableElement(),
|
||||
}))
|
||||
const mockPathname = vi.fn(() => "/store/test")
|
||||
const mockUsePathname = vi.fn(() => mockPathname())
|
||||
|
||||
const mockStoreSidebar: Sidebar.Sidebar = {
|
||||
sidebar_id: "store-sidebar",
|
||||
title: "Store Sidebar",
|
||||
items: [],
|
||||
}
|
||||
|
||||
const mockAdminSidebar: Sidebar.Sidebar = {
|
||||
sidebar_id: "admin-sidebar",
|
||||
title: "Admin Sidebar",
|
||||
items: [],
|
||||
}
|
||||
|
||||
vi.mock("docs-ui", () => ({
|
||||
SidebarProvider: ({
|
||||
children,
|
||||
isLoading,
|
||||
setIsLoading,
|
||||
shouldHandleHashChange,
|
||||
shouldHandlePathChange,
|
||||
scrollableElement,
|
||||
sidebars,
|
||||
persistCategoryState,
|
||||
disableActiveTransition,
|
||||
isSidebarStatic,
|
||||
}: {
|
||||
children: React.ReactNode
|
||||
isLoading: boolean
|
||||
setIsLoading: (value: boolean) => void
|
||||
shouldHandleHashChange: boolean
|
||||
shouldHandlePathChange: boolean
|
||||
scrollableElement: HTMLElement | null
|
||||
sidebars: Sidebar.Sidebar[]
|
||||
persistCategoryState: boolean
|
||||
disableActiveTransition: boolean
|
||||
isSidebarStatic: boolean
|
||||
}) => (
|
||||
<div
|
||||
data-testid="ui-sidebar-provider"
|
||||
data-is-loading={isLoading.toString()}
|
||||
data-should-handle-hash-change={shouldHandleHashChange.toString()}
|
||||
data-should-handle-path-change={shouldHandlePathChange.toString()}
|
||||
data-scrollable-element={scrollableElement ? "present" : "null"}
|
||||
data-sidebars={JSON.stringify(sidebars)}
|
||||
data-persist-category-state={persistCategoryState.toString()}
|
||||
data-disable-active-transition={disableActiveTransition.toString()}
|
||||
data-is-sidebar-static={isSidebarStatic.toString()}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
),
|
||||
usePageLoading: () => mockUsePageLoading(),
|
||||
useScrollController: () => mockUseScrollController(),
|
||||
}))
|
||||
|
||||
vi.mock("next/navigation", () => ({
|
||||
usePathname: () => mockUsePathname(),
|
||||
}))
|
||||
|
||||
vi.mock("@/config", () => ({
|
||||
config: {
|
||||
sidebars: [{
|
||||
sidebar_id: "store-sidebar",
|
||||
title: "Store Sidebar",
|
||||
items: [],
|
||||
}],
|
||||
},
|
||||
}))
|
||||
|
||||
// Mock dynamic imports
|
||||
vi.mock("@/generated/generated-store-sidebar.mjs", () => ({
|
||||
default: mockStoreSidebar,
|
||||
}))
|
||||
|
||||
vi.mock("@/generated/generated-admin-sidebar.mjs", () => ({
|
||||
default: mockAdminSidebar,
|
||||
}))
|
||||
|
||||
describe("SidebarProvider", () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks()
|
||||
cleanup()
|
||||
mockIsLoading.mockReturnValue(false)
|
||||
mockScrollableElement.mockReturnValue(null)
|
||||
mockPathname.mockReturnValue("/store/test")
|
||||
})
|
||||
|
||||
describe("rendering", () => {
|
||||
test("renders children", () => {
|
||||
const { getByText } = render(
|
||||
<SidebarProvider>
|
||||
<div>Test Content</div>
|
||||
</SidebarProvider>
|
||||
)
|
||||
expect(getByText("Test Content")).toBeInTheDocument()
|
||||
})
|
||||
|
||||
test("renders UiSidebarProvider with correct props", async () => {
|
||||
const { getByTestId } = render(
|
||||
<SidebarProvider>
|
||||
<div>Test</div>
|
||||
</SidebarProvider>
|
||||
)
|
||||
|
||||
await waitFor(() => {
|
||||
const uiProvider = getByTestId("ui-sidebar-provider")
|
||||
expect(uiProvider).toBeInTheDocument()
|
||||
expect(uiProvider.getAttribute("data-is-loading")).toBe("false")
|
||||
expect(uiProvider.getAttribute("data-should-handle-hash-change")).toBe("true")
|
||||
expect(uiProvider.getAttribute("data-should-handle-path-change")).toBe("false")
|
||||
expect(uiProvider.getAttribute("data-persist-category-state")).toBe("false")
|
||||
expect(uiProvider.getAttribute("data-disable-active-transition")).toBe("false")
|
||||
expect(uiProvider.getAttribute("data-is-sidebar-static")).toBe("false")
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("sidebar loading", () => {
|
||||
test("loads store sidebar when path starts with /store", async () => {
|
||||
mockPathname.mockReturnValue("/store/test")
|
||||
const { getByTestId } = render(
|
||||
<SidebarProvider>
|
||||
<div>Test</div>
|
||||
</SidebarProvider>
|
||||
)
|
||||
|
||||
await waitFor(() => {
|
||||
const uiProvider = getByTestId("ui-sidebar-provider")
|
||||
const sidebars = JSON.parse(uiProvider.getAttribute("data-sidebars") || "[]")
|
||||
expect(sidebars).toEqual([mockStoreSidebar])
|
||||
})
|
||||
})
|
||||
|
||||
test("loads admin sidebar when path does not start with /store", async () => {
|
||||
mockPathname.mockReturnValue("/admin/test")
|
||||
const { getByTestId } = render(
|
||||
<SidebarProvider>
|
||||
<div>Test</div>
|
||||
</SidebarProvider>
|
||||
)
|
||||
|
||||
await waitFor(() => {
|
||||
const uiProvider = getByTestId("ui-sidebar-provider")
|
||||
const sidebars = JSON.parse(uiProvider.getAttribute("data-sidebars") || "[]")
|
||||
expect(sidebars).toEqual([mockAdminSidebar])
|
||||
})
|
||||
})
|
||||
|
||||
test("uses config sidebars as fallback when sidebar is not loaded", () => {
|
||||
const { getByTestId } = render(
|
||||
<SidebarProvider>
|
||||
<div>Test</div>
|
||||
</SidebarProvider>
|
||||
)
|
||||
|
||||
// Initially should use config sidebars
|
||||
const uiProvider = getByTestId("ui-sidebar-provider")
|
||||
const sidebars = JSON.parse(uiProvider.getAttribute("data-sidebars") || "[]")
|
||||
expect(sidebars).toEqual([mockStoreSidebar])
|
||||
})
|
||||
})
|
||||
|
||||
describe("props passing", () => {
|
||||
test("passes isLoading and setIsLoading to UiSidebarProvider", async () => {
|
||||
mockIsLoading.mockReturnValue(true)
|
||||
const { getByTestId } = render(
|
||||
<SidebarProvider>
|
||||
<div>Test</div>
|
||||
</SidebarProvider>
|
||||
)
|
||||
|
||||
await waitFor(() => {
|
||||
const uiProvider = getByTestId("ui-sidebar-provider")
|
||||
expect(uiProvider.getAttribute("data-is-loading")).toBe("true")
|
||||
})
|
||||
})
|
||||
|
||||
test("passes scrollableElement to UiSidebarProvider", async () => {
|
||||
const mockElement = document.createElement("div")
|
||||
mockScrollableElement.mockReturnValue(mockElement)
|
||||
const { getByTestId } = render(
|
||||
<SidebarProvider>
|
||||
<div>Test</div>
|
||||
</SidebarProvider>
|
||||
)
|
||||
|
||||
await waitFor(() => {
|
||||
const uiProvider = getByTestId("ui-sidebar-provider")
|
||||
expect(uiProvider.getAttribute("data-scrollable-element")).toBe("present")
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("error handling", () => {
|
||||
test("handles sidebar loading errors gracefully", async () => {
|
||||
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => {})
|
||||
|
||||
// Mock a failing import
|
||||
vi.doMock("../generated/generated-store-sidebar.mjs", () => {
|
||||
throw new Error("Failed to load sidebar")
|
||||
})
|
||||
|
||||
const { getByTestId } = render(
|
||||
<SidebarProvider>
|
||||
<div>Test</div>
|
||||
</SidebarProvider>
|
||||
)
|
||||
|
||||
await waitFor(() => {
|
||||
const uiProvider = getByTestId("ui-sidebar-provider")
|
||||
expect(uiProvider).toBeInTheDocument()
|
||||
})
|
||||
|
||||
consoleSpy.mockRestore()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user