1- import { expect , fn , within } from 'storybook/test'
1+ import type { Meta , StoryObj } from '@storybook/vue3'
2+ import { expect , fn , within } from '@storybook/test'
3+ import { ref } from 'vue'
24
35import DsfrRadioButton from './DsfrRadioButton.vue'
46import DsfrRadioButtonSet from './DsfrRadioButtonSet.vue'
@@ -8,7 +10,7 @@ import DsfrRadioButtonSet from './DsfrRadioButtonSet.vue'
810 *
911 * Nous vous invitons à regarder plutôt la [nouvelle documentation](https://vue-ds.fr/composants/DsfrRadioButton) pour ce composant
1012 */
11- export default {
13+ const meta = {
1214 component : DsfrRadioButton ,
1315 title : 'Composants/DsfrRadioButton' ,
1416 tags : [ 'formulaire' ] ,
@@ -27,15 +29,15 @@ export default {
2729 control : 'boolean' ,
2830 description : 'Utilise la version réduite du bouton radio' ,
2931 } ,
30- // label: {
31- // control: 'text',
32- // description: 'Label du bouton radio',
33- // },
3432 modelValue : {
3533 control : 'text' ,
3634 description : 'Valeur de la case cochée' ,
3735 } ,
38- onChange : { action : fn ( ) } ,
36+ 'onUpdate:modelValue' : {
37+ action : fn ( ) ,
38+ description :
39+ 'Événement émis à chaque changement de valeur du groupe de même bouton radio' ,
40+ } ,
3941 img : {
4042 control : 'text' ,
4143 description : 'Permet d\'ajouter une image au composant' ,
@@ -53,161 +55,159 @@ export default {
5355 control : 'object' ,
5456 description : 'Permet de définir des attributs pour le SVG.' ,
5557 } ,
56- 'update:modelValue' : {
57- description :
58- 'Événement émis à chaque changement de valeur du groupe de même bouton radio' ,
59- } ,
6058 } ,
61- }
59+ } satisfies Meta < typeof DsfrRadioButton >
6260
63- export const BoutonRadio = ( args ) => ( {
64- components : { DsfrRadioButton } ,
65- data ( ) {
66- return args
67- } ,
68- template : `
69- <div class="fr-form-group">
70- <fieldset
71- class="fr-fieldset"
72- >
73- <div
74- class="fr-fieldset__content"
75- role="radiogroup"
76- >
77- <DsfrRadioButton
78- v-for="option of options"
79- :modelValue="modelValue"
80- v-bind="option"
81- :small="small"
82- @update:modelValue="updateCheckedValue($event)"
83- />
84- </div>
85- </fieldset>
86- </div>
87- ` ,
88- methods : {
89- updateCheckedValue ( val ) {
90- if ( val === this . modelValue ) {
91- return
61+ export default meta
62+ type Story = StoryObj < typeof meta >
63+
64+ export const BoutonRadio : Story = {
65+ render : ( args ) => ( {
66+ components : { DsfrRadioButton } ,
67+ setup ( ) {
68+ const modelValue = ref ( args . modelValue )
69+ return {
70+ ...args ,
71+ modelValue,
9272 }
93- this . onChange ( val )
94- this . modelValue = val
9573 } ,
74+ template : `
75+ <div class="fr-form-group">
76+ <fieldset
77+ class="fr-fieldset"
78+ >
79+ <div
80+ class="fr-fieldset__content"
81+ role="radiogroup"
82+ >
83+ <DsfrRadioButton
84+ v-for="(option, i) of options"
85+ :key="i"
86+ v-model="modelValue"
87+ v-bind="option"
88+ :small="small"
89+ @update:model-value="args['onUpdate:modelValue']"
90+ />
91+ </div>
92+ </fieldset>
93+ </div>
94+ ` ,
95+ } ) ,
96+ args : {
97+ modelValue : '3' ,
98+ small : false ,
99+ options : [
100+ {
101+ label : 'Valeur 1' ,
102+ value : '1' ,
103+ hint : 'Description 1' ,
104+ name : 'Choix' ,
105+ } ,
106+ {
107+ label : 'Valeur 2' ,
108+ value : '2' ,
109+ disabled : true ,
110+ hint : 'Description 2' ,
111+ name : 'Choix' ,
112+ } ,
113+ {
114+ label : 'Valeur 3' ,
115+ value : '3' ,
116+ name : 'Choix' ,
117+ } ,
118+ ] ,
96119 } ,
97- } )
98- BoutonRadio . args = {
99- modelValue : '3' ,
100- small : false ,
101- options : [
102- {
103- label : 'Valeur 1' ,
104- value : '1' ,
105- hint : 'Description 1' ,
106- name : 'Choix' ,
107- } ,
108- {
109- label : 'Valeur 2' ,
110- value : '2' ,
111- disabled : true ,
112- hint : 'Description 2' ,
113- name : 'Choix' ,
114- } ,
115- {
116- label : 'Valeur 3' ,
117- value : '3' ,
118- name : 'Choix' ,
119- } ,
120- ] ,
121120}
122- BoutonRadio . play = async ( { canvasElement } ) => {
121+
122+ BoutonRadio . play = async ( { canvasElement, args } ) => {
123123 const canvas = within ( canvasElement )
124- const firstInputLabel = canvas . getByText ( BoutonRadio . args . options . at ( 0 ) ! . label )
125- const initialCheckedInputLabel = canvas . getByText ( BoutonRadio . args . options . at ( 2 ) ! . label )
124+ const firstInputLabel = canvas . getByText ( args . options . at ( 0 ) . label )
125+ const initialCheckedInputLabel = canvas . getByText ( args . options . at ( 2 ) . label )
126126 expect ( initialCheckedInputLabel ) . toHaveClass ( 'fr-label' )
127127 expect ( firstInputLabel ) . toHaveClass ( 'fr-label' )
128128 const firstInput = canvas . getAllByRole ( 'radio' ) . at ( 0 ) as HTMLInputElement
129129 const initialCheckedInput = canvas . getAllByRole ( 'radio' ) . at ( 2 ) as HTMLInputElement
130130 expect ( initialCheckedInput . parentElement ) . toHaveClass ( 'fr-radio-group' )
131131 expect ( firstInput ) . not . toBeChecked ( )
132132 expect ( initialCheckedInput ) . toBeChecked ( )
133- firstInputLabel . click ( )
133+ await firstInputLabel . click ( )
134134 expect ( firstInput ) . toBeChecked ( )
135135 expect ( initialCheckedInput ) . not . toBeChecked ( )
136+ expect ( args [ 'onUpdate:modelValue' ] ) . toHaveBeenCalledWith ( '1' )
136137}
137138
138- export const BoutonRadioRiche = ( args ) => ( {
139- components : { DsfrRadioButton, DsfrRadioButtonSet } ,
140- data ( ) {
141- return args
142- } ,
143- template : `
144- <DsfrRadioButtonSet>
145- <DsfrRadioButton
146- v-for="option of options"
147- :modelValue="modelValue"
148- v-bind="option"
149- :small="small"
150- @update:modelValue="updateCheckedValue($event)"
151- />
152- </DsfrRadioButtonSet>
153- ` ,
154- methods : {
155- updateCheckedValue ( val ) {
156- if ( val === this . modelValue ) {
157- return
139+ export const BoutonRadioRiche : Story = {
140+ render : ( args ) => ( {
141+ components : { DsfrRadioButton, DsfrRadioButtonSet } ,
142+ setup ( ) {
143+ const modelValue = ref ( args . modelValue )
144+ return {
145+ ...args ,
146+ modelValue,
158147 }
159- this . onChange ( val )
160- this . modelValue = val
161148 } ,
149+ template : `
150+ <DsfrRadioButtonSet>
151+ <DsfrRadioButton
152+ v-for="(option, i) of options"
153+ :key="i"
154+ v-model="modelValue"
155+ v-bind="option"
156+ :small="small"
157+ @update:model-value="args['onUpdate:modelValue']"
158+ />
159+ </DsfrRadioButtonSet>
160+ ` ,
161+ } ) ,
162+ args : {
163+ modelValue : '3' ,
164+ small : false ,
165+ options : [
166+ {
167+ label : 'Valeur 1' ,
168+ value : '1' ,
169+ hint : 'Description 1' ,
170+ name : 'Choix' ,
171+ img : 'https://loremflickr.com/150/250/cat' ,
172+ imgTitle : 'Un 1er chaton' ,
173+ } ,
174+ {
175+ label : 'Valeur 2' ,
176+ value : '2' ,
177+ disabled : true ,
178+ hint : 'Description 2' ,
179+ name : 'Choix' ,
180+ img : 'https://loremflickr.com/200/250/cat' ,
181+ imgTitle : 'Un 2è chaton' ,
182+ } ,
183+ {
184+ label : 'Valeur 3' ,
185+ value : '3' ,
186+ name : 'Choix' ,
187+ img : 'https://loremflickr.com/250/350/cat' ,
188+ imgTitle : 'Un 3è chaton' ,
189+ } ,
190+ ] ,
162191 } ,
163- } )
164- BoutonRadioRiche . args = {
165- modelValue : '3' ,
166- small : false ,
167- options : [
168- {
169- label : 'Valeur 1' ,
170- value : '1' ,
171- hint : 'Description 1' ,
172- name : 'Choix' ,
173- img : 'https://loremflickr.com/150/200/cat' ,
174- imgTitle : 'Un 1er chaton' ,
175- } ,
176- {
177- label : 'Valeur 2' ,
178- value : '2' ,
179- disabled : true ,
180- hint : 'Description 2' ,
181- name : 'Choix' ,
182- img : 'https://loremflickr.com/200/250/cat' ,
183- imgTitle : 'Un 2è chaton' ,
184- } ,
185- {
186- label : 'Valeur 3' ,
187- value : '3' ,
188- name : 'Choix' ,
189- img : 'https://loremflickr.com/250/350/cat' ,
190- imgTitle : 'Un 3è chaton' ,
191- } ,
192- ] ,
193192}
194- BoutonRadioRiche . play = async ( { canvasElement } ) => {
193+ BoutonRadioRiche . play = async ( { canvasElement, args } ) => {
195194 const canvas = within ( canvasElement )
196- const firstInputLabel = canvas . getByText ( BoutonRadio . args . options . at ( 0 ) ! . label )
197- const initialCheckedInputLabel = canvas . getByText ( BoutonRadio . args . options . at ( 2 ) ! . label )
195+ const firstInputLabel = canvas . getByText ( args . options . at ( 0 ) ! . label )
196+ const initialCheckedInputLabel = canvas . getByText ( args . options . at ( 2 ) ! . label )
198197 const firstInput = canvas . getAllByRole ( 'radio' ) . at ( 0 ) as HTMLInputElement
199198 const initialCheckedInput = canvas . getAllByRole ( 'radio' ) . at ( 2 ) as HTMLInputElement
200- const firstInputImg = canvas . getByTitle ( BoutonRadioRiche . args . options . at ( 0 ) ! . imgTitle )
201- const initialCheckedInputImg = canvas . getByTitle ( BoutonRadioRiche . args . options . at ( 2 ) ! . imgTitle )
199+ const firstInputImg = canvas . getByTitle ( args . options . at ( 0 ) ! . imgTitle )
200+ const initialCheckedInputImg = canvas . getByTitle ( args . options . at ( 2 ) ! . imgTitle )
202201
203- expect ( firstInputImg ) . toHaveAttribute ( 'src' , BoutonRadioRiche . args . options . at ( 0 ) ! . img )
204- expect ( initialCheckedInputImg ) . toHaveAttribute ( 'src' , BoutonRadioRiche . args . options . at ( 2 ) ! . img )
202+ expect ( firstInputImg ) . toHaveAttribute ( 'src' , args . options . at ( 0 ) ! . img )
203+ expect ( initialCheckedInputImg ) . toHaveAttribute ( 'src' , args . options . at ( 2 ) ! . img )
205204 expect ( initialCheckedInputLabel ) . toHaveClass ( 'fr-label' )
206205 expect ( firstInputLabel ) . toHaveClass ( 'fr-label' )
207206 expect ( initialCheckedInput . parentElement ) . toHaveClass ( 'fr-radio-group' )
208207 expect ( firstInput ) . not . toBeChecked ( )
209208 expect ( initialCheckedInput ) . toBeChecked ( )
210- firstInputLabel . click ( )
209+ await firstInputLabel . click ( )
211210 expect ( firstInput ) . toBeChecked ( )
212211 expect ( initialCheckedInput ) . not . toBeChecked ( )
212+ expect ( args [ 'onUpdate:modelValue' ] ) . toHaveBeenCalledWith ( '1' )
213213}
0 commit comments