Skip to content

Commit dd6deb9

Browse files
committed
Keep the visited screens on state to show in the stepper
1 parent b7b321c commit dd6deb9

File tree

4 files changed

+35
-50
lines changed

4 files changed

+35
-50
lines changed

cypress/e2e/errors.cy.ts

Lines changed: 3 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ describe('On application start', () => {
1515
// Since the stepper is separate from the screen itself, it doesn't matter which screen we join
1616
const stepsWithExpectedErrors = ['start', 'authors']
1717
it('should have errors in start and authors, but not in any other steps', () => {
18-
cy.visit('/identifiers')
18+
cy.visit('/finish')
1919
stepsWithExpectedErrors.forEach((step) => {
2020
cy.checkThatStepperValidityIs(false, step)
2121
})
@@ -26,7 +26,6 @@ describe('On application start', () => {
2626
})
2727
})
2828
it('should have error on preview', () => {
29-
cy.visit('/start')
3029
cy.dataCy('text-validation-msg')
3130
.should('contain.text', 'minimum')
3231
})
@@ -40,20 +39,16 @@ describe('From a fixed app', () => {
4039
cy.visit('/authors')
4140
cy.dataCy('btn-add-author')
4241
.click()
43-
cy.visit('/identifiers')
42+
cy.visit('/finish')
4443
})
4544
it('should have no errors', () => {
46-
stepNames.forEach((step) => {
47-
cy.checkThatStepperValidityIs(true, step)
48-
cy.checkThatAppValidityIs(true)
49-
})
45+
cy.checkThatAppValidityIs(true)
5046
})
5147
it('should validate screen Start', () => {
5248
cy.visit('/start')
5349
cy.checkThatInputValidityIs(true, 'message')
5450
cy.dataCy('input-title')
5551
.clear()
56-
cy.checkThatStepperValidityIs(false, 'start')
5752
cy.checkThatAppValidityIs(false)
5853
cy.checkThatInputValidityIs(false, 'title')
5954
cy.get('.q-field__messages > div')
@@ -65,7 +60,6 @@ describe('From a fixed app', () => {
6560
.should('not.exist')
6661

6762
cy.checkThatInputValidityIs(true, 'message')
68-
cy.checkThatStepperValidityIs(true, 'start')
6963
cy.checkThatAppValidityIs(true)
7064
})
7165

@@ -77,13 +71,11 @@ describe('From a fixed app', () => {
7771
it('should validate missing authors', () => {
7872
cy.dataCy('btn-remove')
7973
.click()
80-
cy.checkThatStepperValidityIs(false, 'authors')
8174
cy.checkThatAppValidityIs(false)
8275
cy.dataCy('banner-error-messages')
8376
.should('contain.text', 'Add at least one author')
8477
cy.dataCy('btn-add-author')
8578
.click()
86-
cy.checkThatStepperValidityIs(true, 'authors')
8779
cy.checkThatAppValidityIs(true)
8880
})
8981
it('should validate duplicate authors', () => {
@@ -104,14 +96,12 @@ describe('From a fixed app', () => {
10496

10597
cy.dataCy('card-author0')
10698
.should('have.class', 'red-border')
107-
cy.checkThatStepperValidityIs(false, 'authors')
10899
cy.checkThatAppValidityIs(false)
109100
cy.dataCy('banner-error-messages')
110101
.should('contain.text', 'There are duplicate authors')
111102

112103
cy.dataCy('btn-remove0')
113104
.click()
114-
cy.checkThatStepperValidityIs(true, 'authors')
115105
cy.checkThatAppValidityIs(true)
116106
})
117107
it('should validate authors\' fields', () => {
@@ -121,25 +111,21 @@ describe('From a fixed app', () => {
121111
.click()
122112
cy.dataCy('input-email')
123113
.type('a')
124-
cy.checkThatStepperValidityIs(false, 'authors')
125114
cy.checkThatInputValidityIs(false, 'email')
126115
cy.checkThatAppValidityIs(false)
127116
cy.dataCy('input-email')
128117
.type('@a.com')
129-
cy.checkThatStepperValidityIs(true, 'authors')
130118
cy.checkThatInputValidityIs(true, 'email')
131119
cy.checkThatAppValidityIs(true)
132120

133121
cy.dataCy('input-orcid')
134122
.type('1')
135-
cy.checkThatStepperValidityIs(false, 'authors')
136123
cy.checkThatInputValidityIs(false, 'orcid')
137124
cy.checkThatAppValidityIs(false)
138125
cy.dataCy('input-orcid')
139126
.type('23412341234123X')
140127
.parents('.q-field')
141128
.should('not.have.class', 'q-field--error')
142-
cy.checkThatStepperValidityIs(true, 'authors')
143129
cy.checkThatAppValidityIs(true)
144130
})
145131
})
@@ -151,47 +137,39 @@ describe('From a fixed app', () => {
151137
it('should validate value', () => {
152138
cy.dataCy('btn-add-identifier')
153139
.click()
154-
cy.checkThatStepperValidityIs(false, 'identifiers')
155140
cy.checkThatInputValidityIs(false, 'value')
156141
cy.checkThatAppValidityIs(false)
157142
cy.dataCy('input-value')
158143
.type('10.1234/x')
159-
cy.checkThatStepperValidityIs(true, 'identifiers')
160144
cy.checkThatInputValidityIs(true, 'value')
161145
cy.checkThatAppValidityIs(true)
162146
cy.dataCy('input-value')
163147
.clear()
164148
.type('bad')
165-
cy.checkThatStepperValidityIs(false, 'identifiers')
166149
cy.checkThatInputValidityIs(false, 'value')
167150
cy.checkThatAppValidityIs(false)
168151

169152
cy.dataCy('radio-identifier-url')
170153
.click()
171-
cy.checkThatStepperValidityIs(false, 'identifiers')
172154
cy.checkThatInputValidityIs(false, 'value')
173155
cy.checkThatAppValidityIs(false)
174156
cy.dataCy('input-value')
175157
.clear()
176158
.type('https://a')
177-
cy.checkThatStepperValidityIs(true, 'identifiers')
178159
cy.checkThatInputValidityIs(true, 'value')
179160
cy.checkThatAppValidityIs(true)
180161
cy.dataCy('input-value')
181162
.clear()
182-
cy.checkThatStepperValidityIs(false, 'identifiers')
183163
cy.checkThatInputValidityIs(false, 'value')
184164
cy.checkThatAppValidityIs(false)
185165

186166
cy.dataCy('radio-identifier-swh')
187167
.click()
188-
cy.checkThatStepperValidityIs(false, 'identifiers')
189168
cy.checkThatInputValidityIs(false, 'value')
190169
cy.checkThatAppValidityIs(false)
191170
cy.dataCy('input-value')
192171
.clear()
193172
.type('swh:1:rev:0123456789abcdef0123456789abcdef01234567')
194-
cy.checkThatStepperValidityIs(true, 'identifiers')
195173
cy.checkThatInputValidityIs(true, 'value')
196174
cy.checkThatAppValidityIs(true)
197175
})
@@ -213,11 +191,9 @@ describe('From a fixed app', () => {
213191
.should('have.class', 'red-border')
214192
cy.dataCy('banner-error-messages')
215193
.should('contain.text', 'There are duplicate identifier')
216-
cy.checkThatStepperValidityIs(false, 'identifiers')
217194
cy.checkThatAppValidityIs(false)
218195
cy.dataCy('btn-remove0')
219196
.click()
220-
cy.checkThatStepperValidityIs(true, 'identifiers')
221197
cy.checkThatAppValidityIs(true)
222198
})
223199
})
@@ -228,23 +204,19 @@ describe('From a fixed app', () => {
228204
fields.forEach((field) => {
229205
cy.dataCy(`input-${field}`)
230206
.type('bad')
231-
cy.checkThatStepperValidityIs(false, 'related-resources')
232207
cy.checkThatInputValidityIs(false, field)
233208
cy.checkThatAppValidityIs(false)
234209
cy.dataCy(`input-${field}`)
235210
.clear()
236211
.type('https://a')
237-
cy.checkThatStepperValidityIs(true, 'related-resources')
238212
cy.checkThatInputValidityIs(true, field)
239213
cy.checkThatAppValidityIs(true)
240214
cy.dataCy(`input-${field}`)
241215
.type(' ')
242-
cy.checkThatStepperValidityIs(false, 'related-resources')
243216
cy.checkThatInputValidityIs(false, field)
244217
cy.checkThatAppValidityIs(false)
245218
cy.dataCy(`input-${field}`)
246219
.clear()
247-
cy.checkThatStepperValidityIs(true, 'related-resources')
248220
cy.checkThatInputValidityIs(true, field)
249221
cy.checkThatAppValidityIs(true)
250222
})
@@ -258,12 +230,10 @@ describe('From a fixed app', () => {
258230
cy.dataCy('btn-add-keyword')
259231
.click()
260232
cy.checkThatInputValidityIs(false, 'keyword0')
261-
cy.checkThatStepperValidityIs(false, 'keywords')
262233
cy.checkThatAppValidityIs(false)
263234
cy.dataCy('input-keyword0')
264235
.type('a')
265236
cy.checkThatInputValidityIs(true, 'keyword0')
266-
cy.checkThatStepperValidityIs(true, 'keywords')
267237
cy.checkThatAppValidityIs(true)
268238
})
269239
it('should validate duplicate keywords', () => {
@@ -274,15 +244,13 @@ describe('From a fixed app', () => {
274244
cy.checkThatInputValidityIs(false, 'keyword1')
275245
cy.dataCy('banner-error-messages')
276246
.should('contain.text', 'There are duplicate keywords')
277-
cy.checkThatStepperValidityIs(false, 'keywords')
278247
cy.checkThatAppValidityIs(false)
279248
cy.dataCy('input-keyword0')
280249
.type('a')
281250
cy.dataCy('input-keyword1')
282251
.type('b')
283252
cy.checkThatInputValidityIs(true, 'keyword0')
284253
cy.checkThatInputValidityIs(true, 'keyword1')
285-
cy.checkThatStepperValidityIs(true, 'keywords')
286254
cy.checkThatAppValidityIs(true)
287255
})
288256
})
@@ -292,13 +260,11 @@ describe('From a fixed app', () => {
292260
cy.dataCy('input-date-released')
293261
.type('1')
294262
cy.checkThatInputValidityIs(false, 'date-released')
295-
cy.checkThatStepperValidityIs(false, 'version-specific')
296263
cy.checkThatAppValidityIs(false)
297264
cy.dataCy('input-date-released')
298265
.type('1111111')
299266
.parents('.q-field')
300267
.should('not.have.class', 'q-field--error')
301-
cy.checkThatStepperValidityIs(true, 'version-specific')
302268
cy.checkThatAppValidityIs(true)
303269
})
304270
})

src/components/ScreenFinish.vue

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ export default defineComponent({
5555
DownloadButton
5656
},
5757
setup () {
58-
const { setStepName } = useApp()
58+
const { setStepName, resetState } = useApp()
5959
const { reset: resetCffData } = useCff()
6060
const { errors } = useValidation()
6161
const q = useQuasar()
@@ -68,6 +68,7 @@ export default defineComponent({
6868
persistent: true
6969
}).onOk(() => {
7070
resetCffData()
71+
resetState()
7172
void setStepName('start')
7273
})
7374
},

src/components/Stepper.vue

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@
1818
v-bind:aria-label="toLabel(step)"
1919
v-bind:caption="stepIndex < 2 ? 'required' : 'optional'"
2020
v-bind:data-cy="`step-${step}`"
21-
v-bind:done="currentStepIndex > stepIndex"
22-
v-bind:error="currentStepIndex > stepIndex && errorPerStep[step].value"
21+
v-bind:done="screenVisited(step) && !errorPerStep[step].value"
22+
v-bind:error="currentStepIndex != stepIndex && screenVisited(step) && errorPerStep[step].value"
2323
v-bind:key="step"
2424
v-bind:name="step"
2525
v-bind:order="stepIndex"
@@ -49,7 +49,7 @@ import { useValidation } from 'src/store/validation'
4949
5050
export default {
5151
setup () {
52-
const { currentStepIndex, stepName, setStepName, stepNames } = useApp()
52+
const { currentStepIndex, screenVisited, stepName, setStepName, stepNames } = useApp()
5353
const { errors } = useValidation()
5454
const toLabel = (name: string) => {
5555
if (name === 'start') { // Exception
@@ -110,6 +110,7 @@ export default {
110110
},
111111
currentStepIndex,
112112
errorPerStep,
113+
screenVisited,
113114
setStepName,
114115
stepName,
115116
stepNames,

src/store/app.ts

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,6 @@ import { useRouter } from 'vue-router'
44
export type StepNameType = 'start' | 'authors' | 'identifiers' | 'related-resources' |
55
'abstract' | 'keywords' | 'license' | 'version-specific' | 'finish'
66

7-
const state = ref({
8-
stepIndex: 0
9-
})
10-
117
const stepNames = [
128
'start',
139
'authors',
@@ -20,6 +16,11 @@ const stepNames = [
2016
'finish'
2117
] as Array<StepNameType>
2218

19+
const state = ref({
20+
stepIndex: 0,
21+
screenVisited: Array(stepNames.length).fill(false) as Array<boolean>
22+
})
23+
2324
const firstStepIndex = 0
2425

2526
const lastStepIndex = computed(() => stepNames.length - 1)
@@ -32,6 +33,11 @@ export const useApp = () => {
3233
if (!element) return
3334
element.focus()
3435
}
36+
const visitScreen = (screenName: StepNameType) => {
37+
for (let i = 0; i <= stepNames.indexOf(screenName); i++) {
38+
state.value.screenVisited[i] = true
39+
}
40+
}
3541
return {
3642
cannotGoBack: computed(() => state.value.stepIndex === firstStepIndex),
3743
cannotGoForward: computed(() => state.value.stepIndex === lastStepIndex.value),
@@ -44,25 +50,36 @@ export const useApp = () => {
4450
return
4551
}
4652
state.value.stepIndex = stepNames.indexOf(newStepName)
47-
},
48-
setStepName: async (newStepName: StepNameType) => {
49-
state.value.stepIndex = stepNames.indexOf(newStepName)
50-
await router.push({ path: `/${stepName.value}` })
51-
focusFormTitle()
53+
visitScreen(newStepName)
5254
},
5355
navigateNext: async () => {
5456
if (state.value.stepIndex < lastStepIndex.value) {
5557
state.value.stepIndex++
58+
visitScreen(stepName.value)
5659
await router.push({ path: `/${stepName.value}` })
5760
focusFormTitle()
5861
}
5962
},
6063
navigatePrevious: async () => {
6164
if (state.value.stepIndex > firstStepIndex) {
6265
state.value.stepIndex--
66+
visitScreen(stepName.value)
6367
await router.push({ path: `/${stepName.value}` })
6468
focusFormTitle()
6569
}
70+
},
71+
resetState: () => {
72+
state.value.stepIndex = 0
73+
state.value.screenVisited.fill(false)
74+
},
75+
screenVisited: (screenName: StepNameType) => {
76+
return state.value.screenVisited[stepNames.indexOf(screenName)]
77+
},
78+
setStepName: async (newStepName: StepNameType) => {
79+
state.value.stepIndex = stepNames.indexOf(newStepName)
80+
visitScreen(stepName.value)
81+
await router.push({ path: `/${stepName.value}` })
82+
focusFormTitle()
6683
}
6784
}
6885
}

0 commit comments

Comments
 (0)