mirror of
https://github.com/kamranahmedse/driver.js.git
synced 2026-11-02 05:31:39 +08:00
216 lines
6.0 KiB
TypeScript
216 lines
6.0 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import { createDriver, nextFrame, popoverEl, popoverTitle, useDriverHarness } from "./utils";
|
|
|
|
useDriverHarness();
|
|
|
|
function tick(ms = 10): Promise<void> {
|
|
return new Promise(resolve => setTimeout(resolve, ms));
|
|
}
|
|
|
|
function appendElement(id: string): void {
|
|
const element = document.createElement("div");
|
|
element.id = id;
|
|
document.body.appendChild(element);
|
|
}
|
|
|
|
describe("waitForElement", () => {
|
|
it("stays on the current step until the next element appears", async () => {
|
|
const d = createDriver({
|
|
animate: false,
|
|
steps: [
|
|
{ element: "#intro", popover: { title: "Step 1" } },
|
|
{ element: "#late", waitForElement: 500, popover: { title: "Step 2" } },
|
|
],
|
|
});
|
|
d.drive();
|
|
d.moveNext();
|
|
|
|
expect(d.getActiveIndex()).toBe(0);
|
|
expect(popoverTitle()).toBe("Step 1");
|
|
|
|
appendElement("late");
|
|
await tick();
|
|
|
|
expect(d.getActiveIndex()).toBe(1);
|
|
expect(popoverTitle()).toBe("Step 2");
|
|
expect(d.getActiveElement()?.id).toBe("late");
|
|
});
|
|
|
|
it("hides the current popover while waiting", async () => {
|
|
const d = createDriver({
|
|
animate: false,
|
|
steps: [
|
|
{ element: "#intro", popover: { title: "Step 1" } },
|
|
{ element: "#late", waitForElement: 500, popover: { title: "Step 2" } },
|
|
],
|
|
});
|
|
d.drive();
|
|
d.moveNext();
|
|
|
|
expect(popoverEl()?.style.display).toBe("none");
|
|
expect(document.getElementById("intro")?.classList.contains("driver-active-element")).toBe(true);
|
|
|
|
appendElement("late");
|
|
await tick();
|
|
|
|
expect(popoverEl()?.style.display).toBe("block");
|
|
expect(popoverTitle()).toBe("Step 2");
|
|
});
|
|
|
|
it("shows the fallback popover when the wait times out", async () => {
|
|
const d = createDriver({
|
|
animate: false,
|
|
steps: [
|
|
{ element: "#intro", popover: { title: "Step 1" } },
|
|
{ element: "#never", waitForElement: 40, popover: { title: "Step 2" } },
|
|
],
|
|
});
|
|
d.drive();
|
|
d.moveNext();
|
|
expect(popoverEl()?.style.display).toBe("none");
|
|
|
|
await tick(80);
|
|
|
|
expect(popoverEl()?.style.display).toBe("block");
|
|
expect(popoverTitle()).toBe("Step 2");
|
|
});
|
|
|
|
it("waits for the first step's element on the initial drive", async () => {
|
|
const d = createDriver({
|
|
animate: false,
|
|
steps: [{ element: "#late", waitForElement: 500, popover: { title: "Step 1" } }],
|
|
});
|
|
d.drive();
|
|
expect(popoverTitle()).toBeUndefined();
|
|
|
|
appendElement("late");
|
|
await tick();
|
|
|
|
expect(d.getActiveIndex()).toBe(0);
|
|
expect(popoverTitle()).toBe("Step 1");
|
|
});
|
|
|
|
it("applies the driver-level waitForElement to every step", async () => {
|
|
const d = createDriver({
|
|
animate: false,
|
|
waitForElement: 500,
|
|
steps: [
|
|
{ element: "#intro", popover: { title: "Step 1" } },
|
|
{ element: "#late", popover: { title: "Step 2" } },
|
|
],
|
|
});
|
|
d.drive();
|
|
d.moveNext();
|
|
expect(d.getActiveIndex()).toBe(0);
|
|
|
|
appendElement("late");
|
|
await tick();
|
|
expect(d.getActiveIndex()).toBe(1);
|
|
});
|
|
|
|
it("falls back to the centered popover when the wait times out", async () => {
|
|
const d = createDriver({
|
|
animate: false,
|
|
steps: [
|
|
{ element: "#intro", popover: { title: "Step 1" } },
|
|
{ element: "#never", waitForElement: 40, popover: { title: "Step 2" } },
|
|
],
|
|
});
|
|
d.drive();
|
|
d.moveNext();
|
|
expect(popoverTitle()).toBe("Step 1");
|
|
|
|
await tick(80);
|
|
|
|
expect(d.getActiveIndex()).toBe(1);
|
|
expect(popoverTitle()).toBe("Step 2");
|
|
expect(d.getActiveElement()?.id).toBe("driver-dummy-element");
|
|
});
|
|
|
|
it("skips the step when the wait times out and skipMissingElement is set", async () => {
|
|
const d = createDriver({
|
|
animate: false,
|
|
skipMissingElement: true,
|
|
steps: [
|
|
{ element: "#intro", popover: { title: "Step 1" } },
|
|
{ element: "#never", waitForElement: 40, popover: { title: "Step 2" } },
|
|
{ element: "#card-1", popover: { title: "Step 3" } },
|
|
],
|
|
});
|
|
d.drive();
|
|
d.moveNext();
|
|
expect(popoverTitle()).toBe("Step 1");
|
|
|
|
await tick(80);
|
|
|
|
expect(d.getActiveIndex()).toBe(2);
|
|
expect(popoverTitle()).toBe("Step 3");
|
|
});
|
|
|
|
it("cancels a pending wait when the tour is destroyed", async () => {
|
|
const d = createDriver({
|
|
animate: false,
|
|
steps: [
|
|
{ element: "#intro", popover: { title: "Step 1" } },
|
|
{ element: "#late", waitForElement: 500, popover: { title: "Step 2" } },
|
|
],
|
|
});
|
|
d.drive();
|
|
d.moveNext();
|
|
d.destroy();
|
|
|
|
appendElement("late");
|
|
await tick();
|
|
|
|
expect(d.isActive()).toBe(false);
|
|
expect(popoverTitle()).toBeUndefined();
|
|
});
|
|
|
|
it("cancels a pending wait when navigating elsewhere", async () => {
|
|
const d = createDriver({
|
|
animate: false,
|
|
steps: [
|
|
{ element: "#intro", popover: { title: "Step 1" } },
|
|
{ element: "#late", waitForElement: 500, popover: { title: "Step 2" } },
|
|
{ element: "#card-1", popover: { title: "Step 3" } },
|
|
],
|
|
});
|
|
d.drive();
|
|
d.moveNext();
|
|
d.moveTo(2);
|
|
expect(popoverTitle()).toBe("Step 3");
|
|
|
|
appendElement("late");
|
|
await tick();
|
|
|
|
expect(d.getActiveIndex()).toBe(2);
|
|
expect(popoverTitle()).toBe("Step 3");
|
|
});
|
|
|
|
it("advances through a click-driven step into a waiting step", async () => {
|
|
document.querySelector("#card-1")?.addEventListener("click", () => {
|
|
setTimeout(() => appendElement("modal"), 20);
|
|
});
|
|
|
|
const d = createDriver({
|
|
animate: false,
|
|
steps: [
|
|
{ element: "#card-1", advanceOnClick: true, popover: { title: "Step 1" } },
|
|
{ element: "#modal", waitForElement: 500, popover: { title: "Step 2" } },
|
|
],
|
|
});
|
|
d.drive();
|
|
await nextFrame();
|
|
|
|
document.querySelector("#card-1")?.dispatchEvent(new MouseEvent("click", { bubbles: true, cancelable: true }));
|
|
expect(d.getActiveIndex()).toBe(0);
|
|
expect(popoverTitle()).toBe("Step 1");
|
|
|
|
await tick(60);
|
|
|
|
expect(d.getActiveIndex()).toBe(1);
|
|
expect(popoverTitle()).toBe("Step 2");
|
|
expect(d.getActiveElement()?.id).toBe("modal");
|
|
});
|
|
});
|