@octopusdeploy/design-system-components
Version:
The design systems component library.
412 lines (411 loc) • 20.7 kB
JavaScript
;
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);
});
});
});