jqtree 1.7.1 → 1.7.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/.github/workflows/ci.yml +0 -5
  2. package/.github/workflows/size.yml +24 -0
  3. package/README.md +1 -1
  4. package/bower.json +1 -1
  5. package/docs/Gemfile.lock +15 -13
  6. package/docs/_config.yml +1 -1
  7. package/docs/_entries/03_features.md +1 -1
  8. package/docs/_entries/10_changelog.md +10 -0
  9. package/docs/_entries/16_closedicon.md +17 -3
  10. package/docs/_entries/31_openedicon.md +17 -3
  11. package/docs/package.json +2 -2
  12. package/docs/pnpm-lock.yaml +106 -130
  13. package/docs/static/examples/autoescape.js +15 -17
  14. package/docs/static/examples/autoscroll.js +5 -7
  15. package/docs/static/examples/button-on-right.js +4 -6
  16. package/docs/static/examples/custom_html.js +22 -24
  17. package/docs/static/examples/drag-outside.js +23 -25
  18. package/docs/static/examples/drag_and_drop.js +4 -6
  19. package/docs/static/examples/icon_buttons.js +3 -5
  20. package/docs/static/examples/load_json_data.js +14 -16
  21. package/docs/static/examples/load_json_data_from_server.js +1 -3
  22. package/docs/static/examples/load_on_demand.js +3 -5
  23. package/docs/static/examples/multiple_select.js +19 -21
  24. package/docs/static/examples/right-to-left.js +2 -4
  25. package/docs/static/examples/save_state.js +2 -4
  26. package/docs/tree.jquery.js +2 -2
  27. package/lib/dataLoader.js +3 -3
  28. package/lib/dragAndDropHandler.js +1 -1
  29. package/lib/elementsRenderer.js +1 -1
  30. package/lib/keyHandler.js +1 -1
  31. package/lib/mouse.widget.js +1 -1
  32. package/lib/node.js +4 -4
  33. package/lib/nodeElement.js +1 -1
  34. package/lib/playwright/coverage.js +11 -16
  35. package/lib/playwright/playwright.test.js +37 -58
  36. package/lib/playwright/testUtils.js +27 -44
  37. package/lib/saveStateHandler.js +1 -1
  38. package/lib/scrollHandler.js +1 -1
  39. package/lib/selectNodeHandler.js +1 -1
  40. package/lib/simple.widget.js +3 -3
  41. package/lib/test/jqTree/accessibility.test.js +2 -2
  42. package/lib/test/jqTree/events.test.js +2 -2
  43. package/lib/test/jqTree/loadOnDemand.test.js +5 -4
  44. package/lib/test/jqTree/methods.test.js +2 -2
  45. package/lib/test/jqTree/options.test.js +43 -2
  46. package/lib/test/node.test.js +2 -2
  47. package/lib/tree.jquery.js +5 -5
  48. package/lib/version.js +1 -1
  49. package/package.json +31 -30
  50. package/src/elementsRenderer.ts +17 -17
  51. package/src/jqtreeOptions.ts +2 -2
  52. package/src/test/.eslintrc +2 -1
  53. package/src/test/jqTree/loadOnDemand.test.ts +6 -5
  54. package/src/test/jqTree/methods.test.ts +26 -26
  55. package/src/test/jqTree/options.test.ts +61 -8
  56. package/src/tree.jquery.d.ts +20 -11
  57. package/src/version.ts +1 -1
  58. package/tree.jquery.debug.js +45 -45
  59. package/tree.jquery.debug.js.map +1 -1
  60. package/tree.jquery.js +2 -2
  61. package/tree.jquery.js.map +1 -1
package/package.json CHANGED
@@ -1,13 +1,14 @@
1
1
  {
2
2
  "name": "jqtree",
3
- "version": "1.7.1",
3
+ "version": "1.7.3",
4
4
  "description": "Tree widget for jQuery",
5
5
  "keywords": [
6
6
  "jquery-plugin",
7
7
  "tree"
8
8
  ],
9
9
  "license": "Apache-2.0",
10
- "main": "./lib/tree.jquery.js",
10
+ "browser": "./tree.jquery.js",
11
+ "main": "./tree.jquery.js",
11
12
  "types": "./src/tree.jquery.d.ts",
12
13
  "repository": {
13
14
  "type": "git",
@@ -27,52 +28,52 @@
27
28
  "playwright": "pnpm build-with-coverage && playwright test --config config/playwright.config.js",
28
29
  "test": "pnpm jest && pnpm playwright"
29
30
  },
30
- "dependencies": {
31
- "jquery": "^3.7.0"
31
+ "peerDependencies": {
32
+ "jquery": "^3"
32
33
  },
33
34
  "devDependencies": {
34
- "@babel/cli": "^7.22.9",
35
- "@babel/core": "^7.22.9",
36
- "@babel/preset-env": "^7.22.9",
37
- "@babel/preset-typescript": "^7.22.5",
38
- "@playwright/test": "^1.36.2",
35
+ "@babel/cli": "^7.22.15",
36
+ "@babel/core": "^7.22.17",
37
+ "@babel/preset-env": "^7.22.15",
38
+ "@babel/preset-typescript": "^7.22.15",
39
+ "@playwright/test": "^1.38.0",
39
40
  "@rollup/plugin-babel": "^6.0.3",
40
- "@rollup/plugin-node-resolve": "^15.1.0",
41
+ "@rollup/plugin-node-resolve": "^15.2.1",
41
42
  "@rollup/plugin-terser": "^0.4.3",
42
43
  "@testing-library/dom": "^9.3.1",
43
44
  "@types/debug": "^4.1.8",
44
- "@types/jest": "^29.5.3",
45
+ "@types/jest": "^29.5.4",
45
46
  "@types/jest-axe": "^3.5.5",
46
- "@types/jquery": "^3.5.16",
47
- "@types/node": "^20.4.7",
48
- "@typescript-eslint/eslint-plugin": "^6.2.1",
49
- "@typescript-eslint/parser": "^6.2.1",
50
- "autoprefixer": "^10.4.14",
51
- "babel-jest": "^29.6.2",
47
+ "@types/jquery": "^3.5.18",
48
+ "@types/node": "^20.6.0",
49
+ "@typescript-eslint/eslint-plugin": "^6.7.0",
50
+ "@typescript-eslint/parser": "^6.7.0",
51
+ "autoprefixer": "^10.4.15",
52
+ "babel-jest": "^29.7.0",
52
53
  "babel-plugin-istanbul": "^6.1.1",
53
- "eslint": "^8.46.0",
54
- "eslint-plugin-import": "^2.28.0",
54
+ "eslint": "^8.49.0",
55
+ "eslint-plugin-import": "^2.28.1",
55
56
  "eslint-plugin-jest": "^27.2.3",
56
- "eslint-plugin-playwright": "^0.15.3",
57
- "eslint-plugin-testing-library": "^5.11.0",
57
+ "eslint-plugin-playwright": "^0.16.0",
58
+ "eslint-plugin-testing-library": "^6.0.1",
58
59
  "givens": "^1.3.9",
59
- "graphql": "^16.7.1",
60
- "jest": "^29.6.2",
60
+ "graphql": "^16.8.0",
61
+ "jest": "^29.7.0",
61
62
  "jest-axe": "^8.0.0",
62
- "jest-environment-jsdom": "^29.6.2",
63
+ "jest-environment-jsdom": "^29.7.0",
63
64
  "jest-extended": "^4.0.1",
64
65
  "jsonfile": "^6.1.0",
65
66
  "lodash.template": "^4.5.0",
66
- "msw": "^1.2.3",
67
- "postcss": "^8.4.27",
67
+ "msw": "^1.3.1",
68
+ "postcss": "^8.4.29",
68
69
  "postcss-cli": "^10.1.0",
69
70
  "postcss-import": "^15.1.0",
70
71
  "postcss-load-config": "^4.0.1",
71
72
  "postcss-nested": "^6.0.1",
72
- "prettier": "^3.0.1",
73
- "rollup": "^3.27.2",
73
+ "prettier": "^3.0.3",
74
+ "rollup": "^3.29.1",
74
75
  "rollup-plugin-serve": "^2.0.2",
75
- "tslib": "^2.6.1",
76
- "typescript": "~5.1.6"
76
+ "tslib": "^2.6.2",
77
+ "typescript": "^5.2.2"
77
78
  }
78
79
  }
@@ -2,21 +2,21 @@ import { getBoolString } from "./util";
2
2
  import { Node } from "./node";
3
3
  import { JqTreeWidget } from "./tree.jquery";
4
4
 
5
- type IconElement = Text | Element;
5
+ type IconElement = string | HTMLElement | JQuery<HTMLElement>;
6
6
 
7
7
  export default class ElementsRenderer {
8
- public openedIconElement?: IconElement;
9
- public closedIconElement?: IconElement;
8
+ public openedIconElement?: HTMLElement | Text;
9
+ public closedIconElement?: HTMLElement | Text;
10
10
  private treeWidget: JqTreeWidget;
11
11
 
12
12
  constructor(treeWidget: JqTreeWidget) {
13
13
  this.treeWidget = treeWidget;
14
14
 
15
15
  this.openedIconElement = this.createButtonElement(
16
- treeWidget.options.openedIcon || "+"
16
+ treeWidget.options.openedIcon || "+",
17
17
  );
18
18
  this.closedIconElement = this.createButtonElement(
19
- treeWidget.options.closedIcon || "-"
19
+ treeWidget.options.closedIcon || "-",
20
20
  );
21
21
  }
22
22
 
@@ -37,7 +37,7 @@ export default class ElementsRenderer {
37
37
  $element[0],
38
38
  this.treeWidget.tree.children,
39
39
  true,
40
- 1
40
+ 1,
41
41
  );
42
42
  }
43
43
  }
@@ -62,7 +62,7 @@ export default class ElementsRenderer {
62
62
  li,
63
63
  node.children,
64
64
  false,
65
- node.getLevel() + 1
65
+ node.getLevel() + 1,
66
66
  );
67
67
  }
68
68
  }
@@ -71,7 +71,7 @@ export default class ElementsRenderer {
71
71
  element: Element,
72
72
  children: Node[],
73
73
  isRootNode: boolean,
74
- level: number
74
+ level: number,
75
75
  ): void {
76
76
  const ul = this.createUl(isRootNode);
77
77
  element.appendChild(ul);
@@ -123,7 +123,7 @@ export default class ElementsRenderer {
123
123
 
124
124
  private createLi(node: Node, level: number): HTMLLIElement {
125
125
  const isSelected = Boolean(
126
- this.treeWidget.selectNodeHandler.isNodeSelected(node)
126
+ this.treeWidget.selectNodeHandler.isNodeSelected(node),
127
127
  );
128
128
 
129
129
  const mustShowFolder =
@@ -145,7 +145,7 @@ export default class ElementsRenderer {
145
145
  element: HTMLElement,
146
146
  name: string,
147
147
  level: number,
148
- isSelected: boolean
148
+ isSelected: boolean,
149
149
  ) {
150
150
  element.setAttribute("aria-label", name);
151
151
  element.setAttribute("aria-level", `${level}`);
@@ -156,7 +156,7 @@ export default class ElementsRenderer {
156
156
  private createFolderLi(
157
157
  node: Node,
158
158
  level: number,
159
- isSelected: boolean
159
+ isSelected: boolean,
160
160
  ): HTMLLIElement {
161
161
  const buttonClasses = this.getButtonClasses(node);
162
162
  const folderClasses = this.getFolderClasses(node, isSelected);
@@ -194,7 +194,7 @@ export default class ElementsRenderer {
194
194
  node.name,
195
195
  isSelected,
196
196
  true,
197
- level
197
+ level,
198
198
  );
199
199
  titleSpan.setAttribute("aria-expanded", getBoolString(node.is_open));
200
200
  div.appendChild(titleSpan);
@@ -209,7 +209,7 @@ export default class ElementsRenderer {
209
209
  private createNodeLi(
210
210
  node: Node,
211
211
  level: number,
212
- isSelected: boolean
212
+ isSelected: boolean,
213
213
  ): HTMLLIElement {
214
214
  const liClasses = ["jqtree_common"];
215
215
 
@@ -236,7 +236,7 @@ export default class ElementsRenderer {
236
236
  node.name,
237
237
  isSelected,
238
238
  false,
239
- level
239
+ level,
240
240
  );
241
241
  div.appendChild(titleSpan);
242
242
 
@@ -247,7 +247,7 @@ export default class ElementsRenderer {
247
247
  nodeName: string,
248
248
  isSelected: boolean,
249
249
  isFolder: boolean,
250
- level: number
250
+ level: number,
251
251
  ): HTMLSpanElement {
252
252
  const titleSpan = document.createElement("span");
253
253
 
@@ -317,8 +317,8 @@ export default class ElementsRenderer {
317
317
  }
318
318
 
319
319
  private createButtonElement(
320
- value: string | Element
321
- ): IconElement | undefined {
320
+ value: IconElement,
321
+ ): HTMLElement | Text | undefined {
322
322
  if (typeof value === "string") {
323
323
  // convert value to html
324
324
  const div = document.createElement("div");
@@ -21,7 +21,7 @@ export interface JQTreeOptions {
21
21
  autoEscape: boolean;
22
22
  autoOpen: boolean | number;
23
23
  buttonLeft: boolean;
24
- closedIcon: string | Element | undefined;
24
+ closedIcon?: string | HTMLElement | JQuery<HTMLElement>;
25
25
  data: NodeData[] | undefined;
26
26
  dataFilter: DataFilter | undefined;
27
27
  dataUrl: DataUrl | undefined;
@@ -39,7 +39,7 @@ export interface JQTreeOptions {
39
39
  onLoadFailed: ((response: JQuery.jqXHR) => void) | undefined;
40
40
  onLoading: HandleLoadingMethod | undefined;
41
41
  onSetStateFromStorage: ((data: string) => void) | undefined;
42
- openedIcon: string | Element;
42
+ openedIcon?: string | HTMLElement | JQuery<HTMLElement>;
43
43
  openFolderDelay: number | false;
44
44
  rtl: boolean | undefined;
45
45
  selectable: boolean;
@@ -11,6 +11,7 @@
11
11
  "jest/prefer-expect-assertions": "off",
12
12
  "jest/prefer-strict-equal": "off",
13
13
  "jest/require-hook": "off",
14
- "jest/require-top-level-describe": "off"
14
+ "jest/require-top-level-describe": "off",
15
+ "testing-library/no-node-access": "off"
15
16
  }
16
17
  }
@@ -53,12 +53,12 @@ context("when a node has load_on_demand in the data", () => {
53
53
  if (parentId === "1") {
54
54
  return response(
55
55
  ctx.status(200),
56
- ctx.json([{ id: 2, name: "loaded-on-demand" }])
56
+ ctx.json([{ id: 2, name: "loaded-on-demand" }]),
57
57
  );
58
58
  } else {
59
59
  return response(ctx.status(400));
60
60
  }
61
- })
61
+ }),
62
62
  );
63
63
  });
64
64
 
@@ -87,7 +87,7 @@ context("when a node has load_on_demand in the data", () => {
87
87
 
88
88
  context("when the node is opened", () => {
89
89
  given("node", () =>
90
- given.$tree.tree("getNodeByNameMustExist", "parent-node")
90
+ given.$tree.tree("getNodeByNameMustExist", "parent-node"),
91
91
  );
92
92
 
93
93
  it("loads the subtree", async () => {
@@ -136,8 +136,9 @@ context("when a node has load_on_demand in the data", () => {
136
136
 
137
137
  context("when the node is selected and doesn't have the focus", () => {
138
138
  beforeEach(() => {
139
- given.$tree.tree("selectNode", given.node);
140
- (document.activeElement as HTMLElement).blur();
139
+ given.$tree.tree("selectNode", given.node, {
140
+ mustSetFocus: false,
141
+ });
141
142
  });
142
143
 
143
144
  it("keeps the node selected and not focused", async () => {
@@ -146,7 +146,7 @@ describe("addToSelection", () => {
146
146
 
147
147
  it("selects the nodes", () => {
148
148
  expect(given.$tree.tree("getSelectedNodes")).toEqual(
149
- expect.arrayContaining([given.child1, given.child2])
149
+ expect.arrayContaining([given.child1, given.child2]),
150
150
  );
151
151
  });
152
152
 
@@ -207,7 +207,7 @@ describe("appendNode", () => {
207
207
 
208
208
  context("when appending to a parent node", () => {
209
209
  given("parent", () =>
210
- given.$tree.tree("getNodeByNameMustExist", "node1")
210
+ given.$tree.tree("getNodeByNameMustExist", "node1"),
211
211
  );
212
212
 
213
213
  it("appends the node to parent node", () => {
@@ -244,7 +244,7 @@ describe("appendNode", () => {
244
244
 
245
245
  it("sets the properties of the object", () => {
246
246
  expect(given.$tree.tree("getNodeById", 99)).toMatchObject(
247
- given.nodeData
247
+ given.nodeData,
248
248
  );
249
249
  });
250
250
  });
@@ -302,7 +302,7 @@ describe("getNodeByHtmlElement", () => {
302
302
 
303
303
  const given = getGiven<Vars>();
304
304
  given("htmlElement", () =>
305
- screen.getByText("node1", { selector: ".jqtree-title" })
305
+ screen.getByText("node1", { selector: ".jqtree-title" }),
306
306
  );
307
307
  given("$tree", () => $("#tree1"));
308
308
 
@@ -312,7 +312,7 @@ describe("getNodeByHtmlElement", () => {
312
312
 
313
313
  it("returns the node", () => {
314
314
  expect(
315
- given.$tree.tree("getNodeByHtmlElement", given.htmlElement)
315
+ given.$tree.tree("getNodeByHtmlElement", given.htmlElement),
316
316
  ).toEqual(expect.objectContaining({ name: "node1" }));
317
317
  });
318
318
  });
@@ -394,7 +394,7 @@ describe("getNodesByProperty", () => {
394
394
 
395
395
  it("gets nodes by property", () => {
396
396
  expect(
397
- given.$tree.tree("getNodesByProperty", "intProperty", 1)
397
+ given.$tree.tree("getNodesByProperty", "intProperty", 1),
398
398
  ).toEqual([given.node1]);
399
399
  });
400
400
  });
@@ -417,7 +417,7 @@ describe("getSelectedNode", () => {
417
417
 
418
418
  context("when nodes have ids", () => {
419
419
  given("node", () =>
420
- given.$tree.tree("getNodeByNameMustExist", "node1")
420
+ given.$tree.tree("getNodeByNameMustExist", "node1"),
421
421
  );
422
422
  given("treeData", () => exampleData);
423
423
 
@@ -440,7 +440,7 @@ describe("getSelectedNode", () => {
440
440
 
441
441
  context("when nodes don't have ids", () => {
442
442
  given("node", () =>
443
- given.$tree.tree("getNodeByNameMustExist", "without-id1")
443
+ given.$tree.tree("getNodeByNameMustExist", "without-id1"),
444
444
  );
445
445
  given("treeData", () => ["without-id1", "without-id2"]);
446
446
 
@@ -494,7 +494,7 @@ describe("getSelectedNodes", () => {
494
494
 
495
495
  it("returns the selected nodes", () => {
496
496
  expect(given.$tree.tree("getSelectedNodes")).toEqual(
497
- expect.arrayContaining([given.child1, given.child2])
497
+ expect.arrayContaining([given.child1, given.child2]),
498
498
  );
499
499
  });
500
500
  });
@@ -659,7 +659,7 @@ describe("loadData", () => {
659
659
  given.$tree.tree(
660
660
  "loadData",
661
661
  exampleData,
662
- given.$tree.tree("getNodeByNameMustExist", "initial1")
662
+ given.$tree.tree("getNodeByNameMustExist", "initial1"),
663
663
  );
664
664
  });
665
665
 
@@ -688,7 +688,7 @@ describe("loadData", () => {
688
688
  beforeEach(() => {
689
689
  given.$tree.tree(
690
690
  "selectNode",
691
- given.$tree.tree("getNodeByNameMustExist", "child1")
691
+ given.$tree.tree("getNodeByNameMustExist", "child1"),
692
692
  );
693
693
  });
694
694
 
@@ -696,7 +696,7 @@ describe("loadData", () => {
696
696
  given.$tree.tree(
697
697
  "loadData",
698
698
  ["new-child1"],
699
- given.$tree.tree("getNodeByNameMustExist", "node1")
699
+ given.$tree.tree("getNodeByNameMustExist", "node1"),
700
700
  );
701
701
 
702
702
  expect(given.$tree.tree("getSelectedNode")).toBeFalse();
@@ -712,7 +712,7 @@ describe("loadData", () => {
712
712
  given.$tree.tree(
713
713
  "loadData",
714
714
  ["new-child1"],
715
- given.$tree.tree("getNodeByNameMustExist", "node1")
715
+ given.$tree.tree("getNodeByNameMustExist", "node1"),
716
716
  );
717
717
 
718
718
  expect(given.$tree.tree("getSelectedNode")).toBeFalse();
@@ -723,7 +723,7 @@ describe("loadData", () => {
723
723
  given.$tree.tree(
724
724
  "loadData",
725
725
  ["new-child1"],
726
- given.$tree.tree("getNodeByNameMustExist", "node2")
726
+ given.$tree.tree("getNodeByNameMustExist", "node2"),
727
727
  );
728
728
 
729
729
  expect(given.$tree.tree("getSelectedNode")).toMatchObject({
@@ -750,8 +750,8 @@ describe("loadDataFromUrl", () => {
750
750
  beforeEach(() => {
751
751
  server.use(
752
752
  rest.get("/tree/", (_request, response, ctx) =>
753
- response(ctx.status(200), ctx.json(given.serverData))
754
- )
753
+ response(ctx.status(200), ctx.json(given.serverData)),
754
+ ),
755
755
  );
756
756
 
757
757
  given.$tree.tree({ data: given.initialData });
@@ -775,7 +775,7 @@ describe("loadDataFromUrl", () => {
775
775
  it("loads a subtree", async () => {
776
776
  const parentNode = given.$tree.tree(
777
777
  "getNodeByNameMustExist",
778
- "initial1"
778
+ "initial1",
779
779
  );
780
780
  given.$tree.tree("loadDataFromUrl", "/tree/", parentNode);
781
781
  await screen.findByText("new1");
@@ -949,7 +949,7 @@ describe("prependNode", () => {
949
949
 
950
950
  context("with a parent node", () => {
951
951
  given("parent", () =>
952
- given.$tree.tree("getNodeByNameMustExist", "node1")
952
+ given.$tree.tree("getNodeByNameMustExist", "node1"),
953
953
  );
954
954
 
955
955
  it("prepends the node to the parent", () => {
@@ -1013,8 +1013,8 @@ describe("reload", () => {
1013
1013
  beforeEach(async () => {
1014
1014
  server.use(
1015
1015
  rest.get("/tree2/", (_request, response, ctx) =>
1016
- response(ctx.status(200), ctx.json(exampleData))
1017
- )
1016
+ response(ctx.status(200), ctx.json(exampleData)),
1017
+ ),
1018
1018
  );
1019
1019
 
1020
1020
  given.$tree.tree({ dataUrl: "/tree2/" });
@@ -1070,7 +1070,7 @@ describe("removeNode", () => {
1070
1070
 
1071
1071
  context("with a child node", () => {
1072
1072
  given("node", () =>
1073
- given.$tree.tree("getNodeByNameMustExist", "child1")
1073
+ given.$tree.tree("getNodeByNameMustExist", "child1"),
1074
1074
  );
1075
1075
 
1076
1076
  it("removes the node", () => {
@@ -1103,7 +1103,7 @@ describe("removeNode", () => {
1103
1103
 
1104
1104
  context("with a parent node and its children", () => {
1105
1105
  given("node", () =>
1106
- given.$tree.tree("getNodeByNameMustExist", "node1")
1106
+ given.$tree.tree("getNodeByNameMustExist", "node1"),
1107
1107
  );
1108
1108
 
1109
1109
  it("removes the node", () => {
@@ -1121,7 +1121,7 @@ describe("removeNode", () => {
1121
1121
  beforeEach(() => {
1122
1122
  const child1 = given.$tree.tree(
1123
1123
  "getNodeByNameMustExist",
1124
- "child1"
1124
+ "child1",
1125
1125
  );
1126
1126
  given.$tree.tree("selectNode", child1);
1127
1127
  });
@@ -1139,7 +1139,7 @@ describe("removeNode", () => {
1139
1139
 
1140
1140
  it("raises an exception", () => {
1141
1141
  expect(() => given.$tree.tree("removeNode", given.node)).toThrow(
1142
- "Node has no parent"
1142
+ "Node has no parent",
1143
1143
  );
1144
1144
  });
1145
1145
  });
@@ -1382,7 +1382,7 @@ describe("updateNode", () => {
1382
1382
  expect.objectContaining({ name: "node2" }),
1383
1383
  ]);
1384
1384
  expect(given.$tree.tree("getNodeById", 999)).toMatchObject(
1385
- given.nodeData
1385
+ given.nodeData,
1386
1386
  );
1387
1387
  });
1388
1388
  });
@@ -1406,7 +1406,7 @@ describe("updateNode", () => {
1406
1406
  context("when adding a child to a child node", () => {
1407
1407
  given("nodeData", () => ({ children: ["new-child"] }));
1408
1408
  given("node", () =>
1409
- given.$tree.tree("getNodeByNameMustExist", "child1")
1409
+ given.$tree.tree("getNodeByNameMustExist", "child1"),
1410
1410
  );
1411
1411
 
1412
1412
  it("adds the child node", () => {
@@ -164,6 +164,56 @@ describe("autoOpen", () => {
164
164
  });
165
165
  });
166
166
 
167
+ describe("closedIcon", () => {
168
+ it("renders a string", () => {
169
+ const $tree = $("#tree1");
170
+ $tree.tree({
171
+ closedIcon: "closed",
172
+ data: exampleData,
173
+ });
174
+
175
+ const $button = $tree.find("a.jqtree-toggler:first");
176
+ expect($button.text()).toBe("closed");
177
+ });
178
+
179
+ it("escapes html", () => {
180
+ const $tree = $("#tree1");
181
+ $tree.tree({
182
+ closedIcon: "<span>test</span>",
183
+ data: exampleData,
184
+ });
185
+
186
+ const $button = $tree.find("a.jqtree-toggler:first");
187
+ expect($button.text()).toBe("<span>test</span>");
188
+ });
189
+
190
+ it("renders a jquery element", () => {
191
+ const $tree = $("#tree1");
192
+ $tree.tree({
193
+ closedIcon: $("<span class='abc'>test</span>"),
194
+ data: exampleData,
195
+ });
196
+
197
+ const $span = $tree.find("a.jqtree-toggler:first span.abc");
198
+ expect($span.text()).toBe("test");
199
+ });
200
+
201
+ it("renders a html element", () => {
202
+ const closedIcon = document.createElement("span");
203
+ closedIcon.className = "abc";
204
+ closedIcon.textContent = "test";
205
+
206
+ const $tree = $("#tree1");
207
+ $tree.tree({
208
+ closedIcon,
209
+ data: exampleData,
210
+ });
211
+
212
+ const $span = $tree.find("a.jqtree-toggler:first span.abc");
213
+ expect($span.text()).toBe("test");
214
+ });
215
+ });
216
+
167
217
  describe("dataUrl", () => {
168
218
  const exampleStructure = [
169
219
  expect.objectContaining({ name: "node1" }),
@@ -201,7 +251,7 @@ describe("dataUrl", () => {
201
251
  const data = nodeName ? [nodeName] : exampleData;
202
252
 
203
253
  return response(ctx.status(200), ctx.json(data));
204
- })
254
+ }),
205
255
  );
206
256
  });
207
257
 
@@ -323,7 +373,7 @@ describe("onGetStateFromStorage and onSetStateFromStorage", () => {
323
373
  JSON.stringify({
324
374
  open_nodes: [123],
325
375
  selected_node: [123],
326
- })
376
+ }),
327
377
  );
328
378
 
329
379
  it("restores the state", () => {
@@ -351,8 +401,11 @@ describe("onLoadFailed", () => {
351
401
  beforeEach(() => {
352
402
  server.use(
353
403
  rest.get("/tree/", (_request, response, ctx) =>
354
- response(ctx.status(500), ctx.body("Internal server error"))
355
- )
404
+ response(
405
+ ctx.status(500),
406
+ ctx.body("Internal server error"),
407
+ ),
408
+ ),
356
409
  );
357
410
  });
358
411
 
@@ -366,7 +419,7 @@ describe("onLoadFailed", () => {
366
419
 
367
420
  await waitFor(() => {
368
421
  expect(onLoadFailed).toHaveBeenCalledWith(
369
- expect.objectContaining({ status: 500 })
422
+ expect.objectContaining({ status: 500 }),
370
423
  );
371
424
  });
372
425
  });
@@ -432,7 +485,7 @@ describe("saveState", () => {
432
485
 
433
486
  it("saves the state to local storage", () => {
434
487
  expect(localStorage.getItem("tree")).toBe(
435
- '{"open_nodes":[123],"selected_node":[123]}'
488
+ '{"open_nodes":[123],"selected_node":[123]}',
436
489
  );
437
490
  });
438
491
  });
@@ -442,7 +495,7 @@ describe("saveState", () => {
442
495
 
443
496
  it("uses the string as a key", () => {
444
497
  expect(localStorage.getItem("my-state")).toBe(
445
- '{"open_nodes":[123],"selected_node":[123]}'
498
+ '{"open_nodes":[123],"selected_node":[123]}',
446
499
  );
447
500
  });
448
501
  });
@@ -462,7 +515,7 @@ describe("saveState", () => {
462
515
  beforeEach(() => {
463
516
  localStorage.setItem(
464
517
  "tree",
465
- '{"open_nodes":[123],"selected_node":[123]}'
518
+ '{"open_nodes":[123],"selected_node":[123]}',
466
519
  );
467
520
 
468
521
  given.$tree.tree({