From 7bc004c1c77ce12a21606209a3efa42491015f55 Mon Sep 17 00:00:00 2001 From: "Kent C. Dodds" Date: Fri, 17 Feb 2017 12:26:39 -0700 Subject: [PATCH] total build and e2e script. Will probably change later --- .eslintignore | 3 +- .gitignore | 2 + api/package.json | 10 +- api/public/.keep | 0 api/scripts/generate/article.js | 2 +- api/scripts/generate/comment.js | 2 +- api/scripts/generate/user.js | 2 +- api/{ => src}/config/index.js | 0 api/{ => src}/config/passport.js | 0 api/{app.js => src/index.js} | 6 +- api/{ => src}/models/Article.js | 0 api/{ => src}/models/Comment.js | 0 api/{ => src}/models/User.js | 0 api/{ => src}/routes/api/articles.js | 0 api/{ => src}/routes/api/index.js | 0 api/{ => src}/routes/api/profiles.js | 0 api/{ => src}/routes/api/tags.js | 0 api/{ => src}/routes/api/users.js | 0 api/{ => src}/routes/auth.js | 0 api/{ => src}/routes/index.js | 0 api/{ => src}/routes/utils.js | 0 api/{ => src}/routes/utils.test.js | 0 api/yarn.lock | 2 +- client/package.json | 4 +- client/yarn.lock | 99 +++++++++++++- package-scripts.js | 34 +++-- package.json | 6 +- scripts/e2e.js | 184 +++++++++++++++++++++++++++ yarn.lock | 36 +++++- 29 files changed, 361 insertions(+), 31 deletions(-) delete mode 100644 api/public/.keep rename api/{ => src}/config/index.js (100%) rename api/{ => src}/config/passport.js (100%) rename api/{app.js => src/index.js} (94%) rename api/{ => src}/models/Article.js (100%) rename api/{ => src}/models/Comment.js (100%) rename api/{ => src}/models/User.js (100%) rename api/{ => src}/routes/api/articles.js (100%) rename api/{ => src}/routes/api/index.js (100%) rename api/{ => src}/routes/api/profiles.js (100%) rename api/{ => src}/routes/api/tags.js (100%) rename api/{ => src}/routes/api/users.js (100%) rename api/{ => src}/routes/auth.js (100%) rename api/{ => src}/routes/index.js (100%) rename api/{ => src}/routes/utils.js (100%) rename api/{ => src}/routes/utils.test.js (100%) create mode 100644 scripts/e2e.js diff --git a/.eslintignore b/.eslintignore index b7c45e98..8707b748 100644 --- a/.eslintignore +++ b/.eslintignore @@ -2,4 +2,5 @@ scripts/install.js scripts/verify.js coverage -cypress/examples/** \ No newline at end of file +cypress/examples/** +build diff --git a/.gitignore b/.gitignore index 6c4077ef..589f3266 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,6 @@ build *.log npm-debug.log* .mongo-db +.e2e cypress/videos +dist diff --git a/api/package.json b/api/package.json index 20bca265..e6aaa357 100644 --- a/api/package.json +++ b/api/package.json @@ -4,8 +4,11 @@ "description": "conduit on node", "main": "app.js", "scripts": { - "start": "babel-node ./app.js", - "dev": "nodemon ./app.js", + "start": "node ./dist", + "dev": "nodemon ./src", + "prebuild": "rimraf dist", + "generateData": "babel-node scripts/generate", + "build": "babel --copy-files --out-dir dist --ignore *.test.js,__mocks__ src", "test": "jest --coverage", "test:watch": "jest --watch" }, @@ -42,7 +45,8 @@ "chalk": "^1.1.3", "faker": "^3.1.0", "jest": "^18.1.0", - "lodash": "^4.17.4" + "lodash": "^4.17.4", + "rimraf": "^2.5.4" }, "jest": { "testEnvironment": "jest-environment-node", diff --git a/api/public/.keep b/api/public/.keep deleted file mode 100644 index e69de29b..00000000 diff --git a/api/scripts/generate/article.js b/api/scripts/generate/article.js index 7315e3f4..22b585f4 100644 --- a/api/scripts/generate/article.js +++ b/api/scripts/generate/article.js @@ -2,7 +2,7 @@ import faker from 'faker' import _ from 'lodash' import mongoose from 'mongoose' import {commonProps} from './utils' -import '../../models/Article' +import '../../src/models/Article' const Article = mongoose.model('Article') diff --git a/api/scripts/generate/comment.js b/api/scripts/generate/comment.js index e2e6ff7e..cdb9aa9a 100644 --- a/api/scripts/generate/comment.js +++ b/api/scripts/generate/comment.js @@ -1,7 +1,7 @@ import faker from 'faker' import mongoose from 'mongoose' import {commonProps} from './utils' -import '../../models/Comment' +import '../../src/models/Comment' const Comment = mongoose.model('Comment') diff --git a/api/scripts/generate/user.js b/api/scripts/generate/user.js index da5fd690..a655efdd 100644 --- a/api/scripts/generate/user.js +++ b/api/scripts/generate/user.js @@ -2,7 +2,7 @@ import crypto from 'crypto' import faker from 'faker' import mongoose from 'mongoose' import {commonProps} from './utils' -import '../../models/User' +import '../../src/models/User' const User = mongoose.model('User') diff --git a/api/config/index.js b/api/src/config/index.js similarity index 100% rename from api/config/index.js rename to api/src/config/index.js diff --git a/api/config/passport.js b/api/src/config/passport.js similarity index 100% rename from api/config/passport.js rename to api/src/config/passport.js diff --git a/api/app.js b/api/src/index.js similarity index 94% rename from api/app.js rename to api/src/index.js index a84b35d3..bde02ec0 100644 --- a/api/app.js +++ b/api/src/index.js @@ -33,11 +33,13 @@ if (!isProduction) { app.use(errorhandler()) } -if (isProduction) { +if (process.env.MONGODB_URI) { mongoose.connect(process.env.MONGODB_URI) + if ('MONGODB_DEBUG' in process.env) { + mongoose.set('debug', true) + } } else { mongoose.connect('mongodb://localhost/conduit') - mongoose.set('debug', true) } require('./models/User') diff --git a/api/models/Article.js b/api/src/models/Article.js similarity index 100% rename from api/models/Article.js rename to api/src/models/Article.js diff --git a/api/models/Comment.js b/api/src/models/Comment.js similarity index 100% rename from api/models/Comment.js rename to api/src/models/Comment.js diff --git a/api/models/User.js b/api/src/models/User.js similarity index 100% rename from api/models/User.js rename to api/src/models/User.js diff --git a/api/routes/api/articles.js b/api/src/routes/api/articles.js similarity index 100% rename from api/routes/api/articles.js rename to api/src/routes/api/articles.js diff --git a/api/routes/api/index.js b/api/src/routes/api/index.js similarity index 100% rename from api/routes/api/index.js rename to api/src/routes/api/index.js diff --git a/api/routes/api/profiles.js b/api/src/routes/api/profiles.js similarity index 100% rename from api/routes/api/profiles.js rename to api/src/routes/api/profiles.js diff --git a/api/routes/api/tags.js b/api/src/routes/api/tags.js similarity index 100% rename from api/routes/api/tags.js rename to api/src/routes/api/tags.js diff --git a/api/routes/api/users.js b/api/src/routes/api/users.js similarity index 100% rename from api/routes/api/users.js rename to api/src/routes/api/users.js diff --git a/api/routes/auth.js b/api/src/routes/auth.js similarity index 100% rename from api/routes/auth.js rename to api/src/routes/auth.js diff --git a/api/routes/index.js b/api/src/routes/index.js similarity index 100% rename from api/routes/index.js rename to api/src/routes/index.js diff --git a/api/routes/utils.js b/api/src/routes/utils.js similarity index 100% rename from api/routes/utils.js rename to api/src/routes/utils.js diff --git a/api/routes/utils.test.js b/api/src/routes/utils.test.js similarity index 100% rename from api/routes/utils.test.js rename to api/src/routes/utils.test.js diff --git a/api/yarn.lock b/api/yarn.lock index 9e533592..34afcace 100644 --- a/api/yarn.lock +++ b/api/yarn.lock @@ -2995,7 +2995,7 @@ right-align@^0.1.1: dependencies: align-text "^0.1.1" -rimraf@2, rimraf@^2.4.3, rimraf@^2.4.4, rimraf@~2.5.1, rimraf@~2.5.4: +rimraf@2, rimraf@^2.4.3, rimraf@^2.4.4, rimraf@^2.5.4, rimraf@~2.5.1, rimraf@~2.5.4: version "2.5.4" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.5.4.tgz#96800093cbf1a0c86bd95b4625467535c29dfa04" dependencies: diff --git a/client/package.json b/client/package.json index 70d348fa..aaad94e4 100644 --- a/client/package.json +++ b/client/package.json @@ -7,6 +7,7 @@ "babel-preset-react-app": "^2.1.0", "cross-env": "^3.1.4", "jest": "^18.1.0", + "pushstate-server": "^2.2.1", "react-scripts": "0.6.1", "rimraf": "^2.5.4" }, @@ -25,8 +26,9 @@ "superagent-promise": "^1.1.0" }, "scripts": { - "start": "cross-env PORT=8080 react-scripts start", + "dev": "cross-env PORT=8080 react-scripts start", "build": "react-scripts build", + "start": "pushstate-server build", "test": "jest --coverage", "test:watch": "jest --watch", "postinstall": "echo \"removing client copy of eslint (will use root repo's version)\" && rimraf node_modules/eslint" diff --git a/client/yarn.lock b/client/yarn.lock index f63e113e..b7ae941c 100644 --- a/client/yarn.lock +++ b/client/yarn.lock @@ -14,7 +14,7 @@ abbrev@1, abbrev@1.0.x: version "1.0.9" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.0.9.tgz#91b4792588a7738c25f35dd6f63752a2f8776135" -accepts@~1.3.3: +accepts@^1.2.5, accepts@~1.3.3: version "1.3.3" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.3.tgz#c3ca7434938648c3e0d9c1e328dd68b622c284ca" dependencies: @@ -1456,7 +1456,7 @@ compressible@~2.0.8: dependencies: mime-db ">= 1.24.0 < 2" -compression@^1.5.2: +compression@1.6.2, compression@^1.5.2: version "1.6.2" resolved "https://registry.yarnpkg.com/compression/-/compression-1.6.2.tgz#cceb121ecc9d09c52d7ad0c3350ea93ddd402bc3" dependencies: @@ -1483,6 +1483,23 @@ connect-history-api-fallback@1.3.0, connect-history-api-fallback@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-1.3.0.tgz#e51d17f8f0ef0db90a64fdb47de3051556e9f169" +connect-static-file@1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/connect-static-file/-/connect-static-file-1.1.2.tgz#d1254da775c8d694dba9b0c54994b7550cc1c7a5" + dependencies: + accepts "^1.2.5" + mime "^1.3.4" + send "^0.12.2" + +connect@3.5.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/connect/-/connect-3.5.0.tgz#b357525a0b4c1f50599cd983e1d9efeea9677198" + dependencies: + debug "~2.2.0" + finalhandler "0.5.0" + parseurl "~1.3.1" + utils-merge "1.0.0" + console-browserify@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.1.0.tgz#f0241c45730a9fc6323b206dbf38edc741d0bb10" @@ -1548,6 +1565,10 @@ core-util-is@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" +crc@3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/crc/-/crc-3.2.1.tgz#5d9c8fb77a245cd5eca291e5d2d005334bab0082" + cross-env@^3.1.4: version "3.1.4" resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-3.1.4.tgz#56e8bca96f17908a6eb1bc2012ca126f92842130" @@ -1764,10 +1785,18 @@ delegates@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" +depd@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/depd/-/depd-1.0.1.tgz#80aec64c9d6d97e65cc2a9caa93c0aa6abf73aaa" + depd@~1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.0.tgz#e1bd82c6aab6ced965b97b88b17ed3e528ca18c3" +destroy@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.3.tgz#b433b4724e71fd8551d9885174851c5fc377e2c9" + destroy@~1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" @@ -1859,6 +1888,10 @@ ecc-jsbn@~0.1.1: dependencies: jsbn "~0.1.0" +ee-first@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.0.tgz#6a0d7c6221e490feefd92ec3f441c9ce8cd097f4" + ee-first@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" @@ -1957,6 +1990,10 @@ es6-weak-map@^2.0.1: es6-iterator "2" es6-symbol "3" +escape-html@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.1.tgz#181a286ead397a39a92857cfb1d43052e356bff0" + escape-html@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" @@ -2125,6 +2162,12 @@ esutils@^2.0.0, esutils@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" +etag@~1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/etag/-/etag-1.6.0.tgz#8bcb2c6af1254c481dfc8b997c906ef4e442c207" + dependencies: + crc "3.2.1" + etag@~1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/etag/-/etag-1.7.0.tgz#03d30b5f67dd6e632d2945d30d6652731a34d5d8" @@ -2308,6 +2351,16 @@ fill-range@^2.1.0: repeat-element "^1.1.2" repeat-string "^1.5.2" +finalhandler@0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-0.5.0.tgz#e9508abece9b6dba871a6942a1d7911b91911ac7" + dependencies: + debug "~2.2.0" + escape-html "~1.0.3" + on-finished "~2.3.0" + statuses "~1.3.0" + unpipe "~1.0.0" + finalhandler@0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-0.5.1.tgz#2c400d8d4530935bc232549c5fa385ec07de6fcd" @@ -2384,6 +2437,10 @@ forwarded@~0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.0.tgz#19ef9874c4ae1c297bcf078fde63a09b66a84363" +fresh@0.2.4: + version "0.2.4" + resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.2.4.tgz#3582499206c9723714190edd74b4604feb4a614c" + fresh@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.3.0.tgz#651f838e22424e7566de161d8358caa199f83d4f" @@ -4078,6 +4135,12 @@ object.omit@^2.0.0: for-own "^0.1.4" is-extendable "^0.1.1" +on-finished@~2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.2.1.tgz#5c85c1cc36299f78029653f667f27b6b99ebc029" + dependencies: + ee-first "1.1.0" + on-finished@~2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" @@ -4594,6 +4657,15 @@ punycode@^1.2.4, punycode@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" +pushstate-server@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/pushstate-server/-/pushstate-server-2.2.1.tgz#1d36dd956a7fa9f1ddbb92328ebb961b73a9b663" + dependencies: + compression "1.6.2" + connect "3.5.0" + connect-static-file "1.1.2" + serve-static "1.11.2" + q@^1.1.2: version "1.4.1" resolved "https://registry.yarnpkg.com/q/-/q-1.4.1.tgz#55705bcd93c5f3673530c2c2cbc0c2b3addc286e" @@ -4642,6 +4714,10 @@ range-parser@^1.0.3, range-parser@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e" +range-parser@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.0.3.tgz#6872823535c692e2c2a0103826afd82c2e0ff175" + rc@~1.1.6: version "1.1.6" resolved "https://registry.yarnpkg.com/rc/-/rc-1.1.6.tgz#43651b76b6ae53b5c802f1151fa3fc3b059969c9" @@ -5085,6 +5161,21 @@ send@0.14.2: range-parser "~1.2.0" statuses "~1.3.1" +send@^0.12.2: + version "0.12.3" + resolved "https://registry.yarnpkg.com/send/-/send-0.12.3.tgz#cd12dc58fde21e4f91902b39b2fda05a7a6d9bdc" + dependencies: + debug "~2.2.0" + depd "~1.0.1" + destroy "1.0.3" + escape-html "1.0.1" + etag "~1.6.0" + fresh "0.2.4" + mime "1.3.4" + ms "0.7.1" + on-finished "~2.2.1" + range-parser "~1.0.2" + sentence-case@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/sentence-case/-/sentence-case-2.1.0.tgz#d592fbed457fd1a59e3af0ee17e99f6fd70d7efd" @@ -5104,7 +5195,7 @@ serve-index@^1.7.2: mime-types "~2.1.11" parseurl "~1.3.1" -serve-static@~1.11.2: +serve-static@1.11.2, serve-static@~1.11.2: version "1.11.2" resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.11.2.tgz#2cf9889bd4435a320cc36895c9aa57bd662e6ac7" dependencies: @@ -5252,7 +5343,7 @@ sshpk@^1.7.0: jsbn "~0.1.0" tweetnacl "~0.14.0" -"statuses@>= 1.3.1 < 2", statuses@~1.3.1: +"statuses@>= 1.3.1 < 2", statuses@~1.3.0, statuses@~1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.3.1.tgz#faf51b9eb74aaef3b3acf4ad5f61abf24cb7b93e" diff --git a/package-scripts.js b/package-scripts.js index 969b2205..9164923b 100644 --- a/package-scripts.js +++ b/package-scripts.js @@ -10,19 +10,15 @@ const concurrentTests = { script: 'nps client.test', color: 'black.bgYellow.bold.dim', }, - 'e2e-tests': { - script: 'nps e2e', - color: 'bgGreen.bold.dim', - }, } module.exports = { scripts: { default: { script: series([ - startInNewWindow('npm start mongo'), - startInNewWindow('npm start api'), - startInNewWindow('npm start client'), + startInNewWindow('npm start mongo --silent'), + startInNewWindow('npm start api --silent'), + startInNewWindow('npm start client --silent'), ]), }, mongo: { @@ -34,24 +30,35 @@ module.exports = { stop: 'mongo admin --eval "db.shutdownServer()"', }, api: { - script: series(['cd api', 'npm start']), + script: series(['cd api', 'npm start --silent']), description: 'start the api server', test: { - script: series(['cd api', 'npm test']), + script: series(['cd api', 'npm test --silent']), description: 'run the api tests', }, }, client: { - script: series(['cd client', 'cross-env PORT=8080 npm start']), + script: series(['cd client', 'npm start --silent -- 8080']), description: 'start the client dev server', test: { - script: series(['cd client', 'npm test']), + script: series(['cd client', 'npm test --silent']), description: 'run the client tests', }, }, + dev: { + script: series([ + startInNewWindow('npm start dev.mongo --silent'), + startInNewWindow('npm start dev.client --silent'), + startInNewWindow('npm start dev.api --silent'), + ]), + description: 'starts everything in dev mode', + // dev is the same as live for mongo for now... + mongo: 'npm start mongo --silent', + client: series(['cd client', 'npm run dev --silent']), + api: series(['cd api', 'npm run dev --silent']), + }, e2e: { - script: 'cross-env MOCHA_COLORS=true cypress run', - description: 'run the E2E tests', + script: 'node scripts/e2e.js', }, test: { description: 'run the tests in parallel', @@ -133,6 +140,7 @@ function startInNewWindow(command) { `-e 'end tell'`, ].join(' ') } + // this is not transpiled /* eslint diff --git a/package.json b/package.json index e352cc67..17ee3a72 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "start": "nps", "test": "nps test", "precommit": "nps validate", - "setup": "node ./scripts/verify && node ./scripts/install && node ./scripts/load-database && npm start validate" + "setup": "node ./scripts/verify && node ./scripts/install && node ./scripts/load-database && npm start validate && npm start e2e" }, "devDependencies": { "all-contributors-cli": "^4.0.0", @@ -22,8 +22,10 @@ "is-windows": "^1.0.0", "mkdirp": "^0.5.1", "p-s": "^3.1.0", + "p-series": "^1.0.0", "prettier-eslint-cli": "^1.1.1", "rimraf": "^2.5.4", - "spawn-command-with-kill": "^1.0.0" + "spawn-command-with-kill": "^1.0.0", + "stream-to-promise": "^2.2.0" } } diff --git a/scripts/e2e.js b/scripts/e2e.js new file mode 100644 index 00000000..3064111a --- /dev/null +++ b/scripts/e2e.js @@ -0,0 +1,184 @@ +const path = require('path') +const spawn = require('spawn-command-with-kill') +const pSeries = require('p-series') + +const cwd = path.join(__dirname, '..') +const clientCwd = path.join(cwd, 'client') +const apiCwd = path.join(cwd, 'api') + +const dbPath = path.join(cwd, '.e2e/mongo-db') +const mongoPort = 27018 +const mongoUri = `mongodb://localhost:${mongoPort}/conduit` +const clientServerPort = 9001 + +const apiEnv = Object.assign({}, process.env, { + MONGODB_URI: mongoUri, + MONGOD_DEBUG: true, +}) +const mongoEnv = Object.assign({}, process.env, {MONGODB_URI: mongoUri}) + +// create mongo db folder +const createMongoDbDirectoryCommand = { + script: `./node_modules/.bin/mkdirp ${dbPath}`, + message: 'creating dbpath', +} +// start e2e mongo +const startMongoCommand = { + script: `mongod --dbpath ${dbPath} --port ${mongoPort}`, + resolveEarly: true, + resolveDelay: 1000, + message: 'starting mongodb', +} +// load e2e mongo with data +const loadDataCommand = { + script: `cd api && npm run generateData --silent`, + message: 'loading data into mongodb', +} +// build app server +const buildApiCommand = { + script: `npm run build --silent`, + message: 'running api build', +} +// start app server +const startApiCommand = { + script: `npm start --silent`, + resolveEarly: true, + resolveDelay: 500, + message: 'starting api server', +} +// build client +const buildClientCommand = { + script: `npm run build --silent`, + message: 'running client build', +} +// start (built) client http-server +const startClientCommand = { + script: `npm start --silent -- ${clientServerPort}`, + resolveEarly: true, + resolveDelay: 500, + message: 'string client server', +} +// run cypress +const cypressCommand = { + script: `./node_modules/.bin/cypress run`, + message: 'starting cypress tests', +} +// cleanup: kill app server, client server, mongo + +const mongoSequence = [ + createMongoDbDirectoryCommand, + startMongoCommand, + loadDataCommand, +] +const apiSequence = [buildApiCommand, startApiCommand] +const clientSequence = [buildClientCommand, startClientCommand] + +// const stdio = 'inherit' +const stdio = 'pipe' +const mongoPromise = runSequence(mongoSequence, { + cwd, + stdio, + env: mongoEnv, +}) +const apiPromise = runSequence(apiSequence, { + cwd: apiCwd, + stdio, + env: apiEnv, +}) +const clientPromise = runSequence(clientSequence, { + cwd: clientCwd, + stdio, +}) + +Promise.all([mongoPromise, apiPromise, clientPromise]).then(results => { + const fakeKillable = { + kill() { + console.log('needed to use fake kill') + }, + } + const { + 1: {children: {1: apiChild = fakeKillable}}, + 2: {children: {1: clientChild = fakeKillable}}, + } = results + const {promise} = spawnPromise(cypressCommand, {cwd, stdio: 'inherit'}) + return promise + .catch(error => { + cleanUp() + console.log('🚨 Something went wrong') + console.error(error) + return Promise.reject(error) + }) + .then(cleanUp) + .then(() => { + console.log('🎉 Finished successfully') + }) + + function cleanUp() { + clientChild.kill() + apiChild.kill() + const {promise: killMongoPromise} = spawnPromise({ + script: `mongo admin --eval "db.shutdownServer()" --port ${mongoPort}`, + message: 'shutting down mongodb', + }) + return killMongoPromise + } +}) + +function runSequence(commands, ...spawnArgs) { + return new Promise((resolve, reject) => { + const children = [] + pSeries( + commands.map(command => () => { + const {promise, child} = spawnPromise(command, ...spawnArgs) + children.push(child) + return promise + }) + ) + .then(result => { + resolve({result, children}) + }) + .catch(error => { + reject({error, children}) + }) + }) +} + +function spawnPromise({script, resolveEarly, resolveDelay, message}, ...args) { + console.log(`- ${message}:`, script) + const child = spawn(script, ...args) + const promise = new Promise((resolve, reject) => { + if (resolveEarly) { + setTimeout(resolve, resolveDelay) + } else { + let rejected = false + child.on('exit', exitCode => { + if (!rejected) { + if (exitCode === 0) { + resolve() + } else { + rejected = true + reject(exitCode) + } + } + }) + child.on('error', error => { + rejected = true + reject(error) + }) + } + }) + return {child, promise} +} + +// this is not transpiled +/* + eslint + comma-dangle: [ + 2, + { + arrays: 'always-multiline', + objects: 'always-multiline', + functions: 'never' + } + ] + */ diff --git a/yarn.lock b/yarn.lock index c5fa13bb..acdd28e4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -80,6 +80,10 @@ ansi-styles@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" +any-promise@^1.1.0, any-promise@~1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" + anymatch@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-1.3.0.tgz#a3e52fa39168c825ff57b0248126ce5a8ff95507" @@ -909,6 +913,12 @@ emojis-list@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389" +end-of-stream@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.1.0.tgz#e9353258baa9108965efc41cb0ef8ade2f3cfb07" + dependencies: + once "~1.3.0" + enhanced-resolve@~0.9.0: version "0.9.1" resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-0.9.1.tgz#4d6e689b3725f86090927ccc86cd9f1635b89e2e" @@ -2399,7 +2409,7 @@ once@^1.3.0: dependencies: wrappy "1" -once@~1.3.3: +once@~1.3.0, once@~1.3.3: version "1.3.3" resolved "https://registry.yarnpkg.com/once/-/once-1.3.3.tgz#b2e261557ce4c314ec8304f3fa82663e4297ca20" dependencies: @@ -2468,6 +2478,10 @@ p-locate@^2.0.0: dependencies: p-limit "^1.1.0" +p-reduce@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-reduce/-/p-reduce-1.0.0.tgz#18c2b0dd936a4690a529f8231f58a0fdb6a47dfa" + p-s@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/p-s/-/p-s-3.1.0.tgz#edcf021ce847b2ae3b9b6d2297d5b15fc8cc6cc0" @@ -2486,6 +2500,12 @@ p-s@^3.1.0: shell-escape "0.2.0" spawn-command-with-kill "1.0.0" +p-series@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-series/-/p-series-1.0.0.tgz#7ec9e7b4406cc32066298a6f9860e55e91b36e07" + dependencies: + p-reduce "^1.0.0" + package-json@^2.0.0: version "2.4.0" resolved "https://registry.yarnpkg.com/package-json/-/package-json-2.4.0.tgz#0d15bd67d1cbbddbb2ca222ff2edb86bcb31a8bb" @@ -3143,6 +3163,20 @@ stream-http@^2.3.1: to-arraybuffer "^1.0.0" xtend "^4.0.0" +stream-to-array@~2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/stream-to-array/-/stream-to-array-2.3.0.tgz#bbf6b39f5f43ec30bc71babcb37557acecf34353" + dependencies: + any-promise "^1.1.0" + +stream-to-promise@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/stream-to-promise/-/stream-to-promise-2.2.0.tgz#b1edb2e1c8cb11289d1b503c08d3f2aef51e650f" + dependencies: + any-promise "~1.3.0" + end-of-stream "~1.1.0" + stream-to-array "~2.3.0" + string-width@^1.0.1, string-width@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3"