From ca701bb9afa13652024c777473a46aaf77d933c1 Mon Sep 17 00:00:00 2001 From: Samuel Attard Date: Sun, 10 Mar 2019 15:38:44 -0700 Subject: [PATCH 01/14] spec: initial spike of main-process based tests --- .circleci/config.yml | 8 +- package-lock.json | 269 +++++++----- package.json | 9 +- script/spec-runner.js | 61 ++- spec-main/.eslintrc | 20 + spec-main/ambient.d.ts | 1 + .../api-app-spec.ts | 387 +++++++++--------- spec-main/events-helpers.ts | 40 ++ spec-main/index.js | 90 ++++ spec-main/package.json | 6 + spec-main/window-helpers.ts | 26 ++ spec/package-lock.json | 60 +-- tsconfig.spec.json | 10 + typings/internal-ambient.d.ts | 1 + 14 files changed, 656 insertions(+), 332 deletions(-) create mode 100644 spec-main/.eslintrc create mode 100644 spec-main/ambient.d.ts rename spec/api-app-spec.js => spec-main/api-app-spec.ts (78%) create mode 100644 spec-main/events-helpers.ts create mode 100644 spec-main/index.js create mode 100644 spec-main/package.json create mode 100644 spec-main/window-helpers.ts create mode 100644 tsconfig.spec.json diff --git a/.circleci/config.yml b/.circleci/config.yml index 2671f9a53e..6e6c873389 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -810,7 +810,13 @@ steps-tests: &steps-tests - run: name: Check test results existence command: | - MOCHA_FILE='src/junit/test-results.xml' + MOCHA_FILE='src/junit/test-results-remote.xml' + # Check if it exists and not empty. + if [ ! -s "$MOCHA_FILE" ]; then + exit 1 + fi + + MOCHA_FILE='src/junit/test-results-main.xml' # Check if it exists and not empty. if [ ! -s "$MOCHA_FILE" ]; then exit 1 diff --git a/package-lock.json b/package-lock.json index cf185f4ae1..91a8122a82 100644 --- a/package-lock.json +++ b/package-lock.json @@ -155,12 +155,52 @@ "any-observable": "^0.3.0" } }, + "@types/chai": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.1.7.tgz", + "integrity": "sha512-2Y8uPt0/jwjhQ6EiluT0XCri1Dbplr0ZxfFXUz+ye13gaqE8u5gL5ppao1JrUYr9cIip5S6MvQzBS7Kke7U9VA==", + "dev": true + }, + "@types/chai-as-promised": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@types/chai-as-promised/-/chai-as-promised-7.1.0.tgz", + "integrity": "sha512-MFiW54UOSt+f2bRw8J7LgQeIvE/9b4oGvwU7XW30S9QGAiHGnU/fmiOprsyMkdmH2rl8xSPc0/yrQw8juXU6bQ==", + "dev": true, + "requires": { + "@types/chai": "*" + } + }, + "@types/mocha": { + "version": "5.2.6", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-5.2.6.tgz", + "integrity": "sha512-1axi39YdtBI7z957vdqXI4Ac25e7YihYQtJa+Clnxg1zTJEaIRbndt71O3sP4GAMgiAm0pY26/b9BrY4MR/PMw==", + "dev": true + }, "@types/node": { "version": "10.12.21", "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.21.tgz", "integrity": "sha512-CBgLNk4o3XMnqMc0rhb6lc77IwShMEglz05deDcn2lQxyXEZivfwgYJu7SMha9V5XcrP6qZuevTHV/QrN2vjKQ==", "dev": true }, + "@types/split": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/split/-/split-1.0.0.tgz", + "integrity": "sha512-pm9S1mkr+av0j7D6pFyqhBxXDbnbO9gqj4nb8DtGtCewvj0XhIv089SSwXrjrIizT1UquO8/h83hCut0pa3u8A==", + "dev": true, + "requires": { + "@types/node": "*", + "@types/through": "*" + } + }, + "@types/through": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/through/-/through-0.0.29.tgz", + "integrity": "sha512-9a7C5VHh+1BKblaYiq+7Tfc+EOmjMdZaD1MYtkQjSoxgB69tBjW98ry6SKsi4zEIWztLOMRuL87A3bdT/Fc/4w==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, "@typescript-eslint/eslint-plugin": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-1.4.2.tgz", @@ -4677,28 +4717,27 @@ "dependencies": { "abbrev": { "version": "1.1.1", - "resolved": false, + "resolved": "", "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", "dev": true, "optional": true }, "ansi-regex": { "version": "2.1.1", - "resolved": false, + "resolved": "", "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true, - "optional": true + "dev": true }, "aproba": { "version": "1.2.0", - "resolved": false, + "resolved": "", "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", "dev": true, "optional": true }, "are-we-there-yet": { "version": "1.1.4", - "resolved": false, + "resolved": "", "integrity": "sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0=", "dev": true, "optional": true, @@ -4709,17 +4748,15 @@ }, "balanced-match": { "version": "1.0.0", - "resolved": false, + "resolved": "", "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true, - "optional": true + "dev": true }, "brace-expansion": { "version": "1.1.11", - "resolved": false, + "resolved": "", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, - "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -4727,42 +4764,39 @@ }, "chownr": { "version": "1.0.1", - "resolved": false, + "resolved": "", "integrity": "sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE=", "dev": true, "optional": true }, "code-point-at": { "version": "1.1.0", - "resolved": false, + "resolved": "", "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true, - "optional": true + "dev": true }, "concat-map": { "version": "0.0.1", - "resolved": false, + "resolved": "", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true, - "optional": true + "dev": true }, "console-control-strings": { "version": "1.1.0", - "resolved": false, + "resolved": "", "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", - "dev": true, - "optional": true + "dev": true }, "core-util-is": { "version": "1.0.2", - "resolved": false, + "resolved": "", "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", "dev": true, "optional": true }, "debug": { "version": "2.6.9", - "resolved": false, + "resolved": "", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, "optional": true, @@ -4772,28 +4806,28 @@ }, "deep-extend": { "version": "0.5.1", - "resolved": false, + "resolved": "", "integrity": "sha512-N8vBdOa+DF7zkRrDCsaOXoCs/E2fJfx9B9MrKnnSiHNh4ws7eSys6YQE4KvT1cecKmOASYQBhbKjeuDD9lT81w==", "dev": true, "optional": true }, "delegates": { "version": "1.0.0", - "resolved": false, + "resolved": "", "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", "dev": true, "optional": true }, "detect-libc": { "version": "1.0.3", - "resolved": false, + "resolved": "", "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", "dev": true, "optional": true }, "fs-minipass": { "version": "1.2.5", - "resolved": false, + "resolved": "", "integrity": "sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ==", "dev": true, "optional": true, @@ -4803,14 +4837,14 @@ }, "fs.realpath": { "version": "1.0.0", - "resolved": false, + "resolved": "", "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true, "optional": true }, "gauge": { "version": "2.7.4", - "resolved": false, + "resolved": "", "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", "dev": true, "optional": true, @@ -4827,7 +4861,7 @@ }, "glob": { "version": "7.1.2", - "resolved": false, + "resolved": "", "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", "dev": true, "optional": true, @@ -4842,14 +4876,14 @@ }, "has-unicode": { "version": "2.0.1", - "resolved": false, + "resolved": "", "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", "dev": true, "optional": true }, "iconv-lite": { "version": "0.4.21", - "resolved": false, + "resolved": "", "integrity": "sha512-En5V9za5mBt2oUA03WGD3TwDv0MKAruqsuxstbMUZaj9W9k/m1CV/9py3l0L5kw9Bln8fdHQmzHSYtvpvTLpKw==", "dev": true, "optional": true, @@ -4859,7 +4893,7 @@ }, "ignore-walk": { "version": "3.0.1", - "resolved": false, + "resolved": "", "integrity": "sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ==", "dev": true, "optional": true, @@ -4869,7 +4903,7 @@ }, "inflight": { "version": "1.0.6", - "resolved": false, + "resolved": "", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "dev": true, "optional": true, @@ -4880,58 +4914,53 @@ }, "inherits": { "version": "2.0.3", - "resolved": false, + "resolved": "", "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true, - "optional": true + "dev": true }, "ini": { "version": "1.3.5", - "resolved": false, + "resolved": "", "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", "dev": true, "optional": true }, "is-fullwidth-code-point": { "version": "1.0.0", - "resolved": false, + "resolved": "", "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "dev": true, - "optional": true, "requires": { "number-is-nan": "^1.0.0" } }, "isarray": { "version": "1.0.0", - "resolved": false, + "resolved": "", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true, "optional": true }, "minimatch": { "version": "3.0.4", - "resolved": false, + "resolved": "", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, - "optional": true, "requires": { "brace-expansion": "^1.1.7" } }, "minimist": { "version": "0.0.8", - "resolved": false, + "resolved": "", "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true, - "optional": true + "dev": true }, "minipass": { "version": "2.2.4", - "resolved": false, + "resolved": "", "integrity": "sha512-hzXIWWet/BzWhYs2b+u7dRHlruXhwdgvlTMDKC6Cb1U7ps6Ac6yQlR39xsbjWJE377YTCtKwIXIpJ5oP+j5y8g==", "dev": true, - "optional": true, "requires": { "safe-buffer": "^5.1.1", "yallist": "^3.0.0" @@ -4939,7 +4968,7 @@ }, "minizlib": { "version": "1.1.0", - "resolved": false, + "resolved": "", "integrity": "sha512-4T6Ur/GctZ27nHfpt9THOdRZNgyJ9FZchYO1ceg5S8Q3DNLCKYy44nCZzgCJgcvx2UM8czmqak5BCxJMrq37lA==", "dev": true, "optional": true, @@ -4949,24 +4978,23 @@ }, "mkdirp": { "version": "0.5.1", - "resolved": false, + "resolved": "", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", "dev": true, - "optional": true, "requires": { "minimist": "0.0.8" } }, "ms": { "version": "2.0.0", - "resolved": false, + "resolved": "", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true, "optional": true }, "needle": { "version": "2.2.0", - "resolved": false, + "resolved": "", "integrity": "sha512-eFagy6c+TYayorXw/qtAdSvaUpEbBsDwDyxYFgLZ0lTojfH7K+OdBqAF7TAFwDokJaGpubpSGG0wO3iC0XPi8w==", "dev": true, "optional": true, @@ -4978,7 +5006,7 @@ }, "node-pre-gyp": { "version": "0.10.0", - "resolved": false, + "resolved": "", "integrity": "sha512-G7kEonQLRbcA/mOoFoxvlMrw6Q6dPf92+t/l0DFSMuSlDoWaI9JWIyPwK0jyE1bph//CUEL65/Fz1m2vJbmjQQ==", "dev": true, "optional": true, @@ -4997,7 +5025,7 @@ }, "nopt": { "version": "4.0.1", - "resolved": false, + "resolved": "", "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", "dev": true, "optional": true, @@ -5008,14 +5036,14 @@ }, "npm-bundled": { "version": "1.0.3", - "resolved": false, + "resolved": "", "integrity": "sha512-ByQ3oJ/5ETLyglU2+8dBObvhfWXX8dtPZDMePCahptliFX2iIuhyEszyFk401PZUNQH20vvdW5MLjJxkwU80Ow==", "dev": true, "optional": true }, "npm-packlist": { "version": "1.1.10", - "resolved": false, + "resolved": "", "integrity": "sha512-AQC0Dyhzn4EiYEfIUjCdMl0JJ61I2ER9ukf/sLxJUcZHfo+VyEfz2rMJgLZSS1v30OxPQe1cN0LZA1xbcaVfWA==", "dev": true, "optional": true, @@ -5026,7 +5054,7 @@ }, "npmlog": { "version": "4.1.2", - "resolved": false, + "resolved": "", "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", "dev": true, "optional": true, @@ -5039,45 +5067,43 @@ }, "number-is-nan": { "version": "1.0.1", - "resolved": false, + "resolved": "", "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true, - "optional": true + "dev": true }, "object-assign": { "version": "4.1.1", - "resolved": false, + "resolved": "", "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", "dev": true, "optional": true }, "once": { "version": "1.4.0", - "resolved": false, + "resolved": "", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true, - "optional": true, "requires": { "wrappy": "1" } }, "os-homedir": { "version": "1.0.2", - "resolved": false, + "resolved": "", "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", "dev": true, "optional": true }, "os-tmpdir": { "version": "1.0.2", - "resolved": false, + "resolved": "", "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", "dev": true, "optional": true }, "osenv": { "version": "0.1.5", - "resolved": false, + "resolved": "", "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", "dev": true, "optional": true, @@ -5088,21 +5114,21 @@ }, "path-is-absolute": { "version": "1.0.1", - "resolved": false, + "resolved": "", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true, "optional": true }, "process-nextick-args": { "version": "2.0.0", - "resolved": false, + "resolved": "", "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", "dev": true, "optional": true }, "rc": { "version": "1.2.7", - "resolved": false, + "resolved": "", "integrity": "sha512-LdLD8xD4zzLsAT5xyushXDNscEjB7+2ulnl8+r1pnESlYtlJtVSoCMBGr30eDRJ3+2Gq89jK9P9e4tCEH1+ywA==", "dev": true, "optional": true, @@ -5115,7 +5141,7 @@ "dependencies": { "minimist": { "version": "1.2.0", - "resolved": false, + "resolved": "", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true, "optional": true @@ -5124,7 +5150,7 @@ }, "readable-stream": { "version": "2.3.6", - "resolved": false, + "resolved": "", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "optional": true, @@ -5140,7 +5166,7 @@ }, "rimraf": { "version": "2.6.2", - "resolved": false, + "resolved": "", "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", "dev": true, "optional": true, @@ -5150,52 +5176,50 @@ }, "safe-buffer": { "version": "5.1.1", - "resolved": false, + "resolved": "", "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", - "dev": true, - "optional": true + "dev": true }, "safer-buffer": { "version": "2.1.2", - "resolved": false, + "resolved": "", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true, "optional": true }, "sax": { "version": "1.2.4", - "resolved": false, + "resolved": "", "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", "dev": true, "optional": true }, "semver": { "version": "5.5.0", - "resolved": false, + "resolved": "", "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", "dev": true, "optional": true }, "set-blocking": { "version": "2.0.0", - "resolved": false, + "resolved": "", "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "dev": true, "optional": true }, "signal-exit": { "version": "3.0.2", - "resolved": false, + "resolved": "", "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", "dev": true, "optional": true }, "string-width": { "version": "1.0.2", - "resolved": false, + "resolved": "", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "dev": true, - "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -5204,7 +5228,7 @@ }, "string_decoder": { "version": "1.1.1", - "resolved": false, + "resolved": "", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "optional": true, @@ -5214,24 +5238,23 @@ }, "strip-ansi": { "version": "3.0.1", - "resolved": false, + "resolved": "", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, - "optional": true, "requires": { "ansi-regex": "^2.0.0" } }, "strip-json-comments": { "version": "2.0.1", - "resolved": false, + "resolved": "", "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", "dev": true, "optional": true }, "tar": { "version": "4.4.1", - "resolved": false, + "resolved": "", "integrity": "sha512-O+v1r9yN4tOsvl90p5HAP4AEqbYhx4036AGMm075fH9F8Qwi3oJ+v4u50FkT/KkvywNGtwkk0zRI+8eYm1X/xg==", "dev": true, "optional": true, @@ -5247,14 +5270,14 @@ }, "util-deprecate": { "version": "1.0.2", - "resolved": false, + "resolved": "", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "dev": true, "optional": true }, "wide-align": { "version": "1.1.2", - "resolved": false, + "resolved": "", "integrity": "sha512-ijDLlyQ7s6x1JgCLur53osjm/UXUYD9+0PbYKrBsYisYXzCxN+HC3mYDNy/dWdmf3AwqwU3CXwDCvsNgGK1S0w==", "dev": true, "optional": true, @@ -5264,17 +5287,15 @@ }, "wrappy": { "version": "1.0.2", - "resolved": false, + "resolved": "", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true, - "optional": true + "dev": true }, "yallist": { "version": "3.0.2", - "resolved": false, + "resolved": "", "integrity": "sha1-hFK0u36Dx8GI2AQcGoN8dz1ti7k=", - "dev": true, - "optional": true + "dev": true } } }, @@ -7787,6 +7808,12 @@ } } }, + "make-error": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.5.tgz", + "integrity": "sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g==", + "dev": true + }, "map-cache": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", @@ -11197,6 +11224,24 @@ "urix": "^0.1.0" } }, + "source-map-support": { + "version": "0.5.10", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.10.tgz", + "integrity": "sha512-YfQ3tQFTK/yzlGJuX8pTwa4tifQj4QS2Mj7UegOu8jAz59MqIiMGPXxQhVQiIMNzayuUSF/jEuVnfFF5JqybmQ==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, "source-map-url": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", @@ -12584,6 +12629,30 @@ "integrity": "sha512-FHkoUZvG6Egrv9XZAyYGKEyb1JMsFphgPjoczkZC2y6W93U1jswcVURB8MUvtsahEPEVACyxD47JAL63vF4JsQ==", "dev": true }, + "ts-node": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-6.2.0.tgz", + "integrity": "sha512-ZNT+OEGfUNVMGkpIaDJJ44Zq3Yr0bkU/ugN1PHbU+/01Z7UV1fsELRiTx1KuQNvQ1A3pGh3y25iYF6jXgxV21A==", + "dev": true, + "requires": { + "arrify": "^1.0.0", + "buffer-from": "^1.1.0", + "diff": "^3.1.0", + "make-error": "^1.1.1", + "minimist": "^1.2.0", + "mkdirp": "^0.5.1", + "source-map-support": "^0.5.6", + "yn": "^2.0.0" + }, + "dependencies": { + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + } + } + }, "tsconfig": { "version": "5.0.3", "resolved": "https://registry.npmjs.org/tsconfig/-/tsconfig-5.0.3.tgz", @@ -13614,6 +13683,12 @@ "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.2.tgz", "integrity": "sha1-hFK0u36Dx8GI2AQcGoN8dz1ti7k=", "dev": true + }, + "yn": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yn/-/yn-2.0.0.tgz", + "integrity": "sha1-5a2ryKz0CPY4X8dklWhMiOavaJo=", + "dev": true } } -} \ No newline at end of file +} diff --git a/package.json b/package.json index b3fcaf17db..11b83448c7 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,11 @@ "description": "Build cross platform desktop apps with JavaScript, HTML, and CSS", "devDependencies": { "@octokit/rest": "^16.3.2", + "@types/chai": "^4.1.7", + "@types/chai-as-promised": "^7.1.0", + "@types/mocha": "^5.2.6", "@types/node": "^10.12.21", + "@types/split": "^1.0.0", "@typescript-eslint/eslint-plugin": "^1.4.2", "@typescript-eslint/parser": "^1.4.2", "aliasify": "^2.1.0", @@ -42,6 +46,7 @@ "standard-markdown": "^5.0.0", "sumchecker": "^2.0.2", "temp": "^0.8.3", + "ts-node": "^6.0.3", "tsify": "^4.0.1", "typescript": "~3.3.3333" }, @@ -71,7 +76,7 @@ "prepush": "check-for-leaks", "repl": "node ./script/start.js --interactive", "start": "node ./script/start.js", - "test": "node ./script/spec-runner.js electron/spec", + "test": "node ./script/spec-runner.js", "tsc": "tsc" }, "license": "MIT", @@ -115,4 +120,4 @@ "git add filenames.auto.gni" ] } -} \ No newline at end of file +} diff --git a/script/spec-runner.js b/script/spec-runner.js index d6750db499..3f7770819c 100755 --- a/script/spec-runner.js +++ b/script/spec-runner.js @@ -13,6 +13,15 @@ const NPM_CMD = process.platform === 'win32' ? 'npm.cmd' : 'npm' const specHashPath = path.resolve(__dirname, '../spec/.hash') +let only = null +const onlyArg = process.argv.find(arg => arg.startsWith('--only=')) +if (onlyArg) { + only = onlyArg.substr(7).split(',') + console.log('Only running:', only) +} else { + console.log('Will trigger all spec runners') +} + async function main () { const [lastSpecHash, lastSpecInstallHash] = loadLastSpecHash() const [currentSpecHash, currentSpecInstallHash] = await getSpecHash() @@ -38,14 +47,62 @@ function saveSpecHash ([newSpecHash, newSpecInstallHash]) { } async function runElectronTests () { + const errors = [] + const runners = [ + ['Remote based specs', 'remote', runRemoteBasedElectronTests], + ['Main process specs', 'main', runMainProcessElectronTests] + ] + + const mochaFile = process.env.MOCHA_FILE + for (const runner of runners) { + if (only && !only.includes(runner[1])) { + console.info('\nSkipping:', runner[0]) + continue + } + try { + console.info('\nRunning:', runner[0]) + if (mochaFile) { + process.env.MOCHA_FILE = mochaFile.replace('.xml', `-${runner[1]}.xml`) + } + await runner[2]() + } catch (err) { + errors.push([runner[0], err]) + } + } + + if (errors.length !== 0) { + for (const err of errors) { + console.error('\n\nRunner Failed:', err[0]) + console.error(err[1]) + } + throw new Error('Electron test runners have failed') + } +} + +async function runRemoteBasedElectronTests () { let exe = path.resolve(BASE, utils.getElectronExec()) - const args = process.argv.slice(2) + const args = process.argv.slice(2).filter(arg => !arg.startsWith('--only=')) if (process.platform === 'linux') { args.unshift(path.resolve(__dirname, 'dbus_mock.py'), exe) exe = 'python' } - const { status } = childProcess.spawnSync(exe, args, { + const { status } = childProcess.spawnSync(exe, ['electron/spec', ...args], { + cwd: path.resolve(__dirname, '../..'), + stdio: 'inherit' + }) + if (status !== 0) { + throw new Error(`Electron tests failed with code ${status}.`) + } +} + +async function runMainProcessElectronTests () { + const exe = path.resolve(BASE, utils.getElectronExec()) + const args = process.argv.slice(2).filter(arg => !arg.startsWith('--only=')) + + console.log(exe, args) + + const { status } = childProcess.spawnSync(exe, ['electron/spec-main', ...args], { cwd: path.resolve(__dirname, '../..'), stdio: 'inherit' }) diff --git a/spec-main/.eslintrc b/spec-main/.eslintrc new file mode 100644 index 0000000000..a26475e27d --- /dev/null +++ b/spec-main/.eslintrc @@ -0,0 +1,20 @@ +{ + "env": { + "browser": true, + "mocha": true, + "jquery": true, + "serviceworker": true + }, + "globals": { + "Bindings": true, + "Components": true, + "UI": true, + "WebView": true + }, + "plugins": [ + "mocha" + ], + "rules": { + "mocha/no-exclusive-tests": "error" + } +} diff --git a/spec-main/ambient.d.ts b/spec-main/ambient.d.ts new file mode 100644 index 0000000000..5e6e6eff8d --- /dev/null +++ b/spec-main/ambient.d.ts @@ -0,0 +1 @@ +declare var isCI: boolean; diff --git a/spec/api-app-spec.js b/spec-main/api-app-spec.ts similarity index 78% rename from spec/api-app-spec.js rename to spec-main/api-app-spec.ts index 999f2eca3f..c89d9c95cd 100644 --- a/spec/api-app-spec.js +++ b/spec-main/api-app-spec.ts @@ -1,24 +1,20 @@ -const chai = require('chai') -const chaiAsPromised = require('chai-as-promised') -const dirtyChai = require('dirty-chai') -const ChildProcess = require('child_process') -const https = require('https') -const net = require('net') -const fs = require('fs') -const path = require('path') -const cp = require('child_process') -const split = require('split') -const { ipcRenderer, remote } = require('electron') -const { emittedOnce } = require('./events-helpers') -const { closeWindow } = require('./window-helpers') +import * as chai from 'chai' +import * as chaiAsPromised from 'chai-as-promised' +import * as cp from 'child_process' +import * as https from 'https' +import * as net from 'net' +import * as fs from 'fs' +import * as path from 'path' +import split = require('split') +import { app, BrowserWindow, Menu } from 'electron' +import { emittedOnce } from './events-helpers'; +import { closeWindow } from './window-helpers'; const { expect } = chai -const { app, BrowserWindow, Menu, ipcMain } = remote - -const isCI = remote.getGlobal('isCi') chai.use(chaiAsPromised) -chai.use(dirtyChai) + +const fixturesPath = path.resolve(__dirname, '../spec/fixtures') describe('electron module', () => { it('does not expose internal modules to require', () => { @@ -28,33 +24,16 @@ describe('electron module', () => { }) describe('require("electron")', () => { - let window = null - - beforeEach(() => { - window = new BrowserWindow({ - show: false, - width: 400, - height: 400, - webPreferences: { - nodeIntegration: true - } - }) - }) - - afterEach(() => { - return closeWindow(window).then(() => { window = null }) - }) - - it('always returns the internal electron module', (done) => { - ipcMain.once('answer', () => done()) - window.loadFile(path.join(__dirname, 'fixtures', 'api', 'electron-module-app', 'index.html')) + it('always returns the internal electron module', () => { + require('electron') }) }) }) describe('app module', () => { - let server, secureUrl - const certPath = path.join(__dirname, 'fixtures', 'certificates') + let server: https.Server + let secureUrl: string + const certPath = path.join(fixturesPath, 'certificates') before((done) => { const options = { @@ -69,7 +48,7 @@ describe('app module', () => { } server = https.createServer(options, (req, res) => { - if (req.client.authorized) { + if ((req as any).client.authorized) { res.writeHead(200) res.end('authorized') } else { @@ -79,7 +58,7 @@ describe('app module', () => { }) server.listen(0, '127.0.0.1', () => { - const port = server.address().port + const port = (server.address() as net.AddressInfo).port secureUrl = `https://127.0.0.1:${port}` done() }) @@ -107,13 +86,13 @@ describe('app module', () => { describe('app.getName()', () => { it('returns the name field of package.json', () => { - expect(app.getName()).to.equal('Electron Test') + expect(app.getName()).to.equal('Electron Test Main') }) }) describe('app.setName(name)', () => { it('overrides the name', () => { - expect(app.getName()).to.equal('Electron Test') + expect(app.getName()).to.equal('Electron Test Main') app.setName('test-name') expect(app.getName()).to.equal('test-name') @@ -123,7 +102,7 @@ describe('app module', () => { describe('app.getLocale()', () => { it('should not be empty', () => { - expect(app.getLocale()).to.not.be.empty() + expect(app.getLocale()).to.not.equal('') }) }) @@ -140,7 +119,7 @@ describe('app module', () => { describe('app.isPackaged', () => { it('should be false durings tests', () => { - expect(app.isPackaged).to.be.false() + expect(app.isPackaged).equal(false) }) }) @@ -152,23 +131,23 @@ describe('app module', () => { }) it('should be false during tests', () => { - expect(app.isInApplicationsFolder()).to.be.false() + expect(app.isInApplicationsFolder()).to.equal(false) }) }) describe('app.exit(exitCode)', () => { - let appProcess = null + let appProcess: cp.ChildProcess | null = null afterEach(() => { - if (appProcess != null) appProcess.kill() + if (appProcess) appProcess.kill() }) it('emits a process exit event with the code', async () => { - const appPath = path.join(__dirname, 'fixtures', 'api', 'quit-app') - const electronPath = remote.getGlobal('process').execPath + const appPath = path.join(fixturesPath, 'api', 'quit-app') + const electronPath = process.execPath let output = '' - appProcess = ChildProcess.spawn(electronPath, [appPath]) + appProcess = cp.spawn(electronPath, [appPath]) appProcess.stdout.on('data', data => { output += data }) const [code] = await emittedOnce(appProcess, 'close') @@ -179,10 +158,10 @@ describe('app module', () => { }) it('closes all windows', async function () { - const appPath = path.join(__dirname, 'fixtures', 'api', 'exit-closes-all-windows-app') - const electronPath = remote.getGlobal('process').execPath + const appPath = path.join(fixturesPath, 'api', 'exit-closes-all-windows-app') + const electronPath = process.execPath - appProcess = ChildProcess.spawn(electronPath, [appPath]) + appProcess = cp.spawn(electronPath, [appPath]) const [code, signal] = await emittedOnce(appProcess, 'close') expect(signal).to.equal(null, 'exit signal should be null, if you see this please tag @MarshallOfSound') @@ -195,32 +174,32 @@ describe('app module', () => { return } - const electronPath = remote.getGlobal('process').execPath - const appPath = path.join(__dirname, 'fixtures', 'api', 'singleton') - appProcess = ChildProcess.spawn(electronPath, [appPath]) + const electronPath = process.execPath + const appPath = path.join(fixturesPath, 'api', 'singleton') + appProcess = cp.spawn(electronPath, [appPath]) // Singleton will send us greeting data to let us know it's running. // After that, ask it to exit gracefully and confirm that it does. - appProcess.stdout.on('data', data => appProcess.kill()) + appProcess.stdout.on('data', data => appProcess && appProcess.kill()) const [code, signal] = await emittedOnce(appProcess, 'close') const message = `code:\n${code}\nsignal:\n${signal}` expect(code).to.equal(0, message) - expect(signal).to.be.null(message) + expect(signal).to.equal(null, message) }) }) describe('app.requestSingleInstanceLock', () => { it('prevents the second launch of app', function (done) { this.timeout(120000) - const appPath = path.join(__dirname, 'fixtures', 'api', 'singleton') - const first = ChildProcess.spawn(remote.process.execPath, [appPath]) + const appPath = path.join(fixturesPath, 'api', 'singleton') + const first = cp.spawn(process.execPath, [appPath]) first.once('exit', code => { expect(code).to.equal(0) }) // Start second app when received output. first.stdout.once('data', () => { - const second = ChildProcess.spawn(remote.process.execPath, [appPath]) + const second = cp.spawn(process.execPath, [appPath]) second.once('exit', code => { expect(code).to.equal(1) done() @@ -257,7 +236,7 @@ describe('app module', () => { }) describe('app.relaunch', () => { - let server = null + let server: net.Server | null = null const socketPath = process.platform === 'win32' ? '\\\\.\\pipe\\electron-app-relaunch' : '/tmp/electron-app-relaunch' beforeEach(done => { @@ -269,7 +248,7 @@ describe('app module', () => { }) afterEach((done) => { - server.close(() => { + server!.close(() => { if (process.platform === 'win32') { done() } else { @@ -282,8 +261,8 @@ describe('app module', () => { this.timeout(120000) let state = 'none' - server.once('error', error => done(error)) - server.on('connection', client => { + server!.once('error', error => done(error)) + server!.on('connection', client => { client.once('data', data => { if (String(data) === 'false' && state === 'none') { state = 'first-launch' @@ -295,8 +274,8 @@ describe('app module', () => { }) }) - const appPath = path.join(__dirname, 'fixtures', 'api', 'relaunch') - ChildProcess.spawn(remote.process.execPath, [appPath]) + const appPath = path.join(fixturesPath, 'api', 'relaunch') + cp.spawn(process.execPath, [appPath]) }) }) @@ -313,61 +292,61 @@ describe('app module', () => { }) }) - xdescribe('app.importCertificate', () => { - let w = null + // xdescribe('app.importCertificate', () => { + // let w = null - before(function () { - if (process.platform !== 'linux') { - this.skip() - } - }) + // before(function () { + // if (process.platform !== 'linux') { + // this.skip() + // } + // }) - afterEach(() => closeWindow(w).then(() => { w = null })) + // afterEach(() => closeWindow(w).then(() => { w = null })) - it('can import certificate into platform cert store', done => { - const options = { - certificate: path.join(certPath, 'client.p12'), - password: 'electron' - } + // it('can import certificate into platform cert store', done => { + // const options = { + // certificate: path.join(certPath, 'client.p12'), + // password: 'electron' + // } - w = new BrowserWindow({ - show: false, - webPreferences: { - nodeIntegration: true - } - }) + // w = new BrowserWindow({ + // show: false, + // webPreferences: { + // nodeIntegration: true + // } + // }) - w.webContents.on('did-finish-load', () => { - expect(w.webContents.getTitle()).to.equal('authorized') - done() - }) + // w.webContents.on('did-finish-load', () => { + // expect(w.webContents.getTitle()).to.equal('authorized') + // done() + // }) - ipcRenderer.once('select-client-certificate', (event, webContentsId, list) => { - expect(webContentsId).to.equal(w.webContents.id) - expect(list).to.have.lengthOf(1) + // ipcRenderer.once('select-client-certificate', (event, webContentsId, list) => { + // expect(webContentsId).to.equal(w.webContents.id) + // expect(list).to.have.lengthOf(1) - expect(list[0]).to.deep.equal({ - issuerName: 'Intermediate CA', - subjectName: 'Client Cert', - issuer: { commonName: 'Intermediate CA' }, - subject: { commonName: 'Client Cert' } - }) + // expect(list[0]).to.deep.equal({ + // issuerName: 'Intermediate CA', + // subjectName: 'Client Cert', + // issuer: { commonName: 'Intermediate CA' }, + // subject: { commonName: 'Client Cert' } + // }) - event.sender.send('client-certificate-response', list[0]) - }) + // event.sender.send('client-certificate-response', list[0]) + // }) - app.importCertificate(options, result => { - expect(result).toNotExist() - ipcRenderer.sendSync('set-client-certificate-option', false) - w.loadURL(secureUrl) - }) - }) - }) + // app.importCertificate(options, result => { + // expect(result).toNotExist() + // ipcRenderer.sendSync('set-client-certificate-option', false) + // w.loadURL(secureUrl) + // }) + // }) + // }) describe('BrowserWindow events', () => { - let w = null + let w: BrowserWindow = null as any - afterEach(() => closeWindow(w).then(() => { w = null })) + afterEach(() => closeWindow(w).then(() => { w = null as any })) it('should emit browser-window-focus event when window is focused', (done) => { app.once('browser-window-focus', (e, window) => { @@ -530,7 +509,7 @@ describe('app module', () => { const platformIsSupported = !platformIsNotSupported const expectedBadgeCount = 42 - let returnValue = null + let returnValue: boolean | null = null beforeEach(() => { returnValue = app.setBadgeCount(expectedBadgeCount) }) @@ -547,7 +526,7 @@ describe('app module', () => { }) it('returns true', () => { - expect(returnValue).to.be.true() + expect(returnValue).to.equal(true) }) it('sets a badge count', () => { @@ -563,7 +542,7 @@ describe('app module', () => { }) it('returns false', () => { - expect(returnValue).to.be.false() + expect(returnValue).to.equal(false) }) it('does not set a badge count', () => { @@ -618,28 +597,28 @@ describe('app module', () => { }) it('correctly sets and unsets the LoginItem', function () { - expect(app.getLoginItemSettings().openAtLogin).to.be.false() + expect(app.getLoginItemSettings().openAtLogin).to.equal(false) app.setLoginItemSettings({ openAtLogin: true }) - expect(app.getLoginItemSettings().openAtLogin).to.be.true() + expect(app.getLoginItemSettings().openAtLogin).to.equal(true) app.setLoginItemSettings({ openAtLogin: false }) - expect(app.getLoginItemSettings().openAtLogin).to.be.false() + expect(app.getLoginItemSettings().openAtLogin).to.equal(false) }) it('correctly sets and unsets the LoginItem as hidden', function () { if (process.platform !== 'darwin') this.skip() - expect(app.getLoginItemSettings().openAtLogin).to.be.false() - expect(app.getLoginItemSettings().openAsHidden).to.be.false() + expect(app.getLoginItemSettings().openAtLogin).to.equal(false) + expect(app.getLoginItemSettings().openAsHidden).to.equal(false) app.setLoginItemSettings({ openAtLogin: true, openAsHidden: true }) - expect(app.getLoginItemSettings().openAtLogin).to.be.true() - expect(app.getLoginItemSettings().openAsHidden).to.be.true() + expect(app.getLoginItemSettings().openAtLogin).to.equal(true) + expect(app.getLoginItemSettings().openAsHidden).to.equal(true) app.setLoginItemSettings({ openAtLogin: true, openAsHidden: false }) - expect(app.getLoginItemSettings().openAtLogin).to.be.true() - expect(app.getLoginItemSettings().openAsHidden).to.be.false() + expect(app.getLoginItemSettings().openAtLogin).to.equal(true) + expect(app.getLoginItemSettings().openAsHidden).to.equal(false) }) it('allows you to pass a custom executable and arguments', function () { @@ -647,11 +626,11 @@ describe('app module', () => { app.setLoginItemSettings({ openAtLogin: true, path: updateExe, args: processStartArgs }) - expect(app.getLoginItemSettings().openAtLogin).to.be.false() + expect(app.getLoginItemSettings().openAtLogin).to.equal(false) expect(app.getLoginItemSettings({ path: updateExe, args: processStartArgs - }).openAtLogin).to.be.true() + }).openAtLogin).to.equal(true) }) }) @@ -684,7 +663,7 @@ describe('app module', () => { }) describe('select-client-certificate event', () => { - let w = null + let w: BrowserWindow before(function () { if (process.platform === 'linux') { @@ -702,16 +681,16 @@ describe('app module', () => { }) }) - afterEach(() => closeWindow(w).then(() => { w = null })) + afterEach(() => closeWindow(w).then(() => { w = null as any })) - it('can respond with empty certificate list', done => { - w.webContents.on('did-finish-load', () => { - expect(w.webContents.getTitle()).to.equal('denied') - done() + it('can respond with empty certificate list', async () => { + app.once('select-client-certificate', function (event, webContents, url, list, callback) { + console.log('select-client-certificate emitted') + event.preventDefault() + callback() }) - - ipcRenderer.sendSync('set-client-certificate-option', true) - w.webContents.loadURL(secureUrl) + await w.webContents.loadURL(secureUrl) + expect(w.webContents.getTitle()).to.equal('denied') }) }) @@ -723,8 +702,8 @@ describe('app module', () => { '--process-start-args', `"--hidden"` ] - let Winreg - let classesKey + let Winreg: any + let classesKey: any before(function () { if (process.platform !== 'win32') { @@ -761,34 +740,34 @@ describe('app module', () => { afterEach(() => { app.removeAsDefaultProtocolClient(protocol) - expect(app.isDefaultProtocolClient(protocol)).to.be.false() + expect(app.isDefaultProtocolClient(protocol)).to.equal(false) app.removeAsDefaultProtocolClient(protocol, updateExe, processStartArgs) - expect(app.isDefaultProtocolClient(protocol, updateExe, processStartArgs)).to.be.false() + expect(app.isDefaultProtocolClient(protocol, updateExe, processStartArgs)).to.equal(false) }) it('sets the app as the default protocol client', () => { - expect(app.isDefaultProtocolClient(protocol)).to.be.false() + expect(app.isDefaultProtocolClient(protocol)).to.equal(false) app.setAsDefaultProtocolClient(protocol) - expect(app.isDefaultProtocolClient(protocol)).to.be.true() + expect(app.isDefaultProtocolClient(protocol)).to.equal(true) }) it('allows a custom path and args to be specified', () => { - expect(app.isDefaultProtocolClient(protocol, updateExe, processStartArgs)).to.be.false() + expect(app.isDefaultProtocolClient(protocol, updateExe, processStartArgs)).to.equal(false) app.setAsDefaultProtocolClient(protocol, updateExe, processStartArgs) - expect(app.isDefaultProtocolClient(protocol, updateExe, processStartArgs)).to.be.true() - expect(app.isDefaultProtocolClient(protocol)).to.be.false() + expect(app.isDefaultProtocolClient(protocol, updateExe, processStartArgs)).to.equal(true) + expect(app.isDefaultProtocolClient(protocol)).to.equal(false) }) it('creates a registry entry for the protocol class', (done) => { app.setAsDefaultProtocolClient(protocol) - classesKey.keys((error, keys) => { + classesKey.keys((error: Error, keys: any[]) => { if (error) throw error const exists = !!keys.find(key => key.key.includes(protocol)) - expect(exists).to.be.true() + expect(exists).to.equal(true) done() }) @@ -798,11 +777,11 @@ describe('app module', () => { app.setAsDefaultProtocolClient(protocol) app.removeAsDefaultProtocolClient(protocol) - classesKey.keys((error, keys) => { + classesKey.keys((error: Error, keys: any[]) => { if (error) throw error const exists = !!keys.find(key => key.key.includes(protocol)) - expect(exists).to.be.false() + expect(exists).to.equal(false) done() }) @@ -819,11 +798,11 @@ describe('app module', () => { protocolKey.set('test-value', 'REG_BINARY', '123', () => { app.removeAsDefaultProtocolClient(protocol) - classesKey.keys((error, keys) => { + classesKey.keys((error: Error, keys: any[]) => { if (error) throw error const exists = !!keys.find(key => key.key.includes(protocol)) - expect(exists).to.be.true() + expect(exists).to.equal(true) done() }) @@ -839,9 +818,9 @@ describe('app module', () => { }) it('does not launch for argument following a URL', done => { - const appPath = path.join(__dirname, 'fixtures', 'api', 'quit-app') + const appPath = path.join(fixturesPath, 'api', 'quit-app') // App should exit with non 123 code. - const first = ChildProcess.spawn(remote.process.execPath, [appPath, 'electron-test:?', 'abc']) + const first = cp.spawn(process.execPath, [appPath, 'electron-test:?', 'abc']) first.once('exit', code => { expect(code).to.not.equal(123) done() @@ -849,9 +828,9 @@ describe('app module', () => { }) it('launches successfully for argument following a file path', done => { - const appPath = path.join(__dirname, 'fixtures', 'api', 'quit-app') + const appPath = path.join(fixturesPath, 'api', 'quit-app') // App should exit with code 123. - const first = ChildProcess.spawn(remote.process.execPath, [appPath, 'e:\\abc', 'abc']) + const first = cp.spawn(process.execPath, [appPath, 'e:\\abc', 'abc']) first.once('exit', code => { expect(code).to.equal(123) done() @@ -859,9 +838,9 @@ describe('app module', () => { }) it('launches successfully for multiple URIs following --', done => { - const appPath = path.join(__dirname, 'fixtures', 'api', 'quit-app') + const appPath = path.join(fixturesPath, 'api', 'quit-app') // App should exit with code 123. - const first = ChildProcess.spawn(remote.process.execPath, [appPath, '--', 'http://electronjs.org', 'electron-test://testdata']) + const first = cp.spawn(process.execPath, [appPath, '--', 'http://electronjs.org', 'electron-test://testdata']) first.once('exit', code => { expect(code).to.equal(123) done() @@ -869,7 +848,7 @@ describe('app module', () => { }) }) - describe('getFileIcon() API', (done) => { + describe('getFileIcon() API', () => { const iconPath = path.join(__dirname, 'fixtures/assets/icon.ico') const sizes = { small: 16, @@ -888,13 +867,14 @@ describe('app module', () => { it('fetches a non-empty icon', async () => { const icon = await app.getFileIcon(iconPath) - expect(icon.isEmpty()).to.be.false() + expect(icon.isEmpty()).to.equal(false) }) // TODO(codebytere): remove when promisification is complete it('fetches a non-empty icon (callback)', (done) => { - app.getFileIcon(iconPath, (icon) => { - expect(icon.isEmpty()).to.be.false() + app.getFileIcon(iconPath, (error, icon) => { + expect(error).to.equal(null) + expect(icon.isEmpty()).to.equal(false) done() }) }) @@ -909,7 +889,8 @@ describe('app module', () => { // TODO(codebytere): remove when promisification is complete it('fetches normal icon size by default (callback)', (done) => { - app.getFileIcon(iconPath, (icon) => { + app.getFileIcon(iconPath, (error, icon) => { + expect(error).to.equal(null) const size = icon.getSize() expect(size.height).to.equal(sizes.normal) @@ -937,7 +918,8 @@ describe('app module', () => { // TODO(codebytere): remove when promisification is complete it('fetches a normal icon (callback)', (done) => { - app.getFileIcon(iconPath, { size: 'normal' }, (icon) => { + app.getFileIcon(iconPath, { size: 'normal' }, (error, icon) => { + expect(error).to.equal(null) const size = icon.getSize() expect(size.height).to.equal(sizes.normal) @@ -967,11 +949,11 @@ describe('app module', () => { const types = [] for (const { pid, type, cpu } of appMetrics) { expect(pid).to.be.above(0, 'pid is not > 0') - expect(type).to.be.a('string').that.is.not.empty() + expect(type).to.be.a('string').that.does.not.equal('') types.push(type) - expect(cpu).to.have.own.property('percentCPUUsage').that.is.a('number') - expect(cpu).to.have.own.property('idleWakeupsPerSecond').that.is.a('number') + expect(cpu).to.have.ownProperty('percentCPUUsage').that.is.a('number') + expect(cpu).to.have.ownProperty('idleWakeupsPerSecond').that.is.a('number') } if (process.platform === 'darwin') { @@ -979,23 +961,22 @@ describe('app module', () => { } expect(types).to.include('Browser') - expect(types).to.include('Tab') }) }) describe('getGPUFeatureStatus() API', () => { it('returns the graphic features statuses', () => { const features = app.getGPUFeatureStatus() - expect(features).to.have.own.property('webgl').that.is.a('string') - expect(features).to.have.own.property('gpu_compositing').that.is.a('string') + expect(features).to.have.ownProperty('webgl').that.is.a('string') + expect(features).to.have.ownProperty('gpu_compositing').that.is.a('string') }) }) describe('getGPUInfo() API', () => { - const appPath = path.join(__dirname, 'fixtures', 'api', 'gpu-info.js') + const appPath = path.join(fixturesPath, 'api', 'gpu-info.js') - const getGPUInfo = async (type) => { - const appProcess = ChildProcess.spawn(remote.process.execPath, [appPath, type]) + const getGPUInfo = async (type: string) => { + const appProcess = cp.spawn(process.execPath, [appPath, type]) let gpuInfoData = '' let errorData = '' appProcess.stdout.on('data', (data) => { @@ -1013,11 +994,11 @@ describe('app module', () => { return Promise.reject(new Error(errorData)) } } - const verifyBasicGPUInfo = async (gpuInfo) => { + const verifyBasicGPUInfo = async (gpuInfo: any) => { // Devices information is always present in the available info. - expect(gpuInfo).to.have.own.property('gpuDevice') + expect(gpuInfo).to.have.ownProperty('gpuDevice') .that.is.an('array') - .and.is.not.empty() + .and.does.not.equal([]) const device = gpuInfo.gpuDevice[0] expect(device).to.be.an('object') @@ -1040,11 +1021,11 @@ describe('app module', () => { expect(completeInfo).to.deep.equal(basicInfo) } else { // Gl version is present in the complete info. - expect(completeInfo).to.have.own.property('auxAttributes') + expect(completeInfo).to.have.ownProperty('auxAttributes') .that.is.an('object') - expect(completeInfo.auxAttributes).to.have.own.property('glVersion') + expect(completeInfo.auxAttributes).to.have.ownProperty('glVersion') .that.is.a('string') - .and.not.empty() + .and.does.not.equal([]) } }) @@ -1056,8 +1037,8 @@ describe('app module', () => { }) describe('sandbox options', () => { - let appProcess = null - let server = null + let appProcess: cp.ChildProcess = null as any + let server: net.Server = null as any const socketPath = process.platform === 'win32' ? '\\\\.\\pipe\\electron-mixed-sandbox' : '/tmp/electron-mixed-sandbox' beforeEach(function (done) { @@ -1097,22 +1078,22 @@ describe('app module', () => { describe('when app.enableSandbox() is called', () => { it('adds --enable-sandbox to all renderer processes', done => { - const appPath = path.join(__dirname, 'fixtures', 'api', 'mixed-sandbox-app') - appProcess = ChildProcess.spawn(remote.process.execPath, [appPath, '--app-enable-sandbox']) + const appPath = path.join(fixturesPath, 'api', 'mixed-sandbox-app') + appProcess = cp.spawn(process.execPath, [appPath, '--app-enable-sandbox']) server.once('error', error => { done(error) }) server.on('connection', client => { - client.once('data', data => { - const argv = JSON.parse(data) + client.once('data', (data) => { + const argv = JSON.parse(data.toString()) expect(argv.sandbox).to.include('--enable-sandbox') expect(argv.sandbox).to.not.include('--no-sandbox') expect(argv.noSandbox).to.include('--enable-sandbox') expect(argv.noSandbox).to.not.include('--no-sandbox') - expect(argv.noSandboxDevtools).to.be.true() - expect(argv.sandboxDevtools).to.be.true() + expect(argv.noSandboxDevtools).to.equal(true) + expect(argv.sandboxDevtools).to.equal(true) done() }) @@ -1122,22 +1103,22 @@ describe('app module', () => { describe('when the app is launched with --enable-sandbox', () => { it('adds --enable-sandbox to all renderer processes', done => { - const appPath = path.join(__dirname, 'fixtures', 'api', 'mixed-sandbox-app') - appProcess = ChildProcess.spawn(remote.process.execPath, [appPath, '--enable-sandbox']) + const appPath = path.join(fixturesPath, 'api', 'mixed-sandbox-app') + appProcess = cp.spawn(process.execPath, [appPath, '--enable-sandbox']) server.once('error', error => { done(error) }) server.on('connection', client => { client.once('data', data => { - const argv = JSON.parse(data) + const argv = JSON.parse(data.toString()) expect(argv.sandbox).to.include('--enable-sandbox') expect(argv.sandbox).to.not.include('--no-sandbox') expect(argv.noSandbox).to.include('--enable-sandbox') expect(argv.noSandbox).to.not.include('--no-sandbox') - expect(argv.noSandboxDevtools).to.be.true() - expect(argv.sandboxDevtools).to.be.true() + expect(argv.noSandboxDevtools).to.equal(true) + expect(argv.sandboxDevtools).to.equal(true) done() }) @@ -1156,6 +1137,10 @@ describe('app module', () => { const dockDescribe = process.platform === 'darwin' ? describe : describe.skip dockDescribe('dock APIs', () => { + after(async () => { + await app.dock.show() + }) + describe('dock.setMenu', () => { it('can be retrieved via dock.getMenu', () => { expect(app.dock.getMenu()).to.equal(null) @@ -1173,7 +1158,7 @@ describe('app module', () => { describe('dock.bounce', () => { it('should return -1 for unknown bounce type', () => { - expect(app.dock.bounce('bad type')).to.equal(-1) + expect(app.dock.bounce('bad type' as any)).to.equal(-1) }) it('should return a positive number for informational type', () => { @@ -1223,8 +1208,8 @@ describe('app module', () => { expect(app.dock.show()).to.be.a('promise') }) - it('eventually fulfills', () => { - expect(app.dock.show()).to.be.eventually.fulfilled() + it('eventually fulfills', async () => { + await expect(app.dock.show()).to.eventually.be.fulfilled.equal(undefined) }) }) @@ -1242,31 +1227,31 @@ describe('app module', () => { }) it('becomes fulfilled if the app is already ready', () => { - expect(app.isReady()).to.be.true() - expect(app.whenReady()).to.be.eventually.fulfilled() + expect(app.isReady()).to.equal(true) + expect(app.whenReady()).to.be.eventually.fulfilled.equal(undefined) }) }) describe('commandLine.hasSwitch', () => { it('returns true when present', () => { app.commandLine.appendSwitch('foobar1') - expect(app.commandLine.hasSwitch('foobar1')).to.be.true() + expect(app.commandLine.hasSwitch('foobar1')).to.equal(true) }) it('returns false when not present', () => { - expect(app.commandLine.hasSwitch('foobar2')).to.be.false() + expect(app.commandLine.hasSwitch('foobar2')).to.equal(false) }) }) describe('commandLine.hasSwitch (existing argv)', () => { it('returns true when present', async () => { const { hasSwitch } = await runTestApp('command-line', '--foobar') - expect(hasSwitch).to.be.true() + expect(hasSwitch).to.equal(true) }) it('returns false when not present', async () => { const { hasSwitch } = await runTestApp('command-line') - expect(hasSwitch).to.be.false() + expect(hasSwitch).to.equal(false) }) }) @@ -1335,9 +1320,9 @@ describe('default behavior', () => { }) }) -async function runTestApp (name, ...args) { - const appPath = path.join(__dirname, 'fixtures', 'api', name) - const electronPath = remote.getGlobal('process').execPath +async function runTestApp (name: string, ...args: any[]) { + const appPath = path.join(fixturesPath, 'api', name) + const electronPath = process.execPath const appProcess = cp.spawn(electronPath, [appPath, ...args]) let output = '' diff --git a/spec-main/events-helpers.ts b/spec-main/events-helpers.ts new file mode 100644 index 0000000000..b4e493e101 --- /dev/null +++ b/spec-main/events-helpers.ts @@ -0,0 +1,40 @@ +import { EventEmitter } from "electron"; + +/** + * @fileoverview A set of helper functions to make it easier to work + * with events in async/await manner. + */ + +/** + * @param {!EventTarget} target + * @param {string} eventName + * @return {!Promise} + */ +export const waitForEvent = (target: EventTarget, eventName: string) => { + return new Promise(resolve => { + target.addEventListener(eventName, resolve, { once: true }) + }) +} + +/** + * @param {!EventEmitter} emitter + * @param {string} eventName + * @return {!Promise} With Event as the first item. + */ +export const emittedOnce = (emitter: EventEmitter, eventName: string) => { + return emittedNTimes(emitter, eventName, 1).then(([result]) => result) +} + +export const emittedNTimes = (emitter: EventEmitter, eventName: string, times: number) => { + const events: any[][] = [] + return new Promise(resolve => { + const handler = (...args: any[]) => { + events.push(args) + if (events.length === times) { + emitter.removeListener(eventName, handler) + resolve(events) + } + } + emitter.on(eventName, handler) + }) +} diff --git a/spec-main/index.js b/spec-main/index.js new file mode 100644 index 0000000000..9e5b4f26ae --- /dev/null +++ b/spec-main/index.js @@ -0,0 +1,90 @@ +const Module = require('module') +const path = require('path') +const v8 = require('v8') + +Module.globalPaths.push(path.resolve(__dirname, '../spec/node_modules')) + +// We want to terminate on errors, not throw up a dialog +process.on('uncaughtException', (err) => { + console.error('Unhandled exception in main spec runner:', err) + process.exit(1) +}) + +// Tell ts-node which tsconfig to use +process.env.TS_NODE_PROJECT = path.resolve(__dirname, '../tsconfig.spec.json') + +const { app } = require('electron') + +v8.setFlagsFromString('--expose_gc') +app.commandLine.appendSwitch('js-flags', '--expose_gc') +// Prevent the spec runner quiting when the first window closes +app.on('window-all-closed', () => null) +// TODO: This API should _probably_ only be enabled for the specific test that needs it +// not the entire test suite +app.commandLine.appendSwitch('ignore-certificate-errors') + +app.whenReady().then(() => { + require('ts-node/register') + + const argv = require('yargs') + .boolean('ci') + .string('g').alias('g', 'grep') + .boolean('i').alias('i', 'invert') + .argv + + const isCi = !!argv.ci + global.isCI = isCi + + const Mocha = require('mocha') + const mochaOptions = {} + if (process.env.MOCHA_REPORTER) { + mochaOptions.reporter = process.env.MOCHA_REPORTER + } + if (process.env.MOCHA_MULTI_REPORTERS) { + mochaOptions.reporterOptions = { + reporterEnabled: process.env.MOCHA_MULTI_REPORTERS + } + } + const mocha = new Mocha(mochaOptions) + + if (!process.env.MOCHA_REPORTER) { + mocha.ui('bdd').reporter('tap') + } + mocha.timeout(isCi ? 30000 : 10000) + + if (argv.grep) mocha.grep(argv.grep) + if (argv.invert) mocha.invert() + + // Read all test files. + const walker = require('walkdir').walk(__dirname, { + no_recurse: true + }) + + // This allows you to run specific modules only: + // npm run test -match=menu + const moduleMatch = process.env.npm_config_match + ? new RegExp(process.env.npm_config_match, 'g') + : null + + walker.on('file', (file) => { + if (/-spec\.[tj]s$/.test(file) && + (!moduleMatch || moduleMatch.test(file))) { + mocha.addFile(file) + } + }) + + walker.on('end', () => { + const runner = mocha.run(() => { + if (isCi && runner.hasOnly) { + try { + throw new Error('A spec contains a call to it.only or describe.only and should be reverted.') + } catch (error) { + console.error(error.stack || error) + } + process.exit(1) + } + + process.exit(runner.failures) + }) + }) +}) diff --git a/spec-main/package.json b/spec-main/package.json new file mode 100644 index 0000000000..8a802f6bfd --- /dev/null +++ b/spec-main/package.json @@ -0,0 +1,6 @@ +{ + "name": "electron-test-main", + "productName": "Electron Test Main", + "main": "index.js", + "version": "0.1.0" +} diff --git a/spec-main/window-helpers.ts b/spec-main/window-helpers.ts new file mode 100644 index 0000000000..56345a1bbb --- /dev/null +++ b/spec-main/window-helpers.ts @@ -0,0 +1,26 @@ +import { expect } from 'chai' +import { BrowserWindow, WebContents } from 'electron' +import { emittedOnce } from './events-helpers'; + +export const closeWindow = async ( + window: BrowserWindow | null = null, + { assertNotWindows } = { assertNotWindows: true } +) => { + if (window && !window.isDestroyed()) { + const isClosed = emittedOnce(window, 'closed') + window.setClosable(true) + window.close() + await isClosed + } + + if (assertNotWindows) { + expect(BrowserWindow.getAllWindows()).to.have.lengthOf(0) + } +} + +exports.waitForWebContentsToLoad = async (webContents: WebContents) => { + const didFinishLoadPromise = emittedOnce(webContents, 'did-finish-load') + if (webContents.isLoadingMainFrame()) { + await didFinishLoadPromise + } +} diff --git a/spec/package-lock.json b/spec/package-lock.json index 3ba22e9417..5a35468488 100644 --- a/spec/package-lock.json +++ b/spec/package-lock.json @@ -8,7 +8,6 @@ "version": "github:nornagon/node-abstractsocket#7d9c770f9ffef14373349034f8820ff059879845", "from": "github:nornagon/node-abstractsocket#v8-compat", "dev": true, - "optional": true, "requires": { "bindings": "^1.2.1", "nan": "^2.0.9" @@ -67,7 +66,6 @@ "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.4.0.tgz", "integrity": "sha512-7znEVX22Djn+nYjxCWKDne0RRloa9XfYa84yk3s+HkE3LpDYZmhArYr9O9huBoHY3/oXispx5LorIX7Sl2CgSQ==", "dev": true, - "optional": true, "requires": { "file-uri-to-path": "1.0.0" } @@ -230,7 +228,7 @@ }, "commander": { "version": "2.15.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", + "resolved": "http://registry.npmjs.org/commander/-/commander-2.15.1.tgz", "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", "dev": true }, @@ -243,14 +241,12 @@ "console-control-strings": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", - "optional": true + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" }, "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "optional": true + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, "cross-spawn": { "version": "6.0.5", @@ -285,6 +281,19 @@ "put": "0.0.6", "safe-buffer": "^5.1.1", "xml2js": "^0.4.17" + }, + "dependencies": { + "abstract-socket": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/abstract-socket/-/abstract-socket-2.0.0.tgz", + "integrity": "sha1-2DyT598w0n4j8+gqdj5/XnjZFvk=", + "dev": true, + "optional": true, + "requires": { + "bindings": "^1.2.1", + "nan": "^2.0.9" + } + } } }, "debug": { @@ -364,7 +373,7 @@ }, "duplexer": { "version": "0.1.1", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", + "resolved": "http://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=", "dev": true }, @@ -459,8 +468,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", - "dev": true, - "optional": true + "dev": true }, "find-up": { "version": "3.0.0", @@ -672,8 +680,7 @@ "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "optional": true + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" }, "isexe": { "version": "2.0.0", @@ -778,13 +785,12 @@ }, "minimist": { "version": "1.2.0", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "optional": true + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" }, "mkdirp": { "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", "requires": { "minimist": "0.0.8" @@ -792,7 +798,7 @@ "dependencies": { "minimist": { "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" } } @@ -1043,7 +1049,7 @@ }, "path-is-absolute": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "resolved": "http://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true }, @@ -1061,7 +1067,7 @@ }, "pause-stream": { "version": "0.0.11", - "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", + "resolved": "http://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", "dev": true, "requires": { @@ -1100,8 +1106,7 @@ "process-nextick-args": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", - "optional": true + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" }, "pump": { "version": "2.0.1", @@ -1151,9 +1156,8 @@ }, "readable-stream": { "version": "2.3.6", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "optional": true, "requires": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -1363,7 +1367,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "optional": true, "requires": { "safe-buffer": "~5.1.0" } @@ -1378,7 +1381,7 @@ }, "strip-eof": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "resolved": "http://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", "dev": true }, @@ -1447,7 +1450,7 @@ }, "through": { "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "resolved": "http://registry.npmjs.org/through/-/through-2.3.8.tgz", "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", "dev": true }, @@ -1490,8 +1493,7 @@ "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "optional": true + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, "walkdir": { "version": "0.3.2", @@ -1543,7 +1545,7 @@ }, "wrap-ansi": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "resolved": "http://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", "dev": true, "requires": { diff --git a/tsconfig.spec.json b/tsconfig.spec.json new file mode 100644 index 0000000000..d08253b41f --- /dev/null +++ b/tsconfig.spec.json @@ -0,0 +1,10 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "rootDir": "spec-main" + }, + "include": [ + "spec-main", + "typings" + ] +} diff --git a/typings/internal-ambient.d.ts b/typings/internal-ambient.d.ts index 49886c3dbd..52255f14e5 100644 --- a/typings/internal-ambient.d.ts +++ b/typings/internal-ambient.d.ts @@ -13,6 +13,7 @@ declare namespace NodeJS { interface V8UtilBinding { getHiddenValue(obj: any, key: string): T; setHiddenValue(obj: any, key: string, value: T): void; + requestGarbageCollectionForTesting(): void; } interface Process { /** From 3656d12cba2b94605f6bf593104e5939693f9d8a Mon Sep 17 00:00:00 2001 From: Samuel Attard Date: Sun, 10 Mar 2019 16:24:27 -0700 Subject: [PATCH 02/14] build: auto generate electron.d.ts in the spec runner if it is missing --- script/spec-runner.js | 15 +++++++++++++++ spec/package-lock.json | 20 ++++++++++---------- spec/package.json | 2 +- 3 files changed, 26 insertions(+), 11 deletions(-) diff --git a/script/spec-runner.js b/script/spec-runner.js index 3f7770819c..ac3c27beb6 100755 --- a/script/spec-runner.js +++ b/script/spec-runner.js @@ -33,9 +33,24 @@ async function main () { await getSpecHash().then(saveSpecHash) } + if (!fs.existsSync(path.resolve(__dirname, '../electron.d.ts'))) { + console.log('Generating electron.d.ts as it is missing') + generateTypeDefinitions() + } + await runElectronTests() } +function generateTypeDefinitions () { + const { status } = childProcess.spawnSync('npm', ['run', 'create-typescript-definitions'], { + cwd: path.resolve(__dirname, '..'), + stdio: 'inherit' + }) + if (status !== 0) { + throw new Error(`Electron typescript definition generation failed with exit code: ${status}.`) + } +} + function loadLastSpecHash () { return fs.existsSync(specHashPath) ? fs.readFileSync(specHashPath, 'utf8').split('\n') diff --git a/spec/package-lock.json b/spec/package-lock.json index 5a35468488..a07b78a129 100644 --- a/spec/package-lock.json +++ b/spec/package-lock.json @@ -5,9 +5,9 @@ "requires": true, "dependencies": { "abstract-socket": { - "version": "github:nornagon/node-abstractsocket#7d9c770f9ffef14373349034f8820ff059879845", - "from": "github:nornagon/node-abstractsocket#v8-compat", - "dev": true, + "version": "2.0.0", + "resolved": "github:nornagon/node-abstractsocket#7d9c770f9ffef14373349034f8820ff059879845", + "optional": true, "requires": { "bindings": "^1.2.1", "nan": "^2.0.9" @@ -65,14 +65,14 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.4.0.tgz", "integrity": "sha512-7znEVX22Djn+nYjxCWKDne0RRloa9XfYa84yk3s+HkE3LpDYZmhArYr9O9huBoHY3/oXispx5LorIX7Sl2CgSQ==", - "dev": true, + "optional": true, "requires": { "file-uri-to-path": "1.0.0" } }, "bl": { "version": "1.2.2", - "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz", + "resolved": "http://registry.npmjs.org/bl/-/bl-1.2.2.tgz", "integrity": "sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==", "optional": true, "requires": { @@ -468,7 +468,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", - "dev": true + "optional": true }, "find-up": { "version": "3.0.0", @@ -785,7 +785,7 @@ }, "minimist": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" }, "mkdirp": { @@ -984,7 +984,7 @@ }, "os-homedir": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "resolved": "http://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", "optional": true }, @@ -1156,7 +1156,7 @@ }, "readable-stream": { "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "requires": { "core-util-is": "~1.0.0", @@ -1365,7 +1365,7 @@ }, "string_decoder": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "requires": { "safe-buffer": "~5.1.0" diff --git a/spec/package.json b/spec/package.json index 38f6f32899..fb0ddcaa28 100644 --- a/spec/package.json +++ b/spec/package.json @@ -7,7 +7,6 @@ "postinstall": "node ../tools/run-if-exists.js node_modules/robotjs node-gyp rebuild" }, "devDependencies": { - "abstract-socket": "github:nornagon/node-abstractsocket#v8-compat", "basic-auth": "^2.0.1", "bluebird": "^3.5.3", "chai": "^4.2.0", @@ -33,6 +32,7 @@ "yargs": "^12.0.5" }, "optionalDependencies": { + "abstract-socket": "github:nornagon/node-abstractsocket#v8-compat", "robotjs": "github:nornagon/robotjs#node-12" } } From 2023e32130192ac72e5d7882a53b8b98d0e29da1 Mon Sep 17 00:00:00 2001 From: Samuel Attard Date: Mon, 11 Mar 2019 11:16:46 -0700 Subject: [PATCH 03/14] spec: push electron/spec into the spec runner args before the linux dbus wrapper --- script/spec-runner.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/script/spec-runner.js b/script/spec-runner.js index ac3c27beb6..1869d218d2 100755 --- a/script/spec-runner.js +++ b/script/spec-runner.js @@ -96,13 +96,13 @@ async function runElectronTests () { async function runRemoteBasedElectronTests () { let exe = path.resolve(BASE, utils.getElectronExec()) - const args = process.argv.slice(2).filter(arg => !arg.startsWith('--only=')) + const args = ['electron/spec', ...process.argv.slice(2).filter(arg => !arg.startsWith('--only='))] if (process.platform === 'linux') { args.unshift(path.resolve(__dirname, 'dbus_mock.py'), exe) exe = 'python' } - const { status } = childProcess.spawnSync(exe, ['electron/spec', ...args], { + const { status } = childProcess.spawnSync(exe, args, { cwd: path.resolve(__dirname, '../..'), stdio: 'inherit' }) From b967ae4c511e5cf347e89105838590d8db90c742 Mon Sep 17 00:00:00 2001 From: Samuel Attard Date: Mon, 11 Mar 2019 12:26:53 -0700 Subject: [PATCH 04/14] build: downgrade chai to work around nested adssertion bug --- spec/package-lock.json | 64 ++++++++++++++++++++---------------------- spec/package.json | 2 +- 2 files changed, 32 insertions(+), 34 deletions(-) diff --git a/spec/package-lock.json b/spec/package-lock.json index a07b78a129..3ba22e9417 100644 --- a/spec/package-lock.json +++ b/spec/package-lock.json @@ -5,8 +5,9 @@ "requires": true, "dependencies": { "abstract-socket": { - "version": "2.0.0", - "resolved": "github:nornagon/node-abstractsocket#7d9c770f9ffef14373349034f8820ff059879845", + "version": "github:nornagon/node-abstractsocket#7d9c770f9ffef14373349034f8820ff059879845", + "from": "github:nornagon/node-abstractsocket#v8-compat", + "dev": true, "optional": true, "requires": { "bindings": "^1.2.1", @@ -65,6 +66,7 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.4.0.tgz", "integrity": "sha512-7znEVX22Djn+nYjxCWKDne0RRloa9XfYa84yk3s+HkE3LpDYZmhArYr9O9huBoHY3/oXispx5LorIX7Sl2CgSQ==", + "dev": true, "optional": true, "requires": { "file-uri-to-path": "1.0.0" @@ -72,7 +74,7 @@ }, "bl": { "version": "1.2.2", - "resolved": "http://registry.npmjs.org/bl/-/bl-1.2.2.tgz", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz", "integrity": "sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==", "optional": true, "requires": { @@ -228,7 +230,7 @@ }, "commander": { "version": "2.15.1", - "resolved": "http://registry.npmjs.org/commander/-/commander-2.15.1.tgz", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", "dev": true }, @@ -241,12 +243,14 @@ "console-control-strings": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", + "optional": true }, "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "optional": true }, "cross-spawn": { "version": "6.0.5", @@ -281,19 +285,6 @@ "put": "0.0.6", "safe-buffer": "^5.1.1", "xml2js": "^0.4.17" - }, - "dependencies": { - "abstract-socket": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/abstract-socket/-/abstract-socket-2.0.0.tgz", - "integrity": "sha1-2DyT598w0n4j8+gqdj5/XnjZFvk=", - "dev": true, - "optional": true, - "requires": { - "bindings": "^1.2.1", - "nan": "^2.0.9" - } - } } }, "debug": { @@ -373,7 +364,7 @@ }, "duplexer": { "version": "0.1.1", - "resolved": "http://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=", "dev": true }, @@ -468,6 +459,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "dev": true, "optional": true }, "find-up": { @@ -680,7 +672,8 @@ "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "optional": true }, "isexe": { "version": "2.0.0", @@ -786,11 +779,12 @@ "minimist": { "version": "1.2.0", "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "optional": true }, "mkdirp": { "version": "0.5.1", - "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", "requires": { "minimist": "0.0.8" @@ -798,7 +792,7 @@ "dependencies": { "minimist": { "version": "0.0.8", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" } } @@ -984,7 +978,7 @@ }, "os-homedir": { "version": "1.0.2", - "resolved": "http://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", "optional": true }, @@ -1049,7 +1043,7 @@ }, "path-is-absolute": { "version": "1.0.1", - "resolved": "http://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true }, @@ -1067,7 +1061,7 @@ }, "pause-stream": { "version": "0.0.11", - "resolved": "http://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", + "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", "dev": true, "requires": { @@ -1106,7 +1100,8 @@ "process-nextick-args": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", + "optional": true }, "pump": { "version": "2.0.1", @@ -1158,6 +1153,7 @@ "version": "2.3.6", "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "optional": true, "requires": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -1365,8 +1361,9 @@ }, "string_decoder": { "version": "1.1.1", - "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "optional": true, "requires": { "safe-buffer": "~5.1.0" } @@ -1381,7 +1378,7 @@ }, "strip-eof": { "version": "1.0.0", - "resolved": "http://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", "dev": true }, @@ -1450,7 +1447,7 @@ }, "through": { "version": "2.3.8", - "resolved": "http://registry.npmjs.org/through/-/through-2.3.8.tgz", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", "dev": true }, @@ -1493,7 +1490,8 @@ "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "optional": true }, "walkdir": { "version": "0.3.2", @@ -1545,7 +1543,7 @@ }, "wrap-ansi": { "version": "2.1.0", - "resolved": "http://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", "dev": true, "requires": { diff --git a/spec/package.json b/spec/package.json index fb0ddcaa28..c00ebc0870 100644 --- a/spec/package.json +++ b/spec/package.json @@ -9,7 +9,7 @@ "devDependencies": { "basic-auth": "^2.0.1", "bluebird": "^3.5.3", - "chai": "^4.2.0", + "chai": "~4.1.2", "chai-as-promised": "^7.1.1", "coffee-script": "1.12.7", "dbus-native": "^0.4.0", From 6b65e3523efdd8661ebb5cdc25595b420932ab26 Mon Sep 17 00:00:00 2001 From: Samuel Attard Date: Mon, 11 Mar 2019 16:49:46 -0700 Subject: [PATCH 05/14] wut --- script/spec-runner.js | 2 +- spec/package.json | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/script/spec-runner.js b/script/spec-runner.js index 1869d218d2..5bd89e50aa 100755 --- a/script/spec-runner.js +++ b/script/spec-runner.js @@ -132,7 +132,7 @@ async function installSpecModules () { npm_config_nodedir: nodeDir, npm_config_msvs_version: '2017' }) - const { status } = childProcess.spawnSync(NPM_CMD, ['install'], { + const { status } = childProcess.spawnSync(NPM_CMD, ['ci'], { env, cwd: path.resolve(__dirname, '../spec'), stdio: 'inherit' diff --git a/spec/package.json b/spec/package.json index c00ebc0870..38f6f32899 100644 --- a/spec/package.json +++ b/spec/package.json @@ -7,9 +7,10 @@ "postinstall": "node ../tools/run-if-exists.js node_modules/robotjs node-gyp rebuild" }, "devDependencies": { + "abstract-socket": "github:nornagon/node-abstractsocket#v8-compat", "basic-auth": "^2.0.1", "bluebird": "^3.5.3", - "chai": "~4.1.2", + "chai": "^4.2.0", "chai-as-promised": "^7.1.1", "coffee-script": "1.12.7", "dbus-native": "^0.4.0", @@ -32,7 +33,6 @@ "yargs": "^12.0.5" }, "optionalDependencies": { - "abstract-socket": "github:nornagon/node-abstractsocket#v8-compat", "robotjs": "github:nornagon/robotjs#node-12" } } From a55d1ef3052796a3454dfd1d1076669f232bb695 Mon Sep 17 00:00:00 2001 From: Samuel Attard Date: Mon, 11 Mar 2019 17:07:11 -0700 Subject: [PATCH 06/14] spec: chai is funky --- DEPS | 2 +- spec/package-lock.json | 24 +++++++++++++++++------- spec/package.json | 2 +- spec/static/index.html | 6 ++++++ 4 files changed, 25 insertions(+), 9 deletions(-) diff --git a/DEPS b/DEPS index fc7cde9dac..0403ab4536 100644 --- a/DEPS +++ b/DEPS @@ -107,7 +107,7 @@ hooks = [ 'action': [ 'python', '-c', - 'import os, subprocess; os.chdir(os.path.join("src", "electron")); subprocess.check_call(["python", "script/lib/npm.py", "install"]);', + 'import os, subprocess; os.chdir(os.path.join("src", "electron")); subprocess.check_call(["python", "script/lib/npm.py", "ci"]);', ], }, { diff --git a/spec/package-lock.json b/spec/package-lock.json index 3ba22e9417..331e06744a 100644 --- a/spec/package-lock.json +++ b/spec/package-lock.json @@ -5,9 +5,8 @@ "requires": true, "dependencies": { "abstract-socket": { - "version": "github:nornagon/node-abstractsocket#7d9c770f9ffef14373349034f8820ff059879845", - "from": "github:nornagon/node-abstractsocket#v8-compat", - "dev": true, + "version": "2.0.0", + "resolved": "github:nornagon/node-abstractsocket#7d9c770f9ffef14373349034f8820ff059879845", "optional": true, "requires": { "bindings": "^1.2.1", @@ -66,7 +65,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.4.0.tgz", "integrity": "sha512-7znEVX22Djn+nYjxCWKDne0RRloa9XfYa84yk3s+HkE3LpDYZmhArYr9O9huBoHY3/oXispx5LorIX7Sl2CgSQ==", - "dev": true, "optional": true, "requires": { "file-uri-to-path": "1.0.0" @@ -285,6 +283,19 @@ "put": "0.0.6", "safe-buffer": "^5.1.1", "xml2js": "^0.4.17" + }, + "dependencies": { + "abstract-socket": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/abstract-socket/-/abstract-socket-2.0.0.tgz", + "integrity": "sha1-2DyT598w0n4j8+gqdj5/XnjZFvk=", + "dev": true, + "optional": true, + "requires": { + "bindings": "^1.2.1", + "nan": "^2.0.9" + } + } } }, "debug": { @@ -459,7 +470,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", - "dev": true, "optional": true }, "find-up": { @@ -778,7 +788,7 @@ }, "minimist": { "version": "1.2.0", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "optional": true }, @@ -1151,7 +1161,7 @@ }, "readable-stream": { "version": "2.3.6", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "optional": true, "requires": { diff --git a/spec/package.json b/spec/package.json index 38f6f32899..fb0ddcaa28 100644 --- a/spec/package.json +++ b/spec/package.json @@ -7,7 +7,6 @@ "postinstall": "node ../tools/run-if-exists.js node_modules/robotjs node-gyp rebuild" }, "devDependencies": { - "abstract-socket": "github:nornagon/node-abstractsocket#v8-compat", "basic-auth": "^2.0.1", "bluebird": "^3.5.3", "chai": "^4.2.0", @@ -33,6 +32,7 @@ "yargs": "^12.0.5" }, "optionalDependencies": { + "abstract-socket": "github:nornagon/node-abstractsocket#v8-compat", "robotjs": "github:nornagon/robotjs#node-12" } } diff --git a/spec/static/index.html b/spec/static/index.html index 059495c400..a6e12db00a 100644 --- a/spec/static/index.html +++ b/spec/static/index.html @@ -17,6 +17,12 @@ const electron = require('electron') const { remote, ipcRenderer } = electron + // Set up chai-as-promised here first to avoid conflicts + // It must be loaded first or really strange things happen inside + // chai that cause test failures + // DO NOT MOVE, REMOVE OR EDIT THIS LINE + require('chai').use(require('chai-as-promised')) + // Check if we are running in CI. const isCi = remote.getGlobal('isCi') From 259bc3a918cbaff0f15b1a5fbd16fb92d98b02a7 Mon Sep 17 00:00:00 2001 From: Samuel Attard Date: Mon, 11 Mar 2019 17:09:34 -0700 Subject: [PATCH 07/14] build: remove log from the spec runner --- DEPS | 2 +- script/spec-runner.js | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/DEPS b/DEPS index 0403ab4536..fc7cde9dac 100644 --- a/DEPS +++ b/DEPS @@ -107,7 +107,7 @@ hooks = [ 'action': [ 'python', '-c', - 'import os, subprocess; os.chdir(os.path.join("src", "electron")); subprocess.check_call(["python", "script/lib/npm.py", "ci"]);', + 'import os, subprocess; os.chdir(os.path.join("src", "electron")); subprocess.check_call(["python", "script/lib/npm.py", "install"]);', ], }, { diff --git a/script/spec-runner.js b/script/spec-runner.js index 5bd89e50aa..5c98559c15 100755 --- a/script/spec-runner.js +++ b/script/spec-runner.js @@ -115,8 +115,6 @@ async function runMainProcessElectronTests () { const exe = path.resolve(BASE, utils.getElectronExec()) const args = process.argv.slice(2).filter(arg => !arg.startsWith('--only=')) - console.log(exe, args) - const { status } = childProcess.spawnSync(exe, ['electron/spec-main', ...args], { cwd: path.resolve(__dirname, '../..'), stdio: 'inherit' @@ -132,7 +130,7 @@ async function installSpecModules () { npm_config_nodedir: nodeDir, npm_config_msvs_version: '2017' }) - const { status } = childProcess.spawnSync(NPM_CMD, ['ci'], { + const { status } = childProcess.spawnSync(NPM_CMD, ['install'], { env, cwd: path.resolve(__dirname, '../spec'), stdio: 'inherit' From 46e5767527f81a19321d42c22a6cdae2176bf4ac Mon Sep 17 00:00:00 2001 From: Samuel Attard Date: Wed, 13 Mar 2019 15:09:28 -0700 Subject: [PATCH 08/14] update for PR feedback --- script/spec-runner.js | 17 ++++++++-------- spec-main/api-app-spec.ts | 10 ++++----- spec/events-helpers.js | 43 ++------------------------------------- spec/package-lock.json | 20 ++++++------------ 4 files changed, 22 insertions(+), 68 deletions(-) diff --git a/script/spec-runner.js b/script/spec-runner.js index 5c98559c15..eb6407d409 100755 --- a/script/spec-runner.js +++ b/script/spec-runner.js @@ -5,6 +5,9 @@ const crypto = require('crypto') const fs = require('fs') const { hashElement } = require('folder-hash') const path = require('path') +const args = require('minimist')(process.argv, { + string: ['only'] +}) const utils = require('./lib/utils') @@ -14,9 +17,8 @@ const NPM_CMD = process.platform === 'win32' ? 'npm.cmd' : 'npm' const specHashPath = path.resolve(__dirname, '../spec/.hash') let only = null -const onlyArg = process.argv.find(arg => arg.startsWith('--only=')) -if (onlyArg) { - only = onlyArg.substr(7).split(',') +if (args.only) { + only = args.only.split(',') console.log('Only running:', only) } else { console.log('Will trigger all spec runners') @@ -96,13 +98,13 @@ async function runElectronTests () { async function runRemoteBasedElectronTests () { let exe = path.resolve(BASE, utils.getElectronExec()) - const args = ['electron/spec', ...process.argv.slice(2).filter(arg => !arg.startsWith('--only='))] + const runnerArgs = ['electron/spec', ...args._] if (process.platform === 'linux') { - args.unshift(path.resolve(__dirname, 'dbus_mock.py'), exe) + runnerArgs.unshift(path.resolve(__dirname, 'dbus_mock.py'), exe) exe = 'python' } - const { status } = childProcess.spawnSync(exe, args, { + const { status } = childProcess.spawnSync(exe, runnerArgs, { cwd: path.resolve(__dirname, '../..'), stdio: 'inherit' }) @@ -113,9 +115,8 @@ async function runRemoteBasedElectronTests () { async function runMainProcessElectronTests () { const exe = path.resolve(BASE, utils.getElectronExec()) - const args = process.argv.slice(2).filter(arg => !arg.startsWith('--only=')) - const { status } = childProcess.spawnSync(exe, ['electron/spec-main', ...args], { + const { status } = childProcess.spawnSync(exe, ['electron/spec-main', ...args._], { cwd: path.resolve(__dirname, '../..'), stdio: 'inherit' }) diff --git a/spec-main/api-app-spec.ts b/spec-main/api-app-spec.ts index c89d9c95cd..180464cdea 100644 --- a/spec-main/api-app-spec.ts +++ b/spec-main/api-app-spec.ts @@ -209,7 +209,7 @@ describe('app module', () => { it('passes arguments to the second-instance event', async () => { const appPath = path.join(__dirname, 'fixtures', 'api', 'singleton') - const first = ChildProcess.spawn(remote.process.execPath, [appPath]) + const first = cp.spawn(process.execPath, [appPath]) const firstExited = emittedOnce(first, 'exit') // Wait for the first app to boot. @@ -219,16 +219,16 @@ describe('app module', () => { } const data2Promise = emittedOnce(firstStdoutLines, 'data') - const secondInstanceArgs = [remote.process.execPath, appPath, '--some-switch', 'some-arg'] - const second = ChildProcess.spawn(secondInstanceArgs[0], secondInstanceArgs.slice(1)) + const secondInstanceArgs = [process.execPath, appPath, '--some-switch', 'some-arg'] + const second = cp.spawn(secondInstanceArgs[0], secondInstanceArgs.slice(1)) const [code2] = await emittedOnce(second, 'exit') expect(code2).to.equal(1) const [code1] = await firstExited expect(code1).to.equal(0) - const data2 = (await data2Promise).toString('ascii') + const data2 = (await data2Promise)[0].toString('ascii') const secondInstanceArgsReceived = JSON.parse(data2.toString('ascii')) const expected = process.platform === 'win32' - ? [remote.process.execPath, '--some-switch', '--allow-file-access-from-files', secondInstanceArgsReceived.find(x => x.includes('original-process-start-time')), appPath, 'some-arg'] + ? [process.execPath, '--some-switch', '--allow-file-access-from-files', secondInstanceArgsReceived.find(x => x.includes('original-process-start-time')), appPath, 'some-arg'] : secondInstanceArgs expect(secondInstanceArgsReceived).to.eql(expected, `expected ${JSON.stringify(expected)} but got ${data2.toString('ascii')}`) diff --git a/spec/events-helpers.js b/spec/events-helpers.js index 64a4fba447..4bcbdcabb1 100644 --- a/spec/events-helpers.js +++ b/spec/events-helpers.js @@ -1,42 +1,3 @@ -/** - * @fileoverview A set of helper functions to make it easier to work - * with events in async/await manner. - */ +require('ts-node/register') -/** - * @param {!EventTarget} target - * @param {string} eventName - * @return {!Promise} - */ -const waitForEvent = (target, eventName) => { - return new Promise(resolve => { - target.addEventListener(eventName, resolve, { once: true }) - }) -} - -/** - * @param {!EventEmitter} emitter - * @param {string} eventName - * @return {!Promise} With Event as the first item. - */ -const emittedOnce = (emitter, eventName) => { - return emittedNTimes(emitter, eventName, 1).then(([result]) => result) -} - -const emittedNTimes = (emitter, eventName, times) => { - const events = [] - return new Promise(resolve => { - const handler = (...args) => { - events.push(args) - if (events.length === times) { - emitter.removeListener(eventName, handler) - resolve(events) - } - } - emitter.on(eventName, handler) - }) -} - -exports.emittedOnce = emittedOnce -exports.emittedNTimes = emittedNTimes -exports.waitForEvent = waitForEvent +module.exports = require('../spec-main/window-helpers') diff --git a/spec/package-lock.json b/spec/package-lock.json index 331e06744a..5f7208c3ad 100644 --- a/spec/package-lock.json +++ b/spec/package-lock.json @@ -241,14 +241,12 @@ "console-control-strings": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", - "optional": true + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" }, "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "optional": true + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, "cross-spawn": { "version": "6.0.5", @@ -682,8 +680,7 @@ "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "optional": true + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" }, "isexe": { "version": "2.0.0", @@ -789,8 +786,7 @@ "minimist": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "optional": true + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" }, "mkdirp": { "version": "0.5.1", @@ -1110,8 +1106,7 @@ "process-nextick-args": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", - "optional": true + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" }, "pump": { "version": "2.0.1", @@ -1163,7 +1158,6 @@ "version": "2.3.6", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "optional": true, "requires": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -1373,7 +1367,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "optional": true, "requires": { "safe-buffer": "~5.1.0" } @@ -1500,8 +1493,7 @@ "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "optional": true + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, "walkdir": { "version": "0.3.2", From be60f93bd02255022012b25e4731cf5deba0e9c9 Mon Sep 17 00:00:00 2001 From: Samuel Attard Date: Thu, 14 Mar 2019 13:39:53 -0700 Subject: [PATCH 09/14] fix: we can not use ts-node apaprently --- script/spec-runner.js | 4 ++-- spec/events-helpers.js | 43 ++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 43 insertions(+), 4 deletions(-) diff --git a/script/spec-runner.js b/script/spec-runner.js index eb6407d409..d7d9b8cbfc 100755 --- a/script/spec-runner.js +++ b/script/spec-runner.js @@ -98,7 +98,7 @@ async function runElectronTests () { async function runRemoteBasedElectronTests () { let exe = path.resolve(BASE, utils.getElectronExec()) - const runnerArgs = ['electron/spec', ...args._] + const runnerArgs = ['electron/spec', ...args._.slice(2)] if (process.platform === 'linux') { runnerArgs.unshift(path.resolve(__dirname, 'dbus_mock.py'), exe) exe = 'python' @@ -116,7 +116,7 @@ async function runRemoteBasedElectronTests () { async function runMainProcessElectronTests () { const exe = path.resolve(BASE, utils.getElectronExec()) - const { status } = childProcess.spawnSync(exe, ['electron/spec-main', ...args._], { + const { status } = childProcess.spawnSync(exe, ['electron/spec-main', ...args._.slice(2)], { cwd: path.resolve(__dirname, '../..'), stdio: 'inherit' }) diff --git a/spec/events-helpers.js b/spec/events-helpers.js index 4bcbdcabb1..64a4fba447 100644 --- a/spec/events-helpers.js +++ b/spec/events-helpers.js @@ -1,3 +1,42 @@ -require('ts-node/register') +/** + * @fileoverview A set of helper functions to make it easier to work + * with events in async/await manner. + */ -module.exports = require('../spec-main/window-helpers') +/** + * @param {!EventTarget} target + * @param {string} eventName + * @return {!Promise} + */ +const waitForEvent = (target, eventName) => { + return new Promise(resolve => { + target.addEventListener(eventName, resolve, { once: true }) + }) +} + +/** + * @param {!EventEmitter} emitter + * @param {string} eventName + * @return {!Promise} With Event as the first item. + */ +const emittedOnce = (emitter, eventName) => { + return emittedNTimes(emitter, eventName, 1).then(([result]) => result) +} + +const emittedNTimes = (emitter, eventName, times) => { + const events = [] + return new Promise(resolve => { + const handler = (...args) => { + events.push(args) + if (events.length === times) { + emitter.removeListener(eventName, handler) + resolve(events) + } + } + emitter.on(eventName, handler) + }) +} + +exports.emittedOnce = emittedOnce +exports.emittedNTimes = emittedNTimes +exports.waitForEvent = waitForEvent From df57ac4ce737a6053500de153f3a16470688d5fc Mon Sep 17 00:00:00 2001 From: Samuel Attard Date: Thu, 14 Mar 2019 15:23:21 -0700 Subject: [PATCH 10/14] chore: steal all unknown args for use by the spec runners --- script/spec-runner.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/script/spec-runner.js b/script/spec-runner.js index d7d9b8cbfc..3785252182 100755 --- a/script/spec-runner.js +++ b/script/spec-runner.js @@ -5,8 +5,11 @@ const crypto = require('crypto') const fs = require('fs') const { hashElement } = require('folder-hash') const path = require('path') +const unknownArgs = [] + const args = require('minimist')(process.argv, { - string: ['only'] + string: ['only'], + unknown: arg => unknownArgs.push(arg) }) const utils = require('./lib/utils') @@ -98,7 +101,7 @@ async function runElectronTests () { async function runRemoteBasedElectronTests () { let exe = path.resolve(BASE, utils.getElectronExec()) - const runnerArgs = ['electron/spec', ...args._.slice(2)] + const runnerArgs = ['electron/spec', unknownArgs.slice(2)] if (process.platform === 'linux') { runnerArgs.unshift(path.resolve(__dirname, 'dbus_mock.py'), exe) exe = 'python' @@ -116,7 +119,7 @@ async function runRemoteBasedElectronTests () { async function runMainProcessElectronTests () { const exe = path.resolve(BASE, utils.getElectronExec()) - const { status } = childProcess.spawnSync(exe, ['electron/spec-main', ...args._.slice(2)], { + const { status } = childProcess.spawnSync(exe, ['electron/spec-main', ...unknownArgs.slice(2)], { cwd: path.resolve(__dirname, '../..'), stdio: 'inherit' }) From 6b326f792477e7ec9970a36dc459787324b4d5dc Mon Sep 17 00:00:00 2001 From: Samuel Attard Date: Thu, 14 Mar 2019 16:15:23 -0700 Subject: [PATCH 11/14] build: spread runner args onto the runner --- script/spec-runner.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/spec-runner.js b/script/spec-runner.js index 3785252182..a1b4fe185e 100755 --- a/script/spec-runner.js +++ b/script/spec-runner.js @@ -101,7 +101,7 @@ async function runElectronTests () { async function runRemoteBasedElectronTests () { let exe = path.resolve(BASE, utils.getElectronExec()) - const runnerArgs = ['electron/spec', unknownArgs.slice(2)] + const runnerArgs = ['electron/spec', ...unknownArgs.slice(2)] if (process.platform === 'linux') { runnerArgs.unshift(path.resolve(__dirname, 'dbus_mock.py'), exe) exe = 'python' From 4b6b59cc8254171e45e6655771fe3b37ebfce96d Mon Sep 17 00:00:00 2001 From: Samuel Attard Date: Thu, 14 Mar 2019 17:22:42 -0700 Subject: [PATCH 12/14] chore: update PR as per feedback --- script/spec-runner.js | 12 ++++++------ spec-main/api-app-spec.ts | 8 ++++---- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/script/spec-runner.js b/script/spec-runner.js index a1b4fe185e..139a3d5557 100755 --- a/script/spec-runner.js +++ b/script/spec-runner.js @@ -8,7 +8,7 @@ const path = require('path') const unknownArgs = [] const args = require('minimist')(process.argv, { - string: ['only'], + string: ['runners'], unknown: arg => unknownArgs.push(arg) }) @@ -19,10 +19,10 @@ const NPM_CMD = process.platform === 'win32' ? 'npm.cmd' : 'npm' const specHashPath = path.resolve(__dirname, '../spec/.hash') -let only = null -if (args.only) { - only = args.only.split(',') - console.log('Only running:', only) +let runnersToRun = null +if (args.runners) { + runnersToRun = args.only.split(',') + console.log('Only running:', runnersToRun) } else { console.log('Will trigger all spec runners') } @@ -75,7 +75,7 @@ async function runElectronTests () { const mochaFile = process.env.MOCHA_FILE for (const runner of runners) { - if (only && !only.includes(runner[1])) { + if (runnersToRun && !runnersToRun.includes(runner[1])) { console.info('\nSkipping:', runner[0]) continue } diff --git a/spec-main/api-app-spec.ts b/spec-main/api-app-spec.ts index 180464cdea..7cbb24f1d8 100644 --- a/spec-main/api-app-spec.ts +++ b/spec-main/api-app-spec.ts @@ -119,7 +119,7 @@ describe('app module', () => { describe('app.isPackaged', () => { it('should be false durings tests', () => { - expect(app.isPackaged).equal(false) + expect(app.isPackaged).to.equal(false) }) }) @@ -180,7 +180,7 @@ describe('app module', () => { // Singleton will send us greeting data to let us know it's running. // After that, ask it to exit gracefully and confirm that it does. - appProcess.stdout.on('data', data => appProcess && appProcess.kill()) + appProcess.stdout.on('data', data => appProcess!.kill()) const [code, signal] = await emittedOnce(appProcess, 'close') const message = `code:\n${code}\nsignal:\n${signal}` @@ -1226,9 +1226,9 @@ describe('app module', () => { expect(app.whenReady()).to.be.a('promise') }) - it('becomes fulfilled if the app is already ready', () => { + it('becomes fulfilled if the app is already ready', async () => { expect(app.isReady()).to.equal(true) - expect(app.whenReady()).to.be.eventually.fulfilled.equal(undefined) + await expect(app.whenReady()).to.be.eventually.fulfilled.equal(undefined) }) }) From 984e77e470bb49514613bf574c64f374de1c57e6 Mon Sep 17 00:00:00 2001 From: Samuel Attard Date: Fri, 15 Mar 2019 10:57:12 -0700 Subject: [PATCH 13/14] fix: spec runner not parsing correctly --- script/spec-runner.js | 2 +- spec-main/api-app-spec.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/script/spec-runner.js b/script/spec-runner.js index 139a3d5557..50af2359c8 100755 --- a/script/spec-runner.js +++ b/script/spec-runner.js @@ -21,7 +21,7 @@ const specHashPath = path.resolve(__dirname, '../spec/.hash') let runnersToRun = null if (args.runners) { - runnersToRun = args.only.split(',') + runnersToRun = args.runners.split(',') console.log('Only running:', runnersToRun) } else { console.log('Will trigger all spec runners') diff --git a/spec-main/api-app-spec.ts b/spec-main/api-app-spec.ts index 7cbb24f1d8..02b55ad5c2 100644 --- a/spec-main/api-app-spec.ts +++ b/spec-main/api-app-spec.ts @@ -226,7 +226,7 @@ describe('app module', () => { const [code1] = await firstExited expect(code1).to.equal(0) const data2 = (await data2Promise)[0].toString('ascii') - const secondInstanceArgsReceived = JSON.parse(data2.toString('ascii')) + const secondInstanceArgsReceived: string[] = JSON.parse(data2.toString('ascii')) const expected = process.platform === 'win32' ? [process.execPath, '--some-switch', '--allow-file-access-from-files', secondInstanceArgsReceived.find(x => x.includes('original-process-start-time')), appPath, 'some-arg'] : secondInstanceArgs From b502c62111068b7c8bb4ba0b66fc605474d0dca0 Mon Sep 17 00:00:00 2001 From: Samuel Attard Date: Fri, 15 Mar 2019 12:29:25 -0700 Subject: [PATCH 14/14] spec: fix fixtures path for second instance test --- spec-main/api-app-spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec-main/api-app-spec.ts b/spec-main/api-app-spec.ts index 02b55ad5c2..710ec7ae86 100644 --- a/spec-main/api-app-spec.ts +++ b/spec-main/api-app-spec.ts @@ -208,7 +208,7 @@ describe('app module', () => { }) it('passes arguments to the second-instance event', async () => { - const appPath = path.join(__dirname, 'fixtures', 'api', 'singleton') + const appPath = path.join(fixturesPath, 'api', 'singleton') const first = cp.spawn(process.execPath, [appPath]) const firstExited = emittedOnce(first, 'exit')