diff --git a/appveyor.yml b/appveyor.yml index 931e9d3c..e0f54fee 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,6 @@ environment: + ELECTRON_ENABLE_STACK_DUMPING: 'true' + DEBUG: '*,-nugget*,-eslint*,-extract-zip*,-sumchecker*,-electron-download*,-dependency-check*' matrix: - nodejs_version: "8" diff --git a/package-lock.json b/package-lock.json index 691d90a9..2033d611 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,9 +10,18 @@ "integrity": "sha512-+rr4OgeTNrLuJAf09o3USdttEYiXvZshWMkhD6wR9v1ieXH0JM1Q2yT41/cJuJcqiPpSXlM/g3aR+Y5MWQdr0Q==", "dev": true, "requires": { - "7zip-bin-mac": "1.0.1" + "7zip-bin-linux": "1.3.1", + "7zip-bin-mac": "1.0.1", + "7zip-bin-win": "2.1.1" } }, + "7zip-bin-linux": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/7zip-bin-linux/-/7zip-bin-linux-1.3.1.tgz", + "integrity": "sha512-Wv1uEEeHbTiS1+ycpwUxYNuIcyohU6Y6vEqY3NquBkeqy0YhVdsNUGsj0XKSRciHR6LoJSEUuqYUexmws3zH7Q==", + "dev": true, + "optional": true + }, "7zip-bin-mac": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/7zip-bin-mac/-/7zip-bin-mac-1.0.1.tgz", @@ -20,6 +29,13 @@ "dev": true, "optional": true }, + "7zip-bin-win": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/7zip-bin-win/-/7zip-bin-win-2.1.1.tgz", + "integrity": "sha512-6VGEW7PXGroTsoI2QW3b0ea95HJmbVBHvfANKLLMzSzFA1zKqVX5ybNuhmeGpf6vA0x8FJTt6twpprDANsY5WQ==", + "dev": true, + "optional": true + }, "@types/node": { "version": "7.0.48", "resolved": "https://registry.npmjs.org/@types/node/-/node-7.0.48.tgz", @@ -390,8 +406,8 @@ "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", "dev": true, "requires": { - "core-js": "2.5.1", - "regenerator-runtime": "0.11.0" + "core-js": "2.5.3", + "regenerator-runtime": "0.11.1" } }, "balanced-match": { @@ -1317,9 +1333,9 @@ "integrity": "sha1-aWYs0wVJPJJcAqOEy8rnbWQtd/M=" }, "core-js": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.1.tgz", - "integrity": "sha1-rmh03GaTd4m4B1T/VCjfZoGcpQs=", + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.3.tgz", + "integrity": "sha1-isw4NFgk8W2DZbfJtCWRaOjtYD4=", "dev": true }, "core-util-is": { @@ -1376,9 +1392,9 @@ "dev": true }, "commander": { - "version": "2.12.2", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.12.2.tgz", - "integrity": "sha512-BFnaq5ZOGcDN7FlrtBT4xxkgIToalIIxwjxLWVJ8bGTpe1LroqMiqQXdA7ygc7CRvaYS+9zfPGFnJqFSayx+AA==", + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.13.0.tgz", + "integrity": "sha512-MVuS359B+YzaWqjCL/c+22gfryv+mCBPHAv3zyVI2GN8EY6IRP8VwtasXn8jyyhvvq84R4ImN1OKRtcbIasjYA==", "dev": true }, "cryptiles": { @@ -1414,7 +1430,7 @@ "dev": true, "requires": { "chalk": "1.1.3", - "commander": "2.12.2", + "commander": "2.13.0", "is-my-json-valid": "2.16.1", "pinkie-promise": "2.0.1" } @@ -1891,12 +1907,6 @@ "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", "dev": true }, - "deep-equal": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", - "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=", - "dev": true - }, "deep-extend": { "version": "0.4.2", "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.2.tgz", @@ -1923,16 +1933,6 @@ "clone": "1.0.3" } }, - "define-properties": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz", - "integrity": "sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ=", - "dev": true, - "requires": { - "foreach": "2.0.5", - "object-keys": "1.0.11" - } - }, "defined": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", @@ -2385,9 +2385,9 @@ } }, "electron-chromedriver": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/electron-chromedriver/-/electron-chromedriver-1.7.1.tgz", - "integrity": "sha1-AIyXl2AHqk6xhJHuCV6U0X7kdhA=", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/electron-chromedriver/-/electron-chromedriver-1.8.0.tgz", + "integrity": "sha512-m1f3nle5MaGp94bcDTtMZZMMOgPO54+TXoPBlTbBSUjfINR5SJ46yQXLfuE79/qsFfJKslZB1UzWURDDFIRmpQ==", "dev": true, "requires": { "electron-download": "4.1.0", @@ -2571,30 +2571,6 @@ "is-arrayish": "0.2.1" } }, - "es-abstract": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.10.0.tgz", - "integrity": "sha512-/uh/DhdqIOSkAWifU+8nG78vlQxdLckUdI/sPgy0VhuXi2qJ7T8czBmqIYtLQVpCIFYafChnsRsB5pyb1JdmCQ==", - "dev": true, - "requires": { - "es-to-primitive": "1.1.1", - "function-bind": "1.1.1", - "has": "1.0.1", - "is-callable": "1.1.3", - "is-regex": "1.0.4" - } - }, - "es-to-primitive": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.1.1.tgz", - "integrity": "sha1-RTVSSKiJeQNLZ5Lhm7gfK3l13Q0=", - "dev": true, - "requires": { - "is-callable": "1.1.3", - "is-date-object": "1.0.1", - "is-symbol": "1.0.1" - } - }, "es5-ext": { "version": "0.10.37", "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.37.tgz", @@ -4929,18 +4905,6 @@ "builtin-modules": "1.1.1" } }, - "is-callable": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.3.tgz", - "integrity": "sha1-hut1OSgF3cM69xySoO7fdO52BLI=", - "dev": true - }, - "is-date-object": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", - "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", - "dev": true - }, "is-dom": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/is-dom/-/is-dom-1.0.9.tgz", @@ -5103,15 +5067,6 @@ "integrity": "sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ=", "dev": true }, - "is-regex": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", - "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", - "dev": true, - "requires": { - "has": "1.0.1" - } - }, "is-relative": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-0.2.1.tgz", @@ -5142,12 +5097,6 @@ "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", "dev": true }, - "is-symbol": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.1.tgz", - "integrity": "sha1-PMWfAAJRlLarLjjbrmaJJWtmBXI=", - "dev": true - }, "is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", @@ -5857,6 +5806,23 @@ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" }, + "minipass": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.2.1.tgz", + "integrity": "sha512-u1aUllxPJUI07cOqzR7reGmQxmCqlH88uIIsf6XZFEWgw7gXKpJdR+5R9Y3KEDmWYkdIz9wXZs3C0jOPxejk/Q==", + "dev": true, + "requires": { + "yallist": "3.0.2" + }, + "dependencies": { + "yallist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.2.tgz", + "integrity": "sha1-hFK0u36Dx8GI2AQcGoN8dz1ti7k=", + "dev": true + } + } + }, "mirror-folder": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/mirror-folder/-/mirror-folder-2.1.1.tgz", @@ -6456,15 +6422,15 @@ "dev": true }, "nyc": { - "version": "11.3.0", - "resolved": "https://registry.npmjs.org/nyc/-/nyc-11.3.0.tgz", - "integrity": "sha512-oUu0WHt1k/JMIODvAYXX6C50Mupw2GO34P/Jdg2ty9xrLufBthHiKR2gf08aF+9S0abW1fl24R7iKRBXzibZmg==", + "version": "11.4.1", + "resolved": "https://registry.npmjs.org/nyc/-/nyc-11.4.1.tgz", + "integrity": "sha512-5eCZpvaksFVjP2rt1r60cfXmt3MUtsQDw8bAzNqNEr4WLvUMLgiVENMf/B9bE9YAX0mGVvaGA3v9IS9ekNqB1Q==", "dev": true, "requires": { "archy": "1.0.0", "arrify": "1.0.1", "caching-transform": "1.0.1", - "convert-source-map": "1.5.0", + "convert-source-map": "1.5.1", "debug-log": "1.0.1", "default-require-extensions": "1.0.0", "find-cache-dir": "0.1.1", @@ -6484,7 +6450,7 @@ "resolve-from": "2.0.0", "rimraf": "2.6.2", "signal-exit": "3.0.2", - "spawn-wrap": "1.3.8", + "spawn-wrap": "1.4.2", "test-exclude": "4.1.1", "yargs": "10.0.3", "yargs-parser": "8.0.0" @@ -6594,8 +6560,8 @@ "bundled": true, "dev": true, "requires": { - "core-js": "2.5.1", - "regenerator-runtime": "0.11.0" + "core-js": "2.5.3", + "regenerator-runtime": "0.11.1" } }, "babel-template": { @@ -6744,12 +6710,12 @@ "dev": true }, "convert-source-map": { - "version": "1.5.0", + "version": "1.5.1", "bundled": true, "dev": true }, "core-js": { - "version": "2.5.1", + "version": "2.5.3", "bundled": true, "dev": true }, @@ -7053,7 +7019,7 @@ "dev": true }, "is-buffer": { - "version": "1.1.5", + "version": "1.1.6", "bundled": true, "dev": true }, @@ -7251,7 +7217,7 @@ "bundled": true, "dev": true, "requires": { - "is-buffer": "1.1.5" + "is-buffer": "1.1.6" } }, "lazy-cache": { @@ -7620,7 +7586,7 @@ "bundled": true, "dev": true, "requires": { - "is-buffer": "1.1.5" + "is-buffer": "1.1.6" } } } @@ -7630,7 +7596,7 @@ "bundled": true, "dev": true, "requires": { - "is-buffer": "1.1.5" + "is-buffer": "1.1.6" } } } @@ -7666,7 +7632,7 @@ } }, "regenerator-runtime": { - "version": "0.11.0", + "version": "0.11.1", "bundled": true, "dev": true }, @@ -7772,7 +7738,7 @@ "dev": true }, "spawn-wrap": { - "version": "1.3.8", + "version": "1.4.2", "bundled": true, "dev": true, "requires": { @@ -8848,12 +8814,6 @@ "strip-json-comments": "2.0.1" } }, - "re-emitter": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/re-emitter/-/re-emitter-1.1.3.tgz", - "integrity": "sha1-+p4xn/3u6zWycpbvDz03TawvUqc=", - "dev": true - }, "read-all-stream": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/read-all-stream/-/read-all-stream-3.1.0.tgz", @@ -9005,9 +8965,9 @@ } }, "regenerator-runtime": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.0.tgz", - "integrity": "sha512-/aA0kLeRb5N9K0d4fw7ooEbI+xDe+DKD499EQqygGqeS8N3xto15p09uY2xj7ixP81sNPXvRLnAQIqdVStgb1A==", + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", "dev": true }, "regex-cache": { @@ -9147,15 +9107,6 @@ "onetime": "1.1.0" } }, - "resumer": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/resumer/-/resumer-0.0.0.tgz", - "integrity": "sha1-8ej0YeQGS6Oegq883CqMiT0HZ1k=", - "dev": true, - "requires": { - "through": "2.3.8" - } - }, "rgb2hex": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/rgb2hex/-/rgb2hex-0.1.0.tgz", @@ -9524,16 +9475,16 @@ "dev": true }, "spectron": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/spectron/-/spectron-3.7.2.tgz", - "integrity": "sha1-hvQTBqm3DtbuFQD399Otw4mvtEY=", + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/spectron/-/spectron-3.8.0.tgz", + "integrity": "sha512-fQ7gFp6UuEaONjXFLifLeIUI022pOsm3b+NFAm696r2umUkSZ9IbnEgHwrvBX+pJ3QUDyCEs5bPHUieYU7FvaQ==", "dev": true, "requires": { "dev-null": "0.1.1", - "electron-chromedriver": "1.7.1", + "electron-chromedriver": "1.8.0", "request": "2.83.0", "split": "1.0.1", - "webdriverio": "4.9.11" + "webdriverio": "4.10.1" }, "dependencies": { "split": { @@ -9887,17 +9838,6 @@ "strip-ansi": "3.0.1" } }, - "string.prototype.trim": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz", - "integrity": "sha1-0E3iyJ4Tf019IG8Ia17S+ua+jOo=", - "dev": true, - "requires": { - "define-properties": "1.1.2", - "es-abstract": "1.10.0", - "function-bind": "1.1.1" - } - }, "string_decoder": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", @@ -10074,9 +10014,9 @@ "integrity": "sha512-bq40Dxl0Q9LFcFsoU4BmTlR4Y9Ta/9AClAhmKhBBdXN0isup9dXtYmFIJGYHz2EOVOf/gO/FONEH0BDa/iNYkg==" }, "tap": { - "version": "10.7.3", - "resolved": "https://registry.npmjs.org/tap/-/tap-10.7.3.tgz", - "integrity": "sha512-oS/FIq+tcmxVgYn5usKtLsX+sOHNEj+G7JIQE9SBjO5mVYB1rbaEJJiDbnYp8k0ZqY2Pe4HbYEpkvzm9jfLDyw==", + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/tap/-/tap-11.0.1.tgz", + "integrity": "sha512-YfrPp7FFxASC4tK4DEAKnnTxyg+J7T8kh8NiOmICNhiGvSojPAV34Ir4DDElFvnIiDEMzDP7233lw3WacFvIFQ==", "dev": true, "requires": { "bind-obj-methods": "1.0.0", @@ -10090,21 +10030,37 @@ "glob": "7.1.2", "isexe": "2.0.0", "js-yaml": "3.10.0", - "nyc": "11.3.0", + "minipass": "2.2.1", + "mkdirp": "0.5.1", + "nyc": "11.4.1", "opener": "1.4.3", "os-homedir": "1.0.2", "own-or": "1.0.0", "own-or-env": "1.0.0", - "readable-stream": "2.3.3", + "rimraf": "2.6.2", "signal-exit": "3.0.2", "source-map-support": "0.4.18", "stack-utils": "1.0.1", "tap-mocha-reporter": "3.0.6", - "tap-parser": "5.4.0", + "tap-parser": "7.0.0", "tmatch": "3.1.0", "trivial-deferred": "1.0.1", "tsame": "1.1.2", + "write-file-atomic": "2.3.0", "yapool": "1.0.0" + }, + "dependencies": { + "write-file-atomic": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.3.0.tgz", + "integrity": "sha512-xuPeK4OdjWqtfi59ylvVL0Yn35SF3zgcAcv7rBPFHVaEapaDr4GdGgm3j7ckTwH9wHL7fGmgfAnb0+THrHb8tA==", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "imurmurhash": "0.1.4", + "signal-exit": "3.0.2" + } + } } }, "tap-mocha-reporter": { @@ -10122,118 +10078,30 @@ "readable-stream": "2.3.3", "tap-parser": "5.4.0", "unicode-length": "1.0.3" - } - }, - "tap-out": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/tap-out/-/tap-out-1.4.2.tgz", - "integrity": "sha1-yQfsG/lAURHQiCY+kvVgi4jLs3o=", - "dev": true, - "requires": { - "re-emitter": "1.1.3", - "readable-stream": "2.3.3", - "split": "1.0.1", - "trim": "0.0.1" }, "dependencies": { - "split": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", - "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", + "tap-parser": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/tap-parser/-/tap-parser-5.4.0.tgz", + "integrity": "sha512-BIsIaGqv7uTQgTW1KLTMNPSEQf4zDDPgYOBRdgOfuB+JFOLRBfEu6cLa/KvMvmqggu1FKXDfitjLwsq4827RvA==", "dev": true, "requires": { - "through": "2.3.8" + "events-to-array": "1.1.2", + "js-yaml": "3.10.0", + "readable-stream": "2.3.3" } } } }, "tap-parser": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/tap-parser/-/tap-parser-5.4.0.tgz", - "integrity": "sha512-BIsIaGqv7uTQgTW1KLTMNPSEQf4zDDPgYOBRdgOfuB+JFOLRBfEu6cLa/KvMvmqggu1FKXDfitjLwsq4827RvA==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/tap-parser/-/tap-parser-7.0.0.tgz", + "integrity": "sha512-05G8/LrzqOOFvZhhAk32wsGiPZ1lfUrl+iV7+OkKgfofZxiceZWMHkKmow71YsyVQ8IvGBP2EjcIjE5gL4l5lA==", "dev": true, "requires": { "events-to-array": "1.1.2", "js-yaml": "3.10.0", - "readable-stream": "2.3.3" - } - }, - "tap-spec": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/tap-spec/-/tap-spec-4.1.1.tgz", - "integrity": "sha1-4unyb1IIIysfViKIyXYk1YqI8Fo=", - "dev": true, - "requires": { - "chalk": "1.1.3", - "duplexer": "0.1.1", - "figures": "1.7.0", - "lodash": "3.10.1", - "pretty-ms": "2.1.0", - "repeat-string": "1.6.1", - "tap-out": "1.4.2", - "through2": "2.0.3" - }, - "dependencies": { - "figures": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", - "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", - "dev": true, - "requires": { - "escape-string-regexp": "1.0.5", - "object-assign": "4.1.1" - } - }, - "lodash": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", - "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=", - "dev": true - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true - } - } - }, - "tape": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/tape/-/tape-4.8.0.tgz", - "integrity": "sha512-TWILfEnvO7I8mFe35d98F6T5fbLaEtbFTG/lxWvid8qDfFTxt19EBijWmB4j3+Hoh5TfHE2faWs73ua+EphuBA==", - "dev": true, - "requires": { - "deep-equal": "1.0.1", - "defined": "1.0.0", - "for-each": "0.3.2", - "function-bind": "1.1.1", - "glob": "7.1.2", - "has": "1.0.1", - "inherits": "2.0.3", - "minimist": "1.2.0", - "object-inspect": "1.3.0", - "resolve": "1.4.0", - "resumer": "0.0.0", - "string.prototype.trim": "1.1.2", - "through": "2.3.8" - }, - "dependencies": { - "object-inspect": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.3.0.tgz", - "integrity": "sha512-OHHnLgLNXpM++GnJRyyhbr2bwl3pPVm4YvaraHrRvDt/N3r+s/gDVHciA7EJBTkijKXj61ssgSAikq1fb0IBRg==", - "dev": true - }, - "resolve": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.4.0.tgz", - "integrity": "sha512-aW7sVKPufyHqOmyyLzg/J+8606v5nevBgaliIlV7nUpVMsDnoBGV/cbSLNjZAg9q0Cfd/+easKVKQ8vOu8fn1Q==", - "dev": true, - "requires": { - "path-parse": "1.0.5" - } - } + "minipass": "2.2.1" } }, "tar-stream": { @@ -10892,12 +10760,12 @@ "dev": true }, "webdriverio": { - "version": "4.9.11", - "resolved": "https://registry.npmjs.org/webdriverio/-/webdriverio-4.9.11.tgz", - "integrity": "sha1-qChxPFpEvpmvvgfrW1I9XszQS0Q=", + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/webdriverio/-/webdriverio-4.10.1.tgz", + "integrity": "sha1-Qvekh7czebJ0Oi+uULMUJhX2EXA=", "dev": true, "requires": { - "archiver": "2.1.0", + "archiver": "2.1.1", "babel-runtime": "6.26.0", "css-parse": "2.0.0", "css-value": "0.0.1", @@ -10922,9 +10790,9 @@ }, "dependencies": { "archiver": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/archiver/-/archiver-2.1.0.tgz", - "integrity": "sha1-0t8ujVdzqCwdzOklzMQUUOqZmv0=", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/archiver/-/archiver-2.1.1.tgz", + "integrity": "sha1-/2YrSnggFJSj7lRNOjP+dJZQnrw=", "dev": true, "requires": { "archiver-utils": "1.3.0", diff --git a/package.json b/package.json index 51fbb205..6edfe5b8 100644 --- a/package.json +++ b/package.json @@ -50,8 +50,8 @@ "build-background": "node scripts/build.js background", "start": "cross-env NODE_ENV=development electron .", "test": "standard && npm run deps && npm run test:unit && npm run test:integration", - "test:integration": "node tests", - "test:unit": "node tests/intro.js && electron tests/dat-manager.js", + "test:integration": "node ./tests/index.js", + "test:unit": "electron ./tests/dat-manager.js && node ./tests/intro.js", "postinstall": "node scripts/build.js postinstall", "pack": "build --dir", "dist": "build --publish=onTagOrDraft" @@ -69,12 +69,10 @@ "nodemon": "^1.9.2", "npm-run-path": "^2.0.2", "sheetify-nested": "^1.0.2", - "spectron": "^3.5.0", + "spectron": "^3.8.0", "spok": "^0.7.0", "standard": "^7.1.2", - "tap": "^10.3.2", - "tap-spec": "^4.1.1", - "tape": "^4.6.3", + "tap": "^11.0.1", "through2": "^2.0.3", "watchify": "^3.7.0" }, diff --git a/tests/dat-manager.js b/tests/dat-manager.js old mode 100644 new mode 100755 index a867da32..f6a674be --- a/tests/dat-manager.js +++ b/tests/dat-manager.js @@ -1,8 +1,13 @@ -var tape = require('tape') +#!/usr/bin/env node node_modules/.bin/electron +var tap = require('tap') +var test = tap.test var Multidat = require('multidat') var toilet = require('toiletdb/inmemory') var Manager = require('../lib/dat-manager') +tap.on('result', function (res) { + process.exit(res.ok ? 0 : 1) +}) function setup (db, dbPaused, cb) { if (typeof db === 'function') { @@ -21,7 +26,7 @@ function setup (db, dbPaused, cb) { }) } -tape('dat-manager', function (t) { +test('dat-manager', function (t) { t.test('Manager({ multidat, dbPaused, onupdate })', function (t) { t.test('assert arguments', function (t) { setup(function (err, { multidat, dbPaused }) { @@ -72,6 +77,7 @@ tape('dat-manager', function (t) { }) } }) + t.end() }) t.test('.create(dir, opts, cb)', function (t) { @@ -118,6 +124,7 @@ tape('dat-manager', function (t) { }) }) }) + t.end() }) t.test('.close(key, cb)', function (t) { @@ -147,6 +154,7 @@ tape('dat-manager', function (t) { }) }) }) + t.end() }) t.test('.pause(dat, cb)', function (t) { @@ -173,6 +181,7 @@ tape('dat-manager', function (t) { }) }) }) + t.end() }) t.test('.resume(dat, cb)', function (t) { @@ -205,6 +214,7 @@ tape('dat-manager', function (t) { }) }) }) + t.end() }) t.test('.togglePause(dat, cb)', function (t) { @@ -261,10 +271,8 @@ tape('dat-manager', function (t) { }) }) }) - }) - - t.test('finish', function (t) { t.end() - process.exit(Number(!t._ok)) }) + + t.end() }) diff --git a/tests/index.js b/tests/index.js old mode 100644 new mode 100755 index b0a23b62..1d48952a --- a/tests/index.js +++ b/tests/index.js @@ -1,8 +1,13 @@ +#!/usr/bin/env node var clipboard = require('clipboardy') var spectron = require('spectron') var path = require('path') var tap = require('tap').test var del = require('del') +var { execSync } = require('child_process') +var waitForAndClick = require('./utils/waitForAndClick') +var waitForMatch = require('./utils/waitForMatch') +var wait = require('./utils/wait') var TEST_DATA = path.join(__dirname, 'test_data') var TEST_DATA_DB = path.join(TEST_DATA, 'multidat.json') @@ -11,22 +16,17 @@ tap('init', function (t) { t.test('should be able to boot up the app', function (t) { var app = createApp() return waitForLoad(app) - .then(() => app.browserWindow.isVisible()) - .then((val) => t.ok(val, 'isVisible')) - .then(() => app.client.getWindowCount()) - .then((val) => t.equal(val, 1, 'getWindowCount')) - .then(() => app.browserWindow.isMinimized()) - .then((val) => t.equal(val, false, 'isMinimized')) - .then(() => app.browserWindow.isDevToolsOpened()) - .then((val) => t.equal(val, false, 'isDevToolsOpened')) - .then(() => app.browserWindow.isVisible()) - .then((val) => t.equal(val, true, 'isVisible')) - .then(() => app.browserWindow.isFocused()) - .then((val) => t.equal(val, true, 'isFocused')) - .then(() => app.browserWindow.getBounds()) - .then((val) => t.notEqual(val.width, 0, 'getBounds')) - .then(() => app.browserWindow.getBounds()) - .then((val) => t.notEqual(val.height, 0, 'getBounds')) + .then(() => Promise.all([ + t.resolveMatch(app.browserWindow.isVisible(), true, 'isVisible'), + t.resolveMatch(app.client.getWindowCount(), 1, 'getWindowCount'), + t.resolveMatch(app.browserWindow.isMinimized(), false, 'isMinimized'), + t.resolveMatch(app.browserWindow.isDevToolsOpened(), false, 'isDevToolsOpened'), + t.resolveMatch(app.browserWindow.isVisible(), true, 'isVisible'), + t.resolveMatch(app.browserWindow.isFocused(), true, 'isFocused'), + t.resolveMatch(app.browserWindow.getBounds().then(bounds => bounds.width !== 0), true, 'getBounds'), + t.resolveMatch(app.browserWindow.getBounds().then(bounds => bounds.height !== 0), true, 'getBounds') + ])) + .catch(e => t.fail(e)) .then(() => endTest(app)) }) t.end() @@ -36,23 +36,19 @@ tap('onboarding', function (t) { t.test('intro should show every time you open the app as long as you have no dats', function (t) { var app = createApp() return waitForLoad(app) - .then(() => app.browserWindow.isVisible()) - .then((isVisible) => t.ok(isVisible, 'isVisible')) - .then(() => app.browserWindow.getTitle()) - .then((title) => t.equal(title, 'Dat Desktop | Welcome', 'correct title')) + .then(() => t.resolveMatch(app.browserWindow.isVisible(), true, 'isVisible')) + .then(() => t.resolveMatch(app.browserWindow.getTitle(), 'Dat Desktop | Welcome', 'correct title')) .then(() => app.client.click('button')) - .then(() => wait()) - .then(() => app.client.click('button[title="Skip Intro"]')) - .then(() => wait()) - .then(() => app.browserWindow.getTitle()) - .then((title) => t.equal(title, 'Dat Desktop', 'correct title')) + .then(() => wait(200)) + .then(() => waitForAndClick(t, app, 'button[title="Skip Intro"]')) + .then(() => t.resolveMatch(app.browserWindow.getTitle(), 'Dat Desktop', 'correct title')) .then(() => app.stop()) .then(() => Promise.resolve(app = createApp())) .then(() => waitForLoad(app)) .then(() => app.browserWindow.isVisible()) .then(() => app.client.click('button')) - .then(() => wait()) - .then(() => app.client.getText('button[title="Skip Intro"]')) + .then(() => app.client.waitForExist('button[title="Skip Intro"]')) + .catch(e => t.fail(e)) .then(() => endTest(app)) }) t.end() @@ -61,54 +57,41 @@ tap('onboarding', function (t) { tap('working with dats', function (t) { var app = createApp() return waitForLoad(app) - .then(() => app.browserWindow.isVisible()) - .then((isVisible) => t.ok(isVisible, 'isVisible')) - .then(() => app.client.click('button')) - .then(() => wait(4000)) - .then(() => app.client.click('button[title="Skip Intro"]')) - .then(() => wait()) - .then(() => app.client.click('button')) // create new - .then(() => wait()) - .then(() => app.client.getText('.size')) - .then((text) => { - t.ok(text.match(/(126|52) B/), 'contains correct size') - }) - .then(() => app.client.getText('.network')) - .then((text) => t.ok(text.match(/0/), 'contains network size')) + .then(() => t.resolveMatch(app.browserWindow.isVisible(), true, 'isVisible')) + .then(() => waitForAndClick(t, app, 'button[title="Get Started"]')) + .then(() => waitForAndClick(t, app, 'button[title="Skip Intro"]')) + .then(() => waitForAndClick(t, app, 'button')) + .then(() => waitForMatch(t, app, '.size', /(126|52) B/) + .then(() => waitForMatch(t, app, '.network', /0/))) .then(() => clipboard.write('')) .then(() => app.client.click('button[title="Share Dat"]')) .then(() => app.client.click('button[title="Copy to Clipboard"]')) - .then(() => wait()) - .then(() => clipboard.read()) - .then(text => t.ok(text.match(/^dat:\/\/[0-9a-f]{32}/), 'link copied to clipboard')) + .then(() => wait(200)) + .then(() => t.resolveMatch(clipboard.read(), /^dat:\/\/[0-9a-f]{32}/, 'link copied to clipboard')) .then(() => app.stop()) .then(() => Promise.resolve(app = createApp())) .then(() => waitForLoad(app)) .then(() => app.browserWindow.isVisible()) .then((isVisible) => t.equal(isVisible, true, 'reloaded and is visible')) - .then(() => wait()) - .then(() => app.client.getText('.size')) - .then((text) => { - t.ok(text.match(/(126|52) B/), 'contains correct size') - }) - .then(() => wait()) - .then(() => app.client.click('button.delete')) + .then(() => waitForMatch(t, app, '.size', /(126|52) B/)) + .then(() => waitForAndClick(t, app, 'button.delete')) .then(() => app.client.click('button.cancel-button')) .then(() => app.client.click('button.delete')) .then(() => app.client.click('button.confirm-button')) - .then(() => wait()) - .then(() => app.client.getText('.tutorial')) - .then((text) => t.ok(text.toLowerCase().match(/share/), 'now the dat is gone and welcome screen is back')) + .then(() => waitForMatch(t, app, '.tutorial', /share/i)) // now the dat is gone and welcome screen is back + .catch(e => t.fail(e)) .then(() => endTest(app)) }) // Create a new app instance function createApp () { - return new spectron.Application({ + var app = new spectron.Application({ path: path.join(__dirname, '../node_modules/.bin/electron'), args: [path.join(__dirname, '../index.js'), '--data', TEST_DATA, '--db', TEST_DATA_DB], env: { NODE_ENV: 'test', RUNNING_IN_SPECTRON: true } }) + process.on('SIGTERM', () => endTest(app)) + return app } // Starts the app, waits for it to load, returns a promise @@ -123,17 +106,15 @@ function waitForLoad (app, t) { }) } -// Returns a promise that resolves after 'ms' milliseconds. Default: 1 second -function wait (ms) { - ms = ms || 3000 - return new Promise(function (resolve, reject) { - setTimeout(resolve, ms) - }) -} - // Quit the app, end the test, either in success (!err) or failure (err) function endTest (app) { - var paths = [TEST_DATA, path.join(__dirname, 'fixtures', '.dat')] - return del(paths) - .then(() => app.stop()) + var fixPath = path.join(__dirname, 'fixtures') + return Promise.all([ + del(fixPath), + del(TEST_DATA) + ]) + .then(() => { + execSync(`git checkout -- "${fixPath}"`) + return app.stop() + }) } diff --git a/tests/intro.js b/tests/intro.js old mode 100644 new mode 100755 index f256219b..93611292 --- a/tests/intro.js +++ b/tests/intro.js @@ -1,10 +1,11 @@ +#!/usr/bin/env node var EventEmitter = require('events').EventEmitter -var tape = require('tape') +var test = require('tap').test var spok = require('spok') var intro = require('../models/intro') -tape('models/intro: should initialize with a default state', function (t) { +test('models/intro: should initialize with a default state', function (t) { var state = {} var emitter = new EventEmitter() intro(state, emitter) @@ -16,7 +17,7 @@ tape('models/intro: should initialize with a default state', function (t) { t.end() }) -tape('should show intro screen if there are no dats', function (t) { +test('should show intro screen if there are no dats', function (t) { var state = { dats: { values: [] @@ -36,7 +37,7 @@ tape('should show intro screen if there are no dats', function (t) { t.end() }) -tape('should be able to hide the intro screen', function (t) { +test('should be able to hide the intro screen', function (t) { var state = { intro: { show: true diff --git a/tests/utils/wait.js b/tests/utils/wait.js new file mode 100644 index 00000000..b2b840e0 --- /dev/null +++ b/tests/utils/wait.js @@ -0,0 +1,7 @@ +// Returns a promise that resolves after 'ms' milliseconds. Default: 1 second +module.exports = function wait (ms) { + ms = ms || 3000 + return new Promise(function (resolve, reject) { + setTimeout(resolve, ms) + }) +} diff --git a/tests/utils/waitForAndClick.js b/tests/utils/waitForAndClick.js new file mode 100644 index 00000000..8f14bf76 --- /dev/null +++ b/tests/utils/waitForAndClick.js @@ -0,0 +1,10 @@ +module.exports = function waitForAndClick (t, app, selector, ms, reverse) { + return app.client.waitForExist(selector, ms, reverse) + .then(function () { + t.ok(true, selector + ' exists.') + return app.client.click(selector) + .then(function () { + t.ok(true, selector + ' clicked.') + }) + }) +} diff --git a/tests/utils/waitForMatch.js b/tests/utils/waitForMatch.js new file mode 100644 index 00000000..9a6dedba --- /dev/null +++ b/tests/utils/waitForMatch.js @@ -0,0 +1,33 @@ +var wait = require('./wait') + +module.exports = function waitForMatch (t, app, selector, regexp, ms, reverse) { + if (reverse) { + reverse = true + } else { + reverse = false + } + if (!ms) { + ms = 10000 + } + var lastValue + var end = Date.now() + ms + function check () { + if (Date.now() > end) { + return Promise.reject(new Error('Timeout after ' + ms + 'ms tryin to match "' + selector + '" with ' + String(regexp) + '; last value: ' + lastValue)) + } + return app.client.getText(selector) + .then(function (text) { + lastValue = text + var match = regexp.test(text) ? !reverse : reverse + if (!match) { + return Promise.reject(new Error('no-match')) + } + t.ok(true, '"' + selector + '" matches ' + String(regexp)) + return Promise.resolve(text) + }) + .catch(function (e) { + return wait(100).then(check) + }) + } + return check() +}