diff --git a/.circleci/config.yml b/.circleci/config.yml index 89b12067cd..cb09492dda 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -32,6 +32,62 @@ jobs: name: website deploy command: ./scripts/deploy.sh + # build frontend yarn cache + frontend-cache: + docker: + - image: circleci/node:8 + steps: + - checkout + + # cache yarn deps + - restore_cache: + key: consul-ui-v1-{{ checksum "ui-v2/yarn.lock" }} + + - run: + name: install yarn packages + command: cd ui-v2 && yarn install + + - save_cache: + key: consul-ui-v1-{{ checksum "ui-v2/yarn.lock" }} + paths: + - ui-v2/node_modules + + # build ember so frontend tests run faster + ember-build: + docker: + - image: circleci/node:8 + steps: + - checkout + - restore_cache: + key: consul-ui-v1-{{ checksum "ui-v2/yarn.lock" }} + - run: cd ui-v2 && yarn build-ci --output-path=dist + + # saves the build to a workspace to be passed to a downstream job + - persist_to_workspace: + root: ui-v2 + paths: + - dist + + # run ember frontend tests + ember-test: + docker: + - image: circleci/node:8-browsers + environment: + EMBER_TEST_PARALLEL: true #enables test parallelization with ember-exam + EMBER_TEST_REPORT: test-results/report.xml #outputs test report for CircleCI test summary + parallelism: 4 + steps: + - checkout + - restore_cache: + key: consul-ui-v1-{{ checksum "ui-v2/yarn.lock" }} + - attach_workspace: + at: ui-v2 + - run: + working_directory: ui-v2 + command: node_modules/ember-cli/bin/ember exam --split=$CIRCLE_NODE_TOTAL --partition=`expr $CIRCLE_NODE_INDEX + 1` --path dist --silent -r xunit + - store_test_results: + path: ui-v2/test-results + workflows: version: 2 website: @@ -41,3 +97,12 @@ workflows: filters: branches: only: stable-website + frontend: + jobs: + - frontend-cache + - ember-build: + requires: + - frontend-cache + - ember-test: + requires: + - ember-build diff --git a/ui-v2/README.md b/ui-v2/README.md index fa05757996..de73f132e1 100644 --- a/ui-v2/README.md +++ b/ui-v2/README.md @@ -60,3 +60,20 @@ Please note: You do not need to run `make start-api`/`yarn run start:api` to run * `make test` or `yarn run test` * `make test-view` or `yarn run test:view` to view the tests running in Chrome + +#### Running Tests in Parallel +Alternatively, `ember-exam` can be used to split the tests across multiple browser instances for faster results. Most options are the same as `ember test`. To see a full list of options, run `ember exam --help`. + +**Note:** The `EMBER_EXAM_PARALLEL` environment variable must be set to override the default `parallel` value of `1` browser instance in [testem.js](./testem.js). + +To quickly run the tests across 4 parallel browser instances: +```sh +yarn test-parallel +``` + +To run manually: +```sh +$ EMBER_EXAM_PARALLEL=true ember exam --split --parallel +``` + +More ways to split tests can be found in the [ember-exam README.md](https://github.com/trentmwillis/ember-exam/blob/master/README.md). \ No newline at end of file diff --git a/ui-v2/package.json b/ui-v2/package.json index 84df5a504a..f0e521dd69 100644 --- a/ui-v2/package.json +++ b/ui-v2/package.json @@ -10,12 +10,14 @@ "repository": "", "scripts": { "build": "ember build --environment production", + "build-ci": "ember build --environment test", "lint:dev:js": "eslint -c .dev.eslintrc.js --fix ./*.js ./.*.js app config lib server tests", "lint:js": "eslint -c .eslintrc.js --fix ./*.js ./.*.js app config lib server tests", "format:js": "prettier --write \"{app,config,lib,server,tests}/**/*.js\" ./*.js ./.*.js", "start": "ember serve --port=${EMBER_SERVE_PORT:-4200} --live-reload-port=${EMBER_LIVE_RELOAD_PORT:-7020}", "start:api": "api-double --dir ./node_modules/@hashicorp/consul-api-double", "test": "ember test --test-port=${EMBER_TEST_PORT:-7357}", + "test-parallel": "EMBER_EXAM_PARALLEL=true ember exam --split=4 --parallel", "test:view": "ember test --server --test-port=${EMBER_TEST_PORT:-7357}", "test:coverage": "COVERAGE=true ember test --test-port=${EMBER_TEST_PORT:-7357}", "test:view:coverage": "COVERAGE=true ember test --server --test-port=${EMBER_TEST_PORT:-7357}" @@ -71,6 +73,7 @@ "ember-composable-helpers": "^2.1.0", "ember-computed-style": "^0.3.0", "ember-data": "^3.0.2", + "ember-exam": "^2.0.1", "ember-export-application-global": "^2.0.0", "ember-href-to": "^1.15.1", "ember-inflector": "^3.0.0", @@ -87,14 +90,14 @@ "eslint-plugin-ember": "^5.0.0", "husky": "^1.1.0", "ivy-codemirror": "^2.1.0", + "js-yaml": "^3.12.0", + "jsonlint": "^1.6.3", "lint-staged": "^7.0.0", "loader.js": "^4.2.3", "node-sass": "^4.9.3", "prettier": "^1.10.2", "svgo": "^1.0.5", - "text-encoding": "^0.6.4", - "js-yaml": "^3.12.0", - "jsonlint": "^1.6.3" + "text-encoding": "^0.6.4" }, "engines": { "node": "^4.5 || 6.* || >= 7.*" diff --git a/ui-v2/testem.js b/ui-v2/testem.js index 234f37bf39..2c61c9c068 100644 --- a/ui-v2/testem.js +++ b/ui-v2/testem.js @@ -5,11 +5,9 @@ module.exports = { launch_in_dev: ['Chrome'], browser_args: { Chrome: { - mode: 'ci', - args: [ + "ci": [ // --no-sandbox is needed when running Chrome inside a container - process.env.TRAVIS ? '--no-sandbox' : null, - + process.env.CI ? '--no-sandbox' : null, '--disable-gpu', '--headless', '--remote-debugging-port=0', @@ -18,3 +16,21 @@ module.exports = { }, }, }; + +// outputs XML reports for CI +if (process.env.EMBER_TEST_REPORT) { + module.exports.report_file = process.env.EMBER_TEST_REPORT; + module.exports.xunit_intermediate_output = true; +} + +/* + * ember-exam honors the `parallel` parameter in testem.js. + * By default this value is 1 which means it only uses one client. + * When this is set to -1 it uses the --split value of ember-exam. + * + * https://github.com/trentmwillis/ember-exam#split-test-parallelization + * https://github.com/trentmwillis/ember-exam/issues/108 + */ +if (process.env.EMBER_EXAM_PARALLEL) { + module.exports.parallel = -1 +} diff --git a/ui-v2/tests/test-helper.js b/ui-v2/tests/test-helper.js index 27708aefcb..820a5281aa 100644 --- a/ui-v2/tests/test-helper.js +++ b/ui-v2/tests/test-helper.js @@ -3,7 +3,9 @@ import config from '../config/environment'; import { setApplication } from '@ember/test-helpers'; import { start } from 'ember-qunit'; import './helpers/flash-message'; +import loadEmberExam from 'ember-exam/test-support/load'; +loadEmberExam(); setApplication(Application.create(config.APP)); start(); diff --git a/ui-v2/yarn.lock b/ui-v2/yarn.lock index 1fe965b5d8..c94f398dcb 100644 --- a/ui-v2/yarn.lock +++ b/ui-v2/yarn.lock @@ -904,6 +904,13 @@ amd-name-resolver@1.2.0: dependencies: ensure-posix-path "^1.0.1" +amd-name-resolver@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/amd-name-resolver/-/amd-name-resolver-1.2.1.tgz#cea40abff394268307df647ce340c83eda6e9cfc" + dependencies: + ensure-posix-path "^1.0.1" + object-hash "^1.3.1" + amdefine@>=0.0.4: version "1.0.1" resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" @@ -1490,6 +1497,12 @@ babel-plugin-ember-modules-api-polyfill@^2.5.0: dependencies: ember-rfc176-data "^0.3.5" +babel-plugin-ember-modules-api-polyfill@^2.6.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/babel-plugin-ember-modules-api-polyfill/-/babel-plugin-ember-modules-api-polyfill-2.6.0.tgz#9524a65ef0c31ee82536a19c243fbaec1b977cbb" + dependencies: + ember-rfc176-data "^0.3.6" + babel-plugin-eval@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/babel-plugin-eval/-/babel-plugin-eval-1.0.1.tgz#a2faed25ce6be69ade4bfec263f70169195950da" @@ -2195,6 +2208,21 @@ broccoli-babel-transpiler@^7.0.0: rsvp "^4.8.3" workerpool "^2.3.1" +broccoli-babel-transpiler@^7.1.0: + version "7.1.1" + resolved "https://registry.yarnpkg.com/broccoli-babel-transpiler/-/broccoli-babel-transpiler-7.1.1.tgz#4202cd0653845083ee744fb4eaa4a2b50292f03f" + dependencies: + "@babel/core" "^7.0.0" + broccoli-funnel "^2.0.1" + broccoli-merge-trees "^3.0.0" + broccoli-persistent-filter "^1.4.3" + clone "^2.1.2" + hash-for-dep "^1.2.3" + heimdalljs-logger "^0.1.9" + json-stable-stringify "^1.0.1" + rsvp "^4.8.3" + workerpool "^2.3.1" + broccoli-brocfile-loader@^0.18.0: version "0.18.0" resolved "https://registry.yarnpkg.com/broccoli-brocfile-loader/-/broccoli-brocfile-loader-0.18.0.tgz#2e86021c805c34ffc8d29a2fb721cf273e819e4b" @@ -3076,6 +3104,15 @@ cli-table2@^0.2.0: optionalDependencies: colors "^1.1.2" +cli-table3@^0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.5.1.tgz#0252372d94dfc40dbd8df06005f48f31f656f202" + dependencies: + object-assign "^4.1.0" + string-width "^2.1.1" + optionalDependencies: + colors "^1.1.2" + cli-table@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/cli-table/-/cli-table-0.3.1.tgz#f53b05266a8b1a0b934b3d0821e6e2dc5914ae23" @@ -3614,6 +3651,12 @@ debug@^3.1.0, debug@~3.1.0: dependencies: ms "2.0.0" +debug@^4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" + dependencies: + ms "^2.1.1" + decamelize@^1.0.0, decamelize@^1.1.1, decamelize@^1.1.2: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" @@ -4097,6 +4140,27 @@ ember-cli-babel@^7.1.0: ensure-posix-path "^1.0.2" semver "^5.5.0" +ember-cli-babel@^7.1.3: + version "7.2.0" + resolved "https://registry.yarnpkg.com/ember-cli-babel/-/ember-cli-babel-7.2.0.tgz#5c5bd877fb73f6fb198c878d3127ba9e18e9b8a0" + dependencies: + "@babel/core" "^7.0.0" + "@babel/plugin-transform-modules-amd" "^7.0.0" + "@babel/polyfill" "^7.0.0" + "@babel/preset-env" "^7.0.0" + amd-name-resolver "^1.2.1" + babel-plugin-debug-macros "^0.2.0-beta.6" + babel-plugin-ember-modules-api-polyfill "^2.6.0" + babel-plugin-module-resolver "^3.1.1" + broccoli-babel-transpiler "^7.1.0" + broccoli-debug "^0.6.4" + broccoli-funnel "^2.0.1" + broccoli-source "^1.1.0" + clone "^2.1.2" + ember-cli-version-checker "^2.1.2" + ensure-posix-path "^1.0.2" + semver "^5.5.0" + ember-cli-broccoli-sane-watcher@^2.0.4: version "2.1.1" resolved "https://registry.yarnpkg.com/ember-cli-broccoli-sane-watcher/-/ember-cli-broccoli-sane-watcher-2.1.1.tgz#1687adada9022de26053fba833dc7dd10f03dd08" @@ -4586,6 +4650,18 @@ ember-deep-set@^0.1.4: dependencies: ember-cli-babel "^6.6.0" +ember-exam@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/ember-exam/-/ember-exam-2.0.1.tgz#8fb434da1a81f1c829e3b4b5059e28cc957703ea" + dependencies: + chalk "^2.1.0" + cli-table3 "^0.5.1" + debug "^4.1.0" + ember-cli-babel "^7.1.3" + execa "^1.0.0" + fs-extra "^7.0.1" + rimraf "^2.6.2" + ember-export-application-global@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ember-export-application-global/-/ember-export-application-global-2.0.0.tgz#8d6d7619ac8a1a3f8c43003549eb21ebed685bd2" @@ -4734,6 +4810,10 @@ ember-rfc176-data@^0.3.1: version "0.3.2" resolved "https://registry.yarnpkg.com/ember-rfc176-data/-/ember-rfc176-data-0.3.2.tgz#bde5538939529b263c142b53a47402f8127f8dce" +ember-rfc176-data@^0.3.6: + version "0.3.6" + resolved "https://registry.yarnpkg.com/ember-rfc176-data/-/ember-rfc176-data-0.3.6.tgz#7138db8dfccec39c9a832adfbd4c49d670028907" + ember-router-generator@^1.0.0, ember-router-generator@^1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/ember-router-generator/-/ember-router-generator-1.2.3.tgz#8ed2ca86ff323363120fc14278191e9e8f1315ee" @@ -5243,6 +5323,18 @@ execa@^0.9.0: signal-exit "^3.0.0" strip-eof "^1.0.0" +execa@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8" + dependencies: + cross-spawn "^6.0.0" + get-stream "^4.0.0" + is-stream "^1.1.0" + npm-run-path "^2.0.0" + p-finally "^1.0.0" + signal-exit "^3.0.0" + strip-eof "^1.0.0" + exists-stat@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/exists-stat/-/exists-stat-1.0.0.tgz#0660e3525a2e89d9e446129440c272edfa24b529" @@ -5790,6 +5882,14 @@ fs-extra@^6.0.1: jsonfile "^4.0.0" universalify "^0.1.0" +fs-extra@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9" + dependencies: + graceful-fs "^4.1.2" + jsonfile "^4.0.0" + universalify "^0.1.0" + fs-minipass@^1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.5.tgz#06c277218454ec288df77ada54a03b8702aacb9d" @@ -5930,6 +6030,12 @@ get-stream@^3.0.0: version "3.0.0" resolved "http://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" +get-stream@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" + dependencies: + pump "^3.0.0" + get-value@^2.0.3, get-value@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" @@ -8165,6 +8271,10 @@ ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" +ms@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" + mustache@^2.2.1: version "2.3.0" resolved "https://registry.yarnpkg.com/mustache/-/mustache-2.3.0.tgz#4028f7778b17708a489930a6e52ac3bca0da41d0" @@ -8536,6 +8646,10 @@ object-copy@^0.1.0: define-property "^0.2.5" kind-of "^3.0.3" +object-hash@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-1.3.1.tgz#fde452098a951cb145f039bb7d455449ddc126df" + object-keys@^1.0.12: version "1.0.12" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.12.tgz#09c53855377575310cca62f55bb334abff7b3ed2" @@ -9060,6 +9174,13 @@ pump@^2.0.0, pump@^2.0.1: end-of-stream "^1.1.0" once "^1.3.1" +pump@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + pumpify@^1.3.3: version "1.5.1" resolved "https://registry.yarnpkg.com/pumpify/-/pumpify-1.5.1.tgz#36513be246ab27570b1a374a5ce278bfd74370ce"