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 <azerner3@gmail.com>",
  "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"
  ]
}
Alex Skorkin
  • 4,264
  • 3
  • 25
  • 47
Adam Zerner
  • 17,797
  • 15
  • 90
  • 156

3 Answers3

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"
Tarun Lalwani
  • 142,312
  • 9
  • 204
  • 265
  • 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. – Adam Zerner Apr 17 '18 at 17:41
  • @AdamZerner, please see the edit. Hopefully that should help you out – Tarun Lalwani Apr 17 '18 at 19:25
  • 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.1` – Adam Zerner Apr 17 '18 at 19:51
  • The link says it is there https://www.npmjs.com/package/cross-spawn. I would just try with `npm add cross-spawn` – Tarun Lalwani Apr 17 '18 at 19:54
  • 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. – Adam Zerner Apr 17 '18 at 20:11
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 babel-register@6.22.0 chromedriver@2.27.2 cross-spawn@5.0.1 nightwatch@0.9.12 selenium-server@3.0.1
    
  • 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.

acdcjunior
  • 132,397
  • 37
  • 331
  • 304
  • 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. – Adam Zerner Apr 17 '18 at 17:29
  • 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. – acdcjunior Apr 17 '18 at 17:39
  • 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. – acdcjunior Apr 17 '18 at 17:40
  • 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). – Adam Zerner Apr 17 '18 at 17:43
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.