@griddo/ax 12.4.0 → 12.5.0

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 (35) hide show
  1. package/config/webpack.config.js +5 -0
  2. package/package.json +2 -2
  3. package/src/__tests__/components/ConfigPanel/Form/Form.test.tsx +47 -57
  4. package/src/__tests__/components/ConfigPanel/Header/Header.test.tsx +46 -42
  5. package/src/__tests__/components/ElementsTooltip/ElementsTooltip.test.tsx +6 -17
  6. package/src/__tests__/components/EmptyState/EmptyState.test.tsx +9 -9
  7. package/src/__tests__/components/Fields/AsyncSelect/AsyncSelect.test.tsx +60 -50
  8. package/src/__tests__/components/Fields/ColorPicker/ColorPicker.test.tsx +66 -58
  9. package/src/__tests__/components/Fields/ComponentContainer/ComponentContainer.test.tsx +222 -425
  10. package/src/__tests__/components/Fields/FileField/FileField.test.tsx +13 -14
  11. package/src/__tests__/components/Fields/ImageField/ImageField.test.tsx +275 -259
  12. package/src/__tests__/components/Fields/IntegrationsField/IntegrationsField.test.tsx +50 -48
  13. package/src/__tests__/components/Fields/NoteField/NoteField.test.tsx +9 -8
  14. package/src/__tests__/components/Fields/NumberField/NumberField.test.tsx +8 -12
  15. package/src/__tests__/components/Fields/TextArea/TextArea.test.tsx +6 -2
  16. package/src/__tests__/components/Fields/ToggleField/ToggleField.test.tsx +15 -23
  17. package/src/__tests__/components/Fields/Tooltip/Tooltip.test.tsx +8 -2
  18. package/src/__tests__/components/Fields/VisualUniqueSelection/VisualUniqueSelection.test.tsx +29 -21
  19. package/src/__tests__/components/Fields/Wysiwyg/Wysiwyg.config.test.tsx +103 -0
  20. package/src/__tests__/components/FieldsBehavior/FieldsBehavior.test.tsx +7 -2
  21. package/src/__tests__/components/ResizePanel/ResizePanel.test.tsx +8 -6
  22. package/src/__tests__/components/SideModal/SideModal.test.tsx +150 -104
  23. package/src/__tests__/components/TableFilters/LiveFilter/LiveFilter.test.tsx +15 -29
  24. package/src/__tests__/components/TableFilters/StatusFilter/StatusFilter.test.tsx +61 -36
  25. package/src/__tests__/components/Tabs/Tabs.test.tsx +65 -61
  26. package/src/__tests__/components/Toast/Toast.test.tsx +19 -21
  27. package/src/__tests__/modules/FramePreview/FramePreview.test.tsx +16 -0
  28. package/src/__tests__/modules/Sites/SitesList/ListView/BulkHeader/BulkHeader.test.tsx +24 -19
  29. package/src/__tests__/modules/Sites/SitesList/SitesList.test.tsx +15 -6
  30. package/src/__tests__/modules/Users/Roles/BulkHeader/BulkHeader.test.tsx +69 -64
  31. package/src/__tests__/modules/Users/Roles/Roles.test.tsx +7 -4
  32. package/src/components/Fields/Wysiwyg/config.tsx +68 -17
  33. package/src/components/Fields/Wysiwyg/helpers.tsx +2 -0
  34. package/src/components/Fields/Wysiwyg/index.tsx +41 -10
  35. package/src/components/ResizePanel/index.tsx +7 -2
@@ -14,14 +14,12 @@ import { IQueryValue } from "@ax/types";
14
14
  afterEach(cleanup);
15
15
  vi.mock("axios");
16
16
  const mockedAxios = axios as MockedFunction<typeof axios>;
17
- const defaultProps = mock<ILiveFilterProps>();
17
+ const makeProps = (overrides: Partial<ILiveFilterProps> = {}): ILiveFilterProps =>
18
+ Object.assign(mock<ILiveFilterProps>(), overrides);
18
19
 
19
20
  describe("LiveFilter component rendering", () => {
20
21
  it("should render live filter", async () => {
21
- defaultProps.value = [{ value: "all", label: "All" }];
22
22
  const filterItems = vi.fn() as CalledWithMock<void, [pointer: string, filter: IQueryValue[]]>;
23
-
24
- defaultProps.filterItems = filterItems;
25
23
  const data = {
26
24
  data: [
27
25
  { id: 1, title: "Offline", status: "offline" },
@@ -42,7 +40,7 @@ describe("LiveFilter component rendering", () => {
42
40
  await act(async () => {
43
41
  render(
44
42
  <ThemeProvider theme={parseTheme(globalTheme)}>
45
- <LiveFilter {...defaultProps} />
43
+ <LiveFilter {...makeProps({ value: [{ value: "all", label: "All" }], filterItems: filterItems })} />
46
44
  </ThemeProvider>,
47
45
  );
48
46
  });
@@ -53,11 +51,8 @@ describe("LiveFilter component rendering", () => {
53
51
  });
54
52
 
55
53
  it("should render the component with no options", async () => {
56
- defaultProps.value = [{ value: "all", label: "All" }];
57
54
  const filterItems = vi.fn() as CalledWithMock<void, [pointer: string, filter: IQueryValue[]]>;
58
55
 
59
- defaultProps.filterItems = filterItems;
60
-
61
56
  const data = {
62
57
  data: [],
63
58
  status: 500,
@@ -71,7 +66,7 @@ describe("LiveFilter component rendering", () => {
71
66
  await act(async () => {
72
67
  render(
73
68
  <ThemeProvider theme={parseTheme(globalTheme)}>
74
- <LiveFilter {...defaultProps} />
69
+ <LiveFilter {...makeProps({ value: [{ value: "all", label: "All" }], filterItems: filterItems })} />
75
70
  </ThemeProvider>,
76
71
  );
77
72
  });
@@ -90,10 +85,7 @@ describe("LiveFilter component rendering", () => {
90
85
 
91
86
  describe("LiveFilter events", () => {
92
87
  it("should render check group on click", async () => {
93
- defaultProps.value = [{ value: "all", label: "All" }];
94
88
  const filterItemsMock = vi.fn() as CalledWithMock<void, [pointer: string, filter: IQueryValue[]]>;
95
-
96
- defaultProps.filterItems = filterItemsMock;
97
89
  const data = {
98
90
  data: [
99
91
  { id: 1, title: "Offline", status: "offline" },
@@ -113,7 +105,7 @@ describe("LiveFilter events", () => {
113
105
  await act(async () => {
114
106
  render(
115
107
  <ThemeProvider theme={parseTheme(globalTheme)}>
116
- <LiveFilter {...defaultProps} />
108
+ <LiveFilter {...makeProps({ value: [{ value: "all", label: "All" }], filterItems: filterItemsMock })} />
117
109
  </ThemeProvider>,
118
110
  );
119
111
  });
@@ -130,10 +122,7 @@ describe("LiveFilter events", () => {
130
122
  });
131
123
 
132
124
  it("should check option on click", async () => {
133
- defaultProps.value = [{ value: "all", label: "All" }];
134
125
  const filterItemsMock = vi.fn() as CalledWithMock<void, [pointer: string, filter: IQueryValue[]]>;
135
-
136
- defaultProps.filterItems = filterItemsMock;
137
126
  const data = {
138
127
  data: [
139
128
  { id: 1, title: "Offline", status: "offline" },
@@ -154,7 +143,7 @@ describe("LiveFilter events", () => {
154
143
  await act(async () => {
155
144
  render(
156
145
  <ThemeProvider theme={parseTheme(globalTheme)}>
157
- <LiveFilter {...defaultProps} />
146
+ <LiveFilter {...makeProps({ value: [{ value: "all", label: "All" }], filterItems: filterItemsMock })} />
158
147
  </ThemeProvider>,
159
148
  );
160
149
  });
@@ -173,10 +162,7 @@ describe("LiveFilter events", () => {
173
162
  });
174
163
 
175
164
  it("should uncheck selected option on click and select 'All' option", async () => {
176
- defaultProps.value = [{ value: "all", label: "All" }];
177
165
  const filterItemsMock = vi.fn() as CalledWithMock<void, [pointer: string, filter: IQueryValue[]]>;
178
-
179
- defaultProps.filterItems = filterItemsMock;
180
166
  const data = {
181
167
  data: [
182
168
  { id: 1, title: "Offline", status: "offline" },
@@ -197,7 +183,7 @@ describe("LiveFilter events", () => {
197
183
  await act(async () => {
198
184
  render(
199
185
  <ThemeProvider theme={parseTheme(globalTheme)}>
200
- <LiveFilter {...defaultProps} />
186
+ <LiveFilter {...makeProps({ value: [{ value: "all", label: "All" }], filterItems: filterItemsMock })} />
201
187
  </ThemeProvider>,
202
188
  );
203
189
  });
@@ -221,10 +207,7 @@ describe("LiveFilter events", () => {
221
207
  });
222
208
 
223
209
  it("should call filterItems action on change", async () => {
224
- defaultProps.value = [{ value: "all", label: "All" }];
225
210
  const filterItemsMock = vi.fn() as CalledWithMock<void, [pointer: string, filter: IQueryValue[]]>;
226
-
227
- defaultProps.filterItems = filterItemsMock;
228
211
  const data = {
229
212
  data: [
230
213
  { id: 1, title: "Offline", status: "offline" },
@@ -245,7 +228,7 @@ describe("LiveFilter events", () => {
245
228
  await act(async () => {
246
229
  render(
247
230
  <ThemeProvider theme={parseTheme(globalTheme)}>
248
- <LiveFilter {...defaultProps} />
231
+ <LiveFilter {...makeProps({ value: [{ value: "all", label: "All" }], filterItems: filterItemsMock })} />
249
232
  </ThemeProvider>,
250
233
  );
251
234
  });
@@ -261,10 +244,7 @@ describe("LiveFilter events", () => {
261
244
  });
262
245
 
263
246
  it("should render live filter with filter options", async () => {
264
- defaultProps.value = [{ value: "all", label: "All" }];
265
247
  const filterItems = vi.fn() as CalledWithMock<void, [pointer: string, filter: IQueryValue[]]>;
266
- defaultProps.filterOptions = ["offline", "active", "scheduled"];
267
- defaultProps.filterItems = filterItems;
268
248
  const data = {
269
249
  data: [
270
250
  { id: 1, title: "Offline", status: "offline" },
@@ -285,7 +265,13 @@ describe("LiveFilter events", () => {
285
265
  await act(async () => {
286
266
  render(
287
267
  <ThemeProvider theme={parseTheme(globalTheme)}>
288
- <LiveFilter {...defaultProps} />
268
+ <LiveFilter
269
+ {...makeProps({
270
+ value: [{ value: "all", label: "All" }],
271
+ filterOptions: ["offline", "active", "scheduled"],
272
+ filterItems: filterItems,
273
+ })}
274
+ />
289
275
  </ThemeProvider>,
290
276
  );
291
277
  });
@@ -10,18 +10,22 @@ import StatusFilter, { IStatusFilterProps } from "@ax/components/TableFilters/St
10
10
  import { IQueryValue } from "@ax/types";
11
11
 
12
12
  afterEach(cleanup);
13
- const defaultProps = mock<IStatusFilterProps>();
13
+ const makeProps = (overrides: Partial<IStatusFilterProps> = {}): IStatusFilterProps =>
14
+ Object.assign(mock<IStatusFilterProps>(), overrides);
14
15
  describe("StatusFilter component rendering", () => {
15
16
  it("should render date filter", () => {
16
17
  const onClickMock = vi.fn() as CalledWithMock<any, [orderPointer: IQueryValue[], isAscendent: boolean]> &
17
18
  ((orderPointer: IQueryValue[], isAscendent: boolean) => any);
18
- defaultProps.sortedState = { isAscending: false, sortedByDate: false, sortedByTitle: false, sortedByURL: false };
19
- defaultProps.sortItems = onClickMock;
20
- defaultProps.isStructuredData = false;
21
19
 
22
20
  render(
23
21
  <ThemeProvider theme={parseTheme(globalTheme)}>
24
- <StatusFilter {...defaultProps} />
22
+ <StatusFilter
23
+ {...makeProps({
24
+ sortedState: { isAscending: false, sortedByDate: false, sortedByTitle: false, sortedByURL: false },
25
+ sortItems: onClickMock,
26
+ isStructuredData: false,
27
+ })}
28
+ />
25
29
  </ThemeProvider>,
26
30
  );
27
31
 
@@ -33,13 +37,16 @@ describe("StatusFilter component rendering", () => {
33
37
  it("should render interactive arrow if not filter selected", () => {
34
38
  const onClickMock = vi.fn() as CalledWithMock<any, [orderPointer: IQueryValue[], isAscendent: boolean]> &
35
39
  ((orderPointer: IQueryValue[], isAscendent: boolean) => any);
36
- defaultProps.sortedState = { isAscending: false, sortedByDate: false, sortedByTitle: false, sortedByURL: false };
37
- defaultProps.sortItems = onClickMock;
38
- defaultProps.isStructuredData = false;
39
40
 
40
41
  render(
41
42
  <ThemeProvider theme={parseTheme(globalTheme)}>
42
- <StatusFilter {...defaultProps} />
43
+ <StatusFilter
44
+ {...makeProps({
45
+ sortedState: { isAscending: false, sortedByDate: false, sortedByTitle: false, sortedByURL: false },
46
+ sortItems: onClickMock,
47
+ isStructuredData: false,
48
+ })}
49
+ />
43
50
  </ThemeProvider>,
44
51
  );
45
52
 
@@ -50,13 +57,16 @@ describe("StatusFilter component rendering", () => {
50
57
  it("should render FullArrowDown icon if is filtered by most recent", () => {
51
58
  const onClickMock = vi.fn() as CalledWithMock<any, [orderPointer: IQueryValue[], isAscendent: boolean]> &
52
59
  ((orderPointer: IQueryValue[], isAscendent: boolean) => any);
53
- defaultProps.sortedState = { isAscending: false, sortedByDate: true, sortedByTitle: false, sortedByURL: false };
54
- defaultProps.sortItems = onClickMock;
55
- defaultProps.isStructuredData = false;
56
60
 
57
61
  render(
58
62
  <ThemeProvider theme={parseTheme(globalTheme)}>
59
- <StatusFilter {...defaultProps} />
63
+ <StatusFilter
64
+ {...makeProps({
65
+ sortedState: { isAscending: false, sortedByDate: true, sortedByTitle: false, sortedByURL: false },
66
+ sortItems: onClickMock,
67
+ isStructuredData: false,
68
+ })}
69
+ />
60
70
  </ThemeProvider>,
61
71
  );
62
72
 
@@ -68,12 +78,15 @@ describe("StatusFilter component rendering", () => {
68
78
  describe("StatusFilter events", () => {
69
79
  it("should render check group on click", () => {
70
80
  const onClickMock = vi.fn();
71
- defaultProps.sortedState = { isAscending: false, sortedByDate: false };
72
- defaultProps.sortItems = onClickMock as CalledWithMock<any, [orderPointer: IQueryValue[], isAscendent: boolean]> &
73
- ((orderPointer: IQueryValue[], isAscendent: boolean) => any);
74
81
  render(
75
82
  <ThemeProvider theme={parseTheme(globalTheme)}>
76
- <StatusFilter {...defaultProps} />
83
+ <StatusFilter
84
+ {...makeProps({
85
+ sortedState: { isAscending: false, sortedByDate: false },
86
+ sortItems: onClickMock as CalledWithMock<any, [orderPointer: IQueryValue[], isAscendent: boolean]> &
87
+ ((orderPointer: IQueryValue[], isAscendent: boolean) => any),
88
+ })}
89
+ />
77
90
  </ThemeProvider>,
78
91
  );
79
92
 
@@ -88,12 +101,15 @@ describe("StatusFilter events", () => {
88
101
 
89
102
  it("should call sortItems function with 'modified, true' as param when it's not structured data and is ascending", async () => {
90
103
  const onClickMock = vi.fn();
91
- defaultProps.sortedState = { isAscending: false, sortedByDate: false };
92
- defaultProps.sortItems = onClickMock as CalledWithMock<any, [orderPointer: IQueryValue[], isAscendent: boolean]> &
93
- ((orderPointer: IQueryValue[], isAscendent: boolean) => any);
94
104
  render(
95
105
  <ThemeProvider theme={parseTheme(globalTheme)}>
96
- <StatusFilter {...defaultProps} />
106
+ <StatusFilter
107
+ {...makeProps({
108
+ sortedState: { isAscending: false, sortedByDate: false },
109
+ sortItems: onClickMock as CalledWithMock<any, [orderPointer: IQueryValue[], isAscendent: boolean]> &
110
+ ((orderPointer: IQueryValue[], isAscendent: boolean) => any),
111
+ })}
112
+ />
97
113
  </ThemeProvider>,
98
114
  );
99
115
 
@@ -114,14 +130,17 @@ describe("StatusFilter events", () => {
114
130
 
115
131
  it("should call sortItems function with 'date, true' as param when it's not structured data and is asceding", async () => {
116
132
  const onClickMock = vi.fn();
117
- defaultProps.sortedState = { isAscending: false, sortedByDate: false };
118
- defaultProps.sortItems = onClickMock as CalledWithMock<any, [orderPointer: IQueryValue[], isAscendent: boolean]> &
119
- ((orderPointer: IQueryValue[], isAscendent: boolean) => any);
120
- defaultProps.isStructuredData = true;
121
133
 
122
134
  render(
123
135
  <ThemeProvider theme={parseTheme(globalTheme)}>
124
- <StatusFilter {...defaultProps} />
136
+ <StatusFilter
137
+ {...makeProps({
138
+ sortedState: { isAscending: false, sortedByDate: false },
139
+ sortItems: onClickMock as CalledWithMock<any, [orderPointer: IQueryValue[], isAscendent: boolean]> &
140
+ ((orderPointer: IQueryValue[], isAscendent: boolean) => any),
141
+ isStructuredData: true,
142
+ })}
143
+ />
125
144
  </ThemeProvider>,
126
145
  );
127
146
 
@@ -141,14 +160,17 @@ describe("StatusFilter events", () => {
141
160
 
142
161
  it("should call sortItems function with 'modified, false' as param when it's not structured data and is not ascending", async () => {
143
162
  const onClickMock = vi.fn();
144
- defaultProps.sortedState = { isAscending: false, sortedByDate: false };
145
- defaultProps.sortItems = onClickMock as CalledWithMock<any, [orderPointer: IQueryValue[], isAscendent: boolean]> &
146
- ((orderPointer: IQueryValue[], isAscendent: boolean) => any);
147
- defaultProps.isStructuredData = false;
148
163
 
149
164
  render(
150
165
  <ThemeProvider theme={parseTheme(globalTheme)}>
151
- <StatusFilter {...defaultProps} />
166
+ <StatusFilter
167
+ {...makeProps({
168
+ sortedState: { isAscending: false, sortedByDate: false },
169
+ sortItems: onClickMock as CalledWithMock<any, [orderPointer: IQueryValue[], isAscendent: boolean]> &
170
+ ((orderPointer: IQueryValue[], isAscendent: boolean) => any),
171
+ isStructuredData: false,
172
+ })}
173
+ />
152
174
  </ThemeProvider>,
153
175
  );
154
176
 
@@ -169,14 +191,17 @@ describe("StatusFilter events", () => {
169
191
 
170
192
  it("should call sortItems function with 'date, false' as param when it's not structured data and is not asceding", async () => {
171
193
  const onClickMock = vi.fn();
172
- defaultProps.sortedState = { isAscending: false, sortedByDate: false };
173
- defaultProps.sortItems = onClickMock as CalledWithMock<any, [orderPointer: IQueryValue[], isAscendent: boolean]> &
174
- ((orderPointer: IQueryValue[], isAscendent: boolean) => any);
175
- defaultProps.isStructuredData = true;
176
194
 
177
195
  render(
178
196
  <ThemeProvider theme={parseTheme(globalTheme)}>
179
- <StatusFilter {...defaultProps} />
197
+ <StatusFilter
198
+ {...makeProps({
199
+ sortedState: { isAscending: false, sortedByDate: false },
200
+ sortItems: onClickMock as CalledWithMock<any, [orderPointer: IQueryValue[], isAscendent: boolean]> &
201
+ ((orderPointer: IQueryValue[], isAscendent: boolean) => any),
202
+ isStructuredData: true,
203
+ })}
204
+ />
180
205
  </ThemeProvider>,
181
206
  );
182
207
 
@@ -11,18 +11,15 @@ import Tabs, { ITabsProps } from "@ax/components/Tabs";
11
11
 
12
12
  afterEach(cleanup);
13
13
 
14
- const defaultProps = mock<ITabsProps>();
14
+ const makeProps = (overrides: Partial<ITabsProps> = {}): ITabsProps => Object.assign(mock<ITabsProps>(), overrides);
15
15
 
16
16
  describe("Tabs component rendering", () => {
17
17
  it("should render tabs", () => {
18
- defaultProps.tabs = ["tab1", "tab2"];
19
- defaultProps.active = "tab1";
20
18
  const setSelectedTabAction = vi.fn();
21
- defaultProps.setSelectedTab = setSelectedTabAction;
22
19
 
23
20
  render(
24
21
  <ThemeProvider theme={parseTheme(globalTheme)}>
25
- <Tabs {...defaultProps} />
22
+ <Tabs {...makeProps({ tabs: ["tab1", "tab2"], active: "tab1", setSelectedTab: setSelectedTabAction })} />
26
23
  </ThemeProvider>,
27
24
  );
28
25
 
@@ -34,15 +31,13 @@ describe("Tabs component rendering", () => {
34
31
  });
35
32
 
36
33
  it("should render an empty tabs row when no tabs or icons", () => {
37
- defaultProps.tabs = undefined;
38
- defaultProps.icons = undefined;
39
- defaultProps.active = "tab1";
40
34
  const setSelectedTabAction = vi.fn();
41
- defaultProps.setSelectedTab = setSelectedTabAction;
42
35
 
43
36
  render(
44
37
  <ThemeProvider theme={parseTheme(globalTheme)}>
45
- <Tabs {...defaultProps} />
38
+ <Tabs
39
+ {...makeProps({ tabs: undefined, icons: undefined, active: "tab1", setSelectedTab: setSelectedTabAction })}
40
+ />
46
41
  </ThemeProvider>,
47
42
  );
48
43
 
@@ -52,14 +47,11 @@ describe("Tabs component rendering", () => {
52
47
  });
53
48
 
54
49
  it("should call set selected tab action on click", async () => {
55
- defaultProps.tabs = ["tab1", "tab2"];
56
- defaultProps.active = "tab1";
57
50
  const setSelectedTabAction = vi.fn();
58
- defaultProps.setSelectedTab = setSelectedTabAction;
59
51
 
60
52
  render(
61
53
  <ThemeProvider theme={parseTheme(globalTheme)}>
62
- <Tabs {...defaultProps} />
54
+ <Tabs {...makeProps({ tabs: ["tab1", "tab2"], active: "tab1", setSelectedTab: setSelectedTabAction })} />
63
55
  </ThemeProvider>,
64
56
  );
65
57
  const tabs = screen.getAllByTestId("tab");
@@ -68,15 +60,17 @@ describe("Tabs component rendering", () => {
68
60
  });
69
61
 
70
62
  it("should render tabs row with icons if icons available", async () => {
71
- defaultProps.tabs = undefined;
72
- defaultProps.icons = [
73
- { name: "edit", text: "Edit mode" },
74
- { name: "view", text: "Preview mode" },
75
- ];
76
-
77
63
  render(
78
64
  <ThemeProvider theme={parseTheme(globalTheme)}>
79
- <Tabs {...defaultProps} />
65
+ <Tabs
66
+ {...makeProps({
67
+ tabs: undefined,
68
+ icons: [
69
+ { name: "edit", text: "Edit mode" },
70
+ { name: "view", text: "Preview mode" },
71
+ ],
72
+ })}
73
+ />
80
74
  </ThemeProvider>,
81
75
  );
82
76
 
@@ -85,15 +79,17 @@ describe("Tabs component rendering", () => {
85
79
  });
86
80
 
87
81
  it("should render tabs row with icons if icons available", async () => {
88
- defaultProps.tabs = undefined;
89
- defaultProps.icons = [
90
- { name: "edit", text: "Edit mode" },
91
- { name: "view", text: "Preview mode" },
92
- ];
93
-
94
82
  render(
95
83
  <ThemeProvider theme={parseTheme(globalTheme)}>
96
- <Tabs {...defaultProps} />
84
+ <Tabs
85
+ {...makeProps({
86
+ tabs: undefined,
87
+ icons: [
88
+ { name: "edit", text: "Edit mode" },
89
+ { name: "view", text: "Preview mode" },
90
+ ],
91
+ })}
92
+ />
97
93
  </ThemeProvider>,
98
94
  );
99
95
 
@@ -104,15 +100,17 @@ describe("Tabs component rendering", () => {
104
100
  });
105
101
 
106
102
  it("should render tooltip with icon's text", async () => {
107
- defaultProps.tabs = undefined;
108
- defaultProps.icons = [
109
- { name: "edit", text: "Edit mode" },
110
- { name: "view", text: "Preview mode" },
111
- ];
112
-
113
103
  render(
114
104
  <ThemeProvider theme={parseTheme(globalTheme)}>
115
- <Tabs {...defaultProps} />
105
+ <Tabs
106
+ {...makeProps({
107
+ tabs: undefined,
108
+ icons: [
109
+ { name: "edit", text: "Edit mode" },
110
+ { name: "view", text: "Preview mode" },
111
+ ],
112
+ })}
113
+ />
116
114
  </ThemeProvider>,
117
115
  );
118
116
 
@@ -124,17 +122,20 @@ describe("Tabs component rendering", () => {
124
122
  });
125
123
 
126
124
  it("should not display icon if doesn't exist", async () => {
127
- defaultProps.icons = [
128
- { name: "failed-icon", text: "Edit mode" },
129
- { name: "view", text: "Preview mode" },
130
- ];
131
- defaultProps.active = "edit";
132
125
  const setSelectedTabAction = vi.fn();
133
- defaultProps.setSelectedTab = setSelectedTabAction;
134
126
 
135
127
  render(
136
128
  <ThemeProvider theme={parseTheme(globalTheme)}>
137
- <Tabs {...defaultProps} />
129
+ <Tabs
130
+ {...makeProps({
131
+ icons: [
132
+ { name: "failed-icon", text: "Edit mode" },
133
+ { name: "view", text: "Preview mode" },
134
+ ],
135
+ active: "edit",
136
+ setSelectedTab: setSelectedTabAction,
137
+ })}
138
+ />
138
139
  </ThemeProvider>,
139
140
  );
140
141
  const tooltips = screen.getAllByTestId("tooltip-component");
@@ -147,14 +148,11 @@ describe("Tabs component rendering", () => {
147
148
 
148
149
  describe("Tabs component events", () => {
149
150
  it("should set tab as active on click", async () => {
150
- defaultProps.tabs = ["tab1", "tab2"];
151
- defaultProps.active = "tab1";
152
151
  const setSelectedTabAction = vi.fn();
153
- defaultProps.setSelectedTab = setSelectedTabAction;
154
152
 
155
153
  render(
156
154
  <ThemeProvider theme={parseTheme(globalTheme)}>
157
- <Tabs {...defaultProps} />
155
+ <Tabs {...makeProps({ tabs: ["tab1", "tab2"], active: "tab1", setSelectedTab: setSelectedTabAction })} />
158
156
  </ThemeProvider>,
159
157
  );
160
158
  const tabs = screen.getAllByTestId("tab");
@@ -165,18 +163,21 @@ describe("Tabs component events", () => {
165
163
  });
166
164
 
167
165
  it("should call set selected tab action on click icon tab", async () => {
168
- defaultProps.tabs = undefined;
169
- defaultProps.icons = [
170
- { name: "edit", text: "Edit mode" },
171
- { name: "view", text: "Preview mode" },
172
- ];
173
- defaultProps.active = "edit";
174
166
  const setSelectedTabAction = vi.fn();
175
- defaultProps.setSelectedTab = setSelectedTabAction;
176
167
 
177
168
  render(
178
169
  <ThemeProvider theme={parseTheme(globalTheme)}>
179
- <Tabs {...defaultProps} />
170
+ <Tabs
171
+ {...makeProps({
172
+ tabs: undefined,
173
+ icons: [
174
+ { name: "edit", text: "Edit mode" },
175
+ { name: "view", text: "Preview mode" },
176
+ ],
177
+ active: "edit",
178
+ setSelectedTab: setSelectedTabAction,
179
+ })}
180
+ />
180
181
  </ThemeProvider>,
181
182
  );
182
183
  const tabs = screen.getAllByTestId("icon-tab");
@@ -185,17 +186,20 @@ describe("Tabs component events", () => {
185
186
  });
186
187
 
187
188
  it("should set icon tab as active on click", async () => {
188
- defaultProps.icons = [
189
- { name: "edit", text: "Edit mode" },
190
- { name: "view", text: "Preview mode" },
191
- ];
192
- defaultProps.active = "edit";
193
189
  const setSelectedTabAction = vi.fn();
194
- defaultProps.setSelectedTab = setSelectedTabAction;
195
190
 
196
191
  render(
197
192
  <ThemeProvider theme={parseTheme(globalTheme)}>
198
- <Tabs {...defaultProps} />
193
+ <Tabs
194
+ {...makeProps({
195
+ icons: [
196
+ { name: "edit", text: "Edit mode" },
197
+ { name: "view", text: "Preview mode" },
198
+ ],
199
+ active: "edit",
200
+ setSelectedTab: setSelectedTabAction,
201
+ })}
202
+ />
199
203
  </ThemeProvider>,
200
204
  );
201
205
  const tabs = screen.getAllByTestId("icon-tab");
@@ -17,18 +17,27 @@ vi.mock("react-router-dom", async () => ({
17
17
  }),
18
18
  }));
19
19
 
20
- const defaultProps = mock<IToastProps>();
20
+ const makeProps = (overrides: Partial<IToastProps> = {}): IToastProps => Object.assign(mock<IToastProps>(), overrides);
21
21
 
22
- describe("Toast component rendering", () => {
22
+ // El spy se instala sobre el setTimeout ya falseado, así que el orden importa.
23
+ // Van en hooks (no en el cuerpo del describe) para que se restauren tras cada
24
+ // test: en el cuerpo se ejecutaban una sola vez al recolectar y dejaban los
25
+ // timers falsos y el spy puestos para el resto del fichero.
26
+ beforeEach(() => {
23
27
  vi.useFakeTimers();
24
28
  vi.spyOn(global, "setTimeout");
29
+ });
25
30
 
26
- it("should render the component", () => {
27
- defaultProps.message = "1 module copied to clipboard";
31
+ afterEach(() => {
32
+ vi.useRealTimers();
33
+ vi.restoreAllMocks();
34
+ });
28
35
 
36
+ describe("Toast component rendering", () => {
37
+ it("should render the component", () => {
29
38
  render(
30
39
  <ThemeProvider theme={parseTheme(globalTheme)}>
31
- <Toast {...defaultProps} />
40
+ <Toast {...makeProps({ message: "1 module copied to clipboard" })} />
32
41
  </ThemeProvider>,
33
42
  );
34
43
 
@@ -37,11 +46,9 @@ describe("Toast component rendering", () => {
37
46
  });
38
47
 
39
48
  it("should render the component's message", () => {
40
- defaultProps.message = "1 module copied to clipboard";
41
-
42
49
  render(
43
50
  <ThemeProvider theme={parseTheme(globalTheme)}>
44
- <Toast {...defaultProps} />
51
+ <Toast {...makeProps({ message: "1 module copied to clipboard" })} />
45
52
  </ThemeProvider>,
46
53
  );
47
54
 
@@ -50,11 +57,9 @@ describe("Toast component rendering", () => {
50
57
  });
51
58
 
52
59
  it("should not render the undo button when no action", () => {
53
- defaultProps.message = "1 module copied to clipboard";
54
-
55
60
  render(
56
61
  <ThemeProvider theme={parseTheme(globalTheme)}>
57
- <Toast {...defaultProps} />
62
+ <Toast {...makeProps({ message: "1 module copied to clipboard" })} />
58
63
  </ThemeProvider>,
59
64
  );
60
65
 
@@ -65,12 +70,9 @@ describe("Toast component rendering", () => {
65
70
 
66
71
  describe("Toast component events", () => {
67
72
  it("should render the undo button when action", () => {
68
- defaultProps.message = "1 module copied to clipboard";
69
- defaultProps.action = vi.fn();
70
-
71
73
  render(
72
74
  <ThemeProvider theme={parseTheme(globalTheme)}>
73
- <Toast {...defaultProps} />
75
+ <Toast {...makeProps({ message: "1 module copied to clipboard", action: vi.fn() })} />
74
76
  </ThemeProvider>,
75
77
  );
76
78
 
@@ -79,11 +81,9 @@ describe("Toast component events", () => {
79
81
  });
80
82
 
81
83
  it("should change visibility after 5000 ms", async () => {
82
- defaultProps.message = "1 module copied to clipboard";
83
-
84
84
  render(
85
85
  <ThemeProvider theme={parseTheme(globalTheme)}>
86
- <Toast {...defaultProps} />
86
+ <Toast {...makeProps({ message: "1 module copied to clipboard" })} />
87
87
  </ThemeProvider>,
88
88
  );
89
89
 
@@ -92,11 +92,9 @@ describe("Toast component events", () => {
92
92
  });
93
93
 
94
94
  it("should contain closing animation class on click close button", async () => {
95
- defaultProps.message = "1 module copied to clipboard";
96
-
97
95
  render(
98
96
  <ThemeProvider theme={parseTheme(globalTheme)}>
99
- <Toast {...defaultProps} />
97
+ <Toast {...makeProps({ message: "1 module copied to clipboard" })} />
100
98
  </ThemeProvider>,
101
99
  );
102
100
 
@@ -103,6 +103,22 @@ afterEach(() => {
103
103
  vi.restoreAllMocks();
104
104
  });
105
105
 
106
+ // Los valores por defecto se definen dentro de las factorías de `vi.mock`, que
107
+ // solo corren al cargar el módulo, mientras que el `restoreAllMocks` de arriba
108
+ // los borra tras cada test. Los tests que no fijan los suyos dependían de ser
109
+ // los primeros; aquí se rehacen antes de cada uno.
110
+ beforeEach(() => {
111
+ (hooks.useURLSearchParam as Mock).mockReturnValue(null);
112
+ (hooks.useToast as Mock).mockReturnValue({
113
+ isVisible: false,
114
+ toggleToast: vi.fn(),
115
+ setIsVisible: vi.fn(),
116
+ state: "",
117
+ });
118
+ (frameUtils.observeAndAddIdsToHeadings as Mock).mockReturnValue(vi.fn());
119
+ (frameUtils.observeAndHighlightKeywords as Mock).mockReturnValue(vi.fn());
120
+ });
121
+
106
122
  describe("FramePreview rendering", () => {
107
123
  it("should render Loading when isLoading is true from Redux state", async () => {
108
124
  await renderFramePreview(buildStore({ isLoading: true }));