Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplify fetchIntroSteps and add tests #2043

Merged
merged 2 commits into from
Apr 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 25 additions & 41 deletions src/core/fetchIntroSteps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,6 @@ export default function fetchIntroSteps(
intro: IntroJs,
targetElm: HTMLElement
) {
const allIntroSteps: HTMLElement[] = Array.from(
targetElm.querySelectorAll("*[data-intro]")
);
let introItems: IntroStep[] = [];

if (intro._options.steps && intro._options.steps.length) {
Expand Down Expand Up @@ -69,56 +66,51 @@ export default function fetchIntroSteps(
}
}
} else {
//use steps from data-* annotations
const elmsLength = allIntroSteps.length;
let disableInteraction: boolean;
const elements: HTMLElement[] = Array.from(
targetElm.querySelectorAll("*[data-intro]")
);

//if there's no element to intro
if (elmsLength < 1) {
if (elements.length < 1) {
return [];
}

const itemsWithoutStep: IntroStep[] = [];

for (const currentElement of allIntroSteps) {
for (const element of elements) {
// start intro for groups of elements
if (
intro._options.group &&
currentElement.getAttribute("data-intro-group") !== intro._options.group
element.getAttribute("data-intro-group") !== intro._options.group
) {
continue;
}

// skip hidden elements
if (currentElement.style.display === "none") {
if (element.style.display === "none") {
continue;
}

// get the step for the current element or set as 0 if is not present
const step = parseInt(
currentElement.getAttribute("data-step") || "0",
10
);

disableInteraction = intro._options.disableInteraction;
if (currentElement.hasAttribute("data-disable-interaction")) {
disableInteraction = !!currentElement.getAttribute(
"data-disable-interaction"
);
const step = parseInt(element.getAttribute("data-step") || "0", 10);

let disableInteraction = intro._options.disableInteraction;
if (element.hasAttribute("data-disable-interaction")) {
disableInteraction = !!element.getAttribute("data-disable-interaction");
}

const newIntroStep: IntroStep = {
step: step,
element: currentElement,
title: currentElement.getAttribute("data-title") || "",
intro: currentElement.getAttribute("data-intro") || "",
tooltipClass:
currentElement.getAttribute("data-tooltip-class") || undefined,
step,
element,
title: element.getAttribute("data-title") || "",
intro: element.getAttribute("data-intro") || "",
tooltipClass: element.getAttribute("data-tooltip-class") || undefined,
highlightClass:
currentElement.getAttribute("data-highlight-class") || undefined,
position: (currentElement.getAttribute("data-position") ||
element.getAttribute("data-highlight-class") || undefined,
position: (element.getAttribute("data-position") ||
intro._options.tooltipPosition) as TooltipPosition,
scrollTo:
(currentElement.getAttribute("data-scroll-to") as ScrollTo) ||
(element.getAttribute("data-scroll-to") as ScrollTo) ||
intro._options.scrollTo,
disableInteraction,
};
Expand All @@ -130,7 +122,7 @@ export default function fetchIntroSteps(
}
}

//fill items without step in blanks and update their step
// fill items without step in blanks and update their step
for (let i = 0; itemsWithoutStep.length > 0; i++) {
if (typeof introItems[i] === "undefined") {
const newStep = itemsWithoutStep.shift();
Expand All @@ -142,18 +134,10 @@ export default function fetchIntroSteps(
}
}

//removing undefined/null elements
const tempIntroItems = [];
for (let z = 0; z < introItems.length; z++) {
if (introItems[z]) {
// copy non-falsy values to the end of the array
tempIntroItems.push(introItems[z]);
}
}

introItems = tempIntroItems;
// removing undefined/null elements
introItems = introItems.filter((n) => n);

//Ok, sort all items with given steps
// Sort all items with given steps
introItems.sort((a, b) => a.step - b.step);

return introItems;
Expand Down
1 change: 0 additions & 1 deletion src/util/cloneObject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ export default function cloneObject<T>(source: T): T {
const temp = {} as T;

for (const key in source) {
// @ts-ignore:next-line
if (
"jQuery" in window &&
window.jQuery &&
Expand Down
62 changes: 62 additions & 0 deletions tests/jest/core/fetchIntroSteps.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ import fetchIntroSteps from "../../../src/core/fetchIntroSteps";

describe("fetchIntroSteps", () => {
test("should add floating element from options.steps to the list", () => {
// Arrange
const targetElement = document.createElement("div");

// Act
const steps = fetchIntroSteps(
{
_options: {
Expand All @@ -22,6 +24,7 @@ describe("fetchIntroSteps", () => {
targetElement
);

// Assert
expect(steps.length).toBe(2);

expect(steps[0].position).toBe("floating");
Expand All @@ -34,6 +37,7 @@ describe("fetchIntroSteps", () => {
});

test("should find and add elements from options.steps to the list", () => {
// Arrange
const targetElement = document.createElement("div");

const stepOne = document.createElement("div");
Expand All @@ -45,6 +49,7 @@ describe("fetchIntroSteps", () => {
document.body.appendChild(stepOne);
document.body.appendChild(stepTwo);

// Act
const steps = fetchIntroSteps(
{
_options: {
Expand All @@ -69,6 +74,7 @@ describe("fetchIntroSteps", () => {
targetElement
);

// Assert
expect(steps.length).toBe(3);

expect(steps[0].element).toBe(stepOne);
Expand All @@ -87,6 +93,7 @@ describe("fetchIntroSteps", () => {
});

test("should find the data-* elements from the DOM", () => {
// Arrange
const targetElement = document.createElement("div");

const stepOne = document.createElement("div");
Expand All @@ -99,6 +106,7 @@ describe("fetchIntroSteps", () => {
targetElement.appendChild(stepOne);
targetElement.appendChild(stepTwo);

// Act
const steps = fetchIntroSteps(
{
_options: {
Expand All @@ -108,6 +116,7 @@ describe("fetchIntroSteps", () => {
targetElement
);

// Assert
expect(steps.length).toBe(2);

expect(steps[0].position).toBe("bottom");
Expand All @@ -120,6 +129,7 @@ describe("fetchIntroSteps", () => {
});

test("should respect the custom step attribute (DOM)", () => {
// Arrange
const targetElement = document.createElement("div");

const stepOne = document.createElement("div");
Expand All @@ -132,6 +142,7 @@ describe("fetchIntroSteps", () => {
targetElement.appendChild(stepOne);
targetElement.appendChild(stepTwo);

// Act
const steps = fetchIntroSteps(
{
_options: {
Expand All @@ -141,6 +152,7 @@ describe("fetchIntroSteps", () => {
targetElement
);

// Assert
expect(steps.length).toBe(2);

expect(steps[0].intro).toBe("first");
Expand All @@ -151,6 +163,7 @@ describe("fetchIntroSteps", () => {
});

test("should ignore DOM elements when options.steps is available", () => {
// Arrange
const targetElement = document.createElement("div");

const stepOne = document.createElement("div");
Expand All @@ -162,6 +175,7 @@ describe("fetchIntroSteps", () => {
targetElement.appendChild(stepOne);
targetElement.appendChild(stepTwo);

// Act
const steps = fetchIntroSteps(
{
_options: {
Expand All @@ -178,8 +192,56 @@ describe("fetchIntroSteps", () => {
targetElement
);

// Assert
expect(steps.length).toBe(2);
expect(steps[0].intro).toBe("steps-first");
expect(steps[1].intro).toBe("steps-second");
});

it("should correctly sort based on data-step", () => {
// Arrange
const targetElement = document.createElement("div");

const stepOne = document.createElement("div");
stepOne.setAttribute("data-intro", "one");

const stepTwo = document.createElement("div");
stepTwo.setAttribute("data-intro", "two");

const stepThree = document.createElement("div");
stepThree.setAttribute("data-intro", "three");
stepThree.setAttribute("data-step", "3");

const stepFour = document.createElement("div");
stepFour.setAttribute("data-intro", "four");
stepFour.setAttribute("data-step", "5");

targetElement.appendChild(stepThree);
targetElement.appendChild(stepOne);
targetElement.appendChild(stepFour);
targetElement.appendChild(stepTwo);

// Act
const steps = fetchIntroSteps(
{
_options: {},
} as IntroJs,
targetElement
);

// Assert
expect(steps.length).toBe(4);

expect(steps[0].intro).toBe("one");
expect(steps[0].step).toBe(1);

expect(steps[1].intro).toBe("two");
expect(steps[1].step).toBe(2);

expect(steps[2].intro).toBe("three");
expect(steps[2].step).toBe(3);

expect(steps[3].intro).toBe("four");
expect(steps[3].step).toBe(5);
});
});
Loading