@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,99 @@
1
+ /**
2
+ * ------------------------------------------------------------------
3
+ * TEST for the _sidebar.js
4
+ * ------------------------------------------------------------------
5
+ * The test will take care of:
6
+ * - Constructor: Passing the correct parameters
7
+ * - Constructor: Return the correct properties
8
+ * - #Init: On click on the button toggle the sidebar
9
+ * - #Init: On click on the backdrop, close the sidebar
10
+ */
11
+
12
+ import { describe, test, expect, beforeAll } from "vitest"
13
+ import { fireEvent } from "@testing-library/dom"
14
+ import Sidebar from "../_sidebar"
15
+ import ErrorMessage from "../utilities/_error"
16
+
17
+ let fakeSidebar
18
+
19
+ /**
20
+ * Before all tests
21
+ *
22
+ */
23
+
24
+ beforeAll(() => {
25
+
26
+ document.body.innerHTML =
27
+ '<div id="backdrop"></div>' +
28
+ '<button aria-expanded="false" aria-pressed="false" aria-controls="sidebar"></button>' +
29
+ '<aside id="sidebar" tabindex="0" hidden></aside>'
30
+
31
+ Object.defineProperty(window, 'innerWidth', { configurable: true, value: 1200 })
32
+
33
+ fakeSidebar = new Sidebar(document.getElementById('sidebar'))
34
+
35
+ })
36
+
37
+ describe('Structure of the class', () => {
38
+
39
+ test('Constructor: Passing the correct parameters', () => {
40
+ expect(() => new Sidebar(document.getElementById('sidebar'), { breakpoint: 'make-error' })).toThrowError(ErrorMessage.typeOf('options.breakpoint', 'number'))
41
+ })
42
+
43
+ test('Constructor: Return the correct properties', () => {
44
+ expect(fakeSidebar._buttons).toStrictEqual(document.querySelectorAll('button[aria-controls="sidebar"]'))
45
+ expect(fakeSidebar._backdrop).toStrictEqual(document.getElementById('backdrop'))
46
+ expect(fakeSidebar._isOpen).toBeTruthy()
47
+ })
48
+
49
+ })
50
+
51
+ describe('#Init(', () => {
52
+
53
+ test('On click on the button toggle the sidebar', () => {
54
+
55
+ const button = fakeSidebar._buttons[0]
56
+
57
+ expect(fakeSidebar._isOpen).toBeTruthy()
58
+ expect(fakeSidebar._element.hasAttribute('hidden')).toBeFalsy()
59
+ expect(button.getAttribute('aria-pressed')).toBe('true')
60
+ expect(button.getAttribute('aria-expanded')).toBe('true')
61
+
62
+ fireEvent(button, new MouseEvent('click'))
63
+
64
+ expect(fakeSidebar._isOpen).toBeFalsy()
65
+ expect(fakeSidebar._element.hasAttribute('hidden')).toBeTruthy()
66
+ expect(button.getAttribute('aria-pressed')).toBe('false')
67
+ expect(button.getAttribute('aria-expanded')).toBe('false')
68
+
69
+ fireEvent(button, new MouseEvent('click'))
70
+
71
+ expect(fakeSidebar._isOpen).toBeTruthy()
72
+ expect(fakeSidebar._element.hasAttribute('hidden')).toBeFalsy()
73
+ expect(button.getAttribute('aria-pressed')).toBe('true')
74
+ expect(button.getAttribute('aria-expanded')).toBe('true')
75
+
76
+ })
77
+
78
+ test('On click on the backdrop, close the sidebar', () => {
79
+
80
+ Object.defineProperty(window, 'innerWidth', { configurable: true, value: 800 })
81
+
82
+ const button = fakeSidebar._buttons[0]
83
+
84
+ expect(fakeSidebar._isOpen).toBeTruthy()
85
+ expect(fakeSidebar._element.hasAttribute('hidden')).toBeFalsy()
86
+ expect(button.getAttribute('aria-pressed')).toBe('true')
87
+ expect(button.getAttribute('aria-expanded')).toBe('true')
88
+
89
+ fireEvent(document.getElementById('backdrop'), new MouseEvent('click'))
90
+
91
+ expect(fakeSidebar._isOpen).toBeFalsy()
92
+ expect(fakeSidebar._element.hasAttribute('hidden')).toBeTruthy()
93
+ expect(button.getAttribute('aria-pressed')).toBe('false')
94
+ expect(button.getAttribute('aria-expanded')).toBe('false')
95
+
96
+ })
97
+
98
+ })
99
+
@@ -0,0 +1,307 @@
1
+ /**
2
+ * ------------------------------------------------------------------
3
+ * TEST for the /_slider.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: Passing the correct parameters
9
+ * - Constructor: Return the correct properties
10
+ * - #Init(): Loop will clone the first and last slide
11
+ * - #Init(): Autoplay will emmit next() method every X ms
12
+ * - #Init(): Scroll will change the current attributes
13
+ * - #Init(): Click on <button> with [role=tab] emmit the goTo() method
14
+ * - #Init(): Click on <button> with [data-slider-prev] emmit the prev() method
15
+ * - #Init(): Click on <button> with [data-slider-next] emmit the next() method
16
+ * - GoTo(): Passing the correct parameters
17
+ * - GoTo(): Emit a scroll() method
18
+ * - Prev(): Emmit the goTo() method with correct index
19
+ * - Prev(): Don't emmit the goTo() method if already first slide
20
+ * - Next(): Emmit the goTo() method with correct index
21
+ * - Next(): Don't emmit the goTo() method if already last slide
22
+ * - #Change(): Change the [aria-selected], [aria-hidden] and [disabled] attributes
23
+ * - #Change(): Emmit the slider:changing and slider:changed events
24
+ * - #Loop(): Go to the last slide if too much left
25
+ * - #Loop(): Go to the first slide if too much right
26
+ * - #Loop(): Go to the first or last slide via toGo() method
27
+ */
28
+
29
+ import { describe, test, expect, beforeAll, vi, afterAll } from "vitest"
30
+ import { fireEvent } from "@testing-library/dom"
31
+ import Slider from "../_slider"
32
+ import ErrorMessage from "../utilities/_error"
33
+
34
+ let fakeDiv, fakeSlider, fakeDivLoop, fakeSliderLoop
35
+
36
+ function setScroll(value = 0, el = fakeDiv) {
37
+ Object.assign(el, { scrollLeft: value })
38
+ fireEvent.scroll(el, { target: { scrollX: value } })
39
+ vi.runAllTimers()
40
+ }
41
+
42
+ /**
43
+ * Before all tests
44
+ *
45
+ */
46
+
47
+ beforeAll(() => {
48
+
49
+ document.body.innerHTML =
50
+ '<div id="slider">' +
51
+ '<div id="1" role="tabpanel" aria-hidden="false"><img src="https://fakeimg.pl/760x506/?text=one"></div>' +
52
+ '<div id="2" role="tabpanel" aria-hidden="false"><img src="https://fakeimg.pl/760x506/?text=two"></div>' +
53
+ '<div id="3" role="tabpanel" aria-hidden="false"><img src="https://fakeimg.pl/760x506/?text=three"></div>' +
54
+ '</div>' +
55
+ '<div id="sliderLoop">' +
56
+ '<div id="4" role="tabpanel" aria-hidden="false"><img src="https://fakeimg.pl/760x506/?text=one"></div>' +
57
+ '<div id="5" role="tabpanel" aria-hidden="false"><img src="https://fakeimg.pl/760x506/?text=two"></div>' +
58
+ '<div id="6" role="tabpanel" aria-hidden="false"><img src="https://fakeimg.pl/760x506/?text=three"></div>' +
59
+ '</div>' +
60
+ '<div id="sliderAuto">' +
61
+ '<div id="7" role="tabpanel" aria-hidden="false"><img src="https://fakeimg.pl/760x506/?text=one"></div>' +
62
+ '<div id="8" role="tabpanel" aria-hidden="false"><img src="https://fakeimg.pl/760x506/?text=two"></div>' +
63
+ '</div>' +
64
+ '<div aria-controls="slider" role="tablist">' +
65
+ '<button role="tab" aria-controls="1" aria-selected="true">1</button>' +
66
+ '<button role="tab" aria-controls="2" aria-selected="false">2</button>' +
67
+ '<button role="tab" aria-controls="3" aria-selected="false">3</button>' +
68
+ '</div>' +
69
+ '<div>' +
70
+ '<button aria-controls="slider" data-slider-prev>previous</button>' +
71
+ '<button aria-controls="slider" data-slider-next>next</button>' +
72
+ '</div>'
73
+
74
+ fakeDiv = document.getElementById('slider')
75
+ Object.defineProperty(fakeDiv, 'scrollWidth', { configurable: true, value: 300 })
76
+ Object.defineProperty(fakeDiv, 'clientWidth', { configurable: true, value: 100 })
77
+
78
+ fakeDivLoop = document.getElementById('sliderLoop')
79
+ Object.defineProperty(fakeDivLoop, 'scrollWidth', { configurable: true, value: 300 })
80
+ Object.defineProperty(fakeDivLoop, 'offsetWidth', { configurable: true, value: 100 })
81
+ Object.defineProperty(fakeDivLoop, 'clientWidth', { configurable: true, value: 100 })
82
+
83
+ fakeSlider = new Slider(fakeDiv)
84
+ fakeSliderLoop = new Slider(fakeDivLoop, { loop: true })
85
+
86
+ Object.defineProperty(fakeSlider._slides[0], 'offsetLeft', { configurable: true, value: 0 })
87
+ Object.defineProperty(fakeSlider._slides[1], 'offsetLeft', { configurable: true, value: 100 })
88
+ Object.defineProperty(fakeSlider._slides[2], 'offsetLeft', { configurable: true, value: 200 })
89
+
90
+ let val = 0
91
+ fakeSliderLoop._element.children.forEach(child => {
92
+ Object.defineProperty(child, 'offsetLeft', { configurable: true, value: val })
93
+ val = val + 100
94
+ })
95
+
96
+ })
97
+
98
+ describe('Structure of the class', () => {
99
+
100
+ test('Has all the public method', () => {
101
+ expect(fakeSlider.goTo).toBeTypeOf('function')
102
+ expect(fakeSlider.prev).toBeTypeOf('function')
103
+ expect(fakeSlider.next).toBeTypeOf('function')
104
+ })
105
+
106
+ test('Constructor: Passing the correct parameters', () => {
107
+ const htmlSlider = document.getElementById('slider')
108
+ expect(() => new Slider(htmlSlider, { behavior: 'make-error' })).toThrowError(ErrorMessage.enumOf('options.behavior', 'auto|smooth|instant'))
109
+ expect(() => new Slider(htmlSlider, { loop: 'make-error' })).toThrowError(ErrorMessage.typeOf('options.loop', 'boolean'))
110
+ expect(() => new Slider(htmlSlider, { autoplay: 'make-error' })).toThrowError(ErrorMessage.typeOf('options.autoplay', 'boolean|number'))
111
+ })
112
+
113
+ test('Constructor: Return the correct properties', () => {
114
+ expect(fakeSlider).toHaveProperty('_element')
115
+ expect(fakeSlider).toHaveProperty('_options')
116
+ expect(fakeSlider).toHaveProperty('_slides')
117
+ expect(fakeSlider).toHaveProperty('_buttons')
118
+ expect(fakeSlider).toHaveProperty('_current')
119
+ expect(fakeSlider).toHaveProperty('_interval')
120
+ expect(fakeSlider._slides).toBeTypeOf('object')
121
+ expect(fakeSlider._slides).toStrictEqual(document.querySelectorAll('#slider [role=tabpanel]'))
122
+ expect(fakeSlider._buttons).toBeTypeOf('object')
123
+ expect(fakeSlider._buttons.prev).toBeTypeOf('object')
124
+ expect(fakeSlider._buttons.next).toBeTypeOf('object')
125
+ expect(fakeSlider._buttons.tabs).toBeTypeOf('object')
126
+ expect(fakeSlider._buttons.prev).toStrictEqual(document.querySelector('[data-slider-prev]'))
127
+ expect(fakeSlider._buttons.next).toStrictEqual(document.querySelector('[data-slider-next]'))
128
+ expect(fakeSlider._buttons.tabs).toStrictEqual(document.querySelectorAll('[role=tablist] [role=tab]'))
129
+ expect(fakeSlider._current).toBe(0)
130
+ expect(fakeSlider._interval).toBeNull()
131
+ })
132
+
133
+ })
134
+
135
+ describe('#Init()', () => {
136
+
137
+ test('Loop will clone the first and last slide', () => {
138
+ expect(fakeSliderLoop._slides.length).toBe(3)
139
+ expect(fakeSliderLoop._element.children.length).toBe(5)
140
+ expect(fakeSliderLoop._element.firstElementChild.querySelector('img').getAttribute('src')).toContain('three')
141
+ expect(fakeSliderLoop._element.lastElementChild.querySelector('img').getAttribute('src')).toContain('one')
142
+ })
143
+
144
+ test('Autoplay will emmit next() method every X ms', () => {
145
+ vi.useFakeTimers()
146
+ const fakeSliderAuto = new Slider(document.getElementById('sliderAuto'), { autoplay: 1500 })
147
+ const methodSpy = vi.spyOn(fakeSliderAuto, 'next')
148
+ vi.advanceTimersByTime(3000)
149
+ expect(methodSpy).toHaveBeenCalledTimes(2)
150
+ clearInterval(fakeSliderAuto._interval)
151
+ })
152
+
153
+ test('Scroll will change the current attributes', () => {
154
+ expect(fakeSlider._current).toBe(0)
155
+ setScroll(100)
156
+ expect(fakeSlider._current).toBe(1)
157
+ })
158
+
159
+ test('Click on <button> with [role=tab] emmit the goTo() method', () => {
160
+ const fakeTab = fakeSlider._buttons.tabs[0]
161
+ const methodSpy = vi.spyOn(fakeSlider, 'goTo')
162
+ fireEvent(fakeTab, new MouseEvent('click'))
163
+ expect(methodSpy).toHaveBeenCalled()
164
+ })
165
+
166
+ test('Click on <button> with [data-slider-prev] emmit the prev() method', () => {
167
+ const fakePrev = fakeSlider._buttons.prev
168
+ const methodSpy = vi.spyOn(fakeSlider, 'prev')
169
+ fireEvent(fakePrev, new MouseEvent('click'))
170
+ expect(methodSpy).toHaveBeenCalled()
171
+ })
172
+
173
+ test('Click on <button> with [data-slider-next] emmit the next() method', () => {
174
+ const fakeNext = fakeSlider._buttons.next
175
+ const methodSpy = vi.spyOn(fakeSlider, 'next')
176
+ fireEvent(fakeNext, new MouseEvent('click'))
177
+ expect(methodSpy).toHaveBeenCalled()
178
+ })
179
+
180
+ })
181
+
182
+ describe('GoTo()', () => {
183
+
184
+ test('Passing the correct parameters', () => {
185
+ expect(() => fakeSlider.goTo()).toThrowError(ErrorMessage.typeOf('index', 'number'))
186
+ })
187
+
188
+ test('Emit a scroll() method', () => {
189
+ const scrollSpy = vi.spyOn(fakeDiv, 'scroll')
190
+ fakeSlider.goTo(0)
191
+ expect(scrollSpy).toHaveBeenCalledWith({
192
+ behavior: "smooth",
193
+ left: 0,
194
+ }, undefined)
195
+ })
196
+
197
+ })
198
+
199
+ describe('Prev()', () => {
200
+
201
+ afterAll(() => setScroll())
202
+
203
+ test('Emit a goTo() method with correct index', () => {
204
+ const methodSpy = vi.spyOn(fakeSlider, 'goTo')
205
+ fakeSlider.prev()
206
+ expect(methodSpy).toHaveBeenCalledWith(0)
207
+ })
208
+
209
+ test('Don\'t emmit the goTo() method if already first slide', () => {
210
+ const methodSpy = vi.spyOn(fakeSlider, 'goTo')
211
+ fakeSlider._current = 0
212
+ fakeSlider.prev()
213
+ expect(methodSpy).not.toHaveBeenCalled()
214
+ })
215
+
216
+ })
217
+
218
+ describe('Next()', () => {
219
+
220
+ afterAll(() => setScroll())
221
+
222
+ test('Emit a goTo() method and index is X', () => {
223
+ const methodSpy = vi.spyOn(fakeSlider, 'goTo')
224
+ fakeSlider.next()
225
+ expect(methodSpy).toHaveBeenCalledWith(1)
226
+ })
227
+
228
+ test('Don\'t emmit the goTo() method if already last slide', () => {
229
+ const methodSpy = vi.spyOn(fakeSlider, 'goTo')
230
+ fakeSlider._current = 2
231
+ fakeSlider.next()
232
+ expect(methodSpy).not.toHaveBeenCalled()
233
+ })
234
+
235
+ })
236
+
237
+ describe('#Change()', () => {
238
+
239
+ test('Toggle the [aria-selected], [aria-hidden] and [disabled] attributes', () => {
240
+ expect(fakeSlider._current).toBe(0)
241
+ expect(fakeSlider._slides[0].getAttribute('aria-hidden')).toBe('false')
242
+ expect(fakeSlider._buttons.tabs[0].getAttribute('aria-selected')).toBe('true')
243
+ expect(fakeSlider._buttons.prev.hasAttribute('disabled')).toBeTruthy()
244
+ setScroll(100)
245
+ expect(fakeSlider._current).toBe(1)
246
+ expect(fakeSlider._slides[0].getAttribute('aria-hidden')).toBe('true')
247
+ expect(fakeSlider._slides[1].getAttribute('aria-hidden')).toBe('false')
248
+ expect(fakeSlider._buttons.tabs[0].getAttribute('aria-selected')).toBe('false')
249
+ expect(fakeSlider._buttons.tabs[1].getAttribute('aria-selected')).toBe('true')
250
+ expect(fakeSlider._buttons.prev.hasAttribute('disabled')).toBeFalsy()
251
+ setScroll(200)
252
+ expect(fakeSlider._current).toBe(2)
253
+ expect(fakeSlider._slides[1].getAttribute('aria-hidden')).toBe('true')
254
+ expect(fakeSlider._slides[2].getAttribute('aria-hidden')).toBe('false')
255
+ expect(fakeSlider._buttons.tabs[1].getAttribute('aria-selected')).toBe('false')
256
+ expect(fakeSlider._buttons.tabs[2].getAttribute('aria-selected')).toBe('true')
257
+ expect(fakeSlider._buttons.next.hasAttribute('disabled')).toBeTruthy()
258
+ })
259
+
260
+ test('Emmit the slider:changing and slider:changed events', () => {
261
+ const eventSpy = vi.spyOn(fakeSlider, 'emmitEvent')
262
+ setScroll(0)
263
+ expect(eventSpy).toHaveBeenCalledWith('changing', { current: 2 })
264
+ expect(eventSpy).toHaveBeenCalledWith('changed', { current: 0 })
265
+ })
266
+
267
+ })
268
+
269
+ describe('#Loop()', () => {
270
+
271
+ test('Go to the last slide if too much left', () => {
272
+ const scrollSpy = vi.spyOn(fakeDivLoop, 'scroll')
273
+ expect(fakeSliderLoop._current).toBe(0)
274
+ setScroll(0, fakeDivLoop)
275
+ expect(fakeSliderLoop._current).toBe(2)
276
+ expect(scrollSpy).toHaveBeenCalledWith(300, 0)
277
+ })
278
+
279
+ test('Go to the first slide if too much right', () => {
280
+ const scrollSpy = vi.spyOn(fakeDivLoop, 'scroll')
281
+ expect(fakeSliderLoop._current).toBe(2)
282
+ setScroll(400, fakeDivLoop)
283
+ expect(fakeSliderLoop._current).toBe(0)
284
+ expect(scrollSpy).toHaveBeenCalledWith(100, 0)
285
+ })
286
+
287
+ test('Go to the first or last slide via toGo() method', () => {
288
+
289
+ const scrollSpy = vi.spyOn(fakeDivLoop, 'scroll')
290
+
291
+ fakeSliderLoop.goTo(-1)
292
+
293
+ expect(scrollSpy).toHaveBeenCalledWith({
294
+ behavior: "smooth",
295
+ left: 0,
296
+ }, undefined)
297
+
298
+ fakeSliderLoop.goTo(3)
299
+
300
+ expect(scrollSpy).toHaveBeenCalledWith({
301
+ behavior: "smooth",
302
+ left: 400,
303
+ }, undefined)
304
+
305
+ })
306
+
307
+ })
@@ -0,0 +1,124 @@
1
+ /**
2
+ * ------------------------------------------------------------------
3
+ * TEST for the _sortable.js
4
+ * ------------------------------------------------------------------
5
+ * The test will take care of:
6
+ * ! NONE ! - Has all the public method
7
+ * ! Tested in BaseComponent ! - Constructor: Passing the correct parameters
8
+ * - Constructor: Return the correct properties
9
+ * - Mousedown & Mouseup: Without handle toggle the [draggable] attribute
10
+ * - Mousedown & Mouseup: With handle toggle the [draggable] attribute
11
+ * - #Drag(): Add the [aria-grabbed] attribute
12
+ * - #Drag(): Emmit the sortable:drag event
13
+ * - #Drop(): Remove the [aria-grabbed] attribute
14
+ * - #Drop(): Emmit the sortable:drop event
15
+ */
16
+
17
+ import { describe, test, expect, beforeAll, vi } from "vitest"
18
+ import { fireEvent } from "@testing-library/dom"
19
+ import Sortable from "../_sortable"
20
+
21
+ let fakeListSortable, fakeTableSortable, fakeListItem
22
+
23
+ /**
24
+ * Before all tests
25
+ *
26
+ */
27
+
28
+ beforeAll(() => {
29
+
30
+ document.body.innerHTML =
31
+ '<ul id="fakeList">' +
32
+ '<li draggable="false">One</li>' +
33
+ '<li draggable="false">Two</li>' +
34
+ '<li draggable="false">Three</li>' +
35
+ '</ul>' +
36
+ '<table id="fakeTable">' +
37
+ '<tr draggable="false"><td data-handle>DRAG</td><td>One</td></tr>' +
38
+ '<tr draggable="false"><td data-handle>DRAG</td><td>Two</td></tr>' +
39
+ '<tr draggable="false"><td data-handle>DRAG</td><td>Three</td></tr>' +
40
+ '</table>'
41
+
42
+ fakeListSortable = new Sortable(document.getElementById('fakeList'))
43
+ fakeTableSortable = new Sortable(document.getElementById('fakeTable'))
44
+ fakeListItem = document.querySelector('#fakeList li')
45
+
46
+ })
47
+
48
+ describe('Structure of the class', () => {
49
+
50
+ test('Constructor: Return the correct properties', () => {
51
+ expect(fakeListSortable).toHaveProperty('_withHandle')
52
+ expect(fakeListSortable._withHandle).toBeTypeOf('boolean')
53
+ expect(fakeListSortable._withHandle).toBe(false)
54
+ expect(fakeTableSortable._withHandle).toBe(true)
55
+ expect(fakeListSortable.items).toBeTypeOf('object')
56
+ expect(fakeListSortable.items).toStrictEqual(document.querySelectorAll('#fakeList li'))
57
+ })
58
+
59
+ })
60
+
61
+ describe('Mousedown & Mouseup', () => {
62
+
63
+ test('Without handle toggle the [draggable] attribute', () => {
64
+ expect(fakeListItem.draggable).toBeFalsy()
65
+ fireEvent(fakeListItem, new MouseEvent('mousedown'))
66
+ expect(fakeListItem.draggable).toBeTruthy()
67
+ fireEvent(fakeListItem, new MouseEvent('mouseup'))
68
+ expect(fakeListItem.draggable).toBeFalsy()
69
+ })
70
+
71
+ test('With handle & Mouseup toggle the [draggable] attribute', () => {
72
+ const item = document.querySelector('#fakeTable tr')
73
+ const handle = document.querySelector('#fakeTable tr:first-child [data-handle]')
74
+ const customMousedown = new MouseEvent('mousedown')
75
+ Object.defineProperty(customMousedown, 'target', { value: handle }) // Define the mousedown event with custom target
76
+ expect(item.draggable).toBeFalsy()
77
+ fireEvent(item, new MouseEvent('mousedown'))
78
+ expect(item.draggable).toBeFalsy()
79
+ fireEvent(item, customMousedown)
80
+ expect(item.draggable).toBeTruthy()
81
+ fireEvent(item, new MouseEvent('mouseup'))
82
+ expect(item.draggable).toBeFalsy()
83
+ })
84
+
85
+ })
86
+
87
+ describe('#Drag()', () => {
88
+
89
+ test('Add the [aria-grabbed] attribute', () => {
90
+ expect(fakeListItem.hasAttribute('aria-grabbed')).toBeFalsy()
91
+ fireEvent(fakeListItem, new MouseEvent('mousedown'))
92
+ fireEvent(fakeListItem, new MouseEvent('dragstart'))
93
+ expect(fakeListItem.hasAttribute('aria-grabbed')).toBeTruthy()
94
+ fireEvent(fakeListItem, new MouseEvent('dragend'))
95
+ fireEvent(fakeListItem, new MouseEvent('mouseup'))
96
+ expect(fakeListItem.hasAttribute('aria-grabbed')).toBeFalsy()
97
+ })
98
+
99
+ test('Emmit the sortable:drag event', () => {
100
+ const eventSpy = vi.spyOn(fakeListSortable, 'emmitEvent')
101
+ expect(eventSpy).not.toHaveBeenCalled()
102
+ fireEvent(fakeListItem, new MouseEvent('mousedown'))
103
+ fireEvent(fakeListItem, new MouseEvent('dragstart'))
104
+ expect(eventSpy).toHaveBeenCalledWith('drag', { current: fakeListItem, items: fakeListSortable.items })
105
+ })
106
+
107
+ })
108
+
109
+ describe('#Drop()', () => {
110
+
111
+ test('Remove the [aria-grabbed] attribute', () => {
112
+ expect(fakeListItem.hasAttribute('aria-grabbed')).toBeTruthy()
113
+ fireEvent(fakeListItem, new MouseEvent('dragend'))
114
+ expect(fakeListItem.hasAttribute('aria-grabbed')).toBeFalsy()
115
+ })
116
+
117
+ test('Emmit the sortable:drop event', () => {
118
+ const eventSpy = vi.spyOn(fakeListSortable, 'emmitEvent')
119
+ expect(eventSpy).not.toHaveBeenCalled()
120
+ fireEvent(fakeListItem, new MouseEvent('dragend'))
121
+ expect(eventSpy).toHaveBeenCalledWith('drop', { current: fakeListItem, items: fakeListSortable.items })
122
+ })
123
+
124
+ })
@@ -0,0 +1,114 @@
1
+ /**
2
+ * ------------------------------------------------------------------
3
+ * TEST for the_tabpabel.js
4
+ * ------------------------------------------------------------------
5
+ * The test will take care of:
6
+ * ! herit from BaseComponent - Constructor: Passing the correct parameters
7
+ * - Constructor: Passing the correct parameters
8
+ * - Constructor: Return the correct properties
9
+ * - #Change(): Toggle the [aria-selected] attribute on the tab
10
+ * - #Change(): Toggle the [hidden] attribute on the panel
11
+ * - #Change(): Emmit the tabpanel:changed event
12
+ */
13
+
14
+ import { describe, test, expect, beforeAll, vi } from "vitest"
15
+ import { fireEvent } from "@testing-library/dom"
16
+ import Tabpanel from "../_tabpanel"
17
+ import ErrorMessage from "../utilities/_error"
18
+
19
+ let fakeTabpanel, fakeTabA, fakeTabB, fakeTabC, fakePanelA, fakePanelB
20
+
21
+ /**
22
+ * Before all tests
23
+ *
24
+ */
25
+
26
+ beforeAll(() => {
27
+
28
+ document.body.innerHTML =
29
+ '<div id="tabpanel">' +
30
+ '<div role="tablist">' +
31
+ '<button role="tab" aria-controls="a" aria-selected="false">A</button>' +
32
+ '<button role="tab" aria-controls="b" aria-selected="false">B</button>' +
33
+ '<button role="tab" aria-selected="false">C</button>' +
34
+ '</div>' +
35
+ '<div role="tabpanel" id="a" hidden>AAA</div>' +
36
+ '<div role="tabpanel" id="b" hidden>BBB</div>' +
37
+ '<div role="tabpanel" id="c" hidden>CCC</div>' +
38
+ '</div>'
39
+
40
+ fakeTabpanel = new Tabpanel(document.getElementById('tabpanel'))
41
+ fakeTabA = fakeTabpanel._tabs[0]
42
+ fakeTabB = fakeTabpanel._tabs[1]
43
+ fakeTabC = fakeTabpanel._tabs[2]
44
+ fakePanelA = fakeTabpanel._panels[0]
45
+ fakePanelB = fakeTabpanel._panels[1]
46
+ })
47
+
48
+ describe('Structure of the class', () => {
49
+
50
+ test('Constructor: Passing the correct parameters', () => {
51
+ const fakeWrong = document.createElement('div')
52
+ expect(() => new Tabpanel(fakeWrong)).toThrowError(ErrorMessage.exist('button [role="tab"]'))
53
+ const fakeTab = document.createElement('button')
54
+ fakeTab.setAttribute('role', 'tab')
55
+ fakeWrong.appendChild(fakeTab)
56
+ expect(() => new Tabpanel(fakeWrong)).toThrowError(ErrorMessage.exist('div [role="tabpanel"]'))
57
+ })
58
+
59
+ test('Constructor: Return the correct properties', () => {
60
+ expect(fakeTabpanel).toHaveProperty('_tabs')
61
+ expect(fakeTabpanel).toHaveProperty('_panels')
62
+ expect(fakeTabpanel).toHaveProperty('_current')
63
+ expect(fakeTabpanel._tabs).toBeTypeOf('object')
64
+ expect(fakeTabpanel._panels).toBeTypeOf('object')
65
+ expect(fakeTabpanel._current).toBeTypeOf('object')
66
+ expect(fakeTabpanel._tabs).toStrictEqual(document.querySelectorAll('#tabpanel [role="tab"]'))
67
+ expect(fakeTabpanel._panels).toStrictEqual(document.querySelectorAll('#tabpanel [role="tabpanel"]'))
68
+ expect(fakeTabpanel._current).toStrictEqual(document.querySelector('#tabpanel button'))
69
+ })
70
+
71
+ })
72
+
73
+ describe('#Change()', () => {
74
+
75
+ test('Toggle the [aria-selected] attribute on the tab', () => {
76
+ expect(fakeTabA.getAttribute('aria-selected')).toBe('true')
77
+ expect(fakeTabB.getAttribute('aria-selected')).toBe('false')
78
+ fireEvent(fakeTabB, new MouseEvent('click'))
79
+ expect(fakeTabA.getAttribute('aria-selected')).toBe('false')
80
+ expect(fakeTabB.getAttribute('aria-selected')).toBe('true')
81
+ fireEvent(fakeTabC, new MouseEvent('click'))
82
+ expect(fakeTabA.getAttribute('aria-selected')).toBe('false')
83
+ expect(fakeTabB.getAttribute('aria-selected')).toBe('true')
84
+ fireEvent(fakeTabA, new MouseEvent('click'))
85
+ expect(fakeTabA.getAttribute('aria-selected')).toBe('true')
86
+ expect(fakeTabB.getAttribute('aria-selected')).toBe('false')
87
+ })
88
+
89
+ test('Toggle the [hidden] attribute on the panel', () => {
90
+ expect(fakePanelA.hidden).toBeFalsy()
91
+ expect(fakePanelB.hidden).toBeTruthy()
92
+ fireEvent(fakeTabB, new MouseEvent('click'))
93
+ expect(fakePanelA.hidden).toBeTruthy()
94
+ expect(fakePanelB.hidden).toBeFalsy()
95
+ fireEvent(fakeTabC, new MouseEvent('click'))
96
+ expect(fakePanelA.hidden).toBeTruthy()
97
+ expect(fakePanelB.hidden).toBeFalsy()
98
+ fireEvent(fakeTabA, new MouseEvent('click'))
99
+ expect(fakePanelA.hidden).toBeFalsy()
100
+ expect(fakePanelB.hidden).toBeTruthy()
101
+ })
102
+
103
+ test('Emmit the tabpanel:changed event', () => {
104
+ const eventSpy = vi.spyOn(fakeTabpanel, 'emmitEvent')
105
+ expect(eventSpy).not.toHaveBeenCalled()
106
+ fireEvent(fakeTabA, new MouseEvent('click'))
107
+ expect(eventSpy).not.toHaveBeenCalled()
108
+ fireEvent(fakeTabC, new MouseEvent('click'))
109
+ expect(eventSpy).not.toHaveBeenCalled()
110
+ fireEvent(fakeTabB, new MouseEvent('click'))
111
+ expect(eventSpy).toHaveBeenCalledWith('changed', { current: fakeTabB })
112
+ })
113
+
114
+ })