@osimatic/helpers-js 1.5.2 → 1.5.4
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.
- package/count_down.js +46 -48
- package/date_time.js +0 -1
- package/details_sub_array.js +65 -50
- package/flash_message.js +10 -6
- package/form_date.js +144 -153
- package/form_helper.js +283 -232
- package/google_charts.js +154 -144
- package/google_maps.js +1 -1
- package/import_from_csv.js +198 -160
- package/multi_files_input.js +44 -35
- package/multiple_action_in_table.js +123 -109
- package/package.json +1 -1
- package/paging.js +103 -84
- package/select_all.js +65 -70
- package/sortable_list.js +12 -13
- package/tests/count_down.test.js +131 -352
- package/tests/details_sub_array.test.js +213 -258
- package/tests/flash_message.test.js +21 -153
- package/tests/form_date.test.js +287 -961
- package/tests/form_helper.test.js +553 -673
- package/tests/google_charts.test.js +338 -339
- package/tests/google_maps.test.js +3 -15
- package/tests/import_from_csv.test.js +421 -640
- package/tests/multi_files_input.test.js +305 -737
- package/tests/multiple_action_in_table.test.js +442 -429
- package/tests/open_street_map.test.js +15 -23
- package/tests/paging.test.js +344 -475
- package/tests/select_all.test.js +232 -318
- package/tests/sortable_list.test.js +176 -500
- package/tests/user.test.js +163 -54
- package/user.js +35 -38
|
@@ -2,278 +2,219 @@
|
|
|
2
2
|
* @jest-environment jsdom
|
|
3
3
|
*/
|
|
4
4
|
const { DetailsSubArray } = require('../details_sub_array');
|
|
5
|
-
|
|
6
|
-
// Mock HTTPClient
|
|
7
|
-
jest.mock('../http_client', () => ({
|
|
8
|
-
HTTPClient: {
|
|
9
|
-
request: jest.fn()
|
|
10
|
-
}
|
|
11
|
-
}));
|
|
12
|
-
|
|
13
5
|
const { HTTPClient } = require('../http_client');
|
|
14
6
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
7
|
+
function setupTable(nbLinks = 1) {
|
|
8
|
+
document.body.innerHTML = `
|
|
9
|
+
<table>
|
|
10
|
+
<thead>
|
|
11
|
+
<tr>
|
|
12
|
+
<th>Col1</th><th>Col2</th><th>Col3</th><th>Col4</th><th>Col5</th>
|
|
13
|
+
</tr>
|
|
14
|
+
</thead>
|
|
15
|
+
<tbody>
|
|
16
|
+
${Array.from({ length: nbLinks }, (_, i) => `
|
|
17
|
+
<tr id="tr${i}">
|
|
18
|
+
<td><a class="details_link hide" data-url_details="http://example.com/details/${i}">Details</a></td>
|
|
19
|
+
</tr>`).join('')}
|
|
20
|
+
</tbody>
|
|
21
|
+
</table>
|
|
22
|
+
`;
|
|
23
|
+
return document.querySelector('table');
|
|
24
|
+
}
|
|
20
25
|
|
|
26
|
+
describe('DetailsSubArray', () => {
|
|
21
27
|
beforeEach(() => {
|
|
22
|
-
|
|
23
|
-
jest.clearAllMocks();
|
|
24
|
-
|
|
25
|
-
// Define global labels used by the code
|
|
26
|
-
global.showDetailsLabel = 'Show details';
|
|
27
|
-
global.hideDetailsLabel = 'Hide details';
|
|
28
|
-
global.labelErrorOccured = 'An error occurred';
|
|
29
|
-
|
|
30
|
-
// Make HTTPClient available globally
|
|
31
|
-
global.HTTPClient = HTTPClient;
|
|
32
|
-
|
|
33
|
-
// Create mock DOM structure
|
|
34
|
-
mockThead = {
|
|
35
|
-
find: jest.fn((selector) => {
|
|
36
|
-
if (selector === 'thead tr') {
|
|
37
|
-
return {
|
|
38
|
-
children: jest.fn(() => ({ length: 5 }))
|
|
39
|
-
};
|
|
40
|
-
}
|
|
41
|
-
return {
|
|
42
|
-
children: jest.fn(() => ({ length: 5 }))
|
|
43
|
-
};
|
|
44
|
-
})
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
mockTr = {
|
|
48
|
-
closest: jest.fn((selector) => {
|
|
49
|
-
if (selector === 'table') {
|
|
50
|
-
return {
|
|
51
|
-
find: jest.fn((sel) => {
|
|
52
|
-
if (sel === 'thead tr') {
|
|
53
|
-
return {
|
|
54
|
-
children: jest.fn(() => ({ length: 5 }))
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
return mockThead;
|
|
58
|
-
})
|
|
59
|
-
};
|
|
60
|
-
}
|
|
61
|
-
return mockTr;
|
|
62
|
-
}),
|
|
63
|
-
after: jest.fn(),
|
|
64
|
-
addClass: jest.fn().mockReturnThis(),
|
|
65
|
-
next: jest.fn(() => ({
|
|
66
|
-
hasClass: jest.fn(() => false),
|
|
67
|
-
remove: jest.fn()
|
|
68
|
-
}))
|
|
69
|
-
};
|
|
70
|
-
|
|
71
|
-
mockLink = {
|
|
72
|
-
data: jest.fn((key) => {
|
|
73
|
-
if (key === 'url_details') return 'http://example.com/details';
|
|
74
|
-
return null;
|
|
75
|
-
}),
|
|
76
|
-
closest: jest.fn(() => mockTr),
|
|
77
|
-
prop: jest.fn().mockReturnThis(),
|
|
78
|
-
attr: jest.fn().mockReturnThis(),
|
|
79
|
-
html: jest.fn().mockReturnThis(),
|
|
80
|
-
click: jest.fn().mockReturnThis(),
|
|
81
|
-
stop: jest.fn().mockReturnThis(),
|
|
82
|
-
off: jest.fn().mockReturnThis(),
|
|
83
|
-
removeClass: jest.fn().mockReturnThis()
|
|
84
|
-
};
|
|
85
|
-
|
|
86
|
-
mockTable = {
|
|
87
|
-
find: jest.fn(() => ({
|
|
88
|
-
each: jest.fn((callback) => {
|
|
89
|
-
// Simulate one link found
|
|
90
|
-
callback(0, mockLink);
|
|
91
|
-
})
|
|
92
|
-
}))
|
|
93
|
-
};
|
|
94
|
-
|
|
95
|
-
// Mock jQuery
|
|
96
|
-
global.$ = jest.fn((selector) => {
|
|
97
|
-
if (typeof selector === 'string') {
|
|
98
|
-
if (selector.includes('<tr')) {
|
|
99
|
-
return {
|
|
100
|
-
find: jest.fn().mockReturnThis(),
|
|
101
|
-
append: jest.fn().mockReturnThis(),
|
|
102
|
-
after: jest.fn().mockReturnThis()
|
|
103
|
-
};
|
|
104
|
-
}
|
|
105
|
-
if (selector.includes('<span')) {
|
|
106
|
-
return selector; // Return the HTML string for glyphicon
|
|
107
|
-
}
|
|
108
|
-
if (selector.includes('<i')) {
|
|
109
|
-
return selector; // Return the HTML string for fa icons
|
|
110
|
-
}
|
|
111
|
-
return {
|
|
112
|
-
length: 0,
|
|
113
|
-
remove: jest.fn()
|
|
114
|
-
};
|
|
115
|
-
}
|
|
116
|
-
// Wrap element
|
|
117
|
-
return selector;
|
|
118
|
-
});
|
|
28
|
+
jest.spyOn(HTTPClient, 'request').mockImplementation(() => {});
|
|
119
29
|
});
|
|
120
30
|
|
|
121
31
|
afterEach(() => {
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
delete global.hideDetailsLabel;
|
|
125
|
-
delete global.labelErrorOccured;
|
|
126
|
-
delete global.HTTPClient;
|
|
32
|
+
jest.restoreAllMocks();
|
|
33
|
+
document.body.innerHTML = '';
|
|
127
34
|
});
|
|
128
35
|
|
|
129
36
|
describe('initDetailsLink', () => {
|
|
130
|
-
test('should initialize details links', () => {
|
|
131
|
-
|
|
37
|
+
test('should initialize details links and remove hide class', () => {
|
|
38
|
+
const table = setupTable();
|
|
39
|
+
DetailsSubArray.initDetailsLink(table);
|
|
132
40
|
|
|
133
|
-
|
|
134
|
-
expect(
|
|
41
|
+
const link = table.querySelector('a.details_link');
|
|
42
|
+
expect(link.classList.contains('hide')).toBe(false);
|
|
135
43
|
});
|
|
136
44
|
|
|
137
|
-
test('should
|
|
138
|
-
|
|
45
|
+
test('should show plus button initially', () => {
|
|
46
|
+
const table = setupTable();
|
|
47
|
+
DetailsSubArray.initDetailsLink(table);
|
|
139
48
|
|
|
140
|
-
|
|
49
|
+
const link = table.querySelector('a.details_link');
|
|
50
|
+
expect(link.innerHTML).toContain('glyphicon-plus');
|
|
141
51
|
});
|
|
142
52
|
|
|
143
|
-
test('should
|
|
144
|
-
|
|
53
|
+
test('should set showDetailsLabel as title initially', () => {
|
|
54
|
+
const table = setupTable();
|
|
55
|
+
DetailsSubArray.initDetailsLink(table, { showDetailsLabel: 'Show details' });
|
|
56
|
+
|
|
57
|
+
const link = table.querySelector('a.details_link');
|
|
58
|
+
expect(link.title).toBe('Show details');
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
test('should make HTTP request when link is clicked', () => {
|
|
62
|
+
const table = setupTable();
|
|
63
|
+
DetailsSubArray.initDetailsLink(table);
|
|
145
64
|
|
|
146
|
-
|
|
65
|
+
const link = table.querySelector('a.details_link');
|
|
66
|
+
link.click();
|
|
67
|
+
|
|
68
|
+
expect(HTTPClient.request).toHaveBeenCalledWith(
|
|
69
|
+
'GET',
|
|
70
|
+
'http://example.com/details/0',
|
|
71
|
+
null,
|
|
72
|
+
expect.any(Function),
|
|
73
|
+
expect.any(Function)
|
|
74
|
+
);
|
|
147
75
|
});
|
|
148
76
|
|
|
149
|
-
test('should
|
|
150
|
-
|
|
77
|
+
test('should disable link while loading', () => {
|
|
78
|
+
HTTPClient.request.mockImplementation(() => {
|
|
79
|
+
// Don't call callbacks — simulate loading state
|
|
80
|
+
});
|
|
151
81
|
|
|
152
|
-
|
|
82
|
+
const table = setupTable();
|
|
83
|
+
DetailsSubArray.initDetailsLink(table);
|
|
153
84
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
if (clickHandler) {
|
|
157
|
-
clickHandler.call(mockLink);
|
|
158
|
-
}
|
|
85
|
+
const link = table.querySelector('a.details_link');
|
|
86
|
+
link.click();
|
|
159
87
|
|
|
160
|
-
|
|
161
|
-
// (This tests that the callback is properly wired up)
|
|
88
|
+
expect(link.disabled).toBe(true);
|
|
162
89
|
});
|
|
163
90
|
|
|
164
|
-
test('should
|
|
165
|
-
|
|
91
|
+
test('should show loading row while request is pending', () => {
|
|
92
|
+
HTTPClient.request.mockImplementation(() => {});
|
|
93
|
+
|
|
94
|
+
const table = setupTable();
|
|
95
|
+
DetailsSubArray.initDetailsLink(table);
|
|
166
96
|
|
|
167
|
-
|
|
97
|
+
const link = table.querySelector('a.details_link');
|
|
98
|
+
const tr = link.closest('tr');
|
|
99
|
+
link.click();
|
|
168
100
|
|
|
169
|
-
|
|
170
|
-
expect(
|
|
101
|
+
const loadingRow = tr.nextElementSibling;
|
|
102
|
+
expect(loadingRow).not.toBeNull();
|
|
103
|
+
expect(loadingRow.classList.contains('waiting_icon')).toBe(true);
|
|
171
104
|
});
|
|
172
105
|
|
|
173
|
-
test('should
|
|
174
|
-
const
|
|
106
|
+
test('should call success callback with JSON response', () => {
|
|
107
|
+
const jsonResponse = { items: ['item1', 'item2'] };
|
|
108
|
+
const successCallback = jest.fn(() => '<div>Details</div>');
|
|
175
109
|
|
|
176
|
-
|
|
110
|
+
HTTPClient.request.mockImplementation((method, url, data, successCb) => {
|
|
111
|
+
successCb(jsonResponse);
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
const table = setupTable();
|
|
115
|
+
DetailsSubArray.initDetailsLink(table, { onSuccess: successCallback });
|
|
116
|
+
|
|
117
|
+
const link = table.querySelector('a.details_link');
|
|
118
|
+
link.click();
|
|
177
119
|
|
|
178
|
-
|
|
179
|
-
expect(mockTable.find).toHaveBeenCalled();
|
|
120
|
+
expect(successCallback).toHaveBeenCalledWith(jsonResponse, link);
|
|
180
121
|
});
|
|
181
122
|
|
|
182
|
-
test('should
|
|
183
|
-
HTTPClient.request.mockImplementation((method, url, data, successCb
|
|
123
|
+
test('should show details row after successful request', () => {
|
|
124
|
+
HTTPClient.request.mockImplementation((method, url, data, successCb) => {
|
|
184
125
|
successCb({ data: 'test' });
|
|
185
126
|
});
|
|
186
127
|
|
|
187
|
-
const
|
|
188
|
-
DetailsSubArray.initDetailsLink(
|
|
128
|
+
const table = setupTable();
|
|
129
|
+
DetailsSubArray.initDetailsLink(table, { onSuccess: jest.fn(() => '<div class="content">Details</div>') });
|
|
189
130
|
|
|
190
|
-
|
|
191
|
-
const
|
|
192
|
-
|
|
193
|
-
clickHandler.call(mockLink);
|
|
194
|
-
}
|
|
131
|
+
const link = table.querySelector('a.details_link');
|
|
132
|
+
const tr = link.closest('tr');
|
|
133
|
+
link.click();
|
|
195
134
|
|
|
196
|
-
|
|
197
|
-
expect(
|
|
198
|
-
|
|
199
|
-
'http://example.com/details',
|
|
200
|
-
null,
|
|
201
|
-
expect.any(Function),
|
|
202
|
-
expect.any(Function)
|
|
203
|
-
);
|
|
135
|
+
const detailsRow = tr.nextElementSibling;
|
|
136
|
+
expect(detailsRow).not.toBeNull();
|
|
137
|
+
expect(detailsRow.classList.contains('participants')).toBe(true);
|
|
204
138
|
});
|
|
205
139
|
|
|
206
|
-
test('should
|
|
140
|
+
test('should show minus button after successful request', () => {
|
|
207
141
|
HTTPClient.request.mockImplementation((method, url, data, successCb) => {
|
|
208
|
-
successCb(
|
|
142
|
+
successCb({ data: 'test' });
|
|
209
143
|
});
|
|
210
144
|
|
|
211
|
-
|
|
145
|
+
const table = setupTable();
|
|
146
|
+
DetailsSubArray.initDetailsLink(table, { onSuccess: jest.fn(() => '') });
|
|
212
147
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
if (clickHandler) {
|
|
216
|
-
clickHandler.call(mockLink);
|
|
217
|
-
}
|
|
148
|
+
const link = table.querySelector('a.details_link');
|
|
149
|
+
link.click();
|
|
218
150
|
|
|
219
|
-
|
|
220
|
-
expect(mockTr.after).toHaveBeenCalled();
|
|
151
|
+
expect(link.innerHTML).toContain('glyphicon-minus');
|
|
221
152
|
});
|
|
222
153
|
|
|
223
|
-
test('should
|
|
224
|
-
HTTPClient.request.mockImplementation((method, url, data, successCb
|
|
225
|
-
|
|
154
|
+
test('should set hideDetailsLabel as title after loading', () => {
|
|
155
|
+
HTTPClient.request.mockImplementation((method, url, data, successCb) => {
|
|
156
|
+
successCb({ data: 'test' });
|
|
226
157
|
});
|
|
227
158
|
|
|
228
|
-
|
|
159
|
+
const table = setupTable();
|
|
160
|
+
DetailsSubArray.initDetailsLink(table, {
|
|
161
|
+
onSuccess: jest.fn(() => ''),
|
|
162
|
+
hideDetailsLabel: 'Hide details',
|
|
163
|
+
});
|
|
229
164
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
if (clickHandler) {
|
|
233
|
-
clickHandler.call(mockLink);
|
|
234
|
-
}
|
|
165
|
+
const link = table.querySelector('a.details_link');
|
|
166
|
+
link.click();
|
|
235
167
|
|
|
236
|
-
|
|
237
|
-
expect(mockTr.after).toHaveBeenCalled();
|
|
168
|
+
expect(link.title).toBe('Hide details');
|
|
238
169
|
});
|
|
239
170
|
|
|
240
|
-
test('should
|
|
241
|
-
const jsonResponse = { items: ['item1', 'item2'] };
|
|
242
|
-
const successCallback = jest.fn(() => '<div>Details</div>');
|
|
243
|
-
|
|
171
|
+
test('should hide details row when clicking minus button', () => {
|
|
244
172
|
HTTPClient.request.mockImplementation((method, url, data, successCb) => {
|
|
245
|
-
successCb(
|
|
173
|
+
successCb({ data: 'test' });
|
|
246
174
|
});
|
|
247
175
|
|
|
248
|
-
|
|
176
|
+
const table = setupTable();
|
|
177
|
+
DetailsSubArray.initDetailsLink(table, { onSuccess: jest.fn(() => '<div>Details</div>') });
|
|
249
178
|
|
|
250
|
-
|
|
251
|
-
const
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
}
|
|
179
|
+
const link = table.querySelector('a.details_link');
|
|
180
|
+
const tr = link.closest('tr');
|
|
181
|
+
link.click(); // open
|
|
182
|
+
expect(tr.nextElementSibling?.classList.contains('participants')).toBe(true);
|
|
255
183
|
|
|
256
|
-
//
|
|
257
|
-
expect(
|
|
184
|
+
link.click(); // close
|
|
185
|
+
expect(tr.nextElementSibling?.classList.contains('participants')).toBeFalsy();
|
|
258
186
|
});
|
|
259
187
|
|
|
260
|
-
test('should
|
|
261
|
-
|
|
188
|
+
test('should display error row when response is null with no error callback', () => {
|
|
189
|
+
HTTPClient.request.mockImplementation((method, url, data, successCb) => {
|
|
190
|
+
successCb(null);
|
|
191
|
+
});
|
|
262
192
|
|
|
193
|
+
const table = setupTable();
|
|
194
|
+
DetailsSubArray.initDetailsLink(table);
|
|
195
|
+
|
|
196
|
+
const link = table.querySelector('a.details_link');
|
|
197
|
+
const tr = link.closest('tr');
|
|
198
|
+
link.click();
|
|
199
|
+
|
|
200
|
+
expect(tr.nextElementSibling).not.toBeNull();
|
|
201
|
+
expect(tr.nextElementSibling.classList.contains('text-error')).toBe(true);
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
test('should display error row when HTTP request fails with no error callback', () => {
|
|
263
205
|
HTTPClient.request.mockImplementation((method, url, data, successCb, errorCb) => {
|
|
264
206
|
errorCb();
|
|
265
207
|
});
|
|
266
208
|
|
|
267
|
-
|
|
209
|
+
const table = setupTable();
|
|
210
|
+
DetailsSubArray.initDetailsLink(table);
|
|
268
211
|
|
|
269
|
-
|
|
270
|
-
const
|
|
271
|
-
|
|
272
|
-
clickHandler.call(mockLink);
|
|
273
|
-
}
|
|
212
|
+
const link = table.querySelector('a.details_link');
|
|
213
|
+
const tr = link.closest('tr');
|
|
214
|
+
link.click();
|
|
274
215
|
|
|
275
|
-
|
|
276
|
-
expect(
|
|
216
|
+
expect(tr.nextElementSibling).not.toBeNull();
|
|
217
|
+
expect(tr.nextElementSibling.classList.contains('error')).toBe(true);
|
|
277
218
|
});
|
|
278
219
|
|
|
279
220
|
test('should call error callback when response is null', () => {
|
|
@@ -283,85 +224,99 @@ describe('DetailsSubArray', () => {
|
|
|
283
224
|
successCb(null);
|
|
284
225
|
});
|
|
285
226
|
|
|
286
|
-
|
|
227
|
+
const table = setupTable();
|
|
228
|
+
DetailsSubArray.initDetailsLink(table, { onError: errorCallback });
|
|
229
|
+
|
|
230
|
+
const link = table.querySelector('a.details_link');
|
|
231
|
+
link.click();
|
|
232
|
+
|
|
233
|
+
expect(errorCallback).toHaveBeenCalledWith(link);
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
test('should call error callback on HTTP error', () => {
|
|
237
|
+
const errorCallback = jest.fn();
|
|
238
|
+
|
|
239
|
+
HTTPClient.request.mockImplementation((method, url, data, successCb, errorCb) => {
|
|
240
|
+
errorCb();
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
const table = setupTable();
|
|
244
|
+
DetailsSubArray.initDetailsLink(table, { onError: errorCallback });
|
|
287
245
|
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
if (clickHandler) {
|
|
291
|
-
clickHandler.call(mockLink);
|
|
292
|
-
}
|
|
246
|
+
const link = table.querySelector('a.details_link');
|
|
247
|
+
link.click();
|
|
293
248
|
|
|
294
|
-
|
|
295
|
-
expect(errorCallback).toHaveBeenCalledWith(mockLink);
|
|
249
|
+
expect(errorCallback).toHaveBeenCalledWith(link);
|
|
296
250
|
});
|
|
297
251
|
|
|
298
252
|
test('should use before send callback instead of HTTP request', () => {
|
|
299
253
|
const beforeSendCallback = jest.fn(() => '<div>Immediate content</div>');
|
|
300
254
|
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
// Simulate click
|
|
304
|
-
const clickHandler = mockLink.click.mock.calls[0][0];
|
|
305
|
-
if (clickHandler) {
|
|
306
|
-
clickHandler.call(mockLink);
|
|
307
|
-
}
|
|
255
|
+
const table = setupTable();
|
|
256
|
+
DetailsSubArray.initDetailsLink(table, { onBeforeSend: beforeSendCallback });
|
|
308
257
|
|
|
309
|
-
|
|
310
|
-
|
|
258
|
+
const link = table.querySelector('a.details_link');
|
|
259
|
+
link.click();
|
|
311
260
|
|
|
312
|
-
|
|
261
|
+
expect(beforeSendCallback).toHaveBeenCalledWith(link);
|
|
313
262
|
expect(HTTPClient.request).not.toHaveBeenCalled();
|
|
314
263
|
});
|
|
315
264
|
|
|
316
|
-
test('should
|
|
317
|
-
const
|
|
265
|
+
test('should show details row when using before send callback', () => {
|
|
266
|
+
const table = setupTable();
|
|
267
|
+
DetailsSubArray.initDetailsLink(table, { onBeforeSend: jest.fn(() => '<div>Immediate</div>') });
|
|
318
268
|
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
callback(1, mockLink2);
|
|
323
|
-
})
|
|
324
|
-
}));
|
|
269
|
+
const link = table.querySelector('a.details_link');
|
|
270
|
+
const tr = link.closest('tr');
|
|
271
|
+
link.click();
|
|
325
272
|
|
|
326
|
-
|
|
273
|
+
const detailsRow = tr.nextElementSibling;
|
|
274
|
+
expect(detailsRow).not.toBeNull();
|
|
275
|
+
expect(detailsRow.classList.contains('participants')).toBe(true);
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
test('should handle multiple links independently', () => {
|
|
279
|
+
const table = setupTable(2);
|
|
280
|
+
DetailsSubArray.initDetailsLink(table);
|
|
327
281
|
|
|
328
|
-
|
|
329
|
-
expect(
|
|
282
|
+
const links = table.querySelectorAll('a.details_link');
|
|
283
|
+
expect(links.length).toBe(2);
|
|
284
|
+
links.forEach(link => {
|
|
285
|
+
expect(link.innerHTML).toContain('glyphicon-plus');
|
|
286
|
+
expect(link.classList.contains('hide')).toBe(false);
|
|
287
|
+
});
|
|
330
288
|
});
|
|
331
289
|
|
|
332
|
-
test('should
|
|
333
|
-
HTTPClient.request.mockImplementation(() => {
|
|
334
|
-
|
|
290
|
+
test('should use colspan matching number of columns', () => {
|
|
291
|
+
HTTPClient.request.mockImplementation((method, url, data, successCb) => {
|
|
292
|
+
successCb(null);
|
|
335
293
|
});
|
|
336
294
|
|
|
337
|
-
|
|
295
|
+
const table = setupTable();
|
|
296
|
+
DetailsSubArray.initDetailsLink(table);
|
|
338
297
|
|
|
339
|
-
|
|
340
|
-
const
|
|
341
|
-
|
|
342
|
-
clickHandler.call(mockLink);
|
|
343
|
-
}
|
|
298
|
+
const link = table.querySelector('a.details_link');
|
|
299
|
+
const tr = link.closest('tr');
|
|
300
|
+
link.click();
|
|
344
301
|
|
|
345
|
-
|
|
346
|
-
expect(
|
|
302
|
+
const errorRow = tr.nextElementSibling;
|
|
303
|
+
expect(errorRow.querySelector('td').getAttribute('colspan')).toBe('5');
|
|
347
304
|
});
|
|
348
305
|
|
|
349
|
-
test('should
|
|
350
|
-
HTTPClient.request.mockImplementation(() => {
|
|
351
|
-
|
|
306
|
+
test('should use custom error label', () => {
|
|
307
|
+
HTTPClient.request.mockImplementation((method, url, data, successCb) => {
|
|
308
|
+
successCb(null);
|
|
352
309
|
});
|
|
353
310
|
|
|
354
|
-
|
|
311
|
+
const table = setupTable();
|
|
312
|
+
DetailsSubArray.initDetailsLink(table, { labelErrorOccurred: 'Custom error' });
|
|
355
313
|
|
|
356
|
-
|
|
357
|
-
const
|
|
358
|
-
|
|
359
|
-
clickHandler.call(mockLink);
|
|
360
|
-
}
|
|
314
|
+
const link = table.querySelector('a.details_link');
|
|
315
|
+
const tr = link.closest('tr');
|
|
316
|
+
link.click();
|
|
361
317
|
|
|
362
|
-
|
|
363
|
-
expect(
|
|
364
|
-
expect(mockTr.after).toHaveBeenCalled();
|
|
318
|
+
const errorRow = tr.nextElementSibling;
|
|
319
|
+
expect(errorRow.textContent).toContain('Custom error');
|
|
365
320
|
});
|
|
366
321
|
});
|
|
367
322
|
});
|