I am implementing the front end of a web application using Nuxt and Vuetify at work. I have been manually checking the behavior of each release, and it is tedious each time, so I introduced Cypress (E2E testing) to automate the behavior check and save time.
I would like to share with you some of the difficulties I encountered when introducing Cypress to a project that uses Nuxt and Vuetify.
Environment
The main libraries and versions used are listed below.
Library | Version |
Nuxt | 2.15.8 |
Vue | 2.7.8 |
Vuetify | 2.6.8 |
Cypress | 10.4.0 |
Creating a test project
Create a test project using the npx create-nuxt-app command. The settings are as follows, but be sure to select Vuetify.js in the UI framework, as you will use later.
$ npx create-nuxt-app nuxt-cypress-app
create-nuxt-app v4.0.0
✨ Generating Nuxt.js project in nuxt-cypress-app
? Project name: nuxt-cypress-app
? Programming language: JavaScript
? Package manager: Yarn
? UI framework: Vuetify.js
? Nuxt.js modules: (Press <space> to select, <a> to toggle all, <i> to invert selection)
? Linting tools: ESLint, Prettier
? Testing framework: Jest
? Rendering mode: Single Page App
? Deployment target: Static (Static/Jamstack hosting)
? Development tools: jsconfig.json (Recommended for VS Code if you're not using typescript), Dependabot (For auto-updating dependencies, GitHub only)
? Continuous integration: GitHub Actions (GitHub only)
? What is your GitHub username? yamada
? Version control system: Git
Install cypress.
$ cd nuxt-cypress-app
$ yarn add -D cypress
Create a cypress directory under the project, create the following cypress configuration file (cypress.config.js), and store test files (tests).
nuxt-cypress-app
└── cypress
└── cypress.config.js
Write the following in cypress.config.js.
const { defineConfig } = require('cypress')
module.exports = defineConfig({
e2e: {
baseUrl: 'http://localhost:3000',
specPattern: "**/tests/*.spec.js",
supportFile: false,
video: true,
videoUploadOnPasses: false,
defaultCommandTimeout: 10000
}
})
Add “e2e”: “cypress run –config-file=cypress/cypress.config.js –browser chrome” to the scripts in package.json directly under the project to quickly run E2E tests. Run npm run e2e to run the E2E test.
Create the file to be tested. This time, we will create a form to input name, date of birth, etc., and a completion page.
input form
<template>
<v-container fluid>
<v-text-field
ref="name"
:value="name"
label=""
maxlength="50"
outlined
data-cy="name"
@change="(value) => (name = value)"
>
<template #prepend>Name</template>
</v-text-field>
<v-menu
v-model="menu"
:close-on-content-click="false"
:nudge-right="40"
transition="scale-transition"
offset-y
hide-details
min-width="auto"
>
<template #activator="{ on, attrs }">
<v-text-field
id="birthday"
ref="birthday"
v-model="birthday"
label=""
outlined
readonly
clearable
data-cy="birthday-text-field"
v-bind="attrs"
v-on="on"
@click:clear="birthday = null"
>
<template #prepend>Birthday</template>
</v-text-field>
</template>
<v-date-picker
v-model="birthday"
year-icon="mdi-calendar-edit"
prev-icon="mdi-skip-previous"
next-icon="mdi-skip-next"
data-cy="birthday-date-picker"
:day-format="(date) => new Date(date).getDate()"
@input="menu = false"
></v-date-picker>
</v-menu>
<v-radio-group
ref="sex"
v-model="sex"
row
class="mt-0 mb-0"
>
<template #prepend>Sex</template>
<v-radio
id="male"
value="male"
label="male"
data-cy="sex-male"
></v-radio>
<v-radio
id="female"
value="female"
label="female"
data-cy="sex-female"
></v-radio>
</v-radio-group>
<v-row class="my-5">
<v-col cols="10">
<v-checkbox
v-model="agreedWithEula"
:label="`I agree`"
color="primary"
data-cy="agreed-with-eula"
>
</v-checkbox>
</v-col>
</v-row>
<v-btn
class="mx-0"
cols="12"
large
block
color="primary"
nuxt
data-cy="next-btn"
@click="register"
>
register
</v-btn>
</v-container>
</template>
<script>
export default {
name: 'RegisterIndex',
data() {
return {
menu: false,
name: '',
birthday: '',
sex: '',
agreedWithEula: false
}
},
methods: {
register() {
this.$router.push(
`/register/complete/`
)
}
}
}
</script>
<style scoped>
</style>
completion page
<template>
<v-container fluid>
Your registration is complete.
</v-container>
</template>
<script>
export default {
name: 'RegisterComplete'
}
</script>
<style scoped>
</style>
Implement E2E testing
Implement an E2E test. In the following scenario, you will create a test file.
①Fill in each item on the input form(Select the 8th day of the month 18 months before the present as your birthday).
②When you have completed the input items, click the “Register” button.
③Move to the completion page and verify that the text “Your registration is complete.
Create a test file named register.spec.js in the cypress test directory.
describe('test register page', () => {
it('should register', () => {
cy.visit('/register/')
cy.get('[data-cy=name]').type('John')
cy.get('[data-cy=birthday-text-field]').click()
const datePicker = cy.get('[data-cy=birthday-date-picker]')
for (let i = 0; i < 18; i++) {
datePicker.get('[aria-label="Previous month"]').click()
}
cy.get('[data-cy=birthday-date-picker]').within(() => {
cy.wait(1000)
cy.get('div').contains('8').click()
})
cy.get('[data-cy=sex-female]').parent().click()
cy.get('[data-cy=agreed-with-eula]').parent().click()
cy.wait(1000)
cy.get('[data-cy=next-btn]').click()
cy.wait(1000)
cy.contains(
'Your registration is complete.'
).should('exist')
})
})
If you run Cypress with npm run e2e, you can run the E2E test and take a video, as shown below.
Troubleshooting
Unable to check with v-radio or v-checkbox
It was not checked by simply calling the click method with cy.get(‘[data-cy=agreed-with-eula]’).click().
I need to call the parent method like cy.get(‘[data-cy=agreed-with-eula]’).parent().click() (I have also looked into the reason but have not figured it out yet).
I want to select a specific date with v-date-picker
// Get the date picker component
const datePicker = cy.get('[data-cy=birthday-date-picker]')
// You need to select 18 months forward from the current date in the project, so press the "Back to previous month" icon 18 times.
for (let i = 0; i < 18; i++) {
datePicker.get('[aria-label="Previous month"]').click()
}
cy.get('[data-cy=birthday-date-picker]').within(() => {
// Wait 1 second for browser rendering so the test can retrieve the date DOM.
cy.wait(1000)
// Click on 8th
cy.get('div').contains('8').click()
})
Finally
I have uploaded the above test project to Github, so please clone it and try it out yourself.
コメント