Vue: How do you add E2E tests after not including them in initial webpack template?
Asked Answered
P

3

7

To start my project, I ran vue init webpack my-project, but I excluded E2E tests. Now I changed my mind and do want to include E2E tests. How can I add them to my project?

Note to readers: Tarun Lalwani's answer worked great for me. However you may want to consider using TestCafe, as it works without any configuration.


I've tried creating a dummy project using the command vue init webpack my--project so that I could copy-paste the test/e2e directory and then try to work from there, but it hasn't worked. I copy-pasted the npm script too, tried running npm run e2e and then updated my code based on the error messages I got.

I've reached a point where I've gotten a TypeError: webpack.optimize.ModuleConcatenationPlugin is not a constructor error. const webpack = require('webpack'), and I've ran npm update to make sure that the webpack node module is up to date, so I don't know why I'm getting that error.

Regardless, this approach of trying to run npm run e2e and then update my code based on the error messages seems somewhat unlikely to succeed.


package.json

{
  "name": "premium-poker-tools",
  "version": "1.0.0",
  "description": "A Vue.js project",
  "author": "Adam Zerner <[email protected]>",
  "private": true,
  "scripts": {
    "dev": "node build/dev-server.js",
    "start": "node build/dev-server.js",
    "build": "node build/build.js",
    "test": "BABEL_ENV=test karma start test/unit/karma.conf.js",
    "deploy": "git subtree push --prefix dist heroku master"
  },
  "dependencies": {
    "bootstrap": "^3.3.7",
    "bootstrap-sass": "^3.3.7",
    "chart.js": "^2.5.0",
    "express-sslify": "^1.2.0",
    "jquery": "^3.2.1",
    "lodash": "^4.17.4",
    "vue": "^2.4.2",
    "vue-analytics": "^5.1.1",
    "vue-chartjs": "^2.8.7",
    "vue-router": "^2.7.0",
    "vue-slider-component": "^2.5.8",
    "vuex": "^3.0.0"
  },
  "devDependencies": {
    "autoprefixer": "^7.1.2",
    "babel-core": "^6.22.1",
    "babel-loader": "^7.1.1",
    "babel-plugin-istanbul": "^4.1.1",
    "babel-plugin-transform-runtime": "^6.22.0",
    "babel-polyfill": "^6.26.0",
    "babel-preset-env": "^1.3.2",
    "babel-preset-stage-2": "^6.22.0",
    "babel-register": "^6.22.0",
    "chai": "^3.5.0",
    "chalk": "^2.0.1",
    "connect-history-api-fallback": "^1.3.0",
    "copy-webpack-plugin": "^4.0.1",
    "cross-env": "^5.0.1",
    "css-loader": "^0.28.0",
    "cssnano": "^3.10.0",
    "eventsource-polyfill": "^0.9.6",
    "express": "^4.14.1",
    "extract-text-webpack-plugin": "^2.0.0",
    "file-loader": "^0.11.1",
    "friendly-errors-webpack-plugin": "^1.1.3",
    "html-webpack-plugin": "^2.28.0",
    "http-proxy-middleware": "^0.17.3",
    "inject-loader": "^3.0.0",
    "karma": "^1.4.1",
    "karma-coverage": "^1.1.1",
    "karma-mocha": "^1.3.0",
    "karma-phantomjs-launcher": "^1.0.2",
    "karma-phantomjs-shim": "^1.4.0",
    "karma-sinon-chai": "^1.3.1",
    "karma-sourcemap-loader": "^0.3.7",
    "karma-spec-reporter": "0.0.31",
    "karma-webpack": "^2.0.2",
    "mocha": "^3.2.0",
    "node-sass": "^4.5.3",
    "opn": "^5.1.0",
    "optimize-css-assets-webpack-plugin": "^2.0.0",
    "ora": "^1.2.0",
    "phantomjs-prebuilt": "^2.1.14",
    "rimraf": "^2.6.0",
    "sass-loader": "^6.0.6",
    "semver": "^5.3.0",
    "shelljs": "^0.7.6",
    "sinon": "^2.1.0",
    "sinon-chai": "^2.8.0",
    "url-loader": "^0.5.8",
    "vue-loader": "^13.0.4",
    "vue-style-loader": "^3.0.1",
    "vue-template-compiler": "^2.4.2",
    "webpack": "^2.6.1",
    "webpack-bundle-analyzer": "^2.2.1",
    "webpack-dev-middleware": "^1.10.0",
    "webpack-hot-middleware": "^2.18.0",
    "webpack-merge": "^4.1.0",
    "worker-loader": "^1.1.1"
  },
  "engines": {
    "node": ">= 4.0.0",
    "npm": ">= 3.0.0"
  },
  "browserslist": [
    "> 1%",
    "last 2 versions",
    "not ie <= 8"
  ]
}
Powerless answered 20/1, 2018 at 21:23 Comment(2)
What test runner are you using? Jest? Mocha?Emalee
I'm using Mocha for my unit tests.Powerless
B
3

So there is no command that you can run to fix and add e2e, you need to fix it manually.

Edit

So it seems you created your project it was template 1.1.0

https://github.com/vuejs-templates/webpack/tree/1.1.0/template

So run

npm add chromedriver cross-spawn@^5.0.1 nightwatch@^0.9.12 selenium-server

I have removed chromedriver and selenium-server as the latest version won't hurt.

And download the content of this folder

https://github.com/vuejs-templates/webpack/tree/1.1.0/template/test/e2e

Also add/update "scripts" in package.json

"e2e": "node test/e2e/runner.js",
"test": "npm run unit && npm run e2e",

Original answer

But the easiest way to do that would be to create two new projects project1, project2, name both of them project1 and add e2e in one and not in second. Then you can generate a git diff patch between the two. As per the latest template the patch file is below

e2e.patch

diff --git a/README.md b/README.md
index 500b31c..5960190 100644
--- a/README.md
+++ b/README.md
@@ -20,6 +20,9 @@ npm run build --report
 # run unit tests
 npm run unit

+# run e2e tests
+npm run e2e
+
 # run all tests
 npm test
 ```
diff --git a/package.json b/package.json
index a4e8741..09d6452 100644
--- a/package.json
+++ b/package.json
@@ -8,8 +8,9 @@
     "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
     "start": "npm run dev",
     "unit": "cross-env BABEL_ENV=test karma start test/unit/karma.conf.js --single-run",
-    "test": "npm run unit",
-    "lint": "eslint --ext .js,.vue src test/unit",
+    "e2e": "node test/e2e/runner.js",
+    "test": "npm run unit && npm run e2e",
+    "lint": "eslint --ext .js,.vue src test/unit test/e2e/specs",
     "build": "node build/build.js"
   },
   "dependencies": {
@@ -28,10 +29,13 @@
     "babel-plugin-transform-vue-jsx": "^3.5.0",
     "babel-preset-env": "^1.3.2",
     "babel-preset-stage-2": "^6.22.0",
+    "babel-register": "^6.22.0",
     "chai": "^4.1.2",
     "chalk": "^2.0.1",
+    "chromedriver": "^2.27.2",
     "copy-webpack-plugin": "^4.0.1",
     "cross-env": "^5.0.1",
+    "cross-spawn": "^5.0.1",
     "css-loader": "^0.28.0",
     "eslint": "^4.15.0",
     "eslint-config-standard": "^10.2.1",
@@ -57,6 +61,7 @@
     "karma-spec-reporter": "0.0.31",
     "karma-webpack": "^2.0.2",
     "mocha": "^3.2.0",
+    "nightwatch": "^0.9.12",
     "node-notifier": "^5.1.2",
     "optimize-css-assets-webpack-plugin": "^3.2.0",
     "ora": "^1.2.0",
@@ -66,6 +71,7 @@
     "postcss-loader": "^2.0.8",
     "postcss-url": "^7.2.1",
     "rimraf": "^2.6.0",
+    "selenium-server": "^3.0.1",
     "semver": "^5.3.0",
     "shelljs": "^0.7.6",
     "sinon": "^4.0.0",
diff --git a/test/e2e/custom-assertions/elementCount.js b/test/e2e/custom-assertions/elementCount.js
new file mode 100644
index 0000000..818e602
--- /dev/null
+++ b/test/e2e/custom-assertions/elementCount.js
@@ -0,0 +1,27 @@
+// A custom Nightwatch assertion.
+// The assertion name is the filename.
+// Example usage:
+//
+//   browser.assert.elementCount(selector, count)
+//
+// For more information on custom assertions see:
+// http://nightwatchjs.org/guide#writing-custom-assertions
+
+exports.assertion = function (selector, count) {
+  this.message = 'Testing if element <' + selector + '> has count: ' + count
+  this.expected = count
+  this.pass = function (val) {
+    return val === this.expected
+  }
+  this.value = function (res) {
+    return res.value
+  }
+  this.command = function (cb) {
+    var self = this
+    return this.api.execute(function (selector) {
+      return document.querySelectorAll(selector).length
+    }, [selector], function (res) {
+      cb.call(self, res)
+    })
+  }
+}
diff --git a/test/e2e/nightwatch.conf.js b/test/e2e/nightwatch.conf.js
new file mode 100644
index 0000000..f019c0a
--- /dev/null
+++ b/test/e2e/nightwatch.conf.js
@@ -0,0 +1,46 @@
+require('babel-register')
+var config = require('../../config')
+
+// http://nightwatchjs.org/gettingstarted#settings-file
+module.exports = {
+  src_folders: ['test/e2e/specs'],
+  output_folder: 'test/e2e/reports',
+  custom_assertions_path: ['test/e2e/custom-assertions'],
+
+  selenium: {
+    start_process: true,
+    server_path: require('selenium-server').path,
+    host: '127.0.0.1',
+    port: 4444,
+    cli_args: {
+      'webdriver.chrome.driver': require('chromedriver').path
+    }
+  },
+
+  test_settings: {
+    default: {
+      selenium_port: 4444,
+      selenium_host: 'localhost',
+      silent: true,
+      globals: {
+        devServerURL: 'http://localhost:' + (process.env.PORT || config.dev.port)
+      }
+    },
+
+    chrome: {
+      desiredCapabilities: {
+        browserName: 'chrome',
+        javascriptEnabled: true,
+        acceptSslCerts: true
+      }
+    },
+
+    firefox: {
+      desiredCapabilities: {
+        browserName: 'firefox',
+        javascriptEnabled: true,
+        acceptSslCerts: true
+      }
+    }
+  }
+}
diff --git a/test/e2e/runner.js b/test/e2e/runner.js
new file mode 100644
index 0000000..2722032
--- /dev/null
+++ b/test/e2e/runner.js
@@ -0,0 +1,48 @@
+// 1. start the dev server using production config
+process.env.NODE_ENV = 'testing'
+
+const webpack = require('webpack')
+const DevServer = require('webpack-dev-server')
+
+const webpackConfig = require('../../build/webpack.prod.conf')
+const devConfigPromise = require('../../build/webpack.dev.conf')
+
+let server
+
+devConfigPromise.then(devConfig => {
+  const devServerOptions = devConfig.devServer
+  const compiler = webpack(webpackConfig)
+  server = new DevServer(compiler, devServerOptions)
+  const port = devServerOptions.port
+  const host = devServerOptions.host
+  return server.listen(port, host)
+})
+.then(() => {
+  // 2. run the nightwatch test suite against it
+  // to run in additional browsers:
+  //    1. add an entry in test/e2e/nightwatch.conf.js under "test_settings"
+  //    2. add it to the --env flag below
+  // or override the environment flag, for example: `npm run e2e -- --env chrome,firefox`
+  // For more information on Nightwatch's config file, see
+  // http://nightwatchjs.org/guide#settings-file
+  let opts = process.argv.slice(2)
+  if (opts.indexOf('--config') === -1) {
+    opts = opts.concat(['--config', 'test/e2e/nightwatch.conf.js'])
+  }
+  if (opts.indexOf('--env') === -1) {
+    opts = opts.concat(['--env', 'chrome'])
+  }
+
+  const spawn = require('cross-spawn')
+  const runner = spawn('./node_modules/.bin/nightwatch', opts, { stdio: 'inherit' })
+
+  runner.on('exit', function (code) {
+    server.close()
+    process.exit(code)
+  })
+
+  runner.on('error', function (err) {
+    server.close()
+    throw err
+  })
+})
diff --git a/test/e2e/specs/test.js b/test/e2e/specs/test.js
new file mode 100644
index 0000000..a7b1bd9
--- /dev/null
+++ b/test/e2e/specs/test.js
@@ -0,0 +1,19 @@
+// For authoring Nightwatch tests, see
+// http://nightwatchjs.org/guide#usage
+
+module.exports = {
+  'default e2e tests': function (browser) {
+    // automatically uses dev Server port from /config.index.js
+    // default: http://localhost:8080
+    // see nightwatch.conf.js
+    const devServer = browser.globals.devServerURL
+
+    browser
+      .url(devServer)
+      .waitForElementVisible('#app', 5000)
+      .assert.elementPresent('.hello')
+      .assert.containsText('h1', 'Welcome to Your Vue.js App')
+      .assert.elementCount('img', 1)
+      .end()
+  }
+}

Save this file to your project as e2e.patch. Make sure you have made git repo in the project by running below

git init 
git add .
git commit -m "first version"

And then apply the patch to add e2e

git apply < e2e.patch
git add .
git commit -m "Added e2e"
Bashan answered 17/4, 2018 at 4:50 Comment(5)
When I added your e2e.patch file and then ran git apply < e2e.patch, I get the following error: code/premium-poker-tools [master●] » git apply < e2e.patch error: patch failed: package.json:8 error: package.json: patch does not apply. I think the issue here is the same as with acdcjunior's approach - I started this project 6+ months ago and so the git diff you're creating isn't the same as what the git diff would be for when I initially created my project.Powerless
@AdamZerner, please see the edit. Hopefully that should help you outBashan
I'm getting errors for the @^x.y.z packages: code/premium-poker-tools [master] » npm add chromedriver cross-spawn@^5.0.1 nightwatch@^0.9.12 selenium-server zsh: no matches found: cross-spawn@^5.0.1Powerless
The link says it is there npmjs.com/package/cross-spawn. I would just try with npm add cross-spawnBashan
That works, thanks! Just a few caveats though. I had to remove the @^ for the nightwatch package too (in addition to cross-spawn). I also had to remove a bunch of {{#if_eq lintConfig "airbnb"}} stuff from various files in the test/e2e folder.Powerless
E
2

These vue-cli v2 templates are "rendered" based on what you choose in the menu. When you choose e2e, the e2e flag is activated and every code that has {{#e2e}} (or similar) is added in the generated project. All you have to do is look for it in the template source.

So, basically, using karma+mocha, to have what the e2e flag adds you should:

  • Add the missing npm packages:

    npm i -D [email protected] [email protected] [email protected] [email protected] [email protected]
    
  • Create a test\e2e folder and add the 4 initial files of the e2e template folder (click here to see the folder).

    • Files
    • Example:

      # Being at the root of your project
      curl https://raw.githubusercontent.com/vuejs-templates/webpack/develop/template/test/e2e/custom-assertions/elementCount.js --create-dirs -o test/e2e/custom-assertions/elementCount.js
      curl https://raw.githubusercontent.com/vuejs-templates/webpack/develop/template/test/e2e/specs/test.js --create-dirs -o test/e2e/specs/test.js
      curl https://raw.githubusercontent.com/vuejs-templates/webpack/develop/template/test/e2e/nightwatch.conf.js --create-dirs -o test/e2e/nightwatch.conf.js
      curl https://raw.githubusercontent.com/vuejs-templates/webpack/develop/template/test/e2e/runner.js --create-dirs -o test/e2e/runner.js
      
  • Update the npm scripts in your package.json:

    • Add the e2e script:

      "scripts": {
          (...)
          "e2e": "node test/e2e/runner.js",
      
    • If you want npm test to also run e2e, add && npm run e2e to the test script as well:

      "test": "npm run unit && npm run e2e",
      
    • If you have linting activated, and want to lint the e2e specs, add test/e2e/specs folder:

      "lint": "eslint --ext .js,.vue src test/unit test/e2e/specs",
      

From looking at the template, that should be all.

Emalee answered 17/4, 2018 at 15:27 Comment(4)
I got an error about not having the webpack-dev-server npm module. So I installed it and then ran npm update just to be sure everything is up to date. After doing so and trying npm run e2e again, I got this error: /Users/adamzerner/code/premium-poker-tools/test/e2e/runner.js:12 devConfigPromise.then(devConfig => { TypeError: devConfigPromise.then is not a function These issues could be because I started my project 6+ months ago.Powerless
Aw, I see. Can you post your current package.json, then? I would have to check each dependency you have and what you should have.Emalee
Or, assuming you didn't change any package, if you give us the exact date you created the project (so we can see the exact template you used) it could be another possibility.Emalee
Just added my exact package.json file. I think the issue is more than the npm packages though. Eg. the devConfigPromise.then is not a function error stems from the actual code in webpack.dev.conf being different (in this case, it needs to return a promise and it isn't doing so).Powerless
E
2

The simplest way to add e2e test in an existing vue project is to run

vue add e2e-cypress

This will automatically install all the requirements.

Errancy answered 4/11, 2019 at 13:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.