@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.
@@ -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
- let mockInput;
149
- let mockFormGroup;
150
- let mockDiv;
151
-
152
- beforeEach(() => {
153
- // Mock jQuery
154
- mockDiv = {
155
- find: jest.fn().mockReturnThis(),
156
- removeClass: jest.fn().mockReturnThis(),
157
- addClass: jest.fn().mockReturnThis(),
158
- width: jest.fn().mockReturnThis(),
159
- text: jest.fn().mockReturnThis(),
160
- each: jest.fn(),
161
- };
162
-
163
- mockFormGroup = {
164
- find: jest.fn((selector) => {
165
- if (selector === '.password_strength_content') {
166
- return {
167
- remove: jest.fn(),
168
- };
169
- }
170
- return mockDiv;
171
- }),
172
- append: jest.fn(),
173
- };
174
-
175
- mockInput = {
176
- val: jest.fn(() => 'TestPassword1!'),
177
- closest: jest.fn(() => mockFormGroup),
178
- change: jest.fn(),
179
- off: jest.fn().mockReturnThis(),
180
- on: jest.fn(),
181
- };
182
-
183
- global.$ = jest.fn(() => mockInput);
184
- });
185
-
186
- afterEach(() => {
187
- delete global.$;
188
- });
189
-
190
- test('should initialize jQuery if called', () => {
191
- // This test just ensures the function can be called without throwing
192
- // Actual DOM manipulation testing would require jsdom or similar
193
- expect(() => {
194
- // We can't fully test DOM manipulation without a proper jQuery setup
195
- // Just verify the function exists and is callable
196
- expect(typeof Password.displayPasswordStrength).toBe('function');
197
- }).not.toThrow();
198
- });
199
-
200
- test('should be a static method', () => {
201
- expect(typeof Password.displayPasswordStrength).toBe('function');
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
- input = $(input);
19
- const password = input.val();
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.find('.password_strength_bar');
24
- const strengthText = div.find('.password_strength_text');
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.find('.password_strength_conditions li').each(function () {
36
- const cond = $(this).data('condition');
37
- $(this).removeClass('text-success text-danger');
38
- if (conditions[cond]) {
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.removeClass('bg-danger bg-warning bg-success').addClass('bg-'+color);
54
- strengthText.removeClass('text-bg-danger text-bg-warning text-bg-success hide').addClass(password === '' ? 'hide' : 'text-bg-'+color);
55
- strengthBar.width(width+'%');
56
- strengthText.text(text);
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.find('.password_strength_content').remove();
61
- formGroup.append(''
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.change(() => update(input));
81
- input.off('input').on('input', () => update(input));
77
+ input.onchange = () => update(input);
78
+ input.oninput = () => update(input);
82
79
  update(input);
83
80
  }
84
81
  }