@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
package/tests/user.test.js
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @jest-environment jsdom
|
|
3
|
+
*/
|
|
1
4
|
const { Password } = require('../user');
|
|
2
5
|
|
|
6
|
+
function setupFormGroup(initialValue = '') {
|
|
7
|
+
const formGroup = document.createElement('div');
|
|
8
|
+
formGroup.className = 'form-group';
|
|
9
|
+
const input = document.createElement('input');
|
|
10
|
+
input.type = 'password';
|
|
11
|
+
input.value = initialValue;
|
|
12
|
+
formGroup.appendChild(input);
|
|
13
|
+
document.body.appendChild(formGroup);
|
|
14
|
+
return { formGroup, input };
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
afterEach(() => {
|
|
18
|
+
document.body.innerHTML = '';
|
|
19
|
+
});
|
|
20
|
+
|
|
3
21
|
describe('Password', () => {
|
|
4
22
|
describe('getPasswordStrength', () => {
|
|
5
23
|
test('should return 0 for empty password', () => {
|
|
@@ -145,60 +163,151 @@ describe('Password', () => {
|
|
|
145
163
|
});
|
|
146
164
|
|
|
147
165
|
describe('displayPasswordStrength', () => {
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
};
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
});
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
expect(()
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
166
|
+
test('should inject .password_strength_content into form-group', () => {
|
|
167
|
+
const { input } = setupFormGroup('Test1234!');
|
|
168
|
+
|
|
169
|
+
Password.displayPasswordStrength(input);
|
|
170
|
+
|
|
171
|
+
expect(document.querySelector('.password_strength_content')).not.toBeNull();
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
test('should inject strength bar and text elements', () => {
|
|
175
|
+
const { input } = setupFormGroup('Test1234!');
|
|
176
|
+
|
|
177
|
+
Password.displayPasswordStrength(input);
|
|
178
|
+
|
|
179
|
+
expect(document.querySelector('.password_strength_bar')).not.toBeNull();
|
|
180
|
+
expect(document.querySelector('.password_strength_text')).not.toBeNull();
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
test('should inject condition list items with data-condition', () => {
|
|
184
|
+
const { input } = setupFormGroup('');
|
|
185
|
+
|
|
186
|
+
Password.displayPasswordStrength(input);
|
|
187
|
+
|
|
188
|
+
const conditions = ['length', 'uppercase', 'lowercase', 'number', 'special'];
|
|
189
|
+
conditions.forEach(cond => {
|
|
190
|
+
expect(document.querySelector(`li[data-condition="${cond}"]`)).not.toBeNull();
|
|
191
|
+
});
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
test('should show "Fort" and success color for strong password', () => {
|
|
195
|
+
const { input } = setupFormGroup('AbCdE12!');
|
|
196
|
+
|
|
197
|
+
Password.displayPasswordStrength(input);
|
|
198
|
+
|
|
199
|
+
const text = document.querySelector('.password_strength_text');
|
|
200
|
+
expect(text.textContent).toBe('Fort');
|
|
201
|
+
expect(text.classList.contains('text-bg-success')).toBe(true);
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
test('should show "Moyen" and warning color for medium password', () => {
|
|
205
|
+
const { input } = setupFormGroup('AbCd1234');
|
|
206
|
+
|
|
207
|
+
Password.displayPasswordStrength(input);
|
|
208
|
+
|
|
209
|
+
const text = document.querySelector('.password_strength_text');
|
|
210
|
+
expect(text.textContent).toBe('Moyen');
|
|
211
|
+
expect(text.classList.contains('text-bg-warning')).toBe(true);
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
test('should show "Faible" and danger color for weak password', () => {
|
|
215
|
+
const { input } = setupFormGroup('abcdefgh');
|
|
216
|
+
|
|
217
|
+
Password.displayPasswordStrength(input);
|
|
218
|
+
|
|
219
|
+
const text = document.querySelector('.password_strength_text');
|
|
220
|
+
expect(text.textContent).toBe('Faible');
|
|
221
|
+
expect(text.classList.contains('text-bg-danger')).toBe(true);
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
test('should hide strength text for empty password', () => {
|
|
225
|
+
const { input } = setupFormGroup('');
|
|
226
|
+
|
|
227
|
+
Password.displayPasswordStrength(input);
|
|
228
|
+
|
|
229
|
+
const text = document.querySelector('.password_strength_text');
|
|
230
|
+
expect(text.classList.contains('hide')).toBe(true);
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
test('should set strength bar width based on score', () => {
|
|
234
|
+
const { input } = setupFormGroup('AbCdE12!'); // score=5
|
|
235
|
+
|
|
236
|
+
Password.displayPasswordStrength(input);
|
|
237
|
+
|
|
238
|
+
const bar = document.querySelector('.password_strength_bar');
|
|
239
|
+
const expectedWidth = ((5 / 6) * 100) + '%';
|
|
240
|
+
expect(bar.style.width).toBe(expectedWidth);
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
test('should mark satisfied conditions as text-success', () => {
|
|
244
|
+
const { input } = setupFormGroup('abcdefgh'); // satisfies: length, lowercase
|
|
245
|
+
|
|
246
|
+
Password.displayPasswordStrength(input);
|
|
247
|
+
|
|
248
|
+
expect(document.querySelector('li[data-condition="length"]').classList.contains('text-success')).toBe(true);
|
|
249
|
+
expect(document.querySelector('li[data-condition="lowercase"]').classList.contains('text-success')).toBe(true);
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
test('should mark unsatisfied conditions as text-danger', () => {
|
|
253
|
+
const { input } = setupFormGroup('abcdefgh'); // missing: uppercase, number, special
|
|
254
|
+
|
|
255
|
+
Password.displayPasswordStrength(input);
|
|
256
|
+
|
|
257
|
+
expect(document.querySelector('li[data-condition="uppercase"]').classList.contains('text-danger')).toBe(true);
|
|
258
|
+
expect(document.querySelector('li[data-condition="number"]').classList.contains('text-danger')).toBe(true);
|
|
259
|
+
expect(document.querySelector('li[data-condition="special"]').classList.contains('text-danger')).toBe(true);
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
test('should update display on input event', () => {
|
|
263
|
+
const { input } = setupFormGroup('');
|
|
264
|
+
|
|
265
|
+
Password.displayPasswordStrength(input);
|
|
266
|
+
|
|
267
|
+
input.value = 'AbCdE12!';
|
|
268
|
+
input.dispatchEvent(new Event('input'));
|
|
269
|
+
|
|
270
|
+
const text = document.querySelector('.password_strength_text');
|
|
271
|
+
expect(text.textContent).toBe('Fort');
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
test('should update display on change event', () => {
|
|
275
|
+
const { input } = setupFormGroup('');
|
|
276
|
+
|
|
277
|
+
Password.displayPasswordStrength(input);
|
|
278
|
+
|
|
279
|
+
input.value = 'AbCdE12!';
|
|
280
|
+
input.dispatchEvent(new Event('change'));
|
|
281
|
+
|
|
282
|
+
const text = document.querySelector('.password_strength_text');
|
|
283
|
+
expect(text.textContent).toBe('Fort');
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
test('should replace existing .password_strength_content on re-init', () => {
|
|
287
|
+
const { input } = setupFormGroup('Test1234!');
|
|
288
|
+
|
|
289
|
+
Password.displayPasswordStrength(input);
|
|
290
|
+
Password.displayPasswordStrength(input);
|
|
291
|
+
|
|
292
|
+
expect(document.querySelectorAll('.password_strength_content').length).toBe(1);
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
test('should set bg-success on bar for strong password', () => {
|
|
296
|
+
const { input } = setupFormGroup('AbCdE12!');
|
|
297
|
+
|
|
298
|
+
Password.displayPasswordStrength(input);
|
|
299
|
+
|
|
300
|
+
const bar = document.querySelector('.password_strength_bar');
|
|
301
|
+
expect(bar.classList.contains('bg-success')).toBe(true);
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
test('should set bg-warning on bar for medium password', () => {
|
|
305
|
+
const { input } = setupFormGroup('AbCd1234');
|
|
306
|
+
|
|
307
|
+
Password.displayPasswordStrength(input);
|
|
308
|
+
|
|
309
|
+
const bar = document.querySelector('.password_strength_bar');
|
|
310
|
+
expect(bar.classList.contains('bg-warning')).toBe(true);
|
|
202
311
|
});
|
|
203
312
|
});
|
|
204
313
|
});
|
package/user.js
CHANGED
|
@@ -15,13 +15,12 @@ class Password {
|
|
|
15
15
|
|
|
16
16
|
static displayPasswordStrength(input) {
|
|
17
17
|
function update(input) {
|
|
18
|
-
|
|
19
|
-
const
|
|
20
|
-
const div = input.closest('.form-group').find('.password_strength_content');
|
|
18
|
+
const password = input.value;
|
|
19
|
+
const div = input.closest('.form-group').querySelector('.password_strength_content');
|
|
21
20
|
const score = Password.getPasswordStrength(password);
|
|
22
21
|
|
|
23
|
-
const strengthBar = div.
|
|
24
|
-
const strengthText = div.
|
|
22
|
+
const strengthBar = div.querySelector('.password_strength_bar');
|
|
23
|
+
const strengthText = div.querySelector('.password_strength_text');
|
|
25
24
|
|
|
26
25
|
const conditions = {
|
|
27
26
|
length: password.length >= 8,
|
|
@@ -32,14 +31,10 @@ class Password {
|
|
|
32
31
|
};
|
|
33
32
|
|
|
34
33
|
// Mise à jour des conditions
|
|
35
|
-
div.
|
|
36
|
-
const cond =
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
$(this).addClass('text-success');
|
|
40
|
-
} else {
|
|
41
|
-
$(this).addClass('text-danger');
|
|
42
|
-
}
|
|
34
|
+
div.querySelectorAll('.password_strength_conditions li').forEach(li => {
|
|
35
|
+
const cond = li.dataset.condition;
|
|
36
|
+
li.classList.remove('text-success', 'text-danger');
|
|
37
|
+
li.classList.add(conditions[cond] ? 'text-success' : 'text-danger');
|
|
43
38
|
});
|
|
44
39
|
|
|
45
40
|
let width = (score / 6) * 100;
|
|
@@ -50,35 +45,37 @@ class Password {
|
|
|
50
45
|
if (score >= 4) { color = 'warning'; text = 'Moyen'; }
|
|
51
46
|
if (score >= 5) { color = 'success'; text = 'Fort'; }
|
|
52
47
|
|
|
53
|
-
strengthBar.
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
strengthText.
|
|
48
|
+
strengthBar.classList.remove('bg-danger', 'bg-warning', 'bg-success');
|
|
49
|
+
strengthBar.classList.add('bg-' + color);
|
|
50
|
+
strengthText.classList.remove('text-bg-danger', 'text-bg-warning', 'text-bg-success', 'hide');
|
|
51
|
+
strengthText.classList.add(password === '' ? 'hide' : 'text-bg-' + color);
|
|
52
|
+
strengthBar.style.width = width + '%';
|
|
53
|
+
strengthText.textContent = text;
|
|
57
54
|
}
|
|
58
55
|
|
|
59
56
|
const formGroup = input.closest('.form-group');
|
|
60
|
-
formGroup.
|
|
61
|
-
formGroup.
|
|
62
|
-
+'<div class="password_strength_content mt-1">'
|
|
63
|
-
+' <div class="progress" style="height: 6px;">'
|
|
64
|
-
+' <div class="password_strength_bar progress-bar" role="progressbar"></div>'
|
|
65
|
-
+' </div>'
|
|
66
|
-
+' <div class="d-flex justify-content-between align-items-start mt-2">'
|
|
67
|
-
+' <ul class="password_strength_conditions mb-0 ps-0" style="list-style: none;">'
|
|
68
|
-
+' <li data-condition="length">✔ Au moins 8 caractères</li>'
|
|
69
|
-
+' <li data-condition="uppercase">✔ Une majuscule</li>'
|
|
70
|
-
+' <li data-condition="lowercase">✔ Une minuscule</li>'
|
|
71
|
-
+' <li data-condition="number">✔ Un chiffre</li>'
|
|
72
|
-
+' <li data-condition="special">✔ Un caractère spécial</li>'
|
|
73
|
-
+' </ul>'
|
|
74
|
-
+' <div class="ms-3 text-end">'
|
|
75
|
-
+' <span class="badge password_strength_text" style="font-size: 10pt; font-weight: normal">New</span>'
|
|
76
|
-
+' </div>'
|
|
77
|
-
+' </div>'
|
|
78
|
-
+'</div>'
|
|
57
|
+
formGroup.querySelector('.password_strength_content')?.remove();
|
|
58
|
+
formGroup.insertAdjacentHTML('beforeend', ''
|
|
59
|
+
+ '<div class="password_strength_content mt-1">'
|
|
60
|
+
+ ' <div class="progress" style="height: 6px;">'
|
|
61
|
+
+ ' <div class="password_strength_bar progress-bar" role="progressbar"></div>'
|
|
62
|
+
+ ' </div>'
|
|
63
|
+
+ ' <div class="d-flex justify-content-between align-items-start mt-2">'
|
|
64
|
+
+ ' <ul class="password_strength_conditions mb-0 ps-0" style="list-style: none;">'
|
|
65
|
+
+ ' <li data-condition="length">✔ Au moins 8 caractères</li>'
|
|
66
|
+
+ ' <li data-condition="uppercase">✔ Une majuscule</li>'
|
|
67
|
+
+ ' <li data-condition="lowercase">✔ Une minuscule</li>'
|
|
68
|
+
+ ' <li data-condition="number">✔ Un chiffre</li>'
|
|
69
|
+
+ ' <li data-condition="special">✔ Un caractère spécial</li>'
|
|
70
|
+
+ ' </ul>'
|
|
71
|
+
+ ' <div class="ms-3 text-end">'
|
|
72
|
+
+ ' <span class="badge password_strength_text" style="font-size: 10pt; font-weight: normal">New</span>'
|
|
73
|
+
+ ' </div>'
|
|
74
|
+
+ ' </div>'
|
|
75
|
+
+ '</div>'
|
|
79
76
|
);
|
|
80
|
-
input.
|
|
81
|
-
input.
|
|
77
|
+
input.onchange = () => update(input);
|
|
78
|
+
input.oninput = () => update(input);
|
|
82
79
|
update(input);
|
|
83
80
|
}
|
|
84
81
|
}
|