fcad-core-dragon 2.1.1 → 2.2.0-beta.1

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 (164) hide show
  1. package/.editorconfig +7 -7
  2. package/.gitlab-ci.yml +106 -0
  3. package/.prettierrc +11 -11
  4. package/.vscode/extensions.json +8 -8
  5. package/.vscode/settings.json +16 -16
  6. package/CHANGELOG +529 -520
  7. package/README.md +57 -57
  8. package/artifacts/playwright-report/index.html +85 -0
  9. package/documentation/.vitepress/config.js +114 -114
  10. package/documentation/api-examples.md +49 -49
  11. package/documentation/composants/app-base-button.md +58 -58
  12. package/documentation/composants/app-base-error-display.md +59 -59
  13. package/documentation/composants/app-base-popover.md +68 -68
  14. package/documentation/composants/app-comp-audio.md +75 -75
  15. package/documentation/composants/app-comp-branch-buttons.md +111 -111
  16. package/documentation/composants/app-comp-button-progress.md +53 -53
  17. package/documentation/composants/app-comp-carousel.md +53 -53
  18. package/documentation/composants/app-comp-container.md +53 -53
  19. package/documentation/composants/app-comp-input-checkbox-next.md +42 -42
  20. package/documentation/composants/app-comp-input-dropdown-next.md +34 -34
  21. package/documentation/composants/app-comp-input-radio-next.md +39 -39
  22. package/documentation/composants/app-comp-input-text-next.md +35 -35
  23. package/documentation/composants/app-comp-input-text-table-next.md +34 -34
  24. package/documentation/composants/app-comp-input-text-to-fill-dropdown-next.md +53 -53
  25. package/documentation/composants/app-comp-input-text-to-fill-next.md +31 -31
  26. package/documentation/composants/app-comp-jauge.md +31 -31
  27. package/documentation/composants/app-comp-menu-item.md +55 -55
  28. package/documentation/composants/app-comp-menu.md +29 -29
  29. package/documentation/composants/app-comp-navigation.md +41 -41
  30. package/documentation/composants/app-comp-note-call.md +53 -53
  31. package/documentation/composants/app-comp-note-credit.md +53 -53
  32. package/documentation/composants/app-comp-play-bar-next.md +53 -53
  33. package/documentation/composants/app-comp-pop-up-next.md +93 -93
  34. package/documentation/composants/app-comp-quiz-next.md +235 -235
  35. package/documentation/composants/app-comp-quiz-recall.md +53 -53
  36. package/documentation/composants/app-comp-svg-next.md +53 -53
  37. package/documentation/composants/app-comp-table-of-content.md +50 -50
  38. package/documentation/composants/app-comp-video-player.md +82 -82
  39. package/documentation/composants.md +46 -46
  40. package/documentation/composants_critiques/ModelPageComposant.md +53 -53
  41. package/documentation/composants_critiques/app-base-module.md +43 -43
  42. package/documentation/composants_critiques/app-base-page.md +48 -48
  43. package/documentation/composants_critiques/app-base.md +311 -311
  44. package/documentation/composants_critiques/main.md +15 -15
  45. package/documentation/demarrage.md +50 -50
  46. package/documentation/deploiement.md +57 -57
  47. package/documentation/index.md +33 -33
  48. package/documentation/markdown-examples.md +85 -85
  49. package/documentation/public/vite.svg +14 -14
  50. package/documentation/public/vuejs.svg +1 -1
  51. package/documentation/public/vuetify.svg +5 -5
  52. package/eslint.config.js +60 -60
  53. package/package.json +69 -59
  54. package/playwright/index.html +12 -0
  55. package/playwright/index.js +21 -0
  56. package/playwright-ct.config.js +95 -0
  57. package/src/$locales/en.json +157 -157
  58. package/src/$locales/fr.json +120 -120
  59. package/src/assets/data/onboardingMessages.json +47 -47
  60. package/src/components/AppBase.vue +1171 -1169
  61. package/src/components/AppBaseButton.vue +90 -95
  62. package/src/components/AppBaseErrorDisplay.vue +438 -438
  63. package/src/components/AppBaseFlipCard.vue +84 -84
  64. package/src/components/AppBaseModule.vue +1639 -1634
  65. package/src/components/AppBasePage.vue +862 -866
  66. package/src/components/AppBasePopover.vue +41 -41
  67. package/src/components/AppBaseSkeleton.vue +66 -66
  68. package/src/components/AppCompAudio.vue +261 -256
  69. package/src/components/AppCompBranchButtons.vue +508 -508
  70. package/src/components/AppCompButtonProgress.vue +137 -132
  71. package/src/components/AppCompCarousel.vue +342 -336
  72. package/src/components/AppCompContainer.vue +29 -29
  73. package/src/components/AppCompInputCheckBoxNx.vue +326 -323
  74. package/src/components/AppCompInputDropdownNx.vue +302 -299
  75. package/src/components/AppCompInputRadioNx.vue +288 -284
  76. package/src/components/AppCompInputTextNx.vue +154 -153
  77. package/src/components/AppCompInputTextTableNx.vue +205 -202
  78. package/src/components/AppCompInputTextToFillDropdownNx.vue +341 -340
  79. package/src/components/AppCompInputTextToFillNx.vue +293 -313
  80. package/src/components/AppCompJauge.vue +81 -81
  81. package/src/components/AppCompMenu.vue +6 -1
  82. package/src/components/AppCompMenuItem.vue +246 -240
  83. package/src/components/AppCompNavigation.vue +977 -972
  84. package/src/components/AppCompNoteCall.vue +167 -161
  85. package/src/components/AppCompNoteCredit.vue +496 -491
  86. package/src/components/AppCompPlayBarNext.vue +2288 -2288
  87. package/src/components/AppCompPopUpNext.vue +508 -504
  88. package/src/components/AppCompQuizNext.vue +515 -510
  89. package/src/components/AppCompQuizRecall.vue +365 -350
  90. package/src/components/AppCompSVGNext.vue +346 -346
  91. package/src/components/AppCompSettingsMenu.vue +177 -172
  92. package/src/components/AppCompTableOfContent.vue +433 -427
  93. package/src/components/AppCompVideoPlayer.vue +378 -377
  94. package/src/components/AppCompViewDisplay.vue +6 -6
  95. package/src/components/BaseModule.vue +55 -55
  96. package/src/composables/useIdleDetector.js +56 -56
  97. package/src/composables/useQuiz.js +89 -89
  98. package/src/composables/useTimer.js +172 -172
  99. package/src/directives/nvdaFix.js +53 -53
  100. package/src/externalComps/ModuleView.vue +22 -22
  101. package/src/externalComps/SummaryView.vue +91 -91
  102. package/src/main.js +506 -476
  103. package/src/module/stores/appStore.js +960 -947
  104. package/src/module/xapi/ADL.js +520 -520
  105. package/src/module/xapi/Crypto/Hasher.js +241 -241
  106. package/src/module/xapi/Crypto/WordArray.js +278 -278
  107. package/src/module/xapi/Crypto/algorithms/BufferedBlockAlgorithm.js +103 -103
  108. package/src/module/xapi/Crypto/algorithms/C_algo.js +315 -315
  109. package/src/module/xapi/Crypto/algorithms/HMAC.js +9 -9
  110. package/src/module/xapi/Crypto/algorithms/SHA1.js +9 -9
  111. package/src/module/xapi/Crypto/encoders/Base.js +105 -105
  112. package/src/module/xapi/Crypto/encoders/Base64.js +99 -99
  113. package/src/module/xapi/Crypto/encoders/Hex.js +61 -61
  114. package/src/module/xapi/Crypto/encoders/Latin1.js +61 -61
  115. package/src/module/xapi/Crypto/encoders/Utf8.js +45 -45
  116. package/src/module/xapi/Crypto/index.js +53 -53
  117. package/src/module/xapi/Statement/activity.js +47 -47
  118. package/src/module/xapi/Statement/agent.js +55 -55
  119. package/src/module/xapi/Statement/group.js +26 -26
  120. package/src/module/xapi/Statement/index.js +259 -259
  121. package/src/module/xapi/Statement/statement.js +253 -253
  122. package/src/module/xapi/Statement/statementRef.js +23 -23
  123. package/src/module/xapi/Statement/substatement.js +22 -22
  124. package/src/module/xapi/Statement/verb.js +36 -36
  125. package/src/module/xapi/activitytypes.js +17 -17
  126. package/src/module/xapi/launch.js +157 -157
  127. package/src/module/xapi/utils.js +167 -167
  128. package/src/module/xapi/verbs.js +294 -294
  129. package/src/module/xapi/wrapper.js +1895 -1895
  130. package/src/module/xapi/xapiStatement.js +444 -444
  131. package/src/plugins/analytics.js +34 -34
  132. package/src/plugins/bus.js +12 -8
  133. package/src/plugins/gsap.js +17 -17
  134. package/src/plugins/helper.js +355 -358
  135. package/src/plugins/i18n.js +29 -26
  136. package/src/plugins/idb.js +227 -227
  137. package/src/plugins/save.js +37 -37
  138. package/src/plugins/scorm.js +287 -287
  139. package/src/plugins/xapi.js +11 -11
  140. package/src/public/index.html +33 -33
  141. package/src/router/index.js +57 -57
  142. package/src/router/routes.js +312 -312
  143. package/src/shared/generalfuncs.js +344 -344
  144. package/src/shared/validators.js +1018 -1018
  145. package/tests/component/AppBaseButton.spec.js +53 -0
  146. package/tests/component/pinia.spec.js +24 -0
  147. package/{src/components/tests__ → tests/unit}/AppBaseButton.spec.js +53 -53
  148. package/tests/unit/AppCompAudio.spec.js +134 -0
  149. package/tests/unit/AppCompCarousel.spec.js +54 -0
  150. package/tests/unit/AppCompInputCheckBoxNx.spec.js +59 -0
  151. package/tests/unit/AppCompInputDropdownNx.spec.js +51 -0
  152. package/tests/unit/AppCompInputRadioNx.spec.js +59 -0
  153. package/tests/unit/AppCompInputTextNx.spec.js +44 -0
  154. package/tests/unit/AppCompInputTextTableNx.spec.js +77 -0
  155. package/tests/unit/AppCompInputTextToFillDropdownNx.spec.js +60 -0
  156. package/tests/unit/AppCompInputTextToFillNx.spec.js +45 -0
  157. package/tests/unit/AppCompNoteCredit.spec.js +58 -0
  158. package/tests/unit/AppCompQuizNext.spec.js +112 -0
  159. package/tests/unit/AppCompVideoPlayer.spec.js +169 -0
  160. package/tests/unit/useQuiz.spec.js +72 -0
  161. package/{src/components/tests__ → tests/unit}/useTimer.spec.js +91 -91
  162. package/vitest.config.js +42 -19
  163. package/vitest.setup.js +96 -0
  164. package/src/components/AppBaseButton.test.js +0 -21
@@ -0,0 +1,53 @@
1
+ import { test, expect } from '@playwright/experimental-ct-vue'
2
+ import AppBaseButton from '../../src/components/AppBaseButton.vue'
3
+
4
+ let component, btnElement
5
+
6
+ test.describe('AppBaseButton.vue', () => {
7
+ const btnText = 'Mon bouton custom'
8
+ const handleClick = async (payload) => {
9
+ console.log('👍Click Event - payload Received:', payload)
10
+ }
11
+
12
+ test.beforeEach(async ({ mount, page }) => {
13
+ const onClick = test.info().attach('onClick', {}) // trace visible si besoin
14
+ component = await mount(AppBaseButton, {
15
+ props: { type: 'submit', isDisabled: true, onClick: handleClick },
16
+ slots: {
17
+ default: btnText
18
+ }
19
+ })
20
+
21
+ btnElement = await page.getByRole('button')
22
+ })
23
+
24
+ test('It renders a button', async ({ page }) => {
25
+ await expect(btnElement).toBeVisible()
26
+ await expect(btnElement).toContainText(`${btnText}`)
27
+ })
28
+ //test prop value :type
29
+ test('Button has the correct type', async ({ page }) => {
30
+ await expect(btnElement).toHaveAttribute('type', 'submit')
31
+ })
32
+ // test prop value : isActive
33
+ test('Button render a correct state', async () => {
34
+ await expect(btnElement).toContainClass('md_disabled')
35
+ await expect(btnElement).toHaveAttribute('aria-disabled', 'true')
36
+ })
37
+
38
+ //test click with event emitter
39
+ test('Emit event with value of the the $el when clicked', async ({mount, page}) => {
40
+
41
+ component = await mount(AppBaseButton, {
42
+ props: { type: 'submit', isDisabled: false, onClick: handleClick },
43
+ slots: { default: btnText }})
44
+
45
+ const btnElement = page.getByRole('button')
46
+ await expect(btnElement).toBeVisible()
47
+ //Using spy / mock to listen to event
48
+
49
+ await btnElement.click()
50
+ const elHandle = await btnElement.evaluate(el => el.outerHTML)
51
+ expect(elHandle).toContain('<button')
52
+ })
53
+ })
@@ -0,0 +1,24 @@
1
+ // import { test, expect } from '@playwright/experimental-ct-vue'
2
+ // import { createPinia, setActivePinia } from 'pinia'
3
+ // import { useAppStore } from '../../src/module/stores/appStore.js'
4
+ // import Store from './Store.vue'
5
+
6
+ // test('override initialState', async ({ mount }) => {
7
+ // //create pinia instance
8
+ // const pinia = createPinia()
9
+ // setActivePinia(pinia)
10
+
11
+ // //create app store and set initial state
12
+ // const appStore = useAppStore()
13
+ // appStore.status = 'initialState'
14
+
15
+ // const component = await mount(Store, {
16
+ // hooksConfig: {
17
+ // store: { name: '$appStore' }
18
+ // },
19
+ // global: {
20
+ // plugins: [pinia]
21
+ // }
22
+ // })
23
+ // await expect(component).toContainText('initialState')
24
+ // })
@@ -1,53 +1,53 @@
1
- import { mount } from '@vue/test-utils'
2
- import AppBaseButton from '../AppBaseButton.vue'
3
- import { describe, expect, test } from 'vitest'
4
-
5
- describe('AppBaseButton.vue', () => {
6
- test('It renders a button', () => {
7
- const wrapper = mount(AppBaseButton)
8
-
9
- expect(wrapper.text()).toContain('Button')
10
- })
11
- // test prop value :type
12
- test('Button has the correct type', () => {
13
- const wrapper = mount(AppBaseButton, {
14
- props: { type: 'submit' }
15
- })
16
- // expect(wrapper.props().type).toBe(submit)
17
- expect(wrapper.get('button').attributes('type')).toBe('submit')
18
- })
19
- //test prop value : isActive
20
- test('Button render a correct state', () => {
21
- const wrapper = mount(AppBaseButton, {
22
- props: { isDisabled: true }
23
- })
24
- expect(wrapper.get('button').classes()).toEqual(
25
- expect.arrayContaining(['md_disabled'])
26
- )
27
-
28
- // expect(wrapper.props().isActive).toBe(true)
29
- })
30
-
31
- //test slot
32
- test('Renders slot content properly', () => {
33
- const wrapper = mount(AppBaseButton, {
34
- slots: {
35
- default: 'Mon bouton custome'
36
- }
37
- })
38
-
39
- expect(wrapper.get('button').text()).toBe('Mon bouton custome')
40
- })
41
-
42
- //test click with event emitter
43
- test('Emit event with value of the the $el when clicked', () => {
44
- const wrapper = mount(AppBaseButton, {
45
- slots: {
46
- default: 'Mon bouton custome'
47
- }
48
- })
49
- wrapper.get('button').trigger('click')
50
- const clickEvent = wrapper.emitted('click')[0]
51
- expect(clickEvent[0]).toEqual(wrapper.vm.$el)
52
- })
53
- })
1
+ import { mount } from '@vue/test-utils'
2
+ import AppBaseButton from '../../src/components/AppBaseButton.vue'
3
+ import { describe, expect, test } from 'vitest'
4
+
5
+ describe('AppBaseButton.vue', () => {
6
+ test('It renders a button', () => {
7
+ const wrapper = mount(AppBaseButton)
8
+
9
+ expect(wrapper.text()).toContain('Button')
10
+ })
11
+ // test prop value :type
12
+ test('Button has the correct type', () => {
13
+ const wrapper = mount(AppBaseButton, {
14
+ props: { type: 'submit' }
15
+ })
16
+ // expect(wrapper.props().type).toBe(submit)
17
+ expect(wrapper.get('button').attributes('type')).toBe('submit')
18
+ })
19
+ //test prop value : isActive
20
+ test('Button render a correct state', () => {
21
+ const wrapper = mount(AppBaseButton, {
22
+ props: { isDisabled: true }
23
+ })
24
+ expect(wrapper.get('button').classes()).toEqual(
25
+ expect.arrayContaining(['md_disabled'])
26
+ )
27
+
28
+ // expect(wrapper.props().isActive).toBe(true)
29
+ })
30
+
31
+ //test slot
32
+ test('Renders slot content properly', () => {
33
+ const wrapper = mount(AppBaseButton, {
34
+ slots: {
35
+ default: 'Mon bouton custome'
36
+ }
37
+ })
38
+
39
+ expect(wrapper.get('button').text()).toBe('Mon bouton custome')
40
+ })
41
+
42
+ //test click with event emitter
43
+ test('Emit event with value of the the $el when clicked', () => {
44
+ const wrapper = mount(AppBaseButton, {
45
+ slots: {
46
+ default: 'Mon bouton custome'
47
+ }
48
+ })
49
+ wrapper.get('button').trigger('click')
50
+ const clickEvent = wrapper.emitted('click')[0]
51
+ expect(clickEvent[0]).toEqual(wrapper.vm.$el)
52
+ })
53
+ })
@@ -0,0 +1,134 @@
1
+ import { mount } from '@vue/test-utils'
2
+ import { describe, it, test, expect } from 'vitest'
3
+
4
+ let dummyProps = {
5
+ id: 'P01',
6
+ activityRef: 'A03',
7
+ title: 'Lecteurs médias',
8
+ type: 'pg_normal',
9
+ audiosData: [
10
+ {
11
+ id: 'aud1',
12
+ mTitle: 'Et si... Annie Ernaux nous parlait',
13
+ mSources: [
14
+ {
15
+ type: 'mp3',
16
+ src: ' exemple_audio.mp3'
17
+ }
18
+ ],
19
+ mPoster: 'audio_poster.png',
20
+ mAlt: "Portrait de l'autrice Annie Ernaux",
21
+ mTranscript:
22
+ '<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.</p>'
23
+ }
24
+ ]
25
+ }
26
+
27
+ import AppCompAudioPlayer from '@/components/AppCompAudio.vue'
28
+ import { validateAudioData } from '@/shared/validators.js'
29
+
30
+ describe('AppCompAudioPlayer', () => {
31
+ test('Validate received props', () => {
32
+ validateAudioData.mockReturnValue([])
33
+ const { audiosData } = dummyProps
34
+ mount(AppCompAudioPlayer, {
35
+ props: { audData: audiosData[0] }
36
+ })
37
+
38
+ expect(validateAudioData).toHaveBeenCalledWith({
39
+ id: 'aud1',
40
+ mTitle: 'Et si... Annie Ernaux nous parlait',
41
+ mSources: [
42
+ {
43
+ type: 'mp3',
44
+ src: ' exemple_audio.mp3'
45
+ }
46
+ ],
47
+ mPoster: 'audio_poster.png',
48
+ mAlt: "Portrait de l'autrice Annie Ernaux",
49
+ mTranscript:
50
+ '<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.</p>'
51
+ })
52
+ })
53
+
54
+ it('renders ErrorDisplay When validator returns errors', () => {
55
+ // simulate invalid props
56
+ validateAudioData.mockReturnValue([
57
+ 'WARNING!>>> audio: 💥 Invalid declaration for audio element'
58
+ ])
59
+
60
+ const wrapper = mount(AppCompAudioPlayer, {
61
+ props: { audData: { id: null } }
62
+ })
63
+
64
+ expect(
65
+ wrapper.findComponent({ name: 'AppBaseErrorDisplay' }).exists()
66
+ ).toBe(true)
67
+ expect(wrapper.find('audio').exists()).toBe(false)
68
+ })
69
+
70
+ it('It renders HTML audio Element', () => {
71
+ validateAudioData.mockReturnValue([]) // no Error
72
+ const wrapper = mount(AppCompAudioPlayer, {
73
+ props: { audData: { id: null } }
74
+ })
75
+ expect(
76
+ wrapper.findComponent({ name: 'AppBaseErrorDisplay' }).exists()
77
+ ).toBe(false)
78
+ expect(wrapper.find('audio').exists()).toBe(true)
79
+ })
80
+
81
+ it('audio Element has correct sources', async () => {
82
+ const { audiosData } = dummyProps
83
+
84
+ validateAudioData.mockReturnValue([]) // no Error
85
+ const wrapper = mount(AppCompAudioPlayer, {
86
+ props: { audData: audiosData[0] }
87
+ })
88
+
89
+ expect(wrapper.vm.mSources).toEqual(audiosData[0].mSources)
90
+
91
+ //sources are rendered in the DOM
92
+ await wrapper.vm.$nextTick()
93
+ const sources = wrapper.findAll('source')
94
+ expect(sources.length).toBe(1)
95
+
96
+ // --- 3) valider les valeurs réelles rendues ---
97
+ expect(sources[0].attributes().src).toBe(audiosData[0].mSources[0].src)
98
+ expect(sources[0].attributes().type).toBe('audio/mp3')
99
+ })
100
+
101
+ it('computed $auElement returns correct data structure', async () => {
102
+ validateAudioData.mockReturnValue([])
103
+ const { audiosData } = dummyProps
104
+ const wrapper = mount(AppCompAudioPlayer, {
105
+ props: { audData: audiosData[0] }
106
+ })
107
+ // Simulate refs
108
+ const mockaudioRef = { tagName: 'audio' }
109
+ const mockContainerRef = { className: '__media-container' }
110
+ wrapper.vm.$refs['m-audio'] = mockaudioRef
111
+ wrapper.vm.$refs['$media-container'] = mockContainerRef
112
+ // Simulate refs isSet (audio ready) to true
113
+ wrapper.vm.isSet = true
114
+ await wrapper.vm.$nextTick()
115
+ // get audElement object
116
+ const obj = wrapper.vm.$audElement
117
+ const id = wrapper.vm.$props.audData.id
118
+ // expected data structure to be returned
119
+ const audElement = {
120
+ id,
121
+ mType: 'audio',
122
+ mElement: { localName: 'audio' },
123
+ mTranscript:
124
+ '<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.</p>'
125
+ }
126
+
127
+ expect(obj.id).toEqual(audElement.id)
128
+ expect(obj.mType).toBe(audElement.mType)
129
+ expect(obj.mElement.tagName.toLowerCase()).toBe(
130
+ audElement.mElement.localName
131
+ )
132
+ expect(obj.mTranscript).toBe(audElement.mTranscript)
133
+ })
134
+ })
@@ -0,0 +1,54 @@
1
+ import { mount } from '@vue/test-utils'
2
+ import AppCompCarousel from '@/components/AppCompCarousel.vue'
3
+ import AppBaseButton from '@/components/AppBaseButton.vue'
4
+ import { beforeEach, describe, expect, it } from 'vitest'
5
+
6
+ const dummyProps = {
7
+ slides: [
8
+ {
9
+ imgSrc: 'https://loremflickr.com/500/500/kitten?random=1',
10
+ imgAlt: 'ceci est un chat',
11
+ title: 'Mon premier chat',
12
+ hypertext:
13
+ '<h3>Test</h3><p>Voici un texte de test pour le premier chat.</p>'
14
+ },
15
+ {
16
+ imgSrc: 'https://loremflickr.com/500/500/kitten?random=10',
17
+ imgAlt: 'ceci est un autre chat',
18
+ title: 'Le deuxième chat',
19
+ hypertext: ''
20
+ },
21
+ {
22
+ imgSrc: 'https://loremflickr.com/500/500/kitten?random=100',
23
+ imgAlt: 'ceci est un encore chat',
24
+ title: 'Le troisième chat',
25
+ hypertext: ''
26
+ }
27
+ ],
28
+ name: 'Mon super carousel'
29
+ }
30
+
31
+ describe('AppCompCarousel.vue', () => {
32
+ let wrapper = null
33
+ beforeEach(() => {
34
+ wrapper = mount(AppCompCarousel, {
35
+ props: dummyProps
36
+ })
37
+ })
38
+
39
+ it(`displays the good amount of images`, () => {
40
+ expect(wrapper.findAll('img').length).toBe(dummyProps.slides.length)
41
+ })
42
+
43
+ it('renders two appBaseButton components as controls', () => {
44
+ const btnComponents = wrapper.findAllComponents(AppBaseButton)
45
+ expect(btnComponents.length).toBe(2)
46
+ })
47
+
48
+ it('updates the slide counter after nextSlide click', async () => {
49
+ const btnNext = wrapper.findAllComponents(AppBaseButton)[1]
50
+ await btnNext.trigger('click')
51
+ const counterTxt = wrapper.get('.carousel-index').text()
52
+ expect(counterTxt).toBe('2 / 3')
53
+ })
54
+ })
@@ -0,0 +1,59 @@
1
+ import { mount } from '@vue/test-utils'
2
+ import AppCompInputCheckBoxNx from '@/components/AppCompInputCheckBoxNx.vue'
3
+ import { beforeEach, describe, expect, test } from 'vitest'
4
+
5
+ const dummyProps = {
6
+ modelValue: ['cyan'],
7
+ inputData: [
8
+ {
9
+ id: '1',
10
+ value: 'rouge'
11
+ },
12
+ {
13
+ id: '2',
14
+ value: 'vert'
15
+ },
16
+ {
17
+ id: '3',
18
+ value: 'bleu'
19
+ },
20
+ {
21
+ id: '4',
22
+ value: 'jaune'
23
+ },
24
+ {
25
+ id: '5',
26
+ value: 'magenta'
27
+ },
28
+ {
29
+ id: '6',
30
+ value: 'cyan'
31
+ }
32
+ ],
33
+ solution: ['6'],
34
+ id: 'A02_P02_Q4'
35
+ }
36
+ describe('AppCompInputRadioNx.vue', () => {
37
+ let wrapper = null
38
+ beforeEach(() => {
39
+ wrapper = mount(AppCompInputCheckBoxNx, {
40
+ props: dummyProps
41
+ })
42
+ })
43
+ test(`renders a list of ${dummyProps.inputData.length} checkboxes`, () => {
44
+ expect(wrapper.findAll('input[type="checkbox"]').length).toBe(
45
+ dummyProps.inputData.length
46
+ )
47
+ })
48
+ test(`initially displays a single selected checkbox (checkbox #6 : cyan)`, () => {
49
+ const lastCheckbox = wrapper.findAll('input[type="checkbox"]')[5]
50
+ expect(lastCheckbox.attributes()).toHaveProperty('checked')
51
+ })
52
+ test('emits enable-submit and update:modelValue events on input change', async () => {
53
+ const boxes = wrapper.findAll('input[type="checkbox"]')
54
+ await boxes[0].setValue()
55
+ await boxes[4].setValue()
56
+ expect(wrapper.emitted()).toHaveProperty('enable-submit')
57
+ expect(wrapper.emitted()).toHaveProperty('update:modelValue')
58
+ })
59
+ })
@@ -0,0 +1,51 @@
1
+ import { mount } from '@vue/test-utils'
2
+ import AppCompInputDropdownNx from '@/components/AppCompInputDropdownNx.vue'
3
+ import { beforeEach, describe, expect, test } from 'vitest'
4
+ import { VSelect } from 'vuetify/components/VSelect'
5
+
6
+ const dummyProps = {
7
+ modelValue: ['Données primaires', 'Données secondaires'],
8
+ inputData: [
9
+ {
10
+ id: '0',
11
+ ennonce: 'Quelle sont les données?',
12
+ option: ['Données primaires', 'Données secondaires']
13
+ },
14
+ {
15
+ id: '1',
16
+ ennonce: 'Quelle sont les données?',
17
+ option: ['Données primaires', 'Données secondaires']
18
+ }
19
+ ],
20
+ solution: ['Données primaires', 'Données secondaires'],
21
+ id: 'A02_P02_Q4'
22
+ }
23
+ describe('AppCompInputDropdownNx.vue', () => {
24
+ let wrapper = null
25
+ beforeEach(() => {
26
+ wrapper = mount(AppCompInputDropdownNx, {
27
+ props: dummyProps
28
+ })
29
+ })
30
+ test(`renders a list of vuetify v-select components`, () => {
31
+ expect(wrapper.findAllComponents(VSelect).length).toBe(
32
+ dummyProps.inputData.length
33
+ )
34
+ })
35
+ test(`displays the right labels`, () => {
36
+ const labels = wrapper.findAll('label')
37
+ labels.forEach((label, index) => {
38
+ expect(label.element.textContent).toBe(
39
+ dummyProps.inputData[index].ennonce
40
+ )
41
+ })
42
+ })
43
+ test(`has the right initial data to display (modelValue prop)`, () => {
44
+ expect(wrapper.vm.inputsValue).toStrictEqual(dummyProps.modelValue)
45
+ })
46
+ test('emits enable-submit and update:modelValue events on input change', () => {
47
+ wrapper.vm.inputsValue = ['Données secondaires', 'Données primaires']
48
+ expect(wrapper.emitted()).toHaveProperty('enable-submit')
49
+ expect(wrapper.emitted()).toHaveProperty('update:modelValue')
50
+ })
51
+ })
@@ -0,0 +1,59 @@
1
+ import { mount } from '@vue/test-utils'
2
+ import AppCompInputRadioNx from '@/components/AppCompInputRadioNx.vue'
3
+ import { beforeEach, describe, expect, test } from 'vitest'
4
+
5
+ const dummyProps = {
6
+ modelValue: [{ id: '6', value: 'cyan', selected: true }],
7
+ inputData: [
8
+ {
9
+ id: '1',
10
+ value: 'rouge'
11
+ },
12
+ {
13
+ id: '2',
14
+ value:
15
+ 'Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae'
16
+ },
17
+ {
18
+ id: '3',
19
+ value: 'bleu'
20
+ },
21
+ {
22
+ id: '4',
23
+ value: 'Une couleur'
24
+ },
25
+ {
26
+ id: '5',
27
+ value: 'magenta'
28
+ },
29
+ {
30
+ id: '6',
31
+ value: 'cyan'
32
+ }
33
+ ],
34
+ solution: ['4'],
35
+ id: 'A02_P02_Q4'
36
+ }
37
+
38
+ describe('AppCompInputRadioNx.vue', () => {
39
+ let wrapper = null
40
+ beforeEach(() => {
41
+ wrapper = mount(AppCompInputRadioNx, {
42
+ props: dummyProps
43
+ })
44
+ })
45
+ test(`renders a list of ${dummyProps.inputData.length} radio buttons`, () => {
46
+ expect(wrapper.findAll('input[type="radio"]').length).toBe(
47
+ dummyProps.inputData.length
48
+ )
49
+ })
50
+ test(`has the id ${dummyProps.id}`, () => {
51
+ expect(wrapper.find('div').attributes('id')).toBe(`${dummyProps.id}`)
52
+ })
53
+ test('emits enable-submit and update:modelValue events on input change', async () => {
54
+ const radioBtn = wrapper.find('input[type="radio"]')
55
+ await radioBtn.setValue()
56
+ expect(wrapper.emitted()).toHaveProperty('enable-submit')
57
+ expect(wrapper.emitted()).toHaveProperty('update:modelValue')
58
+ })
59
+ })
@@ -0,0 +1,44 @@
1
+ import { mount } from '@vue/test-utils'
2
+ import AppCompInputTextNx from '@/components/AppCompInputTextNx.vue'
3
+ import { beforeEach, describe, expect, test } from 'vitest'
4
+ import { VTextarea } from 'vuetify/components/VTextarea'
5
+
6
+ const dummyProps = {
7
+ modelValue: ['Bonjour'],
8
+ inputData: null,
9
+ solution: null,
10
+ userAnswer: [],
11
+ id: 'A02_P02_Q4'
12
+ }
13
+ describe('AppCompInputTextNx.vue', () => {
14
+ let wrapper = null
15
+
16
+ beforeEach(() => {
17
+ wrapper = mount(AppCompInputTextNx, {
18
+ props: dummyProps
19
+ })
20
+ })
21
+ test('renders a vuetify textarea component', () => {
22
+ const textarea = wrapper.findComponent(VTextarea)
23
+ expect(textarea.exists()).toBe(true)
24
+ })
25
+ test('contains placeholder text "Écrivez ici."', () => {
26
+ const textarea = wrapper.find('textarea')
27
+ expect(textarea.attributes('placeholder')).toBe('Écrivez ici.')
28
+ })
29
+ test(`has the id textArea_${dummyProps.id}`, () => {
30
+ const textarea = wrapper.find('textarea')
31
+ expect(textarea.attributes('id')).toBe(`textArea_${dummyProps.id}`)
32
+ })
33
+ test('accepts some input text', async () => {
34
+ const textarea = wrapper.find('textarea')
35
+ await textarea.setValue('new value')
36
+ expect(textarea.element.value).toBe('new value')
37
+ })
38
+ test('emits enable-submit and update:modelValue events on input change', async () => {
39
+ const textarea = wrapper.find('textarea')
40
+ await textarea.setValue('new value')
41
+ expect(wrapper.emitted()).toHaveProperty('enable-submit')
42
+ expect(wrapper.emitted()).toHaveProperty('update:modelValue')
43
+ })
44
+ })
@@ -0,0 +1,77 @@
1
+ import { mount } from '@vue/test-utils'
2
+ import AppCompInputTextTableNx from '@/components/AppCompInputTextTableNx.vue'
3
+ import { beforeEach, describe, expect, test } from 'vitest'
4
+ import { VTextField } from 'vuetify/components/VTextField'
5
+
6
+ const dummyProps = {
7
+ modelValue: ['Blablabla', '1234', 'Lorem', 'Ipsum', 'cinq', '10'],
8
+ inputData: [
9
+ {
10
+ id: '0',
11
+ ennonce: 'le nombre « 1 »'
12
+ },
13
+ {
14
+ id: '1',
15
+ ennonce: 'le nombre « 2 »'
16
+ },
17
+ {
18
+ id: '2',
19
+ ennonce: 'le nombre « 3 »'
20
+ },
21
+ {
22
+ id: '3',
23
+ ennonce: 'le nombre « 4 »'
24
+ },
25
+ {
26
+ id: '4',
27
+ ennonce: 'le nombre « 5 »'
28
+ },
29
+ {
30
+ id: '5',
31
+ ennonce: 'le nombre « 10 »'
32
+ }
33
+ ],
34
+ solution: null,
35
+ id: 'A02_P02_Q4'
36
+ }
37
+ describe('AppCompInputTextTableNx.vue', () => {
38
+ let wrapper = null
39
+
40
+ beforeEach(() => {
41
+ wrapper = mount(AppCompInputTextTableNx, {
42
+ props: dummyProps
43
+ })
44
+ })
45
+ test(`renders a list of vuetify v-text-field`, () => {
46
+ const textfields = wrapper.findAllComponents(VTextField)
47
+ expect(textfields.length).toBe(dummyProps.inputData.length)
48
+ })
49
+
50
+ test(`displays a list of labels according to props received`, () => {
51
+ const labels = wrapper.findAll('label')
52
+ labels.forEach((label, index) => {
53
+ expect(label.element.textContent).toBe(
54
+ dummyProps.inputData[index].ennonce
55
+ )
56
+ })
57
+ })
58
+
59
+ test(`displays the user saved answers`, () => {
60
+ const textfields = wrapper.findAll('input[type="text"]')
61
+ textfields.forEach((textfield, index) => {
62
+ expect(textfield.element.value).toBe(dummyProps.modelValue[index])
63
+ })
64
+ })
65
+
66
+ test('accepts some input text', async () => {
67
+ const textfield = wrapper.find('input[type="text"]')
68
+ await textfield.setValue('new value')
69
+ expect(textfield.element.value).toBe('new value')
70
+ })
71
+ test('emits enable-submit and update:modelValue events on input change', async () => {
72
+ const textfield = wrapper.find('input[type="text"]')
73
+ await textfield.setValue('new value')
74
+ expect(wrapper.emitted()).toHaveProperty('enable-submit')
75
+ expect(wrapper.emitted()).toHaveProperty('update:modelValue')
76
+ })
77
+ })