From a4d0bf2e3a21dc20104f04784792466eeed3beee Mon Sep 17 00:00:00 2001 From: Andrew Stanton-Nurse Date: Thu, 29 Mar 2018 10:11:18 -0700 Subject: [PATCH] collect log messages during browser tests (#1670) --- build/repo.targets | 2 +- clients/ts/FunctionalTests/package-lock.json | 437 ++---------------- clients/ts/FunctionalTests/package.json | 3 +- .../FunctionalTests/selenium/run-ci-tests.ts | 28 +- .../ts/FunctionalTests/selenium/run-tests.ts | 18 +- .../ts/FunctionalTests/ts/ConnectionTests.ts | 5 +- .../FunctionalTests/ts/HubConnectionTests.ts | 37 +- clients/ts/FunctionalTests/ts/TestLogger.ts | 17 + .../FunctionalTests/ts/WebDriverReporter.ts | 44 +- 9 files changed, 146 insertions(+), 445 deletions(-) create mode 100644 clients/ts/FunctionalTests/ts/TestLogger.ts diff --git a/build/repo.targets b/build/repo.targets index 954b78e7b4ad..dbad646118b4 100644 --- a/build/repo.targets +++ b/build/repo.targets @@ -33,7 +33,7 @@ - + diff --git a/clients/ts/FunctionalTests/package-lock.json b/clients/ts/FunctionalTests/package-lock.json index ed6372b19379..d0a0e4e235f2 100644 --- a/clients/ts/FunctionalTests/package-lock.json +++ b/clients/ts/FunctionalTests/package-lock.json @@ -4,12 +4,6 @@ "lockfileVersion": 1, "requires": true, "dependencies": { - "@std/esm": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/@std/esm/-/esm-0.18.0.tgz", - "integrity": "sha512-oeHSSVp/WxC08ngpKgyYR4LcI0+EBwZiJcB58jvIqyJnOGxudSkxTgAQKsVfpNsMXfOoILgu9PWhuzIZ8GQEjw==", - "dev": true - }, "@types/debug": { "version": "0.0.30", "resolved": "https://registry.npmjs.org/@types/debug/-/debug-0.0.30.tgz", @@ -43,18 +37,21 @@ "color-convert": "1.9.1" } }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "1.0.3" + } + }, "arrify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", "dev": true }, - "buffer-shims": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz", - "integrity": "sha1-mXjOMXOIxkmth5MCjDR37wRKi1E=", - "dev": true - }, "chalk": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", @@ -81,12 +78,6 @@ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", "dev": 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=", - "dev": true - }, "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", @@ -102,12 +93,6 @@ "integrity": "sha512-QpVuMTEoJMF7cKzi6bvWhRulU1fZqZnvyVQgNhPaxxuTYwyjn/j1v9falseQ/uXWwPnO56RBfwtg4h/EQXmucA==", "dev": true }, - "duplexer": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", - "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=", - "dev": true - }, "es6-promise": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.2.tgz", @@ -120,32 +105,17 @@ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", "dev": true }, - "figures": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", - "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", - "dev": true, - "requires": { - "escape-string-regexp": "1.0.5", - "object-assign": "4.1.1" - } + "esprima": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", + "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==", + "dev": true }, - "has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "dev": true, - "requires": { - "ansi-regex": "2.1.1" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - } - } + "events-to-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/events-to-array/-/events-to-array-1.1.2.tgz", + "integrity": "sha1-LUH1Y+H+QA7Uli/hpNXGp1Od9/Y=", + "dev": true }, "has-flag": { "version": "2.0.0", @@ -162,33 +132,16 @@ "parse-passwd": "1.0.0" } }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true - }, - "is-finite": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", - "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", + "js-yaml": { + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.11.0.tgz", + "integrity": "sha512-saJstZWv7oNeOyBh3+Dx1qWzhW0+e6/8eDzo7p5rDFqxntSztloLtuKu+Ejhtq82jsilwOIZYsCz+lIjthg1Hw==", "dev": true, "requires": { - "number-is-nan": "1.0.1" + "argparse": "1.0.10", + "esprima": "4.0.0" } }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "lodash": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", - "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=", - "dev": true - }, "make-error": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.3.tgz", @@ -201,6 +154,16 @@ "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true }, + "minipass": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.2.4.tgz", + "integrity": "sha512-hzXIWWet/BzWhYs2b+u7dRHlruXhwdgvlTMDKC6Cb1U7ps6Ac6yQlR39xsbjWJE377YTCtKwIXIpJ5oP+j5y8g==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1", + "yallist": "3.0.2" + } + }, "mkdirp": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", @@ -224,79 +187,12 @@ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true - }, - "parse-ms": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-1.0.1.tgz", - "integrity": "sha1-VjRtR0nXjyNDDKDHE4UK75GqNh0=", - "dev": true - }, "parse-passwd": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", "dev": true }, - "plur": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/plur/-/plur-1.0.0.tgz", - "integrity": "sha1-24XGgU9eXlo7Se/CjWBP7GKXUVY=", - "dev": true - }, - "pretty-ms": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-2.1.0.tgz", - "integrity": "sha1-QlfCVt8/sLRR1q/6qwIYhBJpgdw=", - "dev": true, - "requires": { - "is-finite": "1.0.2", - "parse-ms": "1.0.1", - "plur": "1.0.0" - } - }, - "process-nextick-args": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", - "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", - "dev": true - }, - "re-emitter": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/re-emitter/-/re-emitter-1.1.3.tgz", - "integrity": "sha1-+p4xn/3u6zWycpbvDz03TawvUqc=", - "dev": true - }, - "readable-stream": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", - "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "string_decoder": "0.10.31", - "util-deprecate": "1.0.2" - } - }, - "repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", - "dev": true - }, "safe-buffer": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", @@ -318,19 +214,10 @@ "source-map": "0.6.1" } }, - "split": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", - "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", - "dev": true, - "requires": { - "through": "2.3.8" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", "dev": true }, "strip-bom": { @@ -354,179 +241,15 @@ "has-flag": "2.0.0" } }, - "tap-out": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/tap-out/-/tap-out-1.4.2.tgz", - "integrity": "sha1-yQfsG/lAURHQiCY+kvVgi4jLs3o=", - "dev": true, - "requires": { - "re-emitter": "1.1.3", - "readable-stream": "2.0.6", - "split": "1.0.1", - "trim": "0.0.1" - } - }, - "tap-spec": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/tap-spec/-/tap-spec-4.1.1.tgz", - "integrity": "sha1-4unyb1IIIysfViKIyXYk1YqI8Fo=", - "dev": true, - "requires": { - "chalk": "1.1.3", - "duplexer": "0.1.1", - "figures": "1.7.0", - "lodash": "3.10.1", - "pretty-ms": "2.1.0", - "repeat-string": "1.6.1", - "tap-out": "1.4.2", - "through2": "2.0.3" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "2.2.1", - "escape-string-regexp": "1.0.5", - "has-ansi": "2.0.0", - "strip-ansi": "3.0.1", - "supports-color": "2.0.0" - } - }, - "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==", - "dev": true - }, - "readable-stream": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz", - "integrity": "sha512-vuYxeWYM+fde14+rajzqgeohAI7YoJcHE7kXDAc4Nk0EbuKnJfqtY9YtRkLo/tqkuF7MsBQRhPnPeyjYITp3ZQ==", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "2.0.0", - "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", - "util-deprecate": "1.0.2" - } - }, - "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", - "dev": true, - "requires": { - "safe-buffer": "5.1.1" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "2.1.1" - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - }, - "through2": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", - "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", - "dev": true, - "requires": { - "readable-stream": "2.3.4", - "xtend": "4.0.1" - } - }, - "xtend": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", - "dev": true - } - } - }, - "tap-teamcity": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/tap-teamcity/-/tap-teamcity-3.0.2.tgz", - "integrity": "sha512-FI26a4CGNx9LWx2vRh3fLNrel1GJm5smBVJl2tzabTwGrmX9d+KHWP2O9xdKgMtH5IOBpN6goy9Yh4P2NRaoQw==", + "tap-parser": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/tap-parser/-/tap-parser-7.0.0.tgz", + "integrity": "sha512-05G8/LrzqOOFvZhhAk32wsGiPZ1lfUrl+iV7+OkKgfofZxiceZWMHkKmow71YsyVQ8IvGBP2EjcIjE5gL4l5lA==", "dev": true, "requires": { - "@std/esm": "0.18.0", - "duplexer": "0.1.1", - "tap-out": "2.0.0", - "through2": "2.0.3" - }, - "dependencies": { - "readable-stream": { - "version": "2.2.9", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.9.tgz", - "integrity": "sha1-z3jsb0ptHrQ9JkiMrJfwQudLf8g=", - "dev": true, - "requires": { - "buffer-shims": "1.0.0", - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "string_decoder": "1.0.3", - "util-deprecate": "1.0.2" - } - }, - "split": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/split/-/split-1.0.0.tgz", - "integrity": "sha1-xDlc5oOrzSVLwo/h2rtuXCfc/64=", - "dev": true, - "requires": { - "through": "2.3.8" - } - }, - "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", - "dev": true, - "requires": { - "safe-buffer": "5.1.1" - } - }, - "tap-out": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/tap-out/-/tap-out-2.0.0.tgz", - "integrity": "sha1-4pCSskjFzYme3jSCIZAHl6aLmNI=", - "dev": true, - "requires": { - "re-emitter": "1.1.3", - "readable-stream": "2.2.9", - "split": "1.0.0", - "trim": "0.0.1" - } - } + "events-to-array": "1.1.2", + "js-yaml": "3.11.0", + "minipass": "2.2.4" } }, "tee": { @@ -546,60 +269,6 @@ } } }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", - "dev": true - }, - "through2": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", - "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", - "dev": true, - "requires": { - "readable-stream": "2.3.4", - "xtend": "4.0.1" - }, - "dependencies": { - "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==", - "dev": true - }, - "readable-stream": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz", - "integrity": "sha512-vuYxeWYM+fde14+rajzqgeohAI7YoJcHE7kXDAc4Nk0EbuKnJfqtY9YtRkLo/tqkuF7MsBQRhPnPeyjYITp3ZQ==", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "2.0.0", - "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", - "util-deprecate": "1.0.2" - } - }, - "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", - "dev": true, - "requires": { - "safe-buffer": "5.1.1" - } - } - } - }, - "trim": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", - "integrity": "sha1-WFhUf2spB1fulczMZm+1AITEYN0=", - "dev": true - }, "ts-node": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-4.1.0.tgz", @@ -630,12 +299,6 @@ "strip-json-comments": "2.0.1" } }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true - }, "v8flags": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.0.1.tgz", @@ -645,10 +308,10 @@ "homedir-polyfill": "1.0.1" } }, - "xtend": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "yallist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.2.tgz", + "integrity": "sha1-hFK0u36Dx8GI2AQcGoN8dz1ti7k=", "dev": true }, "yn": { diff --git a/clients/ts/FunctionalTests/package.json b/clients/ts/FunctionalTests/package.json index 2d9d1ade72b7..6ed723020eb3 100644 --- a/clients/ts/FunctionalTests/package.json +++ b/clients/ts/FunctionalTests/package.json @@ -10,8 +10,7 @@ "@types/node": "^9.4.6", "debug": "^3.1.0", "es6-promise": "^4.2.2", - "tap-spec": "^4.1.1", - "tap-teamcity": "^3.0.2", + "tap-parser": "^7.0.0", "tee": "^0.2.0", "ts-node": "^4.1.0" }, diff --git a/clients/ts/FunctionalTests/selenium/run-ci-tests.ts b/clients/ts/FunctionalTests/selenium/run-ci-tests.ts index dd71ddadb338..183c388384db 100644 --- a/clients/ts/FunctionalTests/selenium/run-ci-tests.ts +++ b/clients/ts/FunctionalTests/selenium/run-ci-tests.ts @@ -2,9 +2,6 @@ import { ChildProcess, spawn, spawnSync } from "child_process"; import { existsSync } from "fs"; import * as path from "path"; -import * as tapTeamCity from "tap-teamcity"; -import * as tee from "tee"; - const teamcity = !!process.env.TEAMCITY_VERSION; let force = process.env.ASPNETCORE_SIGNALR_FORCE_BROWSER_TESTS === "true"; @@ -56,7 +53,11 @@ function getChromeBinaryPath(): string { switch (process.platform) { case "win32": // tslint:disable-next-line:no-string-literal - return path.resolve(process.env.LOCALAPPDATA, "Google", "Chrome", "Application", "chrome.exe"); + let candidatePath = path.resolve(process.env["ProgramFiles(x86)"], "Google", "Chrome", "Application", "chrome.exe"); + if (!existsSync(candidatePath)) { + candidatePath = path.resolve(process.env.LOCALAPPDATA, "Google", "Chrome", "Application", "chrome.exe"); + } + return candidatePath; case "darwin": return path.resolve("/", "Applications", "Google Chrome.app", "Contents", "MacOS", "Google Chrome"); case "linux": @@ -83,11 +84,22 @@ if (verbose) { args.push("--verbose"); } -const testProcess = spawn("npm", args, { cwd: path.resolve(__dirname, "..") }); -testProcess.stderr.pipe(process.stderr); -if (teamcity) { - testProcess.stdout.pipe(tapTeamCity()).pipe(process.stdout); +let command = "npm"; + +if (process.platform === "win32") { + // NPM is a cmd file, and it's tricky to "spawn". Instead, we'll find the NPM js file and use process.execPath to locate node.exe and run it directly + const npmPath = path.resolve(process.execPath, "..", "node_modules", "npm", "bin", "npm-cli.js"); + if (!existsSync(npmPath)) { + failPrereq(`Unable to locate npm command line at '${npmPath}'`); + } + + args.unshift(npmPath); + command = process.execPath; } +console.log(`running: ${command} ${args.join(" ")}`); + +const testProcess = spawn(command, args, { cwd: path.resolve(__dirname, "..") }); +testProcess.stderr.pipe(process.stderr); testProcess.stdout.pipe(process.stdout); testProcess.on("close", (code) => process.exit(code)); \ No newline at end of file diff --git a/clients/ts/FunctionalTests/selenium/run-tests.ts b/clients/ts/FunctionalTests/selenium/run-tests.ts index a7fea9056699..c74603b12c56 100644 --- a/clients/ts/FunctionalTests/selenium/run-tests.ts +++ b/clients/ts/FunctionalTests/selenium/run-tests.ts @@ -4,8 +4,6 @@ import { EOL } from "os"; import * as path from "path"; import { PassThrough, Readable } from "stream"; -import * as tapSpec from "tap-spec"; - import { run } from "../../webdriver-tap-runner/lib"; import * as _debug from "debug"; @@ -71,16 +69,12 @@ function waitForMatch(command: string, process: ChildProcess, regex: RegExp): Pr }); } -let raw = false; let configuration = "Debug"; let chromePath: string; let spec: string; for (let i = 2; i < process.argv.length; i += 1) { switch (process.argv[i]) { - case "--raw": - raw = true; - break; case "--configuration": i += 1; configuration = process.argv[i]; @@ -104,16 +98,6 @@ if (chromePath) { debug(`Using Google Chrome at: '${chromePath}'`); } -function createOutput() { - if (raw) { - return process.stdout; - } else { - const output = tapSpec(); - output.pipe(process.stdout); - return output; - } -} - (async () => { try { const serverPath = path.resolve(__dirname, "..", "bin", configuration, "netcoreapp2.1", "FunctionalTests.dll"); @@ -150,7 +134,7 @@ function createOutput() { const failureCount = await run("SignalR Browser Functional Tests", { browser: "chrome", chromeBinaryPath: chromePath, - output: createOutput(), + output: process.stdout, url, webdriverPort: 9515, }); diff --git a/clients/ts/FunctionalTests/ts/ConnectionTests.ts b/clients/ts/FunctionalTests/ts/ConnectionTests.ts index 9744a5c268ab..58aae5f2da81 100644 --- a/clients/ts/FunctionalTests/ts/ConnectionTests.ts +++ b/clients/ts/FunctionalTests/ts/ConnectionTests.ts @@ -3,12 +3,13 @@ import { HttpConnection, LogLevel, TransferFormat, TransportType } from "@aspnet/signalr"; import { eachTransport, ECHOENDPOINT_URL } from "./Common"; +import { TestLogger } from "./TestLogger"; describe("connection", () => { it("can connect to the server without specifying transport explicitly", (done) => { const message = "Hello World!"; const connection = new HttpConnection(ECHOENDPOINT_URL, { - logger: LogLevel.Trace, + logger: TestLogger.instance, }); let received = ""; @@ -38,7 +39,7 @@ describe("connection", () => { // the url should be resolved relative to the document.location.host // and the leading '/' should be automatically added to the url const connection = new HttpConnection("echo", { - logger: LogLevel.Trace, + logger: TestLogger.instance, transport: transportType, }); diff --git a/clients/ts/FunctionalTests/ts/HubConnectionTests.ts b/clients/ts/FunctionalTests/ts/HubConnectionTests.ts index faff3b1fabb1..2f7a92c51b05 100644 --- a/clients/ts/FunctionalTests/ts/HubConnectionTests.ts +++ b/clients/ts/FunctionalTests/ts/HubConnectionTests.ts @@ -5,6 +5,7 @@ import { HubConnection, JsonHubProtocol, LogLevel, TransportType } from "@aspnet import { MessagePackHubProtocol } from "@aspnet/signalr-protocol-msgpack"; import { eachTransport, eachTransportAndProtocol } from "./Common"; +import { TestLogger } from "./TestLogger"; const TESTHUBENDPOINT_URL = "/testhub"; const TESTHUB_NOWEBSOCKETS_ENDPOINT_URL = "/testhub-nowebsockets"; @@ -16,7 +17,7 @@ describe("hubConnection", () => { const message = "你好,世界!"; const hubConnection = new HubConnection(TESTHUBENDPOINT_URL, { - logger: LogLevel.Trace, + logger: TestLogger.instance, protocol, transport: transportType, }); @@ -43,7 +44,7 @@ describe("hubConnection", () => { const message = "你好,世界!"; const hubConnection = new HubConnection(TESTHUBENDPOINT_URL, { - logger: LogLevel.Trace, + logger: TestLogger.instance, protocol, transport: transportType, }); @@ -66,7 +67,7 @@ describe("hubConnection", () => { it("can invoke server method structural object and receive structural result", (done) => { const hubConnection = new HubConnection(TESTHUBENDPOINT_URL, { - logger: LogLevel.Trace, + logger: TestLogger.instance, protocol, transport: transportType, }); @@ -92,7 +93,7 @@ describe("hubConnection", () => { it("can stream server method and receive result", (done) => { const hubConnection = new HubConnection(TESTHUBENDPOINT_URL, { - logger: LogLevel.Trace, + logger: TestLogger.instance, protocol, transport: transportType, }); @@ -126,7 +127,7 @@ describe("hubConnection", () => { it("rethrows an exception from the server when invoking", (done) => { const errorMessage = "An unexpected error occurred invoking 'ThrowException' on the server. InvalidOperationException: An error occurred."; const hubConnection = new HubConnection(TESTHUBENDPOINT_URL, { - logger: LogLevel.Trace, + logger: TestLogger.instance, protocol, transport: transportType, }); @@ -150,7 +151,7 @@ describe("hubConnection", () => { it("throws an exception when invoking streaming method with invoke", (done) => { const hubConnection = new HubConnection(TESTHUBENDPOINT_URL, { - logger: LogLevel.Trace, + logger: TestLogger.instance, protocol, transport: transportType, }); @@ -174,7 +175,7 @@ describe("hubConnection", () => { it("throws an exception when receiving a streaming result for method called with invoke", (done) => { const hubConnection = new HubConnection(TESTHUBENDPOINT_URL, { - logger: LogLevel.Trace, + logger: TestLogger.instance, protocol, transport: transportType, }); @@ -199,7 +200,7 @@ describe("hubConnection", () => { it("rethrows an exception from the server when streaming", (done) => { const errorMessage = "An unexpected error occurred invoking 'StreamThrowException' on the server. InvalidOperationException: An error occurred."; const hubConnection = new HubConnection(TESTHUBENDPOINT_URL, { - logger: LogLevel.Trace, + logger: TestLogger.instance, protocol, transport: transportType, }); @@ -228,7 +229,7 @@ describe("hubConnection", () => { it("throws an exception when invoking hub method with stream", (done) => { const hubConnection = new HubConnection(TESTHUBENDPOINT_URL, { - logger: LogLevel.Trace, + logger: TestLogger.instance, protocol, transport: transportType, }); @@ -257,7 +258,7 @@ describe("hubConnection", () => { it("can receive server calls", (done) => { const hubConnection = new HubConnection(TESTHUBENDPOINT_URL, { - logger: LogLevel.Trace, + logger: TestLogger.instance, protocol, transport: transportType, }); @@ -289,7 +290,7 @@ describe("hubConnection", () => { it("can receive server calls without rebinding handler when restarted", (done) => { const hubConnection = new HubConnection(TESTHUBENDPOINT_URL, { - logger: LogLevel.Trace, + logger: TestLogger.instance, protocol, transport: transportType, }); @@ -346,7 +347,7 @@ describe("hubConnection", () => { it("closed with error if hub cannot be created", (done) => { const hubConnection = new HubConnection("http://" + document.location.host + "/uncreatable", { - logger: LogLevel.Trace, + logger: TestLogger.instance, protocol, transport: transportType, }); @@ -360,7 +361,7 @@ describe("hubConnection", () => { it("can handle different types", (done) => { const hubConnection = new HubConnection(TESTHUBENDPOINT_URL, { - logger: LogLevel.Trace, + logger: TestLogger.instance, protocol, transport: transportType, }); @@ -408,7 +409,7 @@ describe("hubConnection", () => { const message = "你好,世界!"; const hubConnection = new HubConnection(TESTHUBENDPOINT_URL, { - logger: LogLevel.Trace, + logger: TestLogger.instance, protocol, transport: transportType, }); @@ -463,7 +464,7 @@ describe("hubConnection", () => { const jwtToken = await getJwtToken("http://" + document.location.host + "/generateJwtToken"); const hubConnection = new HubConnection("/authorizedhub", { accessTokenFactory: () => jwtToken, - logger: LogLevel.Trace, + logger: TestLogger.instance, transport: transportType, }); hubConnection.onclose((error) => { @@ -487,7 +488,7 @@ describe("hubConnection", () => { if (transportType !== TransportType.LongPolling) { it("terminates if no messages received within timeout interval", (done) => { const hubConnection = new HubConnection(TESTHUBENDPOINT_URL, { - logger: LogLevel.Trace, + logger: TestLogger.instance, timeoutInMilliseconds: 100, transport: transportType, }); @@ -511,7 +512,7 @@ describe("hubConnection", () => { if (typeof EventSource !== "undefined") { it("allows Server-Sent Events when negotiating for JSON protocol", async (done) => { const hubConnection = new HubConnection(TESTHUB_NOWEBSOCKETS_ENDPOINT_URL, { - logger: LogLevel.Trace, + logger: TestLogger.instance, protocol: new JsonHubProtocol(), }); @@ -529,7 +530,7 @@ describe("hubConnection", () => { it("skips Server-Sent Events when negotiating for MsgPack protocol", async (done) => { const hubConnection = new HubConnection(TESTHUB_NOWEBSOCKETS_ENDPOINT_URL, { - logger: LogLevel.Trace, + logger: TestLogger.instance, protocol: new MessagePackHubProtocol(), }); diff --git a/clients/ts/FunctionalTests/ts/TestLogger.ts b/clients/ts/FunctionalTests/ts/TestLogger.ts new file mode 100644 index 000000000000..e3fa685dde42 --- /dev/null +++ b/clients/ts/FunctionalTests/ts/TestLogger.ts @@ -0,0 +1,17 @@ +import { ILogger, LogLevel } from "@aspnet/signalr"; + +export class TestLogger implements ILogger { + public static instance: TestLogger = new TestLogger(); + + public messages: Array<[LogLevel, string]> = []; + + public log(logLevel: LogLevel, message: string): void { + this.messages.push([logLevel, message]); + } + + public static getMessagesAndReset(): Array<[LogLevel, string]> { + const messages = TestLogger.instance.messages; + TestLogger.instance = new TestLogger(); + return messages; + } +} diff --git a/clients/ts/FunctionalTests/ts/WebDriverReporter.ts b/clients/ts/FunctionalTests/ts/WebDriverReporter.ts index 85ca1196b9a8..dc81e8a6946d 100644 --- a/clients/ts/FunctionalTests/ts/WebDriverReporter.ts +++ b/clients/ts/FunctionalTests/ts/WebDriverReporter.ts @@ -1,3 +1,5 @@ +import { LogLevel } from "@aspnet/signalr"; +import { TestLogger } from "./TestLogger"; import { getParameterByName } from "./Utils"; function formatValue(v: any): string { @@ -16,6 +18,7 @@ class WebDriverReporter implements jasmine.CustomReporter { private element: HTMLDivElement; private specCounter: number = 1; // TAP number start at 1 private recordCounter: number = 0; + private concurrentSpecCount: number = 0; constructor(private document: Document, show: boolean = false) { // We write to the DOM because it's the most compatible way for WebDriver to read. @@ -36,7 +39,16 @@ class WebDriverReporter implements jasmine.CustomReporter { this.taplog(`1..${suiteInfo.totalSpecsDefined}`); } + public specStarted(result: jasmine.CustomReporterResult): void { + this.concurrentSpecCount += 1; + if (this.concurrentSpecCount > 1) { + throw new Error("Unexpected concurrent tests!"); + } + } + public specDone(result: jasmine.CustomReporterResult): void { + this.concurrentSpecCount -= 1; + const messages = TestLogger.getMessagesAndReset(); if (result.status === "disabled") { return; } else if (result.status === "failed") { @@ -44,17 +56,29 @@ class WebDriverReporter implements jasmine.CustomReporter { // Just report the first failure this.taplog(" ---"); - for (const expectation of result.failedExpectations) { - // Include YAML block with failed expectations - this.taplog(` - message: ${expectation.message}`); - if (expectation.matcherName) { - this.taplog(` operator: ${expectation.matcherName}`); + if (result.failedExpectations.length > 0) { + this.taplog(" - messages:"); + for (const expectation of result.failedExpectations) { + // Include YAML block with failed expectations + this.taplog(` - message: ${expectation.message}`); + if (expectation.matcherName) { + this.taplog(` operator: ${expectation.matcherName}`); + } + if (expectation.expected) { + this.taplog(` expected: ${formatValue(expectation.expected)}`); + } + if (expectation.actual) { + this.taplog(` actual: ${formatValue(expectation.actual)}`); + } } - if (expectation.expected) { - this.taplog(` expected: ${formatValue(expectation.expected)}`); - } - if (expectation.actual) { - this.taplog(` actual: ${formatValue(expectation.actual)}`); + } + + // Report log messages + if (messages.length > 0) { + this.taplog(" - logs: "); + for (const [level, message] of messages) { + this.taplog(` - level: ${LogLevel[level]}`); + this.taplog(` message: ${message}`); } } this.taplog(" ...");