useCompleteOnboarding.spec.js
1 month ago
useDateRangePicker.spec.js
2 months ago
useEmail.spec.js
2 months ago
useEngagementChartData.spec.js
2 months ago
useLicenseSettings.spec.js
2 months ago
useLink.spec.js
2 months ago
useMediaDetail.spec.js
2 months ago
useMediaLibrary.spec.js
2 months ago
useMediaList.spec.js
1 month ago
usePerformanceSettings.spec.js
2 months ago
useRegisterActivePage.spec.js
2 months ago
useSettingOption.spec.js
2 months ago
useSimpleSettingsPage.spec.js
2 months ago
useTopPerforming.spec.js
2 months ago
useTopVideosPaginated.spec.js
2 months ago
useUpgradeCTA.spec.js
2 months ago
useUserDetail.spec.js
2 months ago
useCompleteOnboarding.spec.js
169 lines
| 1 | import { renderHook, act } from "@testing-library/react-hooks"; |
| 2 | import apiFetch from "@wordpress/api-fetch"; |
| 3 | import useCompleteOnboarding, { |
| 4 | __resetInFlightForTests, |
| 5 | } from "../useCompleteOnboarding"; |
| 6 | |
| 7 | jest.mock("@wordpress/api-fetch"); |
| 8 | |
| 9 | let originalLocation; |
| 10 | |
| 11 | beforeEach(() => { |
| 12 | apiFetch.mockReset(); |
| 13 | __resetInFlightForTests(); |
| 14 | |
| 15 | originalLocation = window.location; |
| 16 | delete window.location; |
| 17 | window.location = { href: "" }; |
| 18 | }); |
| 19 | |
| 20 | afterEach(() => { |
| 21 | window.location = originalLocation; |
| 22 | delete window.prestoPlayer; |
| 23 | }); |
| 24 | |
| 25 | describe("useCompleteOnboarding", () => { |
| 26 | it("POSTs the completed status and redirects on success", async () => { |
| 27 | apiFetch.mockResolvedValueOnce({ ok: true }); |
| 28 | |
| 29 | const { result } = renderHook(() => useCompleteOnboarding()); |
| 30 | await act(async () => { |
| 31 | await result.current.completeOnboarding("admin.php?page=done"); |
| 32 | }); |
| 33 | |
| 34 | expect(apiFetch).toHaveBeenCalledWith({ |
| 35 | path: "/presto-player/v1/onboarding/set-status", |
| 36 | method: "POST", |
| 37 | data: { status: "completed" }, |
| 38 | }); |
| 39 | expect(window.location.href).toBe("admin.php?page=done"); |
| 40 | }); |
| 41 | |
| 42 | it("redirects even when the API call fails (best-effort completion)", async () => { |
| 43 | const errorSpy = jest |
| 44 | .spyOn(console, "error") |
| 45 | .mockImplementation(() => {}); |
| 46 | apiFetch.mockRejectedValueOnce(new Error("server")); |
| 47 | |
| 48 | const { result } = renderHook(() => useCompleteOnboarding()); |
| 49 | await act(async () => { |
| 50 | await result.current.completeOnboarding("admin.php?page=done"); |
| 51 | }); |
| 52 | |
| 53 | expect(window.location.href).toBe("admin.php?page=done"); |
| 54 | expect(errorSpy).toHaveBeenCalled(); |
| 55 | errorSpy.mockRestore(); |
| 56 | }); |
| 57 | |
| 58 | it("ignores re-entrant calls while a submission is in flight", async () => { |
| 59 | let resolveFetch; |
| 60 | apiFetch.mockReturnValueOnce( |
| 61 | new Promise((res) => { |
| 62 | resolveFetch = res; |
| 63 | }) |
| 64 | ); |
| 65 | |
| 66 | const { result } = renderHook(() => useCompleteOnboarding()); |
| 67 | |
| 68 | let firstPending; |
| 69 | act(() => { |
| 70 | firstPending = result.current.completeOnboarding("first"); |
| 71 | }); |
| 72 | |
| 73 | await act(async () => { |
| 74 | // Second call should short-circuit (no second apiFetch). |
| 75 | await result.current.completeOnboarding("second"); |
| 76 | }); |
| 77 | |
| 78 | expect(apiFetch).toHaveBeenCalledTimes(1); |
| 79 | |
| 80 | await act(async () => { |
| 81 | resolveFetch({ ok: true }); |
| 82 | await firstPending; |
| 83 | }); |
| 84 | |
| 85 | expect(window.location.href).toBe("first"); |
| 86 | }); |
| 87 | |
| 88 | it("blocks exit from another hook instance while a completion is in flight", async () => { |
| 89 | let resolveFetch; |
| 90 | apiFetch.mockReturnValueOnce( |
| 91 | new Promise((res) => { |
| 92 | resolveFetch = res; |
| 93 | }) |
| 94 | ); |
| 95 | |
| 96 | // Two instances, like the premium step's button and the topbar Exit. |
| 97 | const first = renderHook(() => useCompleteOnboarding()); |
| 98 | const second = renderHook(() => useCompleteOnboarding()); |
| 99 | |
| 100 | let completePending; |
| 101 | act(() => { |
| 102 | completePending = first.result.current.completeOnboarding("license-page"); |
| 103 | }); |
| 104 | |
| 105 | await act(async () => { |
| 106 | await second.result.current.exitOnboarding("premium_features"); |
| 107 | }); |
| 108 | |
| 109 | expect(apiFetch).toHaveBeenCalledTimes(1); |
| 110 | |
| 111 | await act(async () => { |
| 112 | resolveFetch({ ok: true }); |
| 113 | await completePending; |
| 114 | }); |
| 115 | |
| 116 | expect(window.location.href).toBe("license-page"); |
| 117 | }); |
| 118 | |
| 119 | describe("exitOnboarding", () => { |
| 120 | it("POSTs a skip with the step id and redirects to the dashboard", async () => { |
| 121 | window.prestoPlayer = { dashboardUrl: "admin.php?page=presto-dashboard&custom" }; |
| 122 | apiFetch.mockResolvedValueOnce({ ok: true }); |
| 123 | |
| 124 | const { result } = renderHook(() => useCompleteOnboarding()); |
| 125 | await act(async () => { |
| 126 | await result.current.exitOnboarding("premium_features"); |
| 127 | }); |
| 128 | |
| 129 | expect(apiFetch).toHaveBeenCalledWith({ |
| 130 | path: "/presto-player/v1/onboarding/set-status", |
| 131 | method: "POST", |
| 132 | data: { status: "skipped", skipped_on_step: "premium_features" }, |
| 133 | }); |
| 134 | expect(window.location.href).toBe("admin.php?page=presto-dashboard&custom"); |
| 135 | }); |
| 136 | |
| 137 | it("records a completion when exiting from the done step", async () => { |
| 138 | apiFetch.mockResolvedValueOnce({ ok: true }); |
| 139 | |
| 140 | const { result } = renderHook(() => useCompleteOnboarding()); |
| 141 | await act(async () => { |
| 142 | await result.current.exitOnboarding(null); |
| 143 | }); |
| 144 | |
| 145 | expect(apiFetch).toHaveBeenCalledWith({ |
| 146 | path: "/presto-player/v1/onboarding/set-status", |
| 147 | method: "POST", |
| 148 | data: { status: "completed" }, |
| 149 | }); |
| 150 | expect(window.location.href).toBe("admin.php?page=presto-dashboard"); |
| 151 | }); |
| 152 | |
| 153 | it("redirects even when the API call fails", async () => { |
| 154 | const errorSpy = jest |
| 155 | .spyOn(console, "error") |
| 156 | .mockImplementation(() => {}); |
| 157 | apiFetch.mockRejectedValueOnce(new Error("server")); |
| 158 | |
| 159 | const { result } = renderHook(() => useCompleteOnboarding()); |
| 160 | await act(async () => { |
| 161 | await result.current.exitOnboarding("welcome"); |
| 162 | }); |
| 163 | |
| 164 | expect(window.location.href).toBe("admin.php?page=presto-dashboard"); |
| 165 | errorSpy.mockRestore(); |
| 166 | }); |
| 167 | }); |
| 168 | }); |
| 169 |