@natachah/vanilla-frontend 0.0.2

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 (104) hide show
  1. package/.gitlab-ci.yml +40 -0
  2. package/LICENSE.md +7 -0
  3. package/README.md +11 -0
  4. package/docs/index.html +36 -0
  5. package/docs/main.js +32 -0
  6. package/docs/pages/components/badge.html +154 -0
  7. package/docs/pages/components/button.html +186 -0
  8. package/docs/pages/components/card.html +184 -0
  9. package/docs/pages/components/dialog.html +334 -0
  10. package/docs/pages/components/disclosure.html +310 -0
  11. package/docs/pages/components/dropdown.html +255 -0
  12. package/docs/pages/components/form.html +331 -0
  13. package/docs/pages/components/list.html +140 -0
  14. package/docs/pages/components/loading.html +58 -0
  15. package/docs/pages/components/media.html +130 -0
  16. package/docs/pages/components/nav.html +119 -0
  17. package/docs/pages/components/progress.html +47 -0
  18. package/docs/pages/components/slider.html +311 -0
  19. package/docs/pages/components/table.html +168 -0
  20. package/docs/pages/javascript/autofill.html +170 -0
  21. package/docs/pages/javascript/checkall.html +59 -0
  22. package/docs/pages/javascript/comfort.html +134 -0
  23. package/docs/pages/javascript/consent.html +112 -0
  24. package/docs/pages/javascript/cookie.html +81 -0
  25. package/docs/pages/javascript/form.html +199 -0
  26. package/docs/pages/javascript/scroll.html +209 -0
  27. package/docs/pages/javascript/sidebar.html +53 -0
  28. package/docs/pages/javascript/sortable.html +148 -0
  29. package/docs/pages/javascript/toggle.html +191 -0
  30. package/docs/pages/javascript/tree.html +221 -0
  31. package/docs/pages/layout/grid.html +201 -0
  32. package/docs/pages/layout/reset.html +53 -0
  33. package/docs/pages/layout/typography.html +324 -0
  34. package/docs/pages/quick-start/conventions.html +112 -0
  35. package/docs/pages/quick-start/customization.html +187 -0
  36. package/docs/pages/quick-start/installation.html +95 -0
  37. package/docs/pages/quick-start/mixins.html +228 -0
  38. package/docs/pages/test.html +15 -0
  39. package/docs/src/js/demo.js +98 -0
  40. package/docs/src/js/doc-code.js +102 -0
  41. package/docs/src/js/doc-demo.js +14 -0
  42. package/docs/src/js/doc-layout.js +108 -0
  43. package/docs/src/scss/demo.scss +77 -0
  44. package/docs/src/scss/layout.scss +160 -0
  45. package/docs/src/scss/style.scss +278 -0
  46. package/docs/vite.config.mjs +23 -0
  47. package/esbuild.mjs +25 -0
  48. package/js/_autofill.js +131 -0
  49. package/js/_check-all.js +77 -0
  50. package/js/_comfort.js +174 -0
  51. package/js/_consent.js +84 -0
  52. package/js/_dialog.js +164 -0
  53. package/js/_dropdown.js +101 -0
  54. package/js/_scroll.js +184 -0
  55. package/js/_sidebar.js +97 -0
  56. package/js/_slider.js +249 -0
  57. package/js/_sortable.js +143 -0
  58. package/js/_tabpanel.js +88 -0
  59. package/js/_toggle.js +123 -0
  60. package/js/_tree.js +85 -0
  61. package/js/tests/autofill.test.js +157 -0
  62. package/js/tests/base-component.test.js +108 -0
  63. package/js/tests/check-all.test.js +88 -0
  64. package/js/tests/comfort.test.js +219 -0
  65. package/js/tests/consent.test.js +84 -0
  66. package/js/tests/cookie.test.js +102 -0
  67. package/js/tests/dialog.test.js +189 -0
  68. package/js/tests/dropdown.test.js +115 -0
  69. package/js/tests/form-helper.test.js +155 -0
  70. package/js/tests/scroll.test.js +203 -0
  71. package/js/tests/sidebar.test.js +99 -0
  72. package/js/tests/slider.test.js +307 -0
  73. package/js/tests/sortable.test.js +124 -0
  74. package/js/tests/tabpanel.test.js +114 -0
  75. package/js/tests/toggle.test.js +190 -0
  76. package/js/tests/tree.test.js +165 -0
  77. package/js/utilities/_base-component.js +101 -0
  78. package/js/utilities/_cookie.js +98 -0
  79. package/js/utilities/_error.js +80 -0
  80. package/js/utilities/_form-helper.js +101 -0
  81. package/package.json +42 -0
  82. package/scss/_badge.scss +37 -0
  83. package/scss/_button.scss +34 -0
  84. package/scss/_card.scss +122 -0
  85. package/scss/_dialog.scss +116 -0
  86. package/scss/_disclosure.scss +101 -0
  87. package/scss/_dropdown.scss +68 -0
  88. package/scss/_form.scss +197 -0
  89. package/scss/_grid.scss +40 -0
  90. package/scss/_group.scss +57 -0
  91. package/scss/_list.scss +18 -0
  92. package/scss/_loading.scss +49 -0
  93. package/scss/_media.scss +37 -0
  94. package/scss/_nav.scss +72 -0
  95. package/scss/_progress.scss +40 -0
  96. package/scss/_slider.scss +35 -0
  97. package/scss/_table.scss +36 -0
  98. package/scss/utilities/_mixin.scss +322 -0
  99. package/scss/utilities/_reset.scss +145 -0
  100. package/scss/utilities/_typography.scss +107 -0
  101. package/scss/vanilla-frontend.scss +23 -0
  102. package/scss/variables/_root.scss +70 -0
  103. package/scss/variables/_setting.scss +63 -0
  104. package/vitest.config.js +7 -0
@@ -0,0 +1,189 @@
1
+ /**
2
+ * ------------------------------------------------------------------
3
+ * TEST for the _dialog.js
4
+ * ------------------------------------------------------------------
5
+ * The test will take care of:
6
+ * - Has all the public method
7
+ * ! herit from BaseComponent - Constructor: Passing the correct parameters
8
+ * - Constructor: Return the correct properties
9
+ * - Open(): Add the [open] attribute on the <dialog>
10
+ * - Open(): Emmit the dialog:opening & dialog:opened events
11
+ * - Close(): Remove the [open] attribute on the <dialog>
12
+ * - Close(): Emmit the dialog:closing & dialog:closed events
13
+ * - Submit(): By default will exectute submit event
14
+ * - Submit(): By JS will Remove the [open] attribute on the <dialog>
15
+ * - Submit(): Toggle the [aria-busy] attribute on the <button>
16
+ * - Submit(): Emmit the dialog:submiting & dialog:submited events
17
+ * - #toggleBodyAttribute(): As modal will toggle the [inert] attribute on the <body>
18
+ * - #toggleBodyAttribute(): As dialog will NOT toggle the [inert] attribute on the <body>
19
+ * - #toggleBodyAttribute(): The [inert] attribute on the <body> will be removed only if all modal are closed
20
+ */
21
+
22
+ import { describe, test, expect, beforeAll, vi, beforeEach, afterEach } from "vitest"
23
+ import Dialog from "../_dialog"
24
+
25
+ let fakeDialog, fakeModal, fakeFormModal
26
+
27
+ /**
28
+ * Before all tests
29
+ *
30
+ */
31
+
32
+ beforeAll(() => {
33
+
34
+ document.body.innerHTML =
35
+ '<button aria-controls="fakeDialog"></button>' +
36
+ '<dialog id="fakeDialog">' +
37
+ '<button data-dialog-close></button>' +
38
+ '</dialog>' +
39
+ '<dialog id="fakeModal" aria-modal="true"></dialog>' +
40
+ '<dialog id="fakeFormModal" aria-modal="true">' +
41
+ '<form><button type="submit"></button></form>' +
42
+ '</dialog>'
43
+
44
+ fakeDialog = new Dialog(document.getElementById('fakeDialog'))
45
+ fakeModal = new Dialog(document.getElementById('fakeModal'))
46
+ fakeFormModal = new Dialog(document.getElementById('fakeFormModal'))
47
+
48
+ })
49
+
50
+ describe('Structure of the class', () => {
51
+
52
+ test('Has all the public method', () => {
53
+ expect(fakeDialog.open).toBeTypeOf('function')
54
+ expect(fakeDialog.close).toBeTypeOf('function')
55
+ expect(fakeDialog.submit).toBeTypeOf('function')
56
+ })
57
+
58
+ test('Constructor: Return the correct properties', () => {
59
+ expect(fakeDialog).toHaveProperty('_isModal')
60
+ expect(fakeDialog._isModal).toBeTypeOf('boolean')
61
+ expect(fakeDialog._isModal).toBe(false)
62
+ expect(fakeModal._isModal).toBe(true)
63
+ expect(fakeDialog).toHaveProperty('_buttons')
64
+ expect(fakeDialog._buttons).toBeTypeOf('object')
65
+ expect(fakeDialog._buttons.open).toBeTypeOf('object')
66
+ expect(fakeDialog._buttons.close).toBeTypeOf('object')
67
+ expect(fakeDialog._buttons.submit).toBeTypeOf('object')
68
+ expect(fakeDialog._buttons.open).toStrictEqual(document.querySelectorAll('[aria-controls=fakeDialog]'))
69
+ expect(fakeDialog._buttons.close).toStrictEqual(fakeDialog._element.querySelectorAll('[data-dialog-close]'))
70
+ expect(fakeDialog._buttons.submit).toStrictEqual(fakeDialog._element.querySelectorAll('[type=submit]'))
71
+ })
72
+
73
+ })
74
+
75
+ describe('Open()', () => {
76
+
77
+ afterEach(() => {
78
+ fakeDialog._element.removeAttribute('open')
79
+ })
80
+
81
+ test('Add the [open] attribute on the <dialog>', () => {
82
+ expect(fakeDialog._element.open).toBeFalsy()
83
+ fakeDialog.open()
84
+ expect(fakeDialog._element.open).toBeTruthy()
85
+ })
86
+
87
+ test('Emmit the dialog:opening & dialog:opened events', () => {
88
+ const eventSpy = vi.spyOn(fakeDialog, 'emmitEvent')
89
+ expect(eventSpy).not.toHaveBeenCalled()
90
+ fakeDialog.open()
91
+ expect(eventSpy).toHaveBeenCalledWith('opening')
92
+ expect(eventSpy).toHaveBeenCalledWith('opened')
93
+ })
94
+
95
+ })
96
+
97
+ describe('Close()', () => {
98
+
99
+ beforeEach(() => {
100
+ fakeDialog._element.setAttribute('open', true)
101
+ })
102
+
103
+ test('Remove the [open] attribute on the <dialog>', () => {
104
+ expect(fakeDialog._element.open).toBeTruthy()
105
+ fakeDialog.close()
106
+ expect(fakeDialog._element.open).toBeFalsy()
107
+ })
108
+
109
+ test('Emmit the dialog:closing & dialog:closed events', () => {
110
+ const eventSpy = vi.spyOn(fakeDialog, 'emmitEvent')
111
+ expect(eventSpy).not.toHaveBeenCalled()
112
+ fakeDialog.close()
113
+ expect(eventSpy).toHaveBeenCalledWith('closing')
114
+ expect(eventSpy).toHaveBeenCalledWith('closed')
115
+ })
116
+
117
+ })
118
+
119
+ describe('Submit()', () => {
120
+
121
+ beforeEach(() => {
122
+ fakeFormModal._element.setAttribute('open', true)
123
+ })
124
+
125
+ test('By default will exectute submit event', () => {
126
+ fakeFormModal._form.setAttribute('method', 'POST')
127
+ const submitSpy = vi.spyOn(fakeFormModal._form, 'submit')
128
+ expect(submitSpy).not.toHaveBeenCalled()
129
+ fakeFormModal.submit()
130
+ expect(submitSpy).toHaveBeenCalled()
131
+ })
132
+
133
+ test('By JS will Remove the [open] attribute on the <dialog>', () => {
134
+ fakeFormModal._form.setAttribute('method', 'dialog')
135
+ expect(fakeFormModal._element.open).toBeTruthy()
136
+ fakeFormModal.submit()
137
+ expect(fakeFormModal._element.open).toBeFalsy()
138
+ })
139
+
140
+ test('Toggle the [aria-busy] attribute on the <button>', (t) => {
141
+ fakeFormModal._form.setAttribute('method', 'dialog')
142
+ const button = fakeFormModal._buttons.submit[0]
143
+ const testBefore = (e) => expect(button.hasAttribute('aria-busy')).toBeTruthy()
144
+ fakeFormModal._element.addEventListener('dialog:submiting', testBefore)
145
+ const testAfter = (e) => expect(button.hasAttribute('aria-busy')).toBeFalsy()
146
+ fakeFormModal._element.addEventListener('dialog:submited', testAfter)
147
+ fakeFormModal.submit()
148
+ t.onTestFinished(() => fakeFormModal._element.removeEventListener('dialog:submiting', testBefore))
149
+ t.onTestFinished(() => fakeFormModal._element.removeEventListener('dialog:submited', testAfter))
150
+ })
151
+
152
+ test('Emmit the dialog:submiting & dialog:submited events', () => {
153
+ fakeFormModal._form.setAttribute('method', 'dialog')
154
+ const eventSpy = vi.spyOn(fakeFormModal, 'emmitEvent')
155
+ expect(eventSpy).not.toHaveBeenCalled()
156
+ fakeFormModal.submit()
157
+ expect(eventSpy).toHaveBeenCalledWith('submiting', { form: fakeFormModal._form })
158
+ expect(eventSpy).toHaveBeenCalledWith('submited', { form: fakeFormModal._form })
159
+ })
160
+
161
+ })
162
+
163
+ describe('#ToggleBodyAttribute()', () => {
164
+
165
+ test('As modal will toggle the [inert] attribute on the <body>', () => {
166
+ expect(document.body.hasAttribute('inert')).toBeFalsy()
167
+ fakeModal.open()
168
+ expect(document.body.hasAttribute('inert')).toBeTruthy()
169
+ fakeModal.close()
170
+ expect(document.body.hasAttribute('inert')).toBeFalsy()
171
+ })
172
+
173
+ test('As dialog will NOT toggle the [inert] attribute on the <body>', () => {
174
+ expect(document.body.hasAttribute('inert')).toBeFalsy()
175
+ fakeDialog.open()
176
+ expect(document.body.hasAttribute('inert')).toBeFalsy()
177
+ })
178
+
179
+ test('The [inert] attribute on the <body> will be removed only if all modal are closed', () => {
180
+ fakeModal.open()
181
+ fakeFormModal.open()
182
+ expect(document.body.hasAttribute('inert')).toBeTruthy()
183
+ fakeModal.close()
184
+ expect(document.body.hasAttribute('inert')).toBeTruthy()
185
+ fakeFormModal.close()
186
+ expect(document.body.hasAttribute('inert')).toBeFalsy()
187
+ })
188
+
189
+ })
@@ -0,0 +1,115 @@
1
+ /**
2
+ * ------------------------------------------------------------------
3
+ * TEST for the _dropdown.js
4
+ * ------------------------------------------------------------------
5
+ * The test will take care of:
6
+ * ! herit from BaseComponent - Constructor: Passing the correct parameters
7
+ * - Constructor: Return the correct properties
8
+ * - Constructor: Constructor: Passing the correct parameters
9
+ * - #Init(): Close content if click outside
10
+ * - #Toggle(): Toggle the [aria-pressed] and [aria-expanded] attribute on the <button>
11
+ * - #Toggle(): Toggle the [hidden] attribute on the <div>
12
+ * - #Toggle(): Emmit the toggle:changed event
13
+ */
14
+
15
+ import { describe, test, expect, beforeAll, vi } from "vitest"
16
+ import { fireEvent } from "@testing-library/dom"
17
+ import Dropdown from "../_dropdown"
18
+ import ErrorMessage from "../utilities/_error"
19
+
20
+ let fakeDiv, fakeButton, fakeContent, fakeDropdown, fakeDropdownClosable
21
+
22
+ /**
23
+ * Before all tests
24
+ *
25
+ */
26
+
27
+ beforeAll(() => {
28
+
29
+ document.body.innerHTML =
30
+ '<div id="fakeDropdown">' +
31
+ '<button id="fakeButton" aria-controls="fakeContent" aria-expanded="false" aria-pressed="false"></button>' +
32
+ '<div id="fakeContent" tabindex="0" hidden></div>' +
33
+ '</div>' +
34
+ '<div id="fakeDropdownClosable">' +
35
+ '<button aria-controls="fakeContentClosable" aria-expanded="false" aria-pressed="false"></button>' +
36
+ '<div id="fakeContentClosable" tabindex="0" hidden></div>' +
37
+ '</div>'
38
+
39
+ fakeDiv = document.getElementById('fakeDropdown')
40
+ fakeButton = document.getElementById('fakeButton')
41
+ fakeContent = document.getElementById('fakeContent')
42
+
43
+ fakeDropdown = new Dropdown(fakeDiv, {
44
+ closable: false
45
+ })
46
+ fakeDropdownClosable = new Dropdown(document.getElementById('fakeDropdownClosable'), {
47
+ closable: true
48
+ })
49
+ })
50
+
51
+ describe('Structure of the class', () => {
52
+
53
+ test('Constructor: Passing the correct parameters', () => {
54
+ expect(() => new Dropdown(fakeDiv, { closable: 'make-error' })).toThrowError(ErrorMessage.typeOf('options.closable', 'boolean'))
55
+ })
56
+
57
+ test('Constructor: Return the correct properties', () => {
58
+ expect(fakeDropdown).toHaveProperty('_button')
59
+ expect(fakeDropdown).toHaveProperty('_content')
60
+ expect(fakeDropdown._button).toBe(fakeButton)
61
+ expect(fakeDropdown._content).toBe(fakeContent)
62
+ })
63
+
64
+ })
65
+
66
+ describe('#Init()', () => {
67
+
68
+ test('Close content if click outside', () => {
69
+ expect(fakeDropdownClosable._button.getAttribute('aria-pressed')).toBe('false')
70
+ expect(fakeDropdownClosable._button.getAttribute('aria-expanded')).toBe('false')
71
+ expect(fakeDropdownClosable._content.hidden).toBeTruthy()
72
+ fireEvent(fakeDropdownClosable._button, new MouseEvent('click'))
73
+ expect(fakeDropdownClosable._button.getAttribute('aria-pressed')).toBe('true')
74
+ expect(fakeDropdownClosable._button.getAttribute('aria-expanded')).toBe('true')
75
+ expect(fakeDropdownClosable._content.hidden).toBeFalsy()
76
+ fireEvent.blur(fakeDropdownClosable._content)
77
+ expect(fakeDropdownClosable._button.getAttribute('aria-expanded')).toBe('false')
78
+ expect(fakeDropdownClosable._button.getAttribute('aria-pressed')).toBe('false')
79
+ expect(fakeDropdownClosable._content.hidden).toBeTruthy()
80
+ })
81
+
82
+ })
83
+
84
+
85
+ describe('#Toggle()', () => {
86
+
87
+ test('Toggle the [aria-pressed] and [aria-expanded] attribute on the <button>', () => {
88
+ expect(fakeDropdown._button.getAttribute('aria-pressed')).toBe('false')
89
+ expect(fakeDropdown._button.getAttribute('aria-expanded')).toBe('false')
90
+ fireEvent(fakeDropdown._button, new MouseEvent('click'))
91
+ expect(fakeDropdown._button.getAttribute('aria-pressed')).toBe('true')
92
+ expect(fakeDropdown._button.getAttribute('aria-expanded')).toBe('true')
93
+ fireEvent(fakeDropdown._button, new MouseEvent('click'))
94
+ expect(fakeDropdown._button.getAttribute('aria-pressed')).toBe('false')
95
+ expect(fakeDropdown._button.getAttribute('aria-expanded')).toBe('false')
96
+ })
97
+
98
+ test('Toggle the [hidden] attribute on the <div>', () => {
99
+ expect(fakeDropdown._content.hidden).toBeTruthy()
100
+ fireEvent(fakeDropdown._button, new MouseEvent('click'))
101
+ expect(fakeDropdown._content.hidden).toBeFalsy()
102
+ fireEvent.blur(fakeDropdown._content)
103
+ expect(fakeDropdown._content.hidden).toBeFalsy()
104
+ fireEvent(fakeDropdown._button, new MouseEvent('click'))
105
+ expect(fakeDropdown._content.hidden).toBeTruthy()
106
+ })
107
+
108
+ test('Emmit the dropdown:changed event', () => {
109
+ const eventSpy = vi.spyOn(fakeDropdown, 'emmitEvent')
110
+ expect(eventSpy).not.toHaveBeenCalled()
111
+ fireEvent(fakeDropdown._button, new MouseEvent('click'))
112
+ expect(eventSpy).toHaveBeenCalledWith('changed', { isOpen: true })
113
+ })
114
+
115
+ })
@@ -0,0 +1,155 @@
1
+ /**
2
+ * ------------------------------------------------------------------
3
+ * TEST for the utilities/_form-helper.js
4
+ * ------------------------------------------------------------------
5
+ * The test will take care of:
6
+ * - Has all the public method
7
+ * - TogglePassword(): Passing the correct parameters
8
+ * - TogglePassword(): Toggle the [type] attribute on the <input>
9
+ * - TogglePassword(): Toggle the [aria-pressed] attribute on the <button>
10
+ * - ToggleAttributes(): Passing the correct parameters
11
+ * - ToggleAttributes(): Reset the [value] attribute on the <input>
12
+ * - ToggleAttributes(): Toggle the [disabled] attribute on the <input>
13
+ * - ToggleAttributes(): Toggle the [required] attribute on the <input>
14
+ * - ToggleAttributes(): Toggle do not impact <input> if in unchanged option
15
+ */
16
+
17
+ import { describe, test, expect, beforeAll, afterEach } from "vitest"
18
+ import FormHelper from "../utilities/_form-helper"
19
+ import ErrorMessage from "../utilities/_error"
20
+
21
+ let fakeInput, fakeButton, fakeFields, fieldA, fieldB
22
+
23
+ describe('Structure of the class', () => {
24
+
25
+ test('Has all the public method', () => {
26
+ expect(FormHelper.togglePassword).toBeTypeOf('function')
27
+ })
28
+
29
+ })
30
+
31
+ describe('TogglePassword()', () => {
32
+
33
+ beforeAll(() => {
34
+
35
+ document.body.innerHTML =
36
+ '<input id="fakeInput" type="password" value="123456">' +
37
+ '<button id="fakeButton" aria-pressed="false" aria-controls="fakeInput"></button>'
38
+
39
+ fakeInput = document.getElementById('fakeInput')
40
+ fakeButton = document.getElementById('fakeButton')
41
+
42
+ })
43
+
44
+ test('Passing the correct parameters', () => {
45
+ const button = document.createElement('button')
46
+ expect(() => FormHelper.togglePassword('make-error')).toThrowError(ErrorMessage.instanceOf('button', 'HTMLElement'))
47
+ expect(() => FormHelper.togglePassword(button)).toThrowError(ErrorMessage.withAttribute('button', 'aria-controls'))
48
+ button.setAttribute('aria-controls', 'make-error')
49
+ expect(() => FormHelper.togglePassword(button)).toThrowError(ErrorMessage.existById('input', 'make-error'))
50
+ })
51
+
52
+ test('Toggle the [type] attribute on the <input>', () => {
53
+ expect(fakeInput.type).toBe('password')
54
+ FormHelper.togglePassword(fakeButton)
55
+ expect(fakeInput.type).toBe('text')
56
+ FormHelper.togglePassword(fakeButton)
57
+ expect(fakeInput.type).toBe('password')
58
+ })
59
+
60
+ test('Toggle the [aria-pressed] attribute on the <button>', () => {
61
+ expect(fakeButton.getAttribute('aria-pressed')).toBe('false')
62
+ FormHelper.togglePassword(fakeButton)
63
+ expect(fakeButton.getAttribute('aria-pressed')).toBe('true')
64
+ })
65
+
66
+ })
67
+
68
+ describe('ToggleAttributes', () => {
69
+
70
+ beforeAll(() => {
71
+ document.body.innerHTML =
72
+ '<input id="fakeFieldA" name="fakeFieldA" type="text" value="aaa">' +
73
+ '<input id="fakeFieldB" name="fakeFieldB" type="text" value="bbb">'
74
+
75
+ fakeFields = document.querySelectorAll('#fakeFieldA,#fakeFieldB')
76
+ fieldA = document.getElementById('fakeFieldA')
77
+ fieldB = document.getElementById('fakeFieldB')
78
+ })
79
+
80
+ afterEach(() => {
81
+ fieldA.value = 'aaa'
82
+ fieldA.disabled = false
83
+ fieldA.required = false
84
+ fieldB.value = 'bbb'
85
+ fieldB.disabled = false
86
+ fieldB.required = false
87
+ })
88
+
89
+ test('Passing the correct parameters', () => {
90
+ expect(() => FormHelper.toggleAttributes('make-error')).toThrowError(ErrorMessage.instanceOf('fields', 'Object'))
91
+ expect(() => FormHelper.toggleAttributes(fakeFields, 'make-error')).toThrowError(ErrorMessage.typeOf('isVisible', 'boolean'))
92
+ expect(() => FormHelper.toggleAttributes(fakeFields, true, 'make-error')).toThrowError(ErrorMessage.instanceOf('customOptions', 'Object'))
93
+ expect(() => FormHelper.toggleAttributes(fakeFields, true, { reset: 'make-error' })).toThrowError(ErrorMessage.typeOf('customOptions.reset', 'boolean|object'))
94
+ expect(() => FormHelper.toggleAttributes(fakeFields, true, { disabled: 'make-error' })).toThrowError(ErrorMessage.typeOf('customOptions.disabled', 'boolean|object'))
95
+ expect(() => FormHelper.toggleAttributes(fakeFields, true, { required: 'make-error' })).toThrowError(ErrorMessage.typeOf('customOptions.required', 'boolean|object'))
96
+ expect(() => FormHelper.toggleAttributes(fakeFields, true, { unchanged: 'make-error' })).toThrowError(ErrorMessage.typeOf('customOptions.unchanged', 'object'))
97
+ })
98
+
99
+ test('Reset the [value] attribute on the <input>', () => {
100
+ expect(fieldA.value).toBe('aaa')
101
+ expect(fieldB.value).toBe('bbb')
102
+ FormHelper.toggleAttributes(fakeFields, true, { reset: false })
103
+ expect(fieldA.value).toBe('aaa')
104
+ expect(fieldB.value).toBe('bbb')
105
+ FormHelper.toggleAttributes(fakeFields, false, { reset: ['fakeFieldA'] })
106
+ expect(fieldA.value).toBe('null')
107
+ expect(fieldB.value).toBe('bbb')
108
+ })
109
+
110
+ test('Toggle the [disabled] attribute on the <input>', () => {
111
+ expect(fieldA.disabled).toBeFalsy()
112
+ expect(fieldB.disabled).toBeFalsy()
113
+ FormHelper.toggleAttributes(fakeFields, true, { disabled: false })
114
+ expect(fieldA.disabled).toBeFalsy()
115
+ expect(fieldB.disabled).toBeFalsy()
116
+ FormHelper.toggleAttributes(fakeFields, false, { disabled: ['fakeFieldA'] })
117
+ expect(fieldA.disabled).toBeTruthy()
118
+ expect(fieldB.disabled).toBeFalsy()
119
+ })
120
+
121
+ test('Toggle the [required] attribute on the <input>', () => {
122
+ expect(fieldA.required).toBeFalsy()
123
+ expect(fieldB.required).toBeFalsy()
124
+ FormHelper.toggleAttributes(fakeFields, true, { required: false })
125
+ expect(fieldA.required).toBeFalsy()
126
+ expect(fieldB.required).toBeFalsy()
127
+ FormHelper.toggleAttributes(fakeFields, true, { required: ['fakeFieldA'] })
128
+ expect(fieldA.required).toBeTruthy()
129
+ expect(fieldB.required).toBeFalsy()
130
+ })
131
+
132
+ test('Toggle do not impact <input> if in unchanged option', () => {
133
+ expect(fieldA.value).toBe('aaa')
134
+ expect(fieldA.disabled).toBeFalsy()
135
+ expect(fieldA.required).toBeFalsy()
136
+ expect(fieldB.value).toBe('bbb')
137
+ expect(fieldB.disabled).toBeFalsy()
138
+ expect(fieldB.required).toBeFalsy()
139
+ FormHelper.toggleAttributes(fakeFields, true, { reset: true, disabled: true, required: true, unchanged: ['fakeFieldB'] })
140
+ expect(fieldA.value).toBe('aaa')
141
+ expect(fieldA.disabled).toBeFalsy()
142
+ expect(fieldA.required).toBeTruthy()
143
+ expect(fieldB.value).toBe('bbb')
144
+ expect(fieldB.disabled).toBeFalsy()
145
+ expect(fieldB.required).toBeFalsy()
146
+ FormHelper.toggleAttributes(fakeFields, false, { reset: true, disabled: true, required: true, unchanged: ['fakeFieldB'] })
147
+ expect(fieldA.value).toBe('null')
148
+ expect(fieldA.disabled).toBeTruthy()
149
+ expect(fieldA.required).toBeFalsy()
150
+ expect(fieldB.value).toBe('bbb')
151
+ expect(fieldB.disabled).toBeFalsy()
152
+ expect(fieldB.required).toBeFalsy()
153
+ })
154
+
155
+ })
@@ -0,0 +1,203 @@
1
+ /**
2
+ * ------------------------------------------------------------------
3
+ * TEST for the _scroll.js
4
+ * ------------------------------------------------------------------
5
+ * The test will take care of:
6
+ * - Has all the public method
7
+ * - Constructor: Passing the correct parameters
8
+ * - Constructor: Return the correct properties
9
+ * - #Init: Emit the scrollTop() method when click on this._buttons.top
10
+ * - #Init: Emit the scrollBottom() method when click on this._buttons.bottom
11
+ * - GoTo(): Passing the correct parameters
12
+ * - GoTo(): Emit a scroll event
13
+ * - ScrollTop(): Emit a goTo() method and scrollTop is 0
14
+ * - ScrollBottom(): Emit a goTo() method and scrollTop is this._height
15
+ * - #Scroll(): Toggle the [hidden] attribute on the [data-scroll-top] button
16
+ * - #Scroll(): Toggle the [hidden] attribute on the [data-scroll-bottom] button
17
+ * - #Spy(): Toggle the [aria-current] attribute on the <a>
18
+ */
19
+
20
+ import { describe, test, expect, beforeAll, vi } from "vitest"
21
+ import { fireEvent } from "@testing-library/dom"
22
+ import Scroll from "../_scroll"
23
+ import ErrorMessage from "../utilities/_error"
24
+
25
+ let fakeDiv, fakeDivScroll, fakePageScroll, fakeDivOne, fakeDivTwo
26
+
27
+ /**
28
+ * Before all tests
29
+ *
30
+ */
31
+
32
+ beforeAll(() => {
33
+
34
+ document.body.innerHTML =
35
+ '<div id="scrollspy"><a href="#one"></a><a href="#two"></a><a><a/></div>' +
36
+ '<div id="fakeDiv" style="height:200px;overflow-y:scroll">' +
37
+ '<button data-scroll-bottom="fakeDiv"></button>' +
38
+ '<button data-scroll-top="fakeDiv" hidden></button>' +
39
+ '<div id="one"></div>' +
40
+ '<div id="two"></div>' +
41
+ '</div>'
42
+
43
+ fakeDiv = document.getElementById('fakeDiv')
44
+ fakeDivOne = document.getElementById('one')
45
+ fakeDivTwo = document.getElementById('two')
46
+
47
+ // Define the sizes for HTML div
48
+ Object.defineProperty(fakeDiv, 'scrollHeight', { configurable: true, value: 800 })
49
+ Object.defineProperty(fakeDiv, 'clientHeight', { configurable: true, value: 200 })
50
+ Object.defineProperty(fakeDivOne, 'offsetTop', { configurable: true, value: 200 })
51
+ Object.defineProperty(fakeDivTwo, 'offsetTop', { configurable: true, value: 400 })
52
+ Object.defineProperty(document.documentElement, 'scrollHeight', { configurable: true, value: 1200 })
53
+ Object.defineProperty(document.documentElement, 'clientHeight', { configurable: true, value: 600 })
54
+
55
+ // Then init the class
56
+ fakeDivScroll = new Scroll(fakeDiv, { navigation: 'scrollspy', gaps: { spy: 0 } })
57
+ fakePageScroll = new Scroll(document.documentElement)
58
+
59
+ })
60
+
61
+ describe('Structure of the class', () => {
62
+
63
+ test('Has all the public method', () => {
64
+ expect(fakeDivScroll.goTo).toBeTypeOf('function')
65
+ expect(fakeDivScroll.scrollTop).toBeTypeOf('function')
66
+ expect(fakeDivScroll.scrollBottom).toBeTypeOf('function')
67
+ })
68
+
69
+ test('Constructor: Passing the correct parameters', () => {
70
+ expect(() => new Scroll(fakeDiv, { gaps: 'make-error' })).toThrowError(ErrorMessage.instanceOf('options.gaps', 'Object'))
71
+ expect(() => new Scroll(fakeDiv, { gaps: { top: 'make-error' } })).toThrowError(ErrorMessage.typeOf('options.gaps.top', 'number'))
72
+ expect(() => new Scroll(fakeDiv, { gaps: { bottom: 'make-error' } })).toThrowError(ErrorMessage.typeOf('options.gaps.bottom', 'number'))
73
+ expect(() => new Scroll(fakeDiv, { gaps: { spy: 'make-error' } })).toThrowError(ErrorMessage.typeOf('options.gaps.spy', 'number'))
74
+ expect(() => new Scroll(fakeDiv, { behavior: 'make-error' })).toThrowError(ErrorMessage.enumOf('options.behavior', 'auto|smooth|instant'))
75
+ expect(() => new Scroll(fakeDiv, { navigation: 'make-error' })).toThrowError(ErrorMessage.existById('element', 'make-error'))
76
+ })
77
+
78
+ test('Constructor: Return the correct properties', () => {
79
+ expect(fakeDivScroll).toHaveProperty('_height')
80
+ expect(fakeDivScroll._height).toBe(600)
81
+ expect(fakeDivScroll._buttons).toBeTypeOf('object')
82
+ expect(fakeDivScroll._buttons.top).toStrictEqual(document.querySelector('[data-scroll-top="fakeDiv"]'))
83
+ expect(fakeDivScroll._buttons.bottom).toStrictEqual(document.querySelector('[data-scroll-bottom="fakeDiv"]'))
84
+ expect(fakePageScroll._buttons.top).toBeNull()
85
+ expect(fakePageScroll._buttons.bottom).toBeNull()
86
+ expect(fakeDivScroll._spy).toBeTypeOf('object')
87
+ expect(fakeDivScroll._spy.enable).toBeTypeOf('boolean')
88
+ expect(fakeDivScroll._spy.links).toBeTypeOf('object')
89
+ expect(fakeDivScroll._spy.targets).toBeTypeOf('object')
90
+ expect(fakeDivScroll._spy.current).toBeTypeOf('number')
91
+ expect(fakeDivScroll._spy.enable).toBeTruthy()
92
+ expect(fakePageScroll._spy.enable).toBeFalsy()
93
+ expect(fakeDivScroll._spy.links).toStrictEqual([...document.querySelectorAll('#scrollspy a[href^="#"]')])
94
+ expect(fakeDivScroll._spy.targets).toStrictEqual([...document.querySelectorAll('#one,#two')])
95
+ expect(fakeDivScroll._spy.current).toBe(0)
96
+ })
97
+
98
+ })
99
+
100
+ describe('#Init()', () => {
101
+
102
+ test('Emit the scrollTop() method when click on this._buttons.top', () => {
103
+ const methodSpy = vi.spyOn(fakeDivScroll, 'scrollTop')
104
+ fireEvent(document.querySelector('[data-scroll-top="fakeDiv"]'), new MouseEvent('click'))
105
+ expect(methodSpy).toHaveBeenCalled()
106
+ })
107
+
108
+ test('Emit the scrollBottom() method when click on this._buttons.bottom', () => {
109
+ const methodSpy = vi.spyOn(fakeDivScroll, 'scrollBottom')
110
+ fireEvent(document.querySelector('[data-scroll-bottom="fakeDiv"]'), new MouseEvent('click'))
111
+ expect(methodSpy).toHaveBeenCalled()
112
+ })
113
+
114
+ test('Emit the goTo() method when click on this._spy.links', () => {
115
+ const methodSpy = vi.spyOn(fakeDivScroll, 'goTo')
116
+ fireEvent(document.querySelector('a[href="#one"]'), new MouseEvent('click'))
117
+ expect(methodSpy).toHaveBeenCalled()
118
+ })
119
+
120
+ })
121
+
122
+ describe('GoTo()', () => {
123
+
124
+ test('Passing the correct parameters ', () => {
125
+ expect(() => fakeDivScroll.goTo()).toThrowError(ErrorMessage.typeOf('distance', 'number'))
126
+ expect(() => fakeDivScroll.goTo('make-error')).toThrowError(ErrorMessage.typeOf('distance', 'number'))
127
+ })
128
+
129
+ test('Emit a scroll event', () => {
130
+ const scrollSpy = vi.spyOn(fakeDiv, 'scroll')
131
+ fakeDivScroll.goTo(100)
132
+ expect(scrollSpy).toHaveBeenCalled()
133
+ })
134
+
135
+ })
136
+
137
+ describe('ScrollTop()', () => {
138
+
139
+ test('Emit a goTo() method with parameter as 0', () => {
140
+ const methodSpy = vi.spyOn(fakeDivScroll, 'goTo')
141
+ fakeDivScroll.scrollTop()
142
+ expect(methodSpy).toHaveBeenCalledWith(0)
143
+ })
144
+
145
+ })
146
+
147
+ describe('ScrollBottom()', () => {
148
+
149
+ test('Emit a goTo() method with parameter as _height', () => {
150
+ const methodSpy = vi.spyOn(fakeDivScroll, 'goTo')
151
+ fakeDivScroll.scrollBottom()
152
+ expect(methodSpy).toHaveBeenCalledWith(fakeDivScroll._height)
153
+ })
154
+
155
+ })
156
+
157
+ describe('#Scroll()', () => {
158
+
159
+ test('Toggle the [hidden] attribute on the [data-scroll-top] button', () => {
160
+ const topButton = document.querySelector('[data-scroll-top="fakeDiv"]')
161
+ expect(topButton.hidden).toBeTruthy()
162
+ Object.defineProperty(fakeDiv, 'scrollTop', { configurable: true, value: 300 })
163
+ fireEvent.scroll(fakeDiv)
164
+ expect(topButton.hidden).toBeFalsy()
165
+ Object.defineProperty(fakeDiv, 'scrollTop', { configurable: true, value: 0 })
166
+ fireEvent.scroll(fakeDiv)
167
+ expect(topButton.hidden).toBeTruthy()
168
+ })
169
+
170
+ test('Toggle the [hidden] attribute on the [data-scroll-bottom] button', () => {
171
+ const topButton = document.querySelector('[data-scroll-bottom="fakeDiv"]')
172
+ expect(topButton.hidden).toBeFalsy()
173
+ Object.defineProperty(fakeDiv, 'scrollTop', { configurable: true, value: 600 })
174
+ fireEvent.scroll(fakeDiv)
175
+ expect(topButton.hidden).toBeTruthy()
176
+ Object.defineProperty(fakeDiv, 'scrollTop', { configurable: true, value: 0 })
177
+ fireEvent.scroll(fakeDiv)
178
+ expect(topButton.hidden).toBeFalsy()
179
+ })
180
+
181
+ })
182
+
183
+ describe('#Spy()', () => {
184
+
185
+ test('Toggle the [aria-current] attribute on the <a> ', () => {
186
+ const one = document.querySelector('a[href="#one"]')
187
+ const two = document.querySelector('a[href="#two"]')
188
+ expect(fakeDivScroll._spy.current).toBe(2)
189
+ expect(one.hasAttribute('aria-current')).toBeFalsy() //200
190
+ expect(two.hasAttribute('aria-current')).toBeFalsy() //400
191
+ Object.defineProperty(fakeDiv, 'scrollTop', { configurable: true, value: 200 })
192
+ fireEvent.scroll(fakeDiv)
193
+ expect(fakeDivScroll._spy.current).toBe(0)
194
+ expect(one.hasAttribute('aria-current')).toBeTruthy()
195
+ expect(two.hasAttribute('aria-current')).toBeFalsy()
196
+ Object.defineProperty(fakeDiv, 'scrollTop', { configurable: true, value: 400 })
197
+ fireEvent.scroll(fakeDiv)
198
+ expect(fakeDivScroll._spy.current).toBe(1)
199
+ expect(one.hasAttribute('aria-current')).toBeFalsy()
200
+ expect(two.hasAttribute('aria-current')).toBeTruthy()
201
+ })
202
+
203
+ })