Development Tools

Testing your application is part of the web development. Nuxt.js helps you to make it as easy as possible.

End-to-End Testing

AVA is a powerful JavaScript testing framework, mixed with jsdom, we can use them to do end-to-end testing easily.

First, we need to add AVA and jsdom as development dependencies:

  1. npm install --save-dev ava jsdom

Then add a test script to our package.json and configure AVA to compile files that we import into our tests.

  1. "scripts": {
  2. "test": "ava",
  3. },
  4. "ava": {
  5. "files": [
  6. "test/**/*"
  7. ]
  8. }

We are going to write our tests in the test folder:

  1. mkdir test

Let's say we have a page in pages/index.vue:

  1. <template>
  2. <h1 class="red">Hello {{ name }}!</h1>
  3. </template>
  4. <script>
  5. export default {
  6. data () {
  7. return { name: 'world' }
  8. }
  9. }
  10. </script>
  11. <style>
  12. .red {
  13. color: red;
  14. }
  15. </style>

When we launch our app with npm run dev and open http://localhost:3000, we can see our red Hello world! title.

We add our test file test/index.test.js:

  1. import { resolve } from 'path'
  2. import test from 'ava'
  3. import { Nuxt, Builder } from 'nuxt'
  4. // Init Nuxt.js and start listening on localhost:4000
  5. test.before('Init Nuxt.js', async (t) => {
  6. const rootDir = resolve(__dirname, '..')
  7. let config = {}
  8. try { config = require(resolve(rootDir, 'nuxt.config.js')) } catch (e) {}
  9. config.rootDir = rootDir // project folder
  10. config.dev = false // production build
  11. config.mode = 'universal' // Isomorphic application
  12. const nuxt = new Nuxt(config)
  13. t.context.nuxt = nuxt // We keep a reference to Nuxt so we can close the server at the end of the test
  14. await new Builder(nuxt).build()
  15. nuxt.listen(4000, 'localhost')
  16. })
  17. // Example of testing only generated html
  18. test('Route / exists and render HTML', async (t) => {
  19. const { nuxt } = t.context
  20. const context = {}
  21. const { html } = await nuxt.renderRoute('/', context)
  22. t.true(html.includes('<h1 class="red">Hello world!</h1>'))
  23. })
  24. // Example of testing via DOM checking
  25. test('Route / exists and renders HTML with CSS applied', async (t) => {
  26. const { nuxt } = t.context
  27. const window = await nuxt.renderAndGetWindow('http://localhost:4000/')
  28. const element = window.document.querySelector('.red')
  29. t.not(element, null)
  30. t.is(element.textContent, 'Hello world!')
  31. t.is(element.className, 'red')
  32. t.is(window.getComputedStyle(element).color, 'red')
  33. })
  34. // Close the Nuxt server
  35. test.after('Closing server', (t) => {
  36. const { nuxt } = t.context
  37. nuxt.close()
  38. })

We can now launch our tests:

  1. npm test

jsdom has some limitations because it does not use a browser. However, it will cover most of our tests. If you want to use a browser to test your application, you might want to check out Nightwatch.js.

ESLint and Prettier

ESLint is a great tool to keep your code clean.

Prettier is a very popular code formatter.

You can add ESLint with Prettier pretty easily with Nuxt.js, first, you need to add the npm dependencies:

  1. npm install --save-dev babel-eslint eslint eslint-config-prettier eslint-loader eslint-plugin-vue eslint-plugin-prettier prettier

Then, you can configure ESLint via a .eslintrc.js file in your root project directory:

  1. module.exports = {
  2. root: true,
  3. env: {
  4. browser: true,
  5. node: true
  6. },
  7. parserOptions: {
  8. parser: 'babel-eslint'
  9. },
  10. extends: [
  11. 'eslint:recommended',
  12. // https://github.com/vuejs/eslint-plugin-vue#priority-a-essential-error-prevention
  13. // consider switching to `plugin:vue/strongly-recommended` or `plugin:vue/recommended` for stricter rules.
  14. 'plugin:vue/recommended',
  15. 'plugin:prettier/recommended'
  16. ],
  17. // required to lint *.vue files
  18. plugins: [
  19. 'vue'
  20. ],
  21. // add your custom rules here
  22. rules: {
  23. 'semi': [2, 'never'],
  24. 'no-console': 'off',
  25. 'vue/max-attributes-per-line': 'off',
  26. 'prettier/prettier': ['error', { 'semi': false }]
  27. }
  28. }

Then, you can add lint and lintfix scripts to your package.json:

  1. "scripts": {
  2. "lint": "eslint --ext .js,.vue --ignore-path .gitignore .",
  3. "lintfix": "eslint --fix --ext .js,.vue --ignore-path .gitignore ."
  4. }

You can now launch lint to check for errors:

  1. npm run lint

or lintfix to also fix those which are doable

  1. npm run lintfix

ESLint will lint all of your JavaScript and Vue files while ignoring your ignored files defined in your .gitignore.

It is also recommended to enable ESLint hot reloading mode via webpack. This way ESLint will run on save during npm run dev. Just add the following to your nuxt.config.js:

  1. ...
  2. /*
  3. ** Build configuration
  4. */
  5. build: {
  6. /*
  7. ** You can extend webpack config here
  8. */
  9. extend(config, ctx) {
  10. // Run ESLint on save
  11. if (ctx.isDev && ctx.isClient) {
  12. config.module.rules.push({
  13. enforce: "pre",
  14. test: /\.(js|vue)$/,
  15. loader: "eslint-loader",
  16. exclude: /(node_modules)/
  17. })
  18. }
  19. }
  20. }

One best practice is to add also "precommit": "npm run lint" in your package.json to lint your code automatically before committing your code.