From 4b56bb194cfdd2a90a48ee1be50f7e2d97967cb0 Mon Sep 17 00:00:00 2001 From: PelayoFelgueroso Date: Tue, 20 Oct 2026 17:04:00 +0200 Subject: [PATCH 1/3] Change "skip" to "Skip tour" at the Welcome Dialog --- apps/website/screens/theme-generator/components/Tour/Tour.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/website/screens/theme-generator/components/Tour/Tour.tsx b/apps/website/screens/theme-generator/components/Tour/Tour.tsx index 3c17f3719..2c083491c 100644 --- a/apps/website/screens/theme-generator/components/Tour/Tour.tsx +++ b/apps/website/screens/theme-generator/components/Tour/Tour.tsx @@ -261,7 +261,7 @@ const Tour = ({ currentStep, onTourStepIndexChange }: TourProps) => { setDialogVisible(false)} From 44bae90c1e2bc85b141cb44f197829051de25390 Mon Sep 17 00:00:00 2001 From: PelayoFelgueroso Date: Mon, 9 Nov 2026 12:26:31 +0100 Subject: [PATCH 2/3] add take a tour tests --- .../test/theme-generator/Tour.test.tsx | 304 ++++++++++++++++++ 1 file changed, 304 insertions(+) create mode 100644 apps/website/test/theme-generator/Tour.test.tsx diff --git a/apps/website/test/theme-generator/Tour.test.tsx b/apps/website/test/theme-generator/Tour.test.tsx new file mode 100644 index 000000000..e5cc0a96b --- /dev/null +++ b/apps/website/test/theme-generator/Tour.test.tsx @@ -0,0 +1,304 @@ +import type { ComponentType, ReactNode } from "react"; +import { act, fireEvent, render, screen } from "@testing-library/react"; +import "@testing-library/jest-dom"; +import { useRouter } from "next/router"; +import Tour from "../../screens/theme-generator/components/Tour/Tour"; +import type { TourPopoverProps } from "../../screens/theme-generator/components/Tour/types"; + +jest.mock("next/router", () => ({ useRouter: jest.fn() })); + +type MockEvent = { type?: string; action?: string; status?: string; index?: number }; +type MockTooltipProps = Omit; +type MockJoyrideProps = { + run: boolean; + stepIndex: number; + steps: { title?: string; content?: ReactNode; target: string }[]; + onEvent: (event: MockEvent) => void; + tooltipComponent: ComponentType; +}; +type JoyrideMockModule = { __state: { last: MockJoyrideProps | undefined } }; + +// Minimal Joyride stand-in: it records the latest props and renders the custom tooltip for the +// current step. Popover controls emit the same events the real library emits (next/prev/skip). +jest.mock("react-joyride", () => { + const { createElement } = jest.requireActual("react"); + const joyrideState: { last: MockJoyrideProps | undefined } = { last: undefined }; + const EVENTS = { STEP_AFTER: "step:after" }; + const ACTIONS = { NEXT: "next", PREV: "prev", SKIP: "skip" }; + const STATUS = { FINISHED: "finished", SKIPPED: "skipped", PAUSED: "paused", RUNNING: "running" }; + + return { + __state: joyrideState, + ACTIONS: { CLOSE: "close", ...ACTIONS }, + EVENTS, + STATUS, + Joyride: (props: MockJoyrideProps) => { + joyrideState.last = props; + const step = props.steps[props.stepIndex]; + if (!props.run || !step) { + return null; + } + const controls = { + next: () => + props.onEvent({ + type: EVENTS.STEP_AFTER, + action: ACTIONS.NEXT, + index: props.stepIndex, + status: STATUS.RUNNING, + }), + prev: () => + props.onEvent({ + type: EVENTS.STEP_AFTER, + action: ACTIONS.PREV, + index: props.stepIndex, + status: STATUS.RUNNING, + }), + skip: () => + props.onEvent({ type: "tour:end", action: ACTIONS.SKIP, index: props.stepIndex, status: STATUS.SKIPPED }), + }; + return createElement(props.tooltipComponent, { + step, + index: props.stepIndex, + size: props.steps.length, + isLastStep: props.stepIndex === props.steps.length - 1, + controls, + tooltipProps: { "aria-modal": true, role: "dialog" }, + }); + }, + }; +}); + +const joyrideState = jest.requireMock("react-joyride").__state; +const currentProps = (): MockJoyrideProps => { + if (!joyrideState.last) { + throw new Error("Joyride has not rendered yet"); + } + return joyrideState.last; +}; + +const mockUseRouter = useRouter as unknown as jest.Mock; +const routerReplace = jest.fn(); +const onTourStepIndexChange = jest.fn(); + +const SECTIONS = [ + { section: 0, title: "The 3-Step Journey" }, + { section: 1, title: "Preview theme" }, + { section: 2, title: "Review theme" }, +] as const; + +const renderTour = ({ currentStep = 0, welcome = false }: { currentStep?: number; welcome?: boolean } = {}) => { + mockUseRouter.mockReturnValue({ query: welcome ? { tour: "true" } : {}, replace: routerReplace }); + return render(); +}; + +const emitEvent = (event: MockEvent) => { + act(() => { + currentProps().onEvent(event); + }); +}; + +const goToNextStep = (index: number) => emitEvent({ type: "step:after", action: "next", index, status: "running" }); + +const goToPrevStep = (index: number) => emitEvent({ type: "step:after", action: "prev", index, status: "running" }); + +const startTour = () => fireEvent.click(screen.getByRole("button", { name: "Get Started!" })); + +const WELCOME_TITLE = "Welcome to Halstack Theme Generator"; + +beforeEach(() => { + jest.clearAllMocks(); + joyrideState.last = undefined; + mockUseRouter.mockReturnValue({ query: {}, replace: routerReplace }); +}); + +describe("Tour", () => { + describe("welcome dialog", () => { + it("does not show the welcome dialog or run the tour without the tour query parameter", () => { + renderTour(); + + expect(screen.queryByText(WELCOME_TITLE)).not.toBeInTheDocument(); + expect(currentProps().run).toBe(false); + }); + + it("opens the welcome dialog from the Take a tour URL and removes the query parameter", () => { + renderTour({ welcome: true }); + + expect(screen.getByText(WELCOME_TITLE)).toBeInTheDocument(); + expect(routerReplace).toHaveBeenCalledWith("/theme-generator/configuration", undefined, { shallow: true }); + expect(currentProps().run).toBe(false); + }); + + it("closes the welcome dialog with Skip tour without starting the tour", () => { + renderTour({ welcome: true }); + fireEvent.click(screen.getByRole("button", { name: "Skip tour" })); + + expect(screen.queryByText(WELCOME_TITLE)).not.toBeInTheDocument(); + expect(currentProps().run).toBe(false); + }); + + it("closes the welcome dialog with its close button without starting the tour", () => { + renderTour({ welcome: true }); + fireEvent.click(screen.getByRole("button", { name: "Close dialog" })); + + expect(screen.queryByText(WELCOME_TITLE)).not.toBeInTheDocument(); + expect(currentProps().run).toBe(false); + }); + + it("closes the welcome dialog when the tour starts", () => { + renderTour({ welcome: true }); + startTour(); + + expect(screen.queryByText(WELCOME_TITLE)).not.toBeInTheDocument(); + expect(currentProps().run).toBe(true); + }); + }); + + describe("starting a section", () => { + it.each(SECTIONS)("starts section $section at its first step", ({ section, title }) => { + renderTour({ currentStep: section, welcome: true }); + startTour(); + + expect(currentProps().run).toBe(true); + expect(currentProps().stepIndex).toBe(0); + expect(screen.getByText(title)).toBeInTheDocument(); + expect(screen.getByText("1 / 3")).toBeInTheDocument(); + }); + + it("does not start the following section when the welcome dialog was skipped", () => { + const { rerender } = renderTour({ welcome: true }); + fireEvent.click(screen.getByRole("button", { name: "Skip tour" })); + + rerender(); + expect(currentProps().run).toBe(false); + }); + }); + + describe("navigation", () => { + it("moves forward and back through the steps and reports the index", () => { + renderTour({ welcome: true }); + startTour(); + + goToNextStep(0); + expect(currentProps().stepIndex).toBe(1); + expect(onTourStepIndexChange).toHaveBeenLastCalledWith(1); + expect(screen.getByText("2 / 3")).toBeInTheDocument(); + + goToPrevStep(1); + expect(currentProps().stepIndex).toBe(0); + expect(onTourStepIndexChange).toHaveBeenLastCalledWith(0); + }); + + it("ignores step events with other actions", () => { + renderTour({ welcome: true }); + startTour(); + onTourStepIndexChange.mockClear(); + + emitEvent({ type: "step:after", action: "update", index: 0 }); + emitEvent({ type: "tour:start", action: "start", index: 0 }); + + expect(onTourStepIndexChange).not.toHaveBeenCalled(); + expect(currentProps().stepIndex).toBe(0); + }); + + it("shows Skip step and the navigation controls on non-final steps", () => { + renderTour({ welcome: true }); + startTour(); + + expect(screen.getByRole("button", { name: "Skip step" })).toBeInTheDocument(); + expect(screen.queryByRole("button", { name: "Got it!" })).not.toBeInTheDocument(); + }); + }); + + describe("ending a section", () => { + it.each(["finished", "skipped", "paused"])("stops the tour when the status is %s", (status) => { + renderTour({ welcome: true }); + startTour(); + emitEvent({ status, action: "next", index: 0, type: "tour:end" }); + + expect(currentProps().run).toBe(false); + }); + + it("stops the tour when the popover is closed", () => { + renderTour({ welcome: true }); + startTour(); + emitEvent({ action: "close", status: "running", index: 0, type: "tour:end" }); + + expect(currentProps().run).toBe(false); + }); + + it("stops the tour when Skip step is clicked", () => { + renderTour({ welcome: true }); + startTour(); + fireEvent.click(screen.getByRole("button", { name: "Skip step" })); + + expect(currentProps().run).toBe(false); + }); + + it("finishes the tour from the last step with Got it!", () => { + renderTour({ welcome: true }); + startTour(); + goToNextStep(0); + goToNextStep(1); + + expect(screen.getByText("Upload assets")).toBeInTheDocument(); + expect(screen.queryByRole("button", { name: "Skip step" })).not.toBeInTheDocument(); + fireEvent.click(screen.getByRole("button", { name: "Got it!" })); + + expect(currentProps().run).toBe(false); + }); + }); + + describe("restarting a section", () => { + beforeEach(() => { + jest.useFakeTimers(); + }); + + afterEach(() => { + jest.useRealTimers(); + }); + + it("restarts the current section from its first step after a short delay", () => { + renderTour({ welcome: true }); + startTour(); + goToNextStep(0); + goToNextStep(1); + onTourStepIndexChange.mockClear(); + + fireEvent.click(screen.getByRole("button", { name: "Restart" })); + + expect(currentProps().run).toBe(false); + expect(currentProps().stepIndex).toBe(0); + expect(onTourStepIndexChange).toHaveBeenLastCalledWith(0); + + act(() => { + jest.advanceTimersByTime(100); + }); + expect(currentProps().run).toBe(true); + expect(currentProps().stepIndex).toBe(0); + }); + }); + + describe("moving between sections", () => { + it("starts the next section automatically after the current one finishes", () => { + const { rerender } = renderTour({ welcome: true }); + startTour(); + emitEvent({ status: "finished", action: "next", index: 2, type: "tour:end" }); + expect(currentProps().run).toBe(false); + + rerender(); + + expect(currentProps().run).toBe(true); + expect(currentProps().stepIndex).toBe(0); + expect(screen.getByText("Preview theme")).toBeInTheDocument(); + }); + + it("does not start the next section again after the last section ends", () => { + const { rerender } = renderTour({ currentStep: 2, welcome: true }); + startTour(); + emitEvent({ status: "finished", action: "next", index: 2, type: "tour:end" }); + + rerender(); + expect(currentProps().run).toBe(false); + }); + }); +}); From 88d2da0df0a3bfef7e5b2a7b6f097f8771a80ad9 Mon Sep 17 00:00:00 2001 From: PelayoFelgueroso Date: Mon, 9 Nov 2026 16:56:11 +0100 Subject: [PATCH 3/3] fix file structure --- .../test/theme-generator/Tour.test.tsx | 266 +++++++++--------- 1 file changed, 129 insertions(+), 137 deletions(-) diff --git a/apps/website/test/theme-generator/Tour.test.tsx b/apps/website/test/theme-generator/Tour.test.tsx index e5cc0a96b..e847b0e56 100644 --- a/apps/website/test/theme-generator/Tour.test.tsx +++ b/apps/website/test/theme-generator/Tour.test.tsx @@ -5,6 +5,12 @@ import { useRouter } from "next/router"; import Tour from "../../screens/theme-generator/components/Tour/Tour"; import type { TourPopoverProps } from "../../screens/theme-generator/components/Tour/types"; +global.ResizeObserver = class ResizeObserver { + observe() {} + unobserve() {} + disconnect() {} +}; + jest.mock("next/router", () => ({ useRouter: jest.fn() })); type MockEvent = { type?: string; action?: string; status?: string; index?: number }; @@ -18,8 +24,6 @@ type MockJoyrideProps = { }; type JoyrideMockModule = { __state: { last: MockJoyrideProps | undefined } }; -// Minimal Joyride stand-in: it records the latest props and renders the custom tooltip for the -// current step. Popover controls emit the same events the real library emits (next/prev/skip). jest.mock("react-joyride", () => { const { createElement } = jest.requireActual("react"); const joyrideState: { last: MockJoyrideProps | undefined } = { last: undefined }; @@ -86,9 +90,13 @@ const SECTIONS = [ { section: 2, title: "Review theme" }, ] as const; +const tourElement = (currentStep: number) => ( + +); + const renderTour = ({ currentStep = 0, welcome = false }: { currentStep?: number; welcome?: boolean } = {}) => { mockUseRouter.mockReturnValue({ query: welcome ? { tour: "true" } : {}, replace: routerReplace }); - return render(); + return render(tourElement(currentStep)); }; const emitEvent = (event: MockEvent) => { @@ -97,12 +105,20 @@ const emitEvent = (event: MockEvent) => { }); }; -const goToNextStep = (index: number) => emitEvent({ type: "step:after", action: "next", index, status: "running" }); +const emitStepAfter = (action: string, index: number) => + emitEvent({ type: "step:after", action, index, status: "running" }); -const goToPrevStep = (index: number) => emitEvent({ type: "step:after", action: "prev", index, status: "running" }); +const goToNextStep = (index: number) => emitStepAfter("next", index); + +const goToPrevStep = (index: number) => emitStepAfter("prev", index); const startTour = () => fireEvent.click(screen.getByRole("button", { name: "Get Started!" })); +const startTourFromWelcome = () => { + renderTour({ welcome: true }); + startTour(); +}; + const WELCOME_TITLE = "Welcome to Halstack Theme Generator"; beforeEach(() => { @@ -112,154 +128,130 @@ beforeEach(() => { }); describe("Tour", () => { - describe("welcome dialog", () => { - it("does not show the welcome dialog or run the tour without the tour query parameter", () => { - renderTour(); + it("does not show the welcome dialog or run the tour without the tour query parameter", () => { + renderTour(); - expect(screen.queryByText(WELCOME_TITLE)).not.toBeInTheDocument(); - expect(currentProps().run).toBe(false); - }); + expect(screen.queryByText(WELCOME_TITLE)).not.toBeInTheDocument(); + expect(currentProps().run).toBe(false); + }); - it("opens the welcome dialog from the Take a tour URL and removes the query parameter", () => { - renderTour({ welcome: true }); + it("opens the welcome dialog from the Take a tour URL and removes the query parameter", () => { + renderTour({ welcome: true }); - expect(screen.getByText(WELCOME_TITLE)).toBeInTheDocument(); - expect(routerReplace).toHaveBeenCalledWith("/theme-generator/configuration", undefined, { shallow: true }); - expect(currentProps().run).toBe(false); - }); + expect(screen.getByText(WELCOME_TITLE)).toBeInTheDocument(); + expect(routerReplace).toHaveBeenCalledWith("/theme-generator/configuration", undefined, { shallow: true }); + expect(currentProps().run).toBe(false); + }); - it("closes the welcome dialog with Skip tour without starting the tour", () => { - renderTour({ welcome: true }); - fireEvent.click(screen.getByRole("button", { name: "Skip tour" })); + it("closes the welcome dialog with Skip tour without starting the tour", () => { + renderTour({ welcome: true }); + fireEvent.click(screen.getByRole("button", { name: "Skip tour" })); - expect(screen.queryByText(WELCOME_TITLE)).not.toBeInTheDocument(); - expect(currentProps().run).toBe(false); - }); + expect(screen.queryByText(WELCOME_TITLE)).not.toBeInTheDocument(); + expect(currentProps().run).toBe(false); + }); - it("closes the welcome dialog with its close button without starting the tour", () => { - renderTour({ welcome: true }); - fireEvent.click(screen.getByRole("button", { name: "Close dialog" })); + it("closes the welcome dialog with its close button without starting the tour", () => { + renderTour({ welcome: true }); + fireEvent.click(screen.getByRole("button", { name: "Close dialog" })); - expect(screen.queryByText(WELCOME_TITLE)).not.toBeInTheDocument(); - expect(currentProps().run).toBe(false); - }); + expect(screen.queryByText(WELCOME_TITLE)).not.toBeInTheDocument(); + expect(currentProps().run).toBe(false); + }); - it("closes the welcome dialog when the tour starts", () => { - renderTour({ welcome: true }); - startTour(); + it("closes the welcome dialog when the tour starts", () => { + startTourFromWelcome(); - expect(screen.queryByText(WELCOME_TITLE)).not.toBeInTheDocument(); - expect(currentProps().run).toBe(true); - }); + expect(screen.queryByText(WELCOME_TITLE)).not.toBeInTheDocument(); + expect(currentProps().run).toBe(true); }); - describe("starting a section", () => { - it.each(SECTIONS)("starts section $section at its first step", ({ section, title }) => { - renderTour({ currentStep: section, welcome: true }); - startTour(); + it.each(SECTIONS)("starts section $section at its first step", ({ section, title }) => { + renderTour({ currentStep: section, welcome: true }); + startTour(); - expect(currentProps().run).toBe(true); - expect(currentProps().stepIndex).toBe(0); - expect(screen.getByText(title)).toBeInTheDocument(); - expect(screen.getByText("1 / 3")).toBeInTheDocument(); - }); + expect(currentProps().run).toBe(true); + expect(currentProps().stepIndex).toBe(0); + expect(screen.getByText(title)).toBeInTheDocument(); + expect(screen.getByText("1 / 3")).toBeInTheDocument(); + }); - it("does not start the following section when the welcome dialog was skipped", () => { - const { rerender } = renderTour({ welcome: true }); - fireEvent.click(screen.getByRole("button", { name: "Skip tour" })); + it("does not start the following section when the welcome dialog was skipped", () => { + const { rerender } = renderTour({ welcome: true }); + fireEvent.click(screen.getByRole("button", { name: "Skip tour" })); - rerender(); - expect(currentProps().run).toBe(false); - }); + rerender(tourElement(1)); + expect(currentProps().run).toBe(false); }); - describe("navigation", () => { - it("moves forward and back through the steps and reports the index", () => { - renderTour({ welcome: true }); - startTour(); + it("moves forward and back through the steps and reports the index", () => { + startTourFromWelcome(); - goToNextStep(0); - expect(currentProps().stepIndex).toBe(1); - expect(onTourStepIndexChange).toHaveBeenLastCalledWith(1); - expect(screen.getByText("2 / 3")).toBeInTheDocument(); + goToNextStep(0); + expect(currentProps().stepIndex).toBe(1); + expect(onTourStepIndexChange).toHaveBeenLastCalledWith(1); + expect(screen.getByText("2 / 3")).toBeInTheDocument(); - goToPrevStep(1); - expect(currentProps().stepIndex).toBe(0); - expect(onTourStepIndexChange).toHaveBeenLastCalledWith(0); - }); + goToPrevStep(1); + expect(currentProps().stepIndex).toBe(0); + expect(onTourStepIndexChange).toHaveBeenLastCalledWith(0); + }); - it("ignores step events with other actions", () => { - renderTour({ welcome: true }); - startTour(); - onTourStepIndexChange.mockClear(); + it("ignores step events with other actions", () => { + startTourFromWelcome(); + onTourStepIndexChange.mockClear(); - emitEvent({ type: "step:after", action: "update", index: 0 }); - emitEvent({ type: "tour:start", action: "start", index: 0 }); + emitEvent({ type: "step:after", action: "update", index: 0 }); + emitEvent({ type: "tour:start", action: "start", index: 0 }); - expect(onTourStepIndexChange).not.toHaveBeenCalled(); - expect(currentProps().stepIndex).toBe(0); - }); + expect(onTourStepIndexChange).not.toHaveBeenCalled(); + expect(currentProps().stepIndex).toBe(0); + }); - it("shows Skip step and the navigation controls on non-final steps", () => { - renderTour({ welcome: true }); - startTour(); + it("shows Skip step and the navigation controls on non-final steps", () => { + startTourFromWelcome(); - expect(screen.getByRole("button", { name: "Skip step" })).toBeInTheDocument(); - expect(screen.queryByRole("button", { name: "Got it!" })).not.toBeInTheDocument(); - }); + expect(screen.getByRole("button", { name: "Skip step" })).toBeInTheDocument(); + expect(screen.queryByRole("button", { name: "Got it!" })).not.toBeInTheDocument(); }); - describe("ending a section", () => { - it.each(["finished", "skipped", "paused"])("stops the tour when the status is %s", (status) => { - renderTour({ welcome: true }); - startTour(); - emitEvent({ status, action: "next", index: 0, type: "tour:end" }); + it.each(["finished", "skipped", "paused"])("stops the tour when the status is %s", (status) => { + startTourFromWelcome(); + emitEvent({ status, action: "next", index: 0, type: "tour:end" }); - expect(currentProps().run).toBe(false); - }); + expect(currentProps().run).toBe(false); + }); - it("stops the tour when the popover is closed", () => { - renderTour({ welcome: true }); - startTour(); - emitEvent({ action: "close", status: "running", index: 0, type: "tour:end" }); + it("stops the tour when the popover is closed", () => { + startTourFromWelcome(); + emitEvent({ action: "close", status: "running", index: 0, type: "tour:end" }); - expect(currentProps().run).toBe(false); - }); + expect(currentProps().run).toBe(false); + }); - it("stops the tour when Skip step is clicked", () => { - renderTour({ welcome: true }); - startTour(); - fireEvent.click(screen.getByRole("button", { name: "Skip step" })); + it("stops the tour when Skip step is clicked", () => { + startTourFromWelcome(); + fireEvent.click(screen.getByRole("button", { name: "Skip step" })); - expect(currentProps().run).toBe(false); - }); + expect(currentProps().run).toBe(false); + }); - it("finishes the tour from the last step with Got it!", () => { - renderTour({ welcome: true }); - startTour(); - goToNextStep(0); - goToNextStep(1); + it("finishes the tour from the last step with Got it!", () => { + startTourFromWelcome(); + goToNextStep(0); + goToNextStep(1); - expect(screen.getByText("Upload assets")).toBeInTheDocument(); - expect(screen.queryByRole("button", { name: "Skip step" })).not.toBeInTheDocument(); - fireEvent.click(screen.getByRole("button", { name: "Got it!" })); + expect(screen.getByText("Upload assets")).toBeInTheDocument(); + expect(screen.queryByRole("button", { name: "Skip step" })).not.toBeInTheDocument(); + fireEvent.click(screen.getByRole("button", { name: "Got it!" })); - expect(currentProps().run).toBe(false); - }); + expect(currentProps().run).toBe(false); }); - describe("restarting a section", () => { - beforeEach(() => { - jest.useFakeTimers(); - }); - - afterEach(() => { - jest.useRealTimers(); - }); - - it("restarts the current section from its first step after a short delay", () => { - renderTour({ welcome: true }); - startTour(); + it("restarts the current section from its first step after a short delay", () => { + jest.useFakeTimers(); + try { + startTourFromWelcome(); goToNextStep(0); goToNextStep(1); onTourStepIndexChange.mockClear(); @@ -275,30 +267,30 @@ describe("Tour", () => { }); expect(currentProps().run).toBe(true); expect(currentProps().stepIndex).toBe(0); - }); + } finally { + jest.useRealTimers(); + } }); - describe("moving between sections", () => { - it("starts the next section automatically after the current one finishes", () => { - const { rerender } = renderTour({ welcome: true }); - startTour(); - emitEvent({ status: "finished", action: "next", index: 2, type: "tour:end" }); - expect(currentProps().run).toBe(false); + it("starts the next section automatically after the current one finishes", () => { + const { rerender } = renderTour({ welcome: true }); + startTour(); + emitEvent({ status: "finished", action: "next", index: 2, type: "tour:end" }); + expect(currentProps().run).toBe(false); - rerender(); + rerender(tourElement(1)); - expect(currentProps().run).toBe(true); - expect(currentProps().stepIndex).toBe(0); - expect(screen.getByText("Preview theme")).toBeInTheDocument(); - }); + expect(currentProps().run).toBe(true); + expect(currentProps().stepIndex).toBe(0); + expect(screen.getByText("Preview theme")).toBeInTheDocument(); + }); - it("does not start the next section again after the last section ends", () => { - const { rerender } = renderTour({ currentStep: 2, welcome: true }); - startTour(); - emitEvent({ status: "finished", action: "next", index: 2, type: "tour:end" }); + it("does not start the next section again after the last section ends", () => { + const { rerender } = renderTour({ currentStep: 2, welcome: true }); + startTour(); + emitEvent({ status: "finished", action: "next", index: 2, type: "tour:end" }); - rerender(); - expect(currentProps().run).toBe(false); - }); + rerender(tourElement(2)); + expect(currentProps().run).toBe(false); }); });