UNPKG

@octopusdeploy/design-system-components

Version:
412 lines (411 loc) • 20.7 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const react_1 = require("@testing-library/react"); const react_2 = require("react"); const vitest_1 = require("vitest"); const useDialogSteps_1 = require("../useDialogSteps"); const threeSteps = [{}, {}, {}]; (0, vitest_1.describe)("useDialogSteps", () => { (0, vitest_1.describe)("initial state", () => { (0, vitest_1.test)("starts at step 0", () => { const { result } = (0, react_1.renderHook)(() => (0, useDialogSteps_1.useDialogSteps)(threeSteps)); (0, vitest_1.expect)(result.current.currentStepIndex).toBe(0); }); (0, vitest_1.test)("isFirstStep is true for step 0", () => { const { result } = (0, react_1.renderHook)(() => (0, useDialogSteps_1.useDialogSteps)(threeSteps)); (0, vitest_1.expect)(result.current.isFirstStep).toBe(true); }); (0, vitest_1.test)("isLastStep is false for first step", () => { const { result } = (0, react_1.renderHook)(() => (0, useDialogSteps_1.useDialogSteps)(threeSteps)); (0, vitest_1.expect)(result.current.isLastStep).toBe(false); }); (0, vitest_1.test)("totalSteps reflects step count", () => { const { result } = (0, react_1.renderHook)(() => (0, useDialogSteps_1.useDialogSteps)(threeSteps)); (0, vitest_1.expect)(result.current.totalSteps).toBe(3); }); (0, vitest_1.test)("isNavigating is false initially", () => { const { result } = (0, react_1.renderHook)(() => (0, useDialogSteps_1.useDialogSteps)(threeSteps)); (0, vitest_1.expect)(result.current.isNavigating).toBe(false); }); (0, vitest_1.test)("with empty steps, totalSteps is 0 and isLastStep is true", () => { const { result } = (0, react_1.renderHook)(() => (0, useDialogSteps_1.useDialogSteps)([])); (0, vitest_1.expect)(result.current.totalSteps).toBe(0); (0, vitest_1.expect)(result.current.isLastStep).toBe(true); (0, vitest_1.expect)(result.current.currentStepIndex).toBe(0); }); }); (0, vitest_1.describe)("goToNext", () => { (0, vitest_1.test)("moves to the next step", async () => { const { result } = (0, react_1.renderHook)(() => (0, useDialogSteps_1.useDialogSteps)(threeSteps)); await (0, react_2.act)(async () => { await result.current.goToNext(); }); (0, vitest_1.expect)(result.current.currentStepIndex).toBe(1); }); (0, vitest_1.test)("returns true when navigation succeeds", async () => { const { result } = (0, react_1.renderHook)(() => (0, useDialogSteps_1.useDialogSteps)(threeSteps)); let returnValue; await (0, react_2.act)(async () => { returnValue = await result.current.goToNext(); }); (0, vitest_1.expect)(returnValue).toBe(true); }); (0, vitest_1.test)("returns false when already on the last step", async () => { const { result } = (0, react_1.renderHook)(() => (0, useDialogSteps_1.useDialogSteps)(threeSteps)); await (0, react_2.act)(async () => { await result.current.goToNext(); }); await (0, react_2.act)(async () => { await result.current.goToNext(); }); let returnValue; await (0, react_2.act)(async () => { returnValue = await result.current.goToNext(); }); (0, vitest_1.expect)(returnValue).toBe(false); (0, vitest_1.expect)(result.current.currentStepIndex).toBe(2); }); (0, vitest_1.test)("isFirstStep becomes false after navigating forward", async () => { const { result } = (0, react_1.renderHook)(() => (0, useDialogSteps_1.useDialogSteps)(threeSteps)); await (0, react_2.act)(async () => { await result.current.goToNext(); }); (0, vitest_1.expect)(result.current.isFirstStep).toBe(false); }); (0, vitest_1.test)("isLastStep is true on the last step", async () => { const { result } = (0, react_1.renderHook)(() => (0, useDialogSteps_1.useDialogSteps)(threeSteps)); await (0, react_2.act)(async () => { await result.current.goToNext(); }); await (0, react_2.act)(async () => { await result.current.goToNext(); }); (0, vitest_1.expect)(result.current.isLastStep).toBe(true); }); (0, vitest_1.test)("navigation functions have stable references", async () => { const { result } = (0, react_1.renderHook)(() => (0, useDialogSteps_1.useDialogSteps)(threeSteps)); const { goToNext, goToPrevious, reset } = result.current; await (0, react_2.act)(async () => { await result.current.goToNext(); }); (0, vitest_1.expect)(result.current.goToNext).toBe(goToNext); (0, vitest_1.expect)(result.current.goToPrevious).toBe(goToPrevious); (0, vitest_1.expect)(result.current.reset).toBe(reset); }); }); (0, vitest_1.describe)("goToPrevious", () => { (0, vitest_1.test)("moves to the previous step", async () => { const { result } = (0, react_1.renderHook)(() => (0, useDialogSteps_1.useDialogSteps)(threeSteps)); await (0, react_2.act)(async () => { await result.current.goToNext(); }); await (0, react_2.act)(async () => { await result.current.goToPrevious(); }); (0, vitest_1.expect)(result.current.currentStepIndex).toBe(0); }); (0, vitest_1.test)("returns false when already on the first step", async () => { const { result } = (0, react_1.renderHook)(() => (0, useDialogSteps_1.useDialogSteps)(threeSteps)); let returnValue; await (0, react_2.act)(async () => { returnValue = await result.current.goToPrevious(); }); (0, vitest_1.expect)(returnValue).toBe(false); (0, vitest_1.expect)(result.current.currentStepIndex).toBe(0); }); (0, vitest_1.test)("returns true when navigation succeeds", async () => { const { result } = (0, react_1.renderHook)(() => (0, useDialogSteps_1.useDialogSteps)(threeSteps)); await (0, react_2.act)(async () => { await result.current.goToNext(); }); let returnValue; await (0, react_2.act)(async () => { returnValue = await result.current.goToPrevious(); }); (0, vitest_1.expect)(returnValue).toBe(true); }); (0, vitest_1.test)("isFirstStep becomes true after navigating back to step 0", async () => { const { result } = (0, react_1.renderHook)(() => (0, useDialogSteps_1.useDialogSteps)(threeSteps)); await (0, react_2.act)(async () => { await result.current.goToNext(); }); await (0, react_2.act)(async () => { await result.current.goToPrevious(); }); (0, vitest_1.expect)(result.current.isFirstStep).toBe(true); }); }); (0, vitest_1.describe)("reset", () => { (0, vitest_1.test)("returns to step 0 from a later step", async () => { const { result } = (0, react_1.renderHook)(() => (0, useDialogSteps_1.useDialogSteps)(threeSteps)); await (0, react_2.act)(async () => { await result.current.goToNext(); }); await (0, react_2.act)(async () => { await result.current.goToNext(); }); (0, react_2.act)(() => { result.current.reset(); }); (0, vitest_1.expect)(result.current.currentStepIndex).toBe(0); (0, vitest_1.expect)(result.current.isFirstStep).toBe(true); }); }); (0, vitest_1.describe)("onBeforeBack validation", () => { (0, vitest_1.test)("proceeds to previous step when onBeforeBack returns true", async () => { const steps = [{}, { onBeforeBack: async () => true }, {}]; const { result } = (0, react_1.renderHook)(() => (0, useDialogSteps_1.useDialogSteps)(steps)); await (0, react_2.act)(async () => { await result.current.goToNext(); }); await (0, react_2.act)(async () => { await result.current.goToPrevious(); }); (0, vitest_1.expect)(result.current.currentStepIndex).toBe(0); }); (0, vitest_1.test)("blocks navigation when onBeforeBack returns false", async () => { const steps = [{}, { onBeforeBack: async () => false }, {}]; const { result } = (0, react_1.renderHook)(() => (0, useDialogSteps_1.useDialogSteps)(steps)); await (0, react_2.act)(async () => { await result.current.goToNext(); }); let returnValue; await (0, react_2.act)(async () => { returnValue = await result.current.goToPrevious(); }); (0, vitest_1.expect)(returnValue).toBe(false); (0, vitest_1.expect)(result.current.currentStepIndex).toBe(1); }); (0, vitest_1.test)("blocks navigation when onBeforeBack throws", async () => { const steps = [ {}, { onBeforeBack: async () => { throw new Error("Save failed"); }, }, ]; const { result } = (0, react_1.renderHook)(() => (0, useDialogSteps_1.useDialogSteps)(steps)); await (0, react_2.act)(async () => { await result.current.goToNext(); }); await (0, react_2.act)(async () => { await result.current.goToPrevious(); }); (0, vitest_1.expect)(result.current.currentStepIndex).toBe(1); }); (0, vitest_1.test)("calls the onBeforeBack callback", async () => { const onBeforeBack = vitest_1.vi.fn().mockResolvedValue(true); const steps = [{}, { onBeforeBack }]; const { result } = (0, react_1.renderHook)(() => (0, useDialogSteps_1.useDialogSteps)(steps)); await (0, react_2.act)(async () => { await result.current.goToNext(); }); await (0, react_2.act)(async () => { await result.current.goToPrevious(); }); (0, vitest_1.expect)(onBeforeBack).toHaveBeenCalledTimes(1); }); (0, vitest_1.test)("isNavigating is false after async onBeforeBack completes", async () => { const steps = [{}, { onBeforeBack: async () => true }]; const { result } = (0, react_1.renderHook)(() => (0, useDialogSteps_1.useDialogSteps)(steps)); await (0, react_2.act)(async () => { await result.current.goToNext(); }); await (0, react_2.act)(async () => { await result.current.goToPrevious(); }); (0, vitest_1.expect)(result.current.isNavigating).toBe(false); }); (0, vitest_1.test)("isNavigating is false after onBeforeBack returns false", async () => { const steps = [{}, { onBeforeBack: async () => false }]; const { result } = (0, react_1.renderHook)(() => (0, useDialogSteps_1.useDialogSteps)(steps)); await (0, react_2.act)(async () => { await result.current.goToNext(); }); await (0, react_2.act)(async () => { await result.current.goToPrevious(); }); (0, vitest_1.expect)(result.current.isNavigating).toBe(false); }); (0, vitest_1.test)("isNavigating is false after onBeforeBack throws", async () => { const steps = [ {}, { onBeforeBack: async () => { throw new Error("Error"); }, }, ]; const { result } = (0, react_1.renderHook)(() => (0, useDialogSteps_1.useDialogSteps)(steps)); await (0, react_2.act)(async () => { await result.current.goToNext(); }); await (0, react_2.act)(async () => { await result.current.goToPrevious(); }); (0, vitest_1.expect)(result.current.isNavigating).toBe(false); }); }); (0, vitest_1.describe)("onEnter", () => { (0, vitest_1.test)("calls onEnter on the next step when navigating forward", async () => { const onEnter = vitest_1.vi.fn(); const steps = [{}, { onEnter }]; const { result } = (0, react_1.renderHook)(() => (0, useDialogSteps_1.useDialogSteps)(steps)); await (0, react_2.act)(async () => { await result.current.goToNext(); }); (0, vitest_1.expect)(onEnter).toHaveBeenCalledTimes(1); }); (0, vitest_1.test)("calls onEnter on the previous step when navigating back", async () => { const onEnter = vitest_1.vi.fn(); const steps = [{ onEnter }, {}, {}]; const { result } = (0, react_1.renderHook)(() => (0, useDialogSteps_1.useDialogSteps)(steps)); await (0, react_2.act)(async () => { await result.current.goToNext(); }); await (0, react_2.act)(async () => { await result.current.goToPrevious(); }); (0, vitest_1.expect)(onEnter).toHaveBeenCalledTimes(1); }); (0, vitest_1.test)("does not call onEnter on the departing step", async () => { const onEnter = vitest_1.vi.fn(); const steps = [{ onEnter }, {}]; const { result } = (0, react_1.renderHook)(() => (0, useDialogSteps_1.useDialogSteps)(steps)); await (0, react_2.act)(async () => { await result.current.goToNext(); }); (0, vitest_1.expect)(onEnter).not.toHaveBeenCalled(); }); (0, vitest_1.test)("onEnter is called after onBeforeNext succeeds", async () => { const callOrder = []; const steps = [ { onBeforeNext: async () => { callOrder.push("onBeforeNext"); return true; }, }, { onEnter: async () => { callOrder.push("onEnter"); }, }, ]; const { result } = (0, react_1.renderHook)(() => (0, useDialogSteps_1.useDialogSteps)(steps)); await (0, react_2.act)(async () => { await result.current.goToNext(); }); (0, vitest_1.expect)(callOrder).toEqual(["onBeforeNext", "onEnter"]); }); (0, vitest_1.test)("onEnter is not called when onBeforeNext blocks navigation", async () => { const onEnter = vitest_1.vi.fn(); const steps = [{ onBeforeNext: async () => false }, { onEnter }]; const { result } = (0, react_1.renderHook)(() => (0, useDialogSteps_1.useDialogSteps)(steps)); await (0, react_2.act)(async () => { await result.current.goToNext(); }); (0, vitest_1.expect)(onEnter).not.toHaveBeenCalled(); }); (0, vitest_1.test)("navigation still succeeds when onEnter throws", async () => { const steps = [ {}, { onEnter: async () => { throw new Error("Fetch failed"); }, }, ]; const { result } = (0, react_1.renderHook)(() => (0, useDialogSteps_1.useDialogSteps)(steps)); await (0, react_2.act)(async () => { await result.current.goToNext(); }); (0, vitest_1.expect)(result.current.currentStepIndex).toBe(1); }); (0, vitest_1.test)("supports async onEnter", async () => { const onEnter = vitest_1.vi.fn().mockResolvedValue(undefined); const steps = [{}, { onEnter }]; const { result } = (0, react_1.renderHook)(() => (0, useDialogSteps_1.useDialogSteps)(steps)); await (0, react_2.act)(async () => { await result.current.goToNext(); }); (0, vitest_1.expect)(onEnter).toHaveBeenCalledTimes(1); }); }); (0, vitest_1.describe)("onBeforeNext validation", () => { (0, vitest_1.test)("proceeds to next step when onBeforeNext returns true", async () => { const steps = [{ onBeforeNext: async () => true }, {}]; const { result } = (0, react_1.renderHook)(() => (0, useDialogSteps_1.useDialogSteps)(steps)); await (0, react_2.act)(async () => { await result.current.goToNext(); }); (0, vitest_1.expect)(result.current.currentStepIndex).toBe(1); }); (0, vitest_1.test)("blocks navigation when onBeforeNext returns false", async () => { const steps = [{ onBeforeNext: async () => false }, {}]; const { result } = (0, react_1.renderHook)(() => (0, useDialogSteps_1.useDialogSteps)(steps)); let returnValue; await (0, react_2.act)(async () => { returnValue = await result.current.goToNext(); }); (0, vitest_1.expect)(returnValue).toBe(false); (0, vitest_1.expect)(result.current.currentStepIndex).toBe(0); }); (0, vitest_1.test)("blocks navigation when onBeforeNext throws", async () => { const steps = [ { onBeforeNext: async () => { throw new Error("Validation failed"); }, }, {}, ]; const { result } = (0, react_1.renderHook)(() => (0, useDialogSteps_1.useDialogSteps)(steps)); await (0, react_2.act)(async () => { await result.current.goToNext(); }); (0, vitest_1.expect)(result.current.currentStepIndex).toBe(0); }); (0, vitest_1.test)("calls the onBeforeNext callback", async () => { const onBeforeNext = vitest_1.vi.fn().mockResolvedValue(true); const steps = [{ onBeforeNext }, {}]; const { result } = (0, react_1.renderHook)(() => (0, useDialogSteps_1.useDialogSteps)(steps)); await (0, react_2.act)(async () => { await result.current.goToNext(); }); (0, vitest_1.expect)(onBeforeNext).toHaveBeenCalledTimes(1); }); (0, vitest_1.test)("isNavigating is false after async onBeforeNext completes", async () => { const steps = [{ onBeforeNext: async () => true }, {}]; const { result } = (0, react_1.renderHook)(() => (0, useDialogSteps_1.useDialogSteps)(steps)); await (0, react_2.act)(async () => { await result.current.goToNext(); }); (0, vitest_1.expect)(result.current.isNavigating).toBe(false); }); (0, vitest_1.test)("isNavigating is false after onBeforeNext returns false", async () => { const steps = [{ onBeforeNext: async () => false }, {}]; const { result } = (0, react_1.renderHook)(() => (0, useDialogSteps_1.useDialogSteps)(steps)); await (0, react_2.act)(async () => { await result.current.goToNext(); }); (0, vitest_1.expect)(result.current.isNavigating).toBe(false); }); (0, vitest_1.test)("isNavigating is false after onBeforeNext throws", async () => { const steps = [ { onBeforeNext: async () => { throw new Error("Validation error"); }, }, {}, ]; const { result } = (0, react_1.renderHook)(() => (0, useDialogSteps_1.useDialogSteps)(steps)); await (0, react_2.act)(async () => { await result.current.goToNext(); }); (0, vitest_1.expect)(result.current.isNavigating).toBe(false); }); }); });