Skip to content

Commit b51910f

Browse files
authored
Merge pull request #2043 from usablica/steps-tests
Simplify fetchIntroSteps and add tests
2 parents caff54a + f39b421 commit b51910f

File tree

3 files changed

+87
-42
lines changed

3 files changed

+87
-42
lines changed

src/core/fetchIntroSteps.ts

Lines changed: 25 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,6 @@ export default function fetchIntroSteps(
1212
intro: IntroJs,
1313
targetElm: HTMLElement
1414
) {
15-
const allIntroSteps: HTMLElement[] = Array.from(
16-
targetElm.querySelectorAll("*[data-intro]")
17-
);
1815
let introItems: IntroStep[] = [];
1916

2017
if (intro._options.steps && intro._options.steps.length) {
@@ -69,56 +66,51 @@ export default function fetchIntroSteps(
6966
}
7067
}
7168
} else {
72-
//use steps from data-* annotations
73-
const elmsLength = allIntroSteps.length;
74-
let disableInteraction: boolean;
69+
const elements: HTMLElement[] = Array.from(
70+
targetElm.querySelectorAll("*[data-intro]")
71+
);
7572

7673
//if there's no element to intro
77-
if (elmsLength < 1) {
74+
if (elements.length < 1) {
7875
return [];
7976
}
8077

8178
const itemsWithoutStep: IntroStep[] = [];
8279

83-
for (const currentElement of allIntroSteps) {
80+
for (const element of elements) {
8481
// start intro for groups of elements
8582
if (
8683
intro._options.group &&
87-
currentElement.getAttribute("data-intro-group") !== intro._options.group
84+
element.getAttribute("data-intro-group") !== intro._options.group
8885
) {
8986
continue;
9087
}
9188

9289
// skip hidden elements
93-
if (currentElement.style.display === "none") {
90+
if (element.style.display === "none") {
9491
continue;
9592
}
9693

9794
// get the step for the current element or set as 0 if is not present
98-
const step = parseInt(
99-
currentElement.getAttribute("data-step") || "0",
100-
10
101-
);
102-
103-
disableInteraction = intro._options.disableInteraction;
104-
if (currentElement.hasAttribute("data-disable-interaction")) {
105-
disableInteraction = !!currentElement.getAttribute(
106-
"data-disable-interaction"
107-
);
95+
const step = parseInt(element.getAttribute("data-step") || "0", 10);
96+
97+
let disableInteraction = intro._options.disableInteraction;
98+
if (element.hasAttribute("data-disable-interaction")) {
99+
disableInteraction = !!element.getAttribute("data-disable-interaction");
108100
}
101+
109102
const newIntroStep: IntroStep = {
110-
step: step,
111-
element: currentElement,
112-
title: currentElement.getAttribute("data-title") || "",
113-
intro: currentElement.getAttribute("data-intro") || "",
114-
tooltipClass:
115-
currentElement.getAttribute("data-tooltip-class") || undefined,
103+
step,
104+
element,
105+
title: element.getAttribute("data-title") || "",
106+
intro: element.getAttribute("data-intro") || "",
107+
tooltipClass: element.getAttribute("data-tooltip-class") || undefined,
116108
highlightClass:
117-
currentElement.getAttribute("data-highlight-class") || undefined,
118-
position: (currentElement.getAttribute("data-position") ||
109+
element.getAttribute("data-highlight-class") || undefined,
110+
position: (element.getAttribute("data-position") ||
119111
intro._options.tooltipPosition) as TooltipPosition,
120112
scrollTo:
121-
(currentElement.getAttribute("data-scroll-to") as ScrollTo) ||
113+
(element.getAttribute("data-scroll-to") as ScrollTo) ||
122114
intro._options.scrollTo,
123115
disableInteraction,
124116
};
@@ -130,7 +122,7 @@ export default function fetchIntroSteps(
130122
}
131123
}
132124

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

145-
//removing undefined/null elements
146-
const tempIntroItems = [];
147-
for (let z = 0; z < introItems.length; z++) {
148-
if (introItems[z]) {
149-
// copy non-falsy values to the end of the array
150-
tempIntroItems.push(introItems[z]);
151-
}
152-
}
153-
154-
introItems = tempIntroItems;
137+
// removing undefined/null elements
138+
introItems = introItems.filter((n) => n);
155139

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

159143
return introItems;

src/util/cloneObject.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ export default function cloneObject<T>(source: T): T {
1010
const temp = {} as T;
1111

1212
for (const key in source) {
13-
// @ts-ignore:next-line
1413
if (
1514
"jQuery" in window &&
1615
window.jQuery &&

tests/jest/core/fetchIntroSteps.test.ts

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@ import fetchIntroSteps from "../../../src/core/fetchIntroSteps";
33

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

9+
// Act
810
const steps = fetchIntroSteps(
911
{
1012
_options: {
@@ -22,6 +24,7 @@ describe("fetchIntroSteps", () => {
2224
targetElement
2325
);
2426

27+
// Assert
2528
expect(steps.length).toBe(2);
2629

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

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

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

52+
// Act
4853
const steps = fetchIntroSteps(
4954
{
5055
_options: {
@@ -69,6 +74,7 @@ describe("fetchIntroSteps", () => {
6974
targetElement
7075
);
7176

77+
// Assert
7278
expect(steps.length).toBe(3);
7379

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

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

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

109+
// Act
102110
const steps = fetchIntroSteps(
103111
{
104112
_options: {
@@ -108,6 +116,7 @@ describe("fetchIntroSteps", () => {
108116
targetElement
109117
);
110118

119+
// Assert
111120
expect(steps.length).toBe(2);
112121

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

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

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

145+
// Act
135146
const steps = fetchIntroSteps(
136147
{
137148
_options: {
@@ -141,6 +152,7 @@ describe("fetchIntroSteps", () => {
141152
targetElement
142153
);
143154

155+
// Assert
144156
expect(steps.length).toBe(2);
145157

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

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

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

178+
// Act
165179
const steps = fetchIntroSteps(
166180
{
167181
_options: {
@@ -178,8 +192,56 @@ describe("fetchIntroSteps", () => {
178192
targetElement
179193
);
180194

195+
// Assert
181196
expect(steps.length).toBe(2);
182197
expect(steps[0].intro).toBe("steps-first");
183198
expect(steps[1].intro).toBe("steps-second");
184199
});
200+
201+
it("should correctly sort based on data-step", () => {
202+
// Arrange
203+
const targetElement = document.createElement("div");
204+
205+
const stepOne = document.createElement("div");
206+
stepOne.setAttribute("data-intro", "one");
207+
208+
const stepTwo = document.createElement("div");
209+
stepTwo.setAttribute("data-intro", "two");
210+
211+
const stepThree = document.createElement("div");
212+
stepThree.setAttribute("data-intro", "three");
213+
stepThree.setAttribute("data-step", "3");
214+
215+
const stepFour = document.createElement("div");
216+
stepFour.setAttribute("data-intro", "four");
217+
stepFour.setAttribute("data-step", "5");
218+
219+
targetElement.appendChild(stepThree);
220+
targetElement.appendChild(stepOne);
221+
targetElement.appendChild(stepFour);
222+
targetElement.appendChild(stepTwo);
223+
224+
// Act
225+
const steps = fetchIntroSteps(
226+
{
227+
_options: {},
228+
} as IntroJs,
229+
targetElement
230+
);
231+
232+
// Assert
233+
expect(steps.length).toBe(4);
234+
235+
expect(steps[0].intro).toBe("one");
236+
expect(steps[0].step).toBe(1);
237+
238+
expect(steps[1].intro).toBe("two");
239+
expect(steps[1].step).toBe(2);
240+
241+
expect(steps[2].intro).toBe("three");
242+
expect(steps[2].step).toBe(3);
243+
244+
expect(steps[3].intro).toBe("four");
245+
expect(steps[3].step).toBe(5);
246+
});
185247
});

0 commit comments

Comments
 (0)