diff --git a/package-lock.json b/package-lock.json index 82723de..12004fa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "@dojo/test-extras", - "version": "0.3.1-rc.1", + "version": "0.3.1-pre", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -22,7 +22,7 @@ "integrity": "sha512-sgqHsKraTjKDoLfWece/E/ip29CsV3z+vEDSIzuBSWtXDEau6/pDRhbhuSnxjBB1bvvB8Drn93xWkO+PqqQ0Dg==", "dev": true, "requires": { - "@types/yargs": "8.0.2" + "@types/yargs": "8.0.3" } }, "@dojo/loader": { @@ -39,7 +39,7 @@ "requires": { "intersection-observer": "0.4.3", "pepjs": "0.4.3", - "tslib": "1.8.0" + "tslib": "1.8.1" } }, "@theintern/digdug": { @@ -54,7 +54,7 @@ "@dojo/shim": "0.2.3", "decompress": "4.2.0", "semver": "5.4.1", - "tslib": "1.8.0" + "tslib": "1.8.1" } }, "@theintern/leadfoot": { @@ -69,7 +69,7 @@ "@dojo/shim": "0.2.3", "@types/jszip": "0.0.33", "jszip": "3.1.5", - "tslib": "1.8.0" + "tslib": "1.8.1" } }, "@types/babel-types": { @@ -91,13 +91,13 @@ "dev": true, "requires": { "@types/express": "4.0.39", - "@types/node": "8.0.55" + "@types/node": "8.5.1" } }, "@types/chai": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.0.8.tgz", - "integrity": "sha512-m812CONwdZn/dMzkIJEY0yAs4apyTkTORgfB2UsMOxgkUbC205AHnm4T8I0I5gPg9MHrFc1dJ35iS75c0CJkjg==", + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.0.10.tgz", + "integrity": "sha512-Ejh1AXTY8lm+x91X/yar3G2z4x9RyKwdTVdyyu7Xj3dNB35fMNCnEWqTO9FgS3zjzlRNqk1MruYhgb8yhRN9rA==", "dev": true }, "@types/charm": { @@ -106,7 +106,7 @@ "integrity": "sha512-F9OalGhk60p/DnACfa1SWtmVTMni0+w9t/qfb5Bu7CsurkEjZFN7Z+ii/VGmYpaViPz7o3tBahRQae9O7skFlQ==", "dev": true, "requires": { - "@types/node": "8.0.55" + "@types/node": "8.5.1" } }, "@types/diff": { @@ -115,6 +115,12 @@ "integrity": "sha512-q3zfJvaTroV5BjAAR+peTHEGAAhGrPX0z2EzCzpt2mwFA+qzUn2nigJLqSekXRtdULKmT8am7zjvTMZSapIgHw==", "dev": true }, + "@types/events": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@types/events/-/events-1.1.0.tgz", + "integrity": "sha512-y3bR98mzYOo0pAZuiLari+cQyiKk3UXRuT45h1RjhfeCzqkjaVsfZJNaxdgtk7/3tzOm1ozLTqEqMP3VbI48jw==", + "dev": true + }, "@types/express": { "version": "4.0.39", "resolved": "https://registry.npmjs.org/@types/express/-/express-4.0.39.tgz", @@ -132,7 +138,7 @@ "integrity": "sha512-QLAHjdLwEICm3thVbXSKRoisjfgMVI4xJH/HU8F385BR2HI7PmM6ax4ELXf8Du6sLmSpySXMYaI+xc//oQ/IFw==", "dev": true, "requires": { - "@types/node": "8.0.55" + "@types/node": "8.5.1" } }, "@types/fs-extra": { @@ -141,17 +147,18 @@ "integrity": "sha1-qHGcQXsIDAEtNJeyjiKKwJdF/fI=", "dev": true, "requires": { - "@types/node": "8.0.55" + "@types/node": "8.5.1" } }, "@types/glob": { - "version": "5.0.33", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-5.0.33.tgz", - "integrity": "sha512-BcD4yyWz+qmCggaYMSFF0Xn7GkO6tgwm3Fh9Gxk/kQmEU3Z7flQTnVlMyKBUNvXXNTCCyjqK4XT4/2hLd1gQ2A==", + "version": "5.0.34", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-5.0.34.tgz", + "integrity": "sha512-sUvpieq+HsWTLdkeOI8Mi8u22Ag3AoGuM3sv+XMP1bKtbaIAHpEA2f52K2mz6vK5PVhTa3bFyRZLZMqTxOo2Cw==", "dev": true, "requires": { - "@types/minimatch": "3.0.1", - "@types/node": "8.0.55" + "@types/events": "1.1.0", + "@types/minimatch": "3.0.2", + "@types/node": "8.5.1" } }, "@types/grunt": { @@ -160,7 +167,7 @@ "integrity": "sha512-fKrWJ+uFq9j3tP2RLm9cY7Z50LhhPnSHQCliCZP5lPAWC7TydnU+BcLR0KQIHe9Gbn1oGfkRIq3u56MNCC1qyw==", "dev": true, "requires": { - "@types/node": "8.0.55" + "@types/node": "8.5.1" } }, "@types/handlebars": { @@ -234,9 +241,9 @@ } }, "@types/jquery": { - "version": "3.2.16", - "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.2.16.tgz", - "integrity": "sha512-q2WC02YxQoX2nY1HRKlYGHpGP1saPmD7GN0pwCDlTz35a4eOtJG+aHRlXyjCuXokUukSrR2aXyBhSW3j+jPc0A==", + "version": "3.2.17", + "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.2.17.tgz", + "integrity": "sha512-lt8i2ZqymxxN1JnWSOTPU7Xc3ze32lhASkVdsMd6/SZnb/jtBsmFEoYCBSa0tzGDSyO7ZB+4r4aihj+KTlDs5w==", "dev": true }, "@types/jsdom": { @@ -245,8 +252,8 @@ "integrity": "sha512-xaHlMIzlReyciMIWGJBnkEdHngCOEpik2ojt9tJFe7rD+QiObCIcmr9/tAqxn7l1jflQ3wEIkh7+gt4ls5n1Dw==", "dev": true, "requires": { - "@types/jquery": "3.2.16", - "@types/node": "8.0.55" + "@types/jquery": "3.2.17", + "@types/node": "8.5.1" } }, "@types/jszip": { @@ -256,9 +263,9 @@ "dev": true }, "@types/lodash": { - "version": "4.14.87", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.87.tgz", - "integrity": "sha512-AqRC+aEF4N0LuNHtcjKtvF9OTfqZI0iaBoe3dA6m/W+/YZJBZjBmW/QIZ8fBeXC6cnytSY9tBoFBqZ9uSCeVsw==", + "version": "4.14.91", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.91.tgz", + "integrity": "sha512-k+nc3moSlAaXacyvz4/c6D9lnUeI6AKsLvkXFuNzUEEqMw7sjDnLW2GqlJ4nyFgMX/p+QzvVG6zRoDo4lJIV5g==", "dev": true }, "@types/marked": { @@ -280,15 +287,15 @@ "dev": true }, "@types/minimatch": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.1.tgz", - "integrity": "sha512-rUO/jz10KRSyA9SHoCWQ8WX9BICyj5jZYu1/ucKEJKb4KzLZCKMURdYbadP157Q6Zl1x0vHsrU+Z/O0XlhYQDw==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.2.tgz", + "integrity": "sha512-tctoxbfuMCxeI2CAsnwoZQfaBA+T7gPzDzDuiiFnyCSSyGYEB92cmRTh6E3tdR1hWsprbJ9IdbvX3PzLmJU/GA==", "dev": true }, "@types/node": { - "version": "8.0.55", - "resolved": "https://registry.npmjs.org/@types/node/-/node-8.0.55.tgz", - "integrity": "sha512-K8w0FWNsIRcw615d/Et90wMRvLfg8XH1T77fC0xObbusE3+eXwnitdoF9j0CS9zBt8A57J/TKgRVe7RX9ZlT1g==", + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-8.5.1.tgz", + "integrity": "sha512-SrmAO+NhnsuG/6TychSl2VdxBZiw/d6V+8j+DFo8O3PwFi+QeYXWHhAw+b170aSc6zYab6/PjEWRZHIDN9mNUw==", "dev": true }, "@types/platform": { @@ -303,7 +310,7 @@ "integrity": "sha1-m1htZalH3qiMS8JNoLkF/pUgoNU=", "dev": true, "requires": { - "@types/node": "8.0.55" + "@types/node": "8.5.1" } }, "@types/serve-static": { @@ -328,7 +335,7 @@ "integrity": "sha1-32E73biCJe0JzlyDX2INyq8VXms=", "dev": true, "requires": { - "@types/node": "8.0.55" + "@types/node": "8.5.1" } }, "@types/sinon": { @@ -355,13 +362,13 @@ "integrity": "sha512-+30f9gcx24GZRD9EqqiQM+I5pRf/MJiJoEqp2X62QRwfEjdqyn9mPmjxZAEXBUVunWotE5qkadIPqf2MMcDYNw==", "dev": true, "requires": { - "@types/node": "8.0.55" + "@types/node": "8.5.1" } }, "@types/yargs": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-8.0.2.tgz", - "integrity": "sha512-Upj9YsBZRgjEVPvsaeGru48d2JiyzBNZkmkebHyoaQ+UM9wqj/rp5mkilRjSq/Ga45yfd/zwrNuML9f2gGfVpw==", + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-8.0.3.tgz", + "integrity": "sha512-YdxO7zGQf2qJeMgR0fNO8QTlj88L2zCP5GOddovoTyetgLiNDOUXcWzhWKb4EdZZlOjLQUA0JM8lW7VcKQL+9w==", "dev": true }, "abab": { @@ -417,9 +424,9 @@ } }, "ajv": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.1.tgz", - "integrity": "sha1-s4u4h22ehr7plJVqBOch6IskjrI=", + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", "requires": { "co": "4.6.0", "fast-deep-equal": "1.0.0", @@ -459,6 +466,21 @@ "string-width": "2.1.1" } }, + "ansi-escapes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", + "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=", + "dev": true + }, + "ansi-gray": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", + "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", + "dev": true, + "requires": { + "ansi-wrap": "0.1.0" + } + }, "ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", @@ -471,6 +493,18 @@ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", "dev": true }, + "ansi-wrap": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", + "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=", + "dev": true + }, + "any-observable": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/any-observable/-/any-observable-0.2.0.tgz", + "integrity": "sha1-xnhwBYADV5AJCD9UrAq6+1wz0kI=", + "dev": true + }, "any-promise": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", @@ -487,6 +521,12 @@ "normalize-path": "2.1.1" } }, + "app-root-path": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-2.0.1.tgz", + "integrity": "sha1-zWLc+OT9WkF+/GZNLlsQZTxlG0Y=", + "dev": true + }, "append-transform": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-0.4.0.tgz", @@ -619,7 +659,7 @@ "dev": true, "requires": { "browserslist": "1.7.7", - "caniuse-db": "1.0.30000778", + "caniuse-db": "1.0.30000783", "normalize-range": "0.1.2", "num2fraction": "1.2.2", "postcss": "5.2.18", @@ -678,14 +718,14 @@ "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", "dev": true, "requires": { - "core-js": "2.5.1", - "regenerator-runtime": "0.11.0" + "core-js": "2.5.3", + "regenerator-runtime": "0.11.1" }, "dependencies": { "core-js": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.1.tgz", - "integrity": "sha1-rmh03GaTd4m4B1T/VCjfZoGcpQs=", + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.3.tgz", + "integrity": "sha1-isw4NFgk8W2DZbfJtCWRaOjtYD4=", "dev": true } } @@ -944,7 +984,7 @@ "integrity": "sha1-C9dnBCWL6CmyOYu1Dkti0aFmsLk=", "dev": true, "requires": { - "caniuse-db": "1.0.30000778", + "caniuse-db": "1.0.30000783", "electron-to-chromium": "1.3.28" } }, @@ -1008,15 +1048,15 @@ "dev": true, "requires": { "browserslist": "1.7.7", - "caniuse-db": "1.0.30000778", + "caniuse-db": "1.0.30000783", "lodash.memoize": "4.1.2", "lodash.uniq": "4.5.0" } }, "caniuse-db": { - "version": "1.0.30000778", - "resolved": "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30000778.tgz", - "integrity": "sha1-Fnxg6VQqKqYFN8RG+ziB2FOjByo=", + "version": "1.0.30000783", + "resolved": "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30000783.tgz", + "integrity": "sha1-FrMNRyZqT1FcxprgMWtnDJYDzb4=", "dev": true }, "capture-stack-trace": { @@ -1100,6 +1140,12 @@ "readdirp": "1.4.0" } }, + "ci-info": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.1.2.tgz", + "integrity": "sha512-uTGIPNx/nSpBdsF6xnseRXLLtfr9VLqkz8ZqHXr3Y7b6SftyRxBGjwMtJj1OhNbmlc1wZzLNAlAcvyIiE8a6ZA==", + "dev": true + }, "clap": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/clap/-/clap-1.2.3.tgz", @@ -1115,6 +1161,53 @@ "integrity": "sha1-T6kXw+WclKAEzWH47lCdplFocUM=", "dev": true }, + "cli-cursor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", + "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", + "dev": true, + "requires": { + "restore-cursor": "1.0.1" + } + }, + "cli-spinners": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-0.1.2.tgz", + "integrity": "sha1-u3ZNiOGF+54eaiofGXcjGPYF4xw=", + "dev": true + }, + "cli-truncate": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-0.2.1.tgz", + "integrity": "sha1-nxXPuwcFAFNpIWxiasfQWrkN1XQ=", + "dev": true, + "requires": { + "slice-ansi": "0.0.4", + "string-width": "1.0.2" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + } + } + }, "cliui": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", @@ -1404,6 +1497,12 @@ "color-name": "1.1.3" } }, + "color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "dev": true + }, "colormin": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/colormin/-/colormin-1.1.2.tgz", @@ -1552,6 +1651,45 @@ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, + "cosmiconfig": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-3.1.0.tgz", + "integrity": "sha512-zedsBhLSbPBms+kE7AH4vHg6JsKDz6epSv2/+5XHs8ILHlgDciSJfSWf8sX9aQ52Jb7KI7VswUTsLpR/G0cr2Q==", + "dev": true, + "requires": { + "is-directory": "0.3.1", + "js-yaml": "3.10.0", + "parse-json": "3.0.0", + "require-from-string": "2.0.1" + }, + "dependencies": { + "esprima": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", + "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==", + "dev": true + }, + "js-yaml": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.10.0.tgz", + "integrity": "sha512-O2v52ffjLa9VeM43J4XocZE//WT9N0IiwDa3KSHH7Tu8CtH+1qM8SIZvnsTh6v+4yFy5KUY3BHUVwjpfAWsjIA==", + "dev": true, + "requires": { + "argparse": "1.0.9", + "esprima": "4.0.0" + } + }, + "parse-json": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-3.0.0.tgz", + "integrity": "sha1-+m9HsY4jgm6tMvJj50TQ4ehH+xM=", + "dev": true, + "requires": { + "error-ex": "1.3.1" + } + } + } + }, "create-error-class": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz", @@ -1821,6 +1959,12 @@ "assert-plus": "1.0.0" } }, + "date-fns": { + "version": "1.29.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.29.0.tgz", + "integrity": "sha512-lbTXWZ6M20cWH8N9S6afb0SBm6tMk+uUg6z3MqHPKE9atmsY3kJkTm8vKe93izJ2B2+q5MV990sM2CHgtAZaOw==", + "dev": true + }, "dateformat": { "version": "1.0.12", "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz", @@ -1925,6 +2069,12 @@ } } }, + "dedent": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", + "integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=", + "dev": true + }, "deep-eql": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", @@ -2089,6 +2239,12 @@ "integrity": "sha1-jdTmRYCGZE6fnwoc8y4qH53/2e4=", "dev": true }, + "elegant-spinner": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/elegant-spinner/-/elegant-spinner-1.0.1.tgz", + "integrity": "sha1-2wQ1IcldfjA/2PNFvtwzSc+wcp4=", + "dev": true + }, "emojis-list": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", @@ -2149,6 +2305,16 @@ "source-map": "0.5.7" } }, + "eslint-plugin-prettier": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-2.4.0.tgz", + "integrity": "sha512-P0EohHM1MwL36GX5l1TOEYyt/5d7hcxrX3CqCjibTN3dH7VCAy2kjsC/WB6dUHnpB4mFkZq1Ndfh2DYQ2QMEGQ==", + "dev": true, + "requires": { + "fast-diff": "1.1.2", + "jest-docblock": "21.2.0" + } + }, "esprima": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", @@ -2196,6 +2362,12 @@ "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", "dev": true }, + "exit-hook": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz", + "integrity": "sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g=", + "dev": true + }, "expand-brackets": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", @@ -2308,12 +2480,13 @@ "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" }, "fancy-log": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.0.tgz", - "integrity": "sha1-Rb4X0Cu5kX1gzP/UmVyZnmyMmUg=", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.2.tgz", + "integrity": "sha1-9BEl49hPLn2JpD0G2VjI94vha+E=", "dev": true, "requires": { - "chalk": "1.1.3", + "ansi-gray": "0.1.1", + "color-support": "1.1.3", "time-stamp": "1.1.0" } }, @@ -2322,6 +2495,12 @@ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz", "integrity": "sha1-liVqO8l1WV6zbYLpkp0GDYk0Of8=" }, + "fast-diff": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.1.2.tgz", + "integrity": "sha512-KaJUt+M9t1qaIteSvjc6P3RbMdXsNhK61GRftR6SNxqmhthcd9MGIi4T+o0jD8LUSpSnSKXE20nLtJ3fOHxQig==", + "dev": true + }, "fast-json-stable-stringify": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", @@ -2356,6 +2535,16 @@ "pend": "1.2.0" } }, + "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" + } + }, "file-sync-cmp": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/file-sync-cmp/-/file-sync-cmp-0.1.1.tgz", @@ -2425,6 +2614,12 @@ } } }, + "find-parent-dir": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/find-parent-dir/-/find-parent-dir-0.3.0.tgz", + "integrity": "sha1-M8RLQpqysvBkYpnF+fcY83b/jVQ=", + "dev": true + }, "find-up": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", @@ -2584,6 +2779,12 @@ "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", "dev": true }, + "get-own-enumerable-property-symbols": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-2.0.1.tgz", + "integrity": "sha512-TtY/sbOemiMKPRUDDanGCSgBYe7Mf0vbRsWnBZ+9yghpZ1MvcpSpuZFjHdEeY/LZjZy0vdLjS77L6HosisFiug==", + "dev": true + }, "get-stdin": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", @@ -2887,7 +3088,7 @@ "grunt-ts": "5.5.1", "grunt-tslint": "4.0.1", "grunt-typings": "0.1.5", - "intern": "4.1.3", + "intern": "4.1.4", "istanbul-lib-coverage": "1.1.1", "istanbul-lib-report": "1.1.2", "istanbul-reports": "1.1.3", @@ -2906,6 +3107,12 @@ "umd-wrapper": "0.1.0" }, "dependencies": { + "diff": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.4.0.tgz", + "integrity": "sha512-QpVuMTEoJMF7cKzi6bvWhRulU1fZqZnvyVQgNhPaxxuTYwyjn/j1v9falseQ/uXWwPnO56RBfwtg4h/EQXmucA==", + "dev": true + }, "glob": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", @@ -2919,6 +3126,29 @@ "once": "1.4.0", "path-is-absolute": "1.0.1" } + }, + "grunt-tslint": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/grunt-tslint/-/grunt-tslint-4.0.1.tgz", + "integrity": "sha1-dcRuAluereAUYrvrSfb9TBl4O1o=", + "dev": true + }, + "tslint": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/tslint/-/tslint-4.5.1.tgz", + "integrity": "sha1-BTVocb7yOkNJBnNABvwYgza6gks=", + "dev": true, + "requires": { + "babel-code-frame": "6.26.0", + "colors": "1.1.2", + "diff": "3.4.0", + "findup-sync": "0.3.0", + "glob": "7.1.2", + "optimist": "0.6.1", + "resolve": "1.1.7", + "tsutils": "1.9.1", + "update-notifier": "2.3.0" + } } } }, @@ -3053,9 +3283,9 @@ } }, "grunt-tslint": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/grunt-tslint/-/grunt-tslint-4.0.1.tgz", - "integrity": "sha1-dcRuAluereAUYrvrSfb9TBl4O1o=", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/grunt-tslint/-/grunt-tslint-5.0.1.tgz", + "integrity": "sha1-dDK9G9VuijolAACI1cYf3MNC8MI=", "dev": true }, "grunt-typings": { @@ -3078,7 +3308,7 @@ "beeper": "1.1.1", "chalk": "1.1.3", "dateformat": "1.0.12", - "fancy-log": "1.3.0", + "fancy-log": "1.3.2", "gulplog": "1.0.0", "has-gulplog": "0.1.0", "lodash._reescape": "3.0.0", @@ -3170,7 +3400,7 @@ "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", "requires": { - "ajv": "5.5.1", + "ajv": "5.5.2", "har-schema": "2.0.0" } }, @@ -3312,6 +3542,31 @@ "extend": "3.0.1" } }, + "husky": { + "version": "0.14.3", + "resolved": "https://registry.npmjs.org/husky/-/husky-0.14.3.tgz", + "integrity": "sha512-e21wivqHpstpoiWA/Yi8eFti8E+sQDSS53cpJsPptPs295QTOQR0ZwnHo2TXy1XOpZFD9rPOd3NpmqTK6uMLJA==", + "dev": true, + "requires": { + "is-ci": "1.0.10", + "normalize-path": "1.0.0", + "strip-indent": "2.0.0" + }, + "dependencies": { + "normalize-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-1.0.0.tgz", + "integrity": "sha1-MtDkcvkf80VwHBWoMRAY07CpA3k=", + "dev": true + }, + "strip-indent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-2.0.0.tgz", + "integrity": "sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g=", + "dev": true + } + } + }, "iconv-lite": { "version": "0.4.19", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", @@ -3385,9 +3640,9 @@ "dev": true }, "intern": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/intern/-/intern-4.1.3.tgz", - "integrity": "sha512-IWaqzIwc+KQcoyiG+INvvv9L0fPKmgDSj+LySSWgnPc0VnYT1vgEmmxpwSlMPHDtfMMqq28/5/tsQVRx4EM2bQ==", + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/intern/-/intern-4.1.4.tgz", + "integrity": "sha512-QL5+pVjpjNVtp5mB2QwTgf3fuG3l+lA3UzhHTxjhahWt0Z84LfdFfHFXN6UeB72IYQq7LDhjStO6I51rsTjb6Q==", "dev": true, "requires": { "@dojo/core": "0.3.0", @@ -3397,7 +3652,7 @@ "@theintern/digdug": "2.0.4", "@theintern/leadfoot": "2.0.3", "@types/benchmark": "1.0.31", - "@types/chai": "4.0.8", + "@types/chai": "4.0.10", "@types/charm": "1.0.1", "@types/diff": "3.2.2", "@types/express": "4.0.39", @@ -3408,7 +3663,7 @@ "@types/istanbul-lib-report": "1.1.0", "@types/istanbul-lib-source-maps": "1.2.0", "@types/istanbul-reports": "1.1.0", - "@types/lodash": "4.14.87", + "@types/lodash": "4.14.91", "@types/mime-types": "2.1.0", "@types/platform": "1.3.1", "@types/resolve": "0.0.4", @@ -3438,7 +3693,7 @@ "shell-quote": "1.6.1", "source-map": "0.5.7", "statuses": "1.3.1", - "tslib": "1.8.0", + "tslib": "1.8.1", "ws": "2.3.1" }, "dependencies": { @@ -3632,6 +3887,21 @@ "builtin-modules": "1.1.1" } }, + "is-ci": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.0.10.tgz", + "integrity": "sha1-9zkzayYyNlBhqdSCcM1WrjNpMY4=", + "dev": true, + "requires": { + "ci-info": "1.1.2" + } + }, + "is-directory": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", + "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=", + "dev": true + }, "is-dotfile": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", @@ -3717,6 +3987,15 @@ "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", "dev": true }, + "is-observable": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/is-observable/-/is-observable-0.2.0.tgz", + "integrity": "sha1-s2ExHYPG5dcmyr9eJQsCNxBvWuI=", + "dev": true, + "requires": { + "symbol-observable": "0.2.4" + } + }, "is-path-inside": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", @@ -3744,12 +4023,24 @@ "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", "dev": true }, + "is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", + "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", + "dev": true + }, "is-redirect": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-redirect/-/is-redirect-1.0.0.tgz", "integrity": "sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ=", "dev": true }, + "is-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", + "integrity": "sha1-/S2INUXEa6xaYz57mgnof6LLUGk=", + "dev": true + }, "is-relative": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-0.2.1.tgz", @@ -4040,6 +4331,67 @@ "handlebars": "4.0.11" } }, + "jest-docblock": { + "version": "21.2.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-21.2.0.tgz", + "integrity": "sha512-5IZ7sY9dBAYSV+YjQ0Ovb540Ku7AO9Z5o2Cg789xj167iQuZ2cG+z0f3Uct6WeYLbU6aQiM2pCs7sZ+4dotydw==", + "dev": true + }, + "jest-get-type": { + "version": "21.2.0", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-21.2.0.tgz", + "integrity": "sha512-y2fFw3C+D0yjNSDp7ab1kcd6NUYfy3waPTlD8yWkAtiocJdBRQqNoRqVfMNxgj+IjT0V5cBIHJO0z9vuSSZ43Q==", + "dev": true + }, + "jest-validate": { + "version": "21.2.1", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-21.2.1.tgz", + "integrity": "sha512-k4HLI1rZQjlU+EC682RlQ6oZvLrE5SCh3brseQc24vbZTxzT/k/3urar5QMCVgjadmSO7lECeGdc6YxnM3yEGg==", + "dev": true, + "requires": { + "chalk": "2.3.0", + "jest-get-type": "21.2.0", + "leven": "2.1.0", + "pretty-format": "21.2.1" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", + "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", + "dev": true, + "requires": { + "ansi-styles": "3.2.0", + "escape-string-regexp": "1.0.5", + "supports-color": "4.5.0" + } + }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "dev": true + }, + "supports-color": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + } + } + }, "js-base64": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.4.0.tgz", @@ -4232,6 +4584,12 @@ "invert-kv": "1.0.0" } }, + "leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=", + "dev": true + }, "levn": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", @@ -4250,48 +4608,278 @@ "immediate": "3.0.6" } }, - "listify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/listify/-/listify-1.0.0.tgz", - "integrity": "sha1-A8p7otFQ1CZ3c/dOV1WNEFPSvuM=", - "dev": true - }, - "livereload-js": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/livereload-js/-/livereload-js-2.2.2.tgz", - "integrity": "sha1-bIclfmSKtHW8JOoldFftzB+NC8I=", - "dev": true - }, - "load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "dev": true, - "requires": { - "graceful-fs": "4.1.11", - "parse-json": "2.2.0", - "pify": "2.3.0", - "pinkie-promise": "2.0.1", - "strip-bom": "2.0.0" - } - }, - "loader-utils": { - "version": "0.2.17", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz", - "integrity": "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=", + "lint-staged": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-6.0.0.tgz", + "integrity": "sha512-ZUftK94S4vedpQG1LlA2tc2AuQXXBwc+1lB+j8SEfG5+p2dqu3Ug8iYQ8jdap+uLkhDw4OaJXqE+CZ/L+vfv+Q==", "dev": true, "requires": { - "big.js": "3.2.0", - "emojis-list": "2.1.0", - "json5": "0.5.1", - "object-assign": "4.1.1" - } - }, - "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, + "app-root-path": "2.0.1", + "chalk": "2.3.0", + "commander": "2.12.2", + "cosmiconfig": "3.1.0", + "debug": "3.1.0", + "dedent": "0.7.0", + "execa": "0.8.0", + "find-parent-dir": "0.3.0", + "is-glob": "4.0.0", + "jest-validate": "21.2.1", + "listr": "0.13.0", + "lodash": "4.17.4", + "log-symbols": "2.1.0", + "minimatch": "3.0.4", + "npm-which": "3.0.1", + "p-map": "1.2.0", + "path-is-inside": "1.0.2", + "pify": "3.0.0", + "staged-git-files": "0.0.4", + "stringify-object": "3.2.1" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", + "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", + "dev": true, + "requires": { + "ansi-styles": "3.2.0", + "escape-string-regexp": "1.0.5", + "supports-color": "4.5.0" + } + }, + "commander": { + "version": "2.12.2", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.12.2.tgz", + "integrity": "sha512-BFnaq5ZOGcDN7FlrtBT4xxkgIToalIIxwjxLWVJ8bGTpe1LroqMiqQXdA7ygc7CRvaYS+9zfPGFnJqFSayx+AA==", + "dev": true + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "execa": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.8.0.tgz", + "integrity": "sha1-2NdrvBtVIX7RkP1t1J08d07PyNo=", + "dev": true, + "requires": { + "cross-spawn": "5.1.0", + "get-stream": "3.0.0", + "is-stream": "1.1.0", + "npm-run-path": "2.0.2", + "p-finally": "1.0.0", + "signal-exit": "3.0.2", + "strip-eof": "1.0.0" + } + }, + "get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", + "dev": true + }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "dev": true + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-glob": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", + "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", + "dev": true, + "requires": { + "is-extglob": "2.1.1" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dev": true, + "requires": { + "path-key": "2.0.1" + } + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, + "supports-color": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + } + } + }, + "listify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/listify/-/listify-1.0.0.tgz", + "integrity": "sha1-A8p7otFQ1CZ3c/dOV1WNEFPSvuM=", + "dev": true + }, + "listr": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/listr/-/listr-0.13.0.tgz", + "integrity": "sha1-ILsLowuuZg7oTMBQPfS+PVYjiH0=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "cli-truncate": "0.2.1", + "figures": "1.7.0", + "indent-string": "2.1.0", + "is-observable": "0.2.0", + "is-promise": "2.1.0", + "is-stream": "1.1.0", + "listr-silent-renderer": "1.1.1", + "listr-update-renderer": "0.4.0", + "listr-verbose-renderer": "0.4.1", + "log-symbols": "1.0.2", + "log-update": "1.0.2", + "ora": "0.2.3", + "p-map": "1.2.0", + "rxjs": "5.5.5", + "stream-to-observable": "0.2.0", + "strip-ansi": "3.0.1" + }, + "dependencies": { + "log-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz", + "integrity": "sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=", + "dev": true, + "requires": { + "chalk": "1.1.3" + } + } + } + }, + "listr-silent-renderer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz", + "integrity": "sha1-kktaN1cVN3C/Go4/v3S4u/P5JC4=", + "dev": true + }, + "listr-update-renderer": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/listr-update-renderer/-/listr-update-renderer-0.4.0.tgz", + "integrity": "sha1-NE2YDaLKLosUW6MFkI8yrj9MyKc=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "cli-truncate": "0.2.1", + "elegant-spinner": "1.0.1", + "figures": "1.7.0", + "indent-string": "3.2.0", + "log-symbols": "1.0.2", + "log-update": "1.0.2", + "strip-ansi": "3.0.1" + }, + "dependencies": { + "indent-string": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", + "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=", + "dev": true + }, + "log-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz", + "integrity": "sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=", + "dev": true, + "requires": { + "chalk": "1.1.3" + } + } + } + }, + "listr-verbose-renderer": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/listr-verbose-renderer/-/listr-verbose-renderer-0.4.1.tgz", + "integrity": "sha1-ggb0z21S3cWCfl/RSYng6WWTOjU=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "cli-cursor": "1.0.2", + "date-fns": "1.29.0", + "figures": "1.7.0" + } + }, + "livereload-js": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/livereload-js/-/livereload-js-2.2.2.tgz", + "integrity": "sha1-bIclfmSKtHW8JOoldFftzB+NC8I=", + "dev": true + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "parse-json": "2.2.0", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "strip-bom": "2.0.0" + } + }, + "loader-utils": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz", + "integrity": "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=", + "dev": true, + "requires": { + "big.js": "3.2.0", + "emojis-list": "2.1.0", + "json5": "0.5.1", + "object-assign": "4.1.1" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, "requires": { "p-locate": "2.0.0", "path-exists": "3.0.0" @@ -4439,6 +5027,62 @@ "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=", "dev": true }, + "log-symbols": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.1.0.tgz", + "integrity": "sha512-zLeLrzMA1A2vRF1e/0Mo+LNINzi6jzBylHj5WqvQ/WK/5WCZt8si9SyN4p9llr/HRYvVR1AoXHRHl4WTHyQAzQ==", + "dev": true, + "requires": { + "chalk": "2.3.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", + "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", + "dev": true, + "requires": { + "ansi-styles": "3.2.0", + "escape-string-regexp": "1.0.5", + "supports-color": "4.5.0" + } + }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "dev": true + }, + "supports-color": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + } + } + }, + "log-update": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-1.0.2.tgz", + "integrity": "sha1-GZKfZMQJPS0ucHWh2tivWcKWuNE=", + "dev": true, + "requires": { + "ansi-escapes": "1.4.0", + "cli-cursor": "1.0.2" + } + }, "lolex": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/lolex/-/lolex-1.6.0.tgz", @@ -4765,6 +5409,15 @@ "sort-keys": "1.1.2" } }, + "npm-path": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/npm-path/-/npm-path-2.0.3.tgz", + "integrity": "sha1-Fc/04ciaONp39W9gVbJPl137K74=", + "dev": true, + "requires": { + "which": "1.2.14" + } + }, "npm-run-path": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-1.0.0.tgz", @@ -4774,6 +5427,25 @@ "path-key": "1.0.0" } }, + "npm-which": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/npm-which/-/npm-which-3.0.1.tgz", + "integrity": "sha1-kiXybsOihcIJyuZ8OxGmtKtxQKo=", + "dev": true, + "requires": { + "commander": "2.12.2", + "npm-path": "2.0.3", + "which": "1.2.14" + }, + "dependencies": { + "commander": { + "version": "2.12.2", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.12.2.tgz", + "integrity": "sha512-BFnaq5ZOGcDN7FlrtBT4xxkgIToalIIxwjxLWVJ8bGTpe1LroqMiqQXdA7ygc7CRvaYS+9zfPGFnJqFSayx+AA==", + "dev": true + } + } + }, "num2fraction": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", @@ -4853,6 +5525,12 @@ "integrity": "sha1-pT7D/xccNEYBbdUhDRobVEv32HQ=", "dev": true }, + "onetime": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", + "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", + "dev": true + }, "optimist": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", @@ -4890,6 +5568,18 @@ "wordwrap": "1.0.0" } }, + "ora": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/ora/-/ora-0.2.3.tgz", + "integrity": "sha1-N1J9Igrc1Tw5tzVx11QVbV22V6Q=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "cli-cursor": "1.0.2", + "cli-spinners": "0.1.2", + "object-assign": "4.1.1" + } + }, "os-homedir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", @@ -4982,6 +5672,12 @@ "p-limit": "1.1.0" } }, + "p-map": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-1.2.0.tgz", + "integrity": "sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==", + "dev": true + }, "package-json": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/package-json/-/package-json-4.0.1.tgz", @@ -6263,6 +6959,39 @@ "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", "dev": true }, + "prettier": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.9.2.tgz", + "integrity": "sha512-piXx9N2WT8hWb7PBbX1glAuJVIkEyUV9F5fMXFINpZ0x3otVOFKKeGmeuiclFJlP/UrgTckyV606VjH2rNK4bw==", + "dev": true + }, + "pretty-format": { + "version": "21.2.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-21.2.1.tgz", + "integrity": "sha512-ZdWPGYAnYfcVP8yKA3zFjCn8s4/17TeYH28MXuC8vTp0o21eXjbFGcOAXZEaDaOFJjc3h2qa7HQNHNshhvoh2A==", + "dev": true, + "requires": { + "ansi-regex": "3.0.0", + "ansi-styles": "3.2.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + } + } + }, "process-nextick-args": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", @@ -6560,9 +7289,9 @@ "dev": true }, "regenerator-runtime": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.0.tgz", - "integrity": "sha512-/aA0kLeRb5N9K0d4fw7ooEbI+xDe+DKD499EQqygGqeS8N3xto15p09uY2xj7ixP81sNPXvRLnAQIqdVStgb1A==", + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", "dev": true }, "regex-cache": { @@ -6727,6 +7456,12 @@ "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", "dev": true }, + "require-from-string": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.1.tgz", + "integrity": "sha1-xUUjPp19pmFunVmt+zn8n1iGdv8=", + "dev": true + }, "require-main-filename": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", @@ -6745,6 +7480,16 @@ "integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c=", "dev": true }, + "restore-cursor": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", + "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", + "dev": true, + "requires": { + "exit-hook": "1.1.1", + "onetime": "1.1.0" + } + }, "resumer": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/resumer/-/resumer-0.0.0.tgz", @@ -6782,6 +7527,23 @@ "integrity": "sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI=", "dev": true }, + "rxjs": { + "version": "5.5.5", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.5.tgz", + "integrity": "sha512-D/MfQnPMBk8P8gfwGxvCkuaWBcG58W7dUMT//URPoYzIbDEKT0GezdirkK5whMgKFBATfCoTpxO8bJQGJ04W5A==", + "dev": true, + "requires": { + "symbol-observable": "1.0.1" + }, + "dependencies": { + "symbol-observable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.1.tgz", + "integrity": "sha1-g0D8RwLDEi310iKI+IKD9RPT/dQ=", + "dev": true + } + } + }, "safe-buffer": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", @@ -6997,6 +7759,12 @@ } } }, + "slice-ansi": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", + "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=", + "dev": true + }, "slide": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz", @@ -7082,6 +7850,12 @@ "tweetnacl": "0.14.5" } }, + "staged-git-files": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/staged-git-files/-/staged-git-files-0.0.4.tgz", + "integrity": "sha1-15fhtVHKemOd7AI33G60u5vhfTU=", + "dev": true + }, "statuses": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", @@ -7102,6 +7876,15 @@ "duplexer": "0.1.1" } }, + "stream-to-observable": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/stream-to-observable/-/stream-to-observable-0.2.0.tgz", + "integrity": "sha1-WdbqOT2HwsDdrBCqDVYbxrpvDhA=", + "dev": true, + "requires": { + "any-observable": "0.2.0" + } + }, "strict-uri-encode": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", @@ -7153,6 +7936,17 @@ "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", "dev": true }, + "stringify-object": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.2.1.tgz", + "integrity": "sha512-jPcQYw/52HUPP8uOE4kkjxl5bB9LfHkKCTptIk3qw7ozP5XMIMlHMLjt00GGSwW6DJAf/njY5EU6Vpwl4LlBKQ==", + "dev": true, + "requires": { + "get-own-enumerable-property-symbols": "2.0.1", + "is-obj": "1.0.1", + "is-regexp": "1.0.0" + } + }, "stringstream": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", @@ -7245,6 +8039,12 @@ } } }, + "symbol-observable": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-0.2.4.tgz", + "integrity": "sha1-lag9smGG1q9+ehjb2XYKL4bQj0A=", + "dev": true + }, "symbol-tree": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.2.tgz", @@ -7520,28 +8320,56 @@ "dev": true }, "tslib": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.8.0.tgz", - "integrity": "sha512-ymKWWZJST0/CkgduC2qkzjMOWr4bouhuURNXCn/inEX0L57BnRG6FhX76o7FOnsjHazCjfU2LKeSrlS2sIKQJg==", + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.8.1.tgz", + "integrity": "sha1-aUavLR1lGnsYY7Ux1uWvpBqkTqw=", "dev": true }, "tslint": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/tslint/-/tslint-4.5.1.tgz", - "integrity": "sha1-BTVocb7yOkNJBnNABvwYgza6gks=", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.8.0.tgz", + "integrity": "sha1-H0mtWy53x2w69N3K5VKuTjYS6xM=", "dev": true, "requires": { "babel-code-frame": "6.26.0", - "colors": "1.1.2", + "builtin-modules": "1.1.1", + "chalk": "2.3.0", + "commander": "2.12.2", "diff": "3.4.0", - "findup-sync": "0.3.0", "glob": "7.1.2", - "optimist": "0.6.1", - "resolve": "1.1.7", - "tsutils": "1.9.1", - "update-notifier": "2.3.0" + "minimatch": "3.0.4", + "resolve": "1.5.0", + "semver": "5.4.1", + "tslib": "1.8.1", + "tsutils": "2.13.1" }, "dependencies": { + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", + "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", + "dev": true, + "requires": { + "ansi-styles": "3.2.0", + "escape-string-regexp": "1.0.5", + "supports-color": "4.5.0" + } + }, + "commander": { + "version": "2.12.2", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.12.2.tgz", + "integrity": "sha512-BFnaq5ZOGcDN7FlrtBT4xxkgIToalIIxwjxLWVJ8bGTpe1LroqMiqQXdA7ygc7CRvaYS+9zfPGFnJqFSayx+AA==", + "dev": true + }, "diff": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/diff/-/diff-3.4.0.tgz", @@ -7561,9 +8389,52 @@ "once": "1.4.0", "path-is-absolute": "1.0.1" } + }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "dev": true + }, + "resolve": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz", + "integrity": "sha512-hgoSGrc3pjzAPHNBg+KnFcK2HwlHTs/YrAGUr6qgTVUZmXv1UEXXl0bZNBKMA9fud6lRYFdPGz0xXxycPzmmiw==", + "dev": true, + "requires": { + "path-parse": "1.0.5" + } + }, + "supports-color": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + }, + "tsutils": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.13.1.tgz", + "integrity": "sha512-XMOEvc2TiYesVSOJMI7OYPnBMSgcvERuGW5Li/J+2A0TuH607BPQnOLQ82oSPZCssB8c9+QGi6qhTBa/f1xQRA==", + "dev": true, + "requires": { + "tslib": "1.8.1" + } } } }, + "tslint-plugin-prettier": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/tslint-plugin-prettier/-/tslint-plugin-prettier-1.3.0.tgz", + "integrity": "sha512-6UqeeV6EABp0RdQkW6eC1vwnAXcKMGJgPeJ5soXiKdSm2vv7c3dp+835CM8pjgx9l4uSa7tICm1Kli+SMsADDg==", + "dev": true, + "requires": { + "eslint-plugin-prettier": "2.4.0", + "tslib": "1.8.1" + } + }, "tsutils": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-1.9.1.tgz", @@ -8794,7 +9665,7 @@ "@types/fs-extra": "0.0.33", "@types/handlebars": "4.0.36", "@types/highlight.js": "9.12.2", - "@types/lodash": "4.14.87", + "@types/lodash": "4.14.91", "@types/marked": "0.0.28", "@types/minimatch": "2.0.29", "@types/shelljs": "0.3.33", diff --git a/package.json b/package.json index 23b4461..3738a70 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,8 @@ }, "scripts": { "prepublish": "grunt peerDepInstall", + "precommit": "lint-staged", + "prettier": "prettier --write 'src/**/*.ts' 'tests/**/*.ts'", "test": "grunt test" }, "peerDependencies": { @@ -46,8 +48,28 @@ "@types/sinon": "^1.16.31", "grunt": "~1.0.1", "grunt-dojo2": "latest", + "grunt-tslint": "5.0.1", + "husky": "0.14.3", "intern": "~4.1.0", + "lint-staged": "6.0.0", + "prettier": "1.9.2", "sinon": "^2.2.0", + "tslint": "5.8.0", + "tslint-plugin-prettier": "1.3.0", "typescript": "~2.6.1" + }, + "lint-staged": { + "*.{ts,tsx}": [ + "prettier --write", + "git add" + ] + }, + "prettier": { + "singleQuote": true, + "tabWidth": 4, + "useTabs": true, + "parser": "typescript", + "printWidth": 120, + "arrowParens": "always" } } diff --git a/src/harness.ts b/src/harness.ts index 7a5fca0..2e076d0 100644 --- a/src/harness.ts +++ b/src/harness.ts @@ -47,14 +47,12 @@ export function findDNodeByKey(target: RenderResults, key: string | object): HNo if (findDNodeByKey(node, key)) { console.warn(`Duplicate key of "${key}" found.`); } - } - else { + } else { found = findDNodeByKey(node, key); } }); return found; - } - else { + } else { if (target && typeof target === 'object') { if (target.properties && target.properties.key === key) { return target; @@ -88,9 +86,10 @@ function decorateTarget(target: DNode): void { const { widgetConstructor, properties } = dNode; dNode.widgetConstructor = StubWidget; (properties as StubWidgetProperties)._stubTag = WIDGET_STUB_CUSTOM_ELEMENT; - (properties as StubWidgetProperties)._widgetName = typeof widgetConstructor === 'string' - ? widgetConstructor - : (widgetConstructor as any).name || ''; + (properties as StubWidgetProperties)._widgetName = + typeof widgetConstructor === 'string' + ? widgetConstructor + : (widgetConstructor as any).name || ''; }, isWNode ); @@ -123,8 +122,10 @@ interface SpyTarget { * @param base The base class to add the render spy to * @param target An object with a property named `lastRender` which will be set to the result of the `render()` method */ -function SpyWidgetMixin>>(base: T, target: SpyTarget): T & Constructor { - +function SpyWidgetMixin>>( + base: T, + target: SpyTarget +): T & Constructor { class SpyRender extends base { @afterRender() spyRender(result: RenderResults): RenderResults { @@ -150,7 +151,7 @@ interface MetaData { * the harnessed widget. */ class WidgetHarness extends WidgetBase { - private _id = ROOT_CUSTOM_ELEMENT_NAME + '-' + (++harnessId); + private _id = ROOT_CUSTOM_ELEMENT_NAME + '-' + ++harnessId; private _metaData: WeakMap, MetaData>; private _widgetConstructor: Constructor; @@ -213,11 +214,7 @@ class WidgetHarness extends WidgetBase { */ public render(): RenderResults { const { _id: id, _widgetConstructor, children, properties } = this; - return v( - ROOT_CUSTOM_ELEMENT_NAME, - { id }, - [ w(_widgetConstructor, properties, children) ] - ); + return v(ROOT_CUSTOM_ELEMENT_NAME, { id }, [w(_widgetConstructor, properties, children)]); } } @@ -248,7 +245,8 @@ export type MetaMockContext = T & { invalidate(): void; }; -type ProjectorWidgetHarness> = ProjectorMixin & WidgetHarness; +type ProjectorWidgetHarness> = ProjectorMixin & + WidgetHarness; const ProjectorWidgetHarness = ProjectorMixin(WidgetHarness); @@ -283,7 +281,7 @@ export class Harness> extends Evented { constructor(widgetConstructor: Constructor, root?: HTMLElement) { super(); - const widgetHarness = this._widgetHarness = new ProjectorWidgetHarness(widgetConstructor, this._metaMap); + const widgetHarness = (this._widgetHarness = new ProjectorWidgetHarness(widgetConstructor, this._metaMap)); // we want to control when the render gets scheduled, so we will hijack the projects one this._scheduleRender = widgetHarness.scheduleRender.bind(widgetHarness); widgetHarness.scheduleRender = () => {}; @@ -333,7 +331,7 @@ export class Harness> extends Evented { if (!this._projectorHandle) { this._invalidate(); } - if (!(this._widgetHarness.lastRender) || !(this._widgetHarness.lastRender as any).domNode) { + if (!this._widgetHarness.lastRender || !(this._widgetHarness.lastRender as any).domNode) { throw new Error('No root node has been rendered'); } return (this._widgetHarness.lastRender as any).domNode as HTMLElement; @@ -354,8 +352,7 @@ export class Harness> extends Evented { // TODO: no need to coerce in 2.5.2 mocks: mocks as any }); - } - else { + } else { // TODO: no need to coerce in 2.5.2 _metaMap.get(provider)!.mocks = mocks as any; } @@ -386,8 +383,7 @@ export class Harness> extends Evented { const dnode = findDNodeByKey(this._widgetHarness.lastRender, key); if (isHNode(dnode)) { target = (dnode as any).domNode as Element; - } - else { + } else { throw new Error(`Could not find key of "${key}" to sendEvent`); } } @@ -419,6 +415,9 @@ export class Harness> extends Evented { * @param widgetConstructor The constructor function/class of widget that should be harnessed. * @param root The root where the harness should append itself to the DOM. Defaults to `document.body` */ -export default function harness>(widgetConstructor: Constructor, root?: HTMLElement): Harness { +export default function harness>( + widgetConstructor: Constructor, + root?: HTMLElement +): Harness { return new Harness(widgetConstructor, root); } diff --git a/src/main.ts b/src/main.ts index 1b9921e..d2f234f 100644 --- a/src/main.ts +++ b/src/main.ts @@ -2,7 +2,15 @@ import harness from './harness'; import assertRender from './support/assertRender'; import callListener from './support/callListener'; import sendEvent from './support/sendEvent'; -import { assignChildProperties, assignProperties, findIndex, findKey, replaceChild, replaceChildProperties, replaceProperties } from './support/d'; +import { + assignChildProperties, + assignProperties, + findIndex, + findKey, + replaceChild, + replaceChildProperties, + replaceProperties +} from './support/d'; export { assertRender, diff --git a/src/resolvers.ts b/src/resolvers.ts index 9f51467..289c300 100644 --- a/src/resolvers.ts +++ b/src/resolvers.ts @@ -34,8 +34,7 @@ export function createResolvers() { rAFStub = stub(global, 'requestAnimationFrame').returns(1); if (global.requestIdleCallback) { rICStub = stub(global, 'requestIdleCallback').returns(1); - } - else { + } else { rICStub = stub(global, 'setTimeout').returns(1); } }, diff --git a/src/support/AssertionError.ts b/src/support/AssertionError.ts index 36805c0..811f095 100644 --- a/src/support/AssertionError.ts +++ b/src/support/AssertionError.ts @@ -35,9 +35,8 @@ * @param excluds excluded properties */ function exclude(...excludes: string[]) { - function excludeProps(res: any, obj: any) { - Object.keys(obj).forEach(function (key) { + Object.keys(obj).forEach(function(key) { if (!~excludes.indexOf(key)) { res[key] = obj[key]; } @@ -53,7 +52,7 @@ function exclude(...excludes: string[]) { return res; }; -}; +} export interface AssertionError extends Error { [prop: string]: any; @@ -91,12 +90,10 @@ function AssertionError(this: AssertionError, message?: string, _props?: any, ss // capture stack trace if (ssf && Error.captureStackTrace) { Error.captureStackTrace(this, ssf); - } - else { + } else { try { throw new Error(); - } - catch (e) { + } catch (e) { this.stack = e.stack; } } @@ -125,7 +122,7 @@ AssertionError.prototype.constructor = AssertionError; * * @param stack include stack (default: `true`) */ -AssertionError.prototype.toJSON = function (this: AssertionError, stack?: boolean) { +AssertionError.prototype.toJSON = function(this: AssertionError, stack?: boolean) { const extend = exclude('constructor', 'toJSON', 'stack'); const props: { [prop: string]: any } = extend({ name: this.name }, this); @@ -138,6 +135,6 @@ AssertionError.prototype.toJSON = function (this: AssertionError, stack?: boolea }; /* tslint:disable:variable-name */ -const AssertionErrorConstructor: AssertionErrorConstructor = AssertionError; +const AssertionErrorConstructor: AssertionErrorConstructor = AssertionError; export default AssertionErrorConstructor; diff --git a/src/support/assertRender.ts b/src/support/assertRender.ts index eae9027..fec8c14 100644 --- a/src/support/assertRender.ts +++ b/src/support/assertRender.ts @@ -26,9 +26,9 @@ export interface AssertRenderOptions extends DiffOptions { * @param expected The expected DNode */ function getArrayPreamble(actual: DNode | DNode[], expected: DNode | DNode[]): string { - return Array.isArray(actual) ? - `Expected "${getTypeOf(expected)}" but got an array` : - `Expected an array but got "${getTypeOf(actual)}"`; + return Array.isArray(actual) + ? `Expected "${getTypeOf(expected)}" but got an array` + : `Expected an array but got "${getTypeOf(actual)}"`; } /** @@ -40,8 +40,7 @@ function getChildMessage(childIndex: number, message: string = '') { const lastIndex = message.lastIndexOf(']'); if (lastIndex === -1) { return `[${childIndex}] ${message}`; - } - else { + } else { return message.slice(0, lastIndex + 1) + `[${childIndex}]` + message.slice(lastIndex + 1); } } @@ -71,11 +70,15 @@ function getTypeOf(value: any) { * @param message any message to be part of the error */ function throwAssertionError(actual: any, expected: any, prolog: string, message?: string): never { - throw new AssertionError(`${RENDER_FAIL_MESSAGE}: ${prolog}${message ? `: ${message}` : ''}`, { - actual, - expected, - showDiff: true - }, assertRender); + throw new AssertionError( + `${RENDER_FAIL_MESSAGE}: ${prolog}${message ? `: ${message}` : ''}`, + { + actual, + expected, + showDiff: true + }, + assertRender + ); } /** @@ -83,7 +86,7 @@ function throwAssertionError(actual: any, expected: any, prolog: string, message */ const defaultDiffOptions: DiffOptions = { allowFunctionValues: true, - ignoreProperties: [ 'bind' ] + ignoreProperties: ['bind'] }; /** @@ -97,13 +100,24 @@ const defaultDiffOptions: DiffOptions = { * @param message Any message to be part of an error thrown if actual and expected do not match */ export default function assertRender(actual: DNode | DNode[], expected: DNode | DNode[], message?: string): void; -export default function assertRender(actual: DNode | DNode[], expected: DNode | DNode[], options: AssertRenderOptions, message?: string): void; -export default function assertRender(actual: DNode | DNode[], expected: DNode | DNode[], options?: AssertRenderOptions | string, message?: string): void { +export default function assertRender( + actual: DNode | DNode[], + expected: DNode | DNode[], + options: AssertRenderOptions, + message?: string +): void; +export default function assertRender( + actual: DNode | DNode[], + expected: DNode | DNode[], + options?: AssertRenderOptions | string, + message?: string +): void { if (typeof options === 'string') { message = options; options = undefined; } - const { isHNode: localIsHNode = isHNode, isWNode: localIsWNode = isWNode, ...passedDiffOptions } = (options || {}) as AssertRenderOptions; + const { isHNode: localIsHNode = isHNode, isWNode: localIsWNode = isWNode, ...passedDiffOptions } = (options || + {}) as AssertRenderOptions; const diffOptions: DiffOptions = assign({}, defaultDiffOptions, passedDiffOptions); function assertChildren(actual?: DNode[], expected?: DNode[]) { @@ -112,10 +126,14 @@ export default function assertRender(actual: DNode | DNode[], expected: DNode | throwAssertionError(actual, expected, `Children's length mismatch`, message); } actual.forEach((actualChild, index) => { - assertRender(actualChild, expected[index], (options || {}) as AssertRenderOptions, getChildMessage(index, message)); + assertRender( + actualChild, + expected[index], + (options || {}) as AssertRenderOptions, + getChildMessage(index, message) + ); }); - } - else { + } else { if (actual || expected) { throwAssertionError(actual, expected, actual ? 'Unxpected children' : 'Expected children', message); } @@ -124,69 +142,74 @@ export default function assertRender(actual: DNode | DNode[], expected: DNode | if (Array.isArray(actual) && Array.isArray(expected)) { assertChildren(actual, expected); - } - else if (Array.isArray(actual) || Array.isArray(expected)) { + } else if (Array.isArray(actual) || Array.isArray(expected)) { throwAssertionError(actual, expected, getArrayPreamble(actual, expected), message); - } - else if ((localIsHNode(actual) && localIsHNode(expected)) || (localIsWNode(actual) && localIsWNode(expected))) { + } else if ((localIsHNode(actual) && localIsHNode(expected)) || (localIsWNode(actual) && localIsWNode(expected))) { if (localIsHNode(actual) && localIsHNode(expected)) { if (actual.tag !== expected.tag) { /* The tags do not match */ throwAssertionError(actual.tag, expected.tag, `Tags do not match`, message); } - } - /* istanbul ignore else: not being tracked by TypeScript properly */ - else if (localIsWNode(actual) && localIsWNode(expected)) { + } else if (localIsWNode(actual) && localIsWNode(expected)) { + /* istanbul ignore else: not being tracked by TypeScript properly */ if (actual.widgetConstructor !== expected.widgetConstructor) { /* The WNode does not share the same constructor */ - throwAssertionError(actual.widgetConstructor, expected.widgetConstructor, `WNodes do not share constructor`, message); + throwAssertionError( + actual.widgetConstructor, + expected.widgetConstructor, + `WNodes do not share constructor`, + message + ); } } /* Inject a custom comparator for class names */ - const expectedClasses: SupportedClassName | SupportedClassName[] = expected.properties && (expected.properties as any).classes; + const expectedClasses: SupportedClassName | SupportedClassName[] = + expected.properties && (expected.properties as any).classes; if (expectedClasses && !isCustomDiff(expectedClasses)) { - (expected.properties as any).classes = compareProperty((value: SupportedClassName | SupportedClassName[]) => { - const expectedValue = typeof expectedClasses === 'string' ? [ expectedClasses ] : expectedClasses; - value = (typeof value === 'string' ? [ value ] : value) || []; - const expectedSet = new Set(expectedValue.filter(expectedClass => Boolean(expectedClass))); - const actualSet = new Set(value.filter(actualClass => Boolean(actualClass))); + (expected.properties as any).classes = compareProperty( + (value: SupportedClassName | SupportedClassName[]) => { + const expectedValue = typeof expectedClasses === 'string' ? [expectedClasses] : expectedClasses; + value = (typeof value === 'string' ? [value] : value) || []; + const expectedSet = new Set(expectedValue.filter((expectedClass) => Boolean(expectedClass))); + const actualSet = new Set(value.filter((actualClass) => Boolean(actualClass))); - if (expectedSet.size !== actualSet.size) { - return false; - } + if (expectedSet.size !== actualSet.size) { + return false; + } - let allMatch = true; - actualSet.forEach(actualClass => { - allMatch = allMatch && expectedSet.has(actualClass); - }); - return allMatch; - } -); + let allMatch = true; + actualSet.forEach((actualClass) => { + allMatch = allMatch && expectedSet.has(actualClass); + }); + return allMatch; + } + ); } const delta = diff(actual.properties, expected.properties, diffOptions); if (delta.length) { /* The properties do not match */ - const { comparableA, comparableB } = getComparableObjects(actual.properties, expected.properties, diffOptions); + const { comparableA, comparableB } = getComparableObjects( + actual.properties, + expected.properties, + diffOptions + ); throwAssertionError(comparableA, comparableB, `Properties do not match`, message); } /* We need to assert the children match */ assertChildren(actual.children, expected.children); - } - else if (typeof actual === 'string' && typeof expected === 'string') { + } else if (typeof actual === 'string' && typeof expected === 'string') { /* Both DNodes are strings */ if (actual !== expected) { /* The strings do not match */ throwAssertionError(actual, expected, `Unexpected string values`, message); } - } - else if (isHNode(actual) && typeof expected === 'string') { + } else if (isHNode(actual) && typeof expected === 'string') { // when doing an expected render on already rendered nodes, strings are converted to _shell_ HNodes // so we want to compare to those instead if (actual.text !== expected) { throwAssertionError(actual.text, expected, `Expected text differs from rendered text`, message); } - } - else if (!(actual === null && expected === null)) { + } else if (!(actual === null && expected === null)) { /* There is a mismatch between the types of DNodes */ throwAssertionError(actual, expected, getMismatchPreamble(actual, expected), message); } diff --git a/src/support/callListener.ts b/src/support/callListener.ts index ff76a29..2149175 100644 --- a/src/support/callListener.ts +++ b/src/support/callListener.ts @@ -44,7 +44,7 @@ export default function callListener(node: RenderResults, method: string, option if (resolvedTargets == null || !resolvedTargets.length) { throw new TypeError(`Cannot resolve target`); } - resolvedTargets.forEach( (target) => { + resolvedTargets.forEach((target) => { const listener: ((...args: any[]) => void) | undefined = target.properties[method]; if (!listener) { throw new TypeError(`Cannot resolve listener: "${method}"`); @@ -67,27 +67,23 @@ function resolveTarget(node: RenderResults, options: CallListenerOptions): any[] } } return resolvedTargets; - } - else { + } else { let resolvedTarget: any; const { index, key, target } = options; if (target) { resolvedTarget = target; - } - else if (node != null && (typeof node !== 'string')) { + } else if (node != null && typeof node !== 'string') { if (key) { resolvedTarget = findKey(node, key); - } - else if (typeof index !== 'undefined') { + } else if (typeof index !== 'undefined') { const byIndex = findIndex(node, index); if (typeof byIndex === 'object' && byIndex !== null && 'properties' in byIndex) { resolvedTarget = byIndex; } - } - else { + } else { resolvedTarget = node; } } - return resolvedTarget && [ resolvedTarget ]; + return resolvedTarget && [resolvedTarget]; } } diff --git a/src/support/compare.ts b/src/support/compare.ts index cac685c..ddc9702 100644 --- a/src/support/compare.ts +++ b/src/support/compare.ts @@ -103,37 +103,39 @@ export interface ConstructRecord extends AnonymousConstructRecord { * A record that describes the mutations necessary to a property of an object to make that property look * like another */ -export type PatchRecord = { - /** - * The name of the property on the Object - */ - name: string; - - /** - * The type of the patch - */ - type: 'delete'; - } | { - /** - * A property descriptor that describes the property in `name` - */ - descriptor: PropertyDescriptor; - - /** - * The name of the property on the Object - */ - name: string; - - /** - * The type of the patch - */ - type: 'add' | 'update'; - - /** - * Additional patch records which describe the value of the property - */ - valueRecords?: (ConstructRecord | PatchRecord | SpliceRecord)[]; - }; +export type PatchRecord = + | { + /** + * The name of the property on the Object + */ + name: string; + + /** + * The type of the patch + */ + type: 'delete'; + } + | { + /** + * A property descriptor that describes the property in `name` + */ + descriptor: PropertyDescriptor; + + /** + * The name of the property on the Object + */ + name: string; + + /** + * The type of the patch + */ + type: 'add' | 'update'; + + /** + * Additional patch records which describe the value of the property + */ + valueRecords?: (ConstructRecord | PatchRecord | SpliceRecord)[]; + }; /** * The different types of patch records supported @@ -171,7 +173,11 @@ export interface SpliceRecord { * @param args Any arguments to be passed to the constructor function */ /* tslint:disable:variable-name */ -export function createConstructRecord(Ctor: Constructor, args?: any[], descriptor?: ConstructDescriptor): AnonymousConstructRecord { +export function createConstructRecord( + Ctor: Constructor, + args?: any[], + descriptor?: ConstructDescriptor +): AnonymousConstructRecord { const record: AnonymousConstructRecord = assign(objectCreate(null), { Ctor }); if (args) { record.args = args; @@ -191,7 +197,12 @@ export function createConstructRecord(Ctor: Constructor, args?: any[], descripto * @param descriptor The property descriptor to be installed on the object * @param valueRecords Any subsequenet patch recrds to be applied to the value of the descriptor */ -function createPatchRecord(type: PatchTypes, name: string, descriptor?: PropertyDescriptor, valueRecords?: (ConstructRecord | PatchRecord | SpliceRecord)[]): PatchRecord { +function createPatchRecord( + type: PatchTypes, + name: string, + descriptor?: PropertyDescriptor, + valueRecords?: (ConstructRecord | PatchRecord | SpliceRecord)[] +): PatchRecord { const patchRecord = assign(objectCreate(null), { type, name @@ -237,7 +248,12 @@ function createSpliceRecord(start: number, deleteCount: number, add?: any[]): Sp * @param enumerable Defaults to `true` if not specified * @param configurable Defaults to `true` if not specified */ -function createValuePropertyDescriptor(value: any, writable: boolean = true, enumerable: boolean = true, configurable: boolean = true): PropertyDescriptor { +function createValuePropertyDescriptor( + value: any, + writable: boolean = true, + enumerable: boolean = true, + configurable: boolean = true +): PropertyDescriptor { return assign(objectCreate(null), { value, writable, @@ -249,7 +265,11 @@ function createValuePropertyDescriptor(value: any, writable: boolean = true, enu /** * A function that returns a constructor record or `undefined` when diffing a value */ -export type CustomDiffFunction = (value: T, nameOrIndex: string | number, parent: object) => AnonymousConstructRecord | void; +export type CustomDiffFunction = ( + value: T, + nameOrIndex: string | number, + parent: object +) => AnonymousConstructRecord | void; /** * A class which is used when making a custom comparison of a non-plain object or array @@ -298,7 +318,8 @@ function diffArray(a: any[], b: any, options: DiffOptions): SpliceRecord[] { const lengthB = arrayB.length; const patchRecords: SpliceRecord[] = []; - if (!lengthA && lengthB) { /* empty array */ + if (!lengthA && lengthB) { + /* empty array */ patchRecords.push(createSpliceRecord(0, lengthB)); return patchRecords; } @@ -310,12 +331,15 @@ function diffArray(a: any[], b: any, options: DiffOptions): SpliceRecord[] { function flushSpliceRecord() { if (deleteCount || add.length) { - patchRecords.push(createSpliceRecord(start, start + deleteCount > lengthB ? lengthB - start : deleteCount, add)); + patchRecords.push( + createSpliceRecord(start, start + deleteCount > lengthB ? lengthB - start : deleteCount, add) + ); } } function addDifference(index: number, adding: boolean, value?: any) { - if (index > (last + 1)) { /* flush the splice */ + if (index > last + 1) { + /* flush the splice */ flushSpliceRecord(); start = index; deleteCount = 0; @@ -334,7 +358,10 @@ function diffArray(a: any[], b: any, options: DiffOptions): SpliceRecord[] { arrayA.forEach((valueA, index) => { const valueB = arrayB[index]; - if (index in arrayB && (valueA === valueB || (allowFunctionValues && typeof valueA === 'function' && typeof valueB === 'function'))) { + if ( + index in arrayB && + (valueA === valueB || (allowFunctionValues && typeof valueA === 'function' && typeof valueB === 'function')) + ) { return; /* not different */ } @@ -342,20 +369,22 @@ function diffArray(a: any[], b: any, options: DiffOptions): SpliceRecord[] { const isValueAPlainObject = isPlainObject(valueA); if (isValueAArray || isValueAPlainObject) { - const value = isValueAArray ? isArray(valueB) ? valueB : [] : isPlainObject(valueB) ? valueB : Object.create(null); + const value = isValueAArray + ? isArray(valueB) ? valueB : [] + : isPlainObject(valueB) ? valueB : Object.create(null); const valueRecords = diff(valueA, value, options); - if (valueRecords.length) { /* only add if there are changes */ + if (valueRecords.length) { + /* only add if there are changes */ addDifference(index, true, diff(valueA, value, options)); } - } - else if (isPrimitive(valueA)) { + } else if (isPrimitive(valueA)) { addDifference(index, true, valueA); - } - else if (allowFunctionValues && typeof valueA === 'function') { + } else if (allowFunctionValues && typeof valueA === 'function') { addDifference(index, true, valueA); - } - else { - throw new TypeError(`Value of array element "${index}" from first argument is not a primative, plain Object, or Array.`); + } else { + throw new TypeError( + `Value of array element "${index}" from first argument is not a primative, plain Object, or Array.` + ); } }); @@ -390,47 +419,58 @@ function diffPlainObject(a: any, b: any, options: DiffOptions): (ConstructRecord const valueB = b[name]; const bHasOwnProperty = hasOwnProperty.call(comparableB, name); - if (bHasOwnProperty && (valueA === valueB || - (allowFunctionValues && typeof valueA === 'function' && typeof valueB === 'function'))) { /* not different */ - /* when `allowFunctionValues` is true, functions are simply considered to be equal by `typeof` */ - return patchRecords; + if ( + bHasOwnProperty && + (valueA === valueB || (allowFunctionValues && typeof valueA === 'function' && typeof valueB === 'function')) + ) { + /* not different */ + /* when `allowFunctionValues` is true, functions are simply considered to be equal by `typeof` */ + return patchRecords; } const type = bHasOwnProperty ? 'update' : 'add'; const isValueAArray = isArray(valueA); const isValueAPlainObject = isPlainObject(valueA); - if (isCustomDiff(valueA) && !isCustomDiff(valueB)) { /* complex diff left hand */ + if (isCustomDiff(valueA) && !isCustomDiff(valueB)) { + /* complex diff left hand */ const result = valueA.diff(valueB, name, b); if (result) { patchRecords.push(result); } - } - else if (isCustomDiff(valueB)) { /* complex diff right hand */ + } else if (isCustomDiff(valueB)) { + /* complex diff right hand */ const result = valueB.diff(valueA, name, a); if (result) { patchRecords.push(result); } - } - else if ((isValueAArray || isValueAPlainObject)) { /* non-primitive values we can diff */ + } else if (isValueAArray || isValueAPlainObject) { + /* non-primitive values we can diff */ /* this is a bit complicated, but essentially if valueA and valueB are both arrays or plain objects, then * we can diff those two values, if not, then we need to use an empty array or an empty object and diff * the valueA with that */ - const value = (isValueAArray && isArray(valueB)) || (isValueAPlainObject && isPlainObject(valueB)) ? - valueB : isValueAArray ? - [] : objectCreate(null); + const value = + (isValueAArray && isArray(valueB)) || (isValueAPlainObject && isPlainObject(valueB)) + ? valueB + : isValueAArray ? [] : objectCreate(null); const valueRecords = diff(valueA, value, options); - if (valueRecords.length) { /* only add if there are changes */ - patchRecords.push(createPatchRecord(type, name, createValuePropertyDescriptor(value), diff(valueA, value, options))); + if (valueRecords.length) { + /* only add if there are changes */ + patchRecords.push( + createPatchRecord(type, name, createValuePropertyDescriptor(value), diff(valueA, value, options)) + ); } - } - else if (isPrimitive(valueA) || (allowFunctionValues && typeof valueA === 'function') || - isIgnoredPropertyValue(name, a, b, ignorePropertyValues)) { - /* primitive values, functions values if allowed, or ignored property values can just be copied */ - patchRecords.push(createPatchRecord(type, name, createValuePropertyDescriptor(valueA))); - } - else { - throw new TypeError(`Value of property named "${name}" from first argument is not a primative, plain Object, or Array.`); + } else if ( + isPrimitive(valueA) || + (allowFunctionValues && typeof valueA === 'function') || + isIgnoredPropertyValue(name, a, b, ignorePropertyValues) + ) { + /* primitive values, functions values if allowed, or ignored property values can just be copied */ + patchRecords.push(createPatchRecord(type, name, createValuePropertyDescriptor(valueA))); + } else { + throw new TypeError( + `Value of property named "${name}" from first argument is not a primative, plain Object, or Array.` + ); } return patchRecords; }, patchRecords); @@ -460,30 +500,42 @@ export function getComparableObjects(a: any, b: any, options: DiffOptions) { const ignore = new Set(); const keep = new Set(); - const isIgnoredProperty = Array.isArray(ignoreProperties) ? (name: string) => { - return ignoreProperties.some((value) => typeof value === 'string' ? name === value : value.test(name)); - } : (name: string) => ignoreProperties(name, a, b); - - const comparableA = keys(a).reduce((obj, name) => { - if (isIgnoredProperty(name) || - hasOwnProperty.call(b, name) && isIgnoredPropertyValue(name, a, b, ignorePropertyValues)) { + const isIgnoredProperty = Array.isArray(ignoreProperties) + ? (name: string) => { + return ignoreProperties.some( + (value) => (typeof value === 'string' ? name === value : value.test(name)) + ); + } + : (name: string) => ignoreProperties(name, a, b); + + const comparableA = keys(a).reduce( + (obj, name) => { + if ( + isIgnoredProperty(name) || + (hasOwnProperty.call(b, name) && isIgnoredPropertyValue(name, a, b, ignorePropertyValues)) + ) { ignore.add(name); return obj; - } - - keep.add(name); - obj[name] = a[name]; - return obj; - }, {} as { [key: string]: any }); + } - const comparableB = keys(b).reduce((obj, name) => { - if (ignore.has(name) || !keep.has(name) && isIgnoredProperty(name)) { + keep.add(name); + obj[name] = a[name]; return obj; - } + }, + {} as { [key: string]: any } + ); - obj[name] = b[name]; - return obj; - }, {} as { [key: string]: any }); + const comparableB = keys(b).reduce( + (obj, name) => { + if (ignore.has(name) || (!keep.has(name) && isIgnoredProperty(name))) { + return obj; + } + + obj[name] = b[name]; + return obj; + }, + {} as { [key: string]: any } + ); return { comparableA, comparableB, ignore }; } @@ -504,10 +556,17 @@ function isConstructRecord(value: any): value is ConstructRecord { return Boolean(value && typeof value === 'object' && value !== null && value.Ctor && value.name); } -function isIgnoredPropertyValue(name: string, a: any, b: any, ignoredPropertyValues: (string | RegExp)[] | IgnorePropertyFunction) { - return Array.isArray(ignoredPropertyValues) ? ignoredPropertyValues.some((value) => { - return typeof value === 'string' ? name === value : value.test(name); - }) : ignoredPropertyValues(name, a, b); +function isIgnoredPropertyValue( + name: string, + a: any, + b: any, + ignoredPropertyValues: (string | RegExp)[] | IgnorePropertyFunction +) { + return Array.isArray(ignoredPropertyValues) + ? ignoredPropertyValues.some((value) => { + return typeof value === 'string' ? name === value : value.test(name); + }) + : ignoredPropertyValues(name, a, b); } /** @@ -536,9 +595,7 @@ function isPatchRecordArray(value: any): value is PatchRecord[] { */ function isPlainObject(value: any): value is Object { return Boolean( - value && - typeof value === 'object' && - (value.constructor === Object || value.constructor === undefined) + value && typeof value === 'object' && (value.constructor === Object || value.constructor === undefined) ); } @@ -548,13 +605,15 @@ function isPlainObject(value: any): value is Object { * * @param value The value to check */ -function isPrimitive(value: any): value is (string | number | boolean | undefined | null) { +function isPrimitive(value: any): value is string | number | boolean | undefined | null { const typeofValue = typeof value; - return value === null || + return ( + value === null || typeofValue === 'undefined' || typeofValue === 'string' || typeofValue === 'number' || - typeofValue === 'boolean'; + typeofValue === 'boolean' + ); } /** @@ -583,8 +642,7 @@ function patchSplice(target: any[], { add, deleteCount, start }: SpliceRecord): const deletedItems = deleteCount ? target.slice(start, start + deleteCount) : []; add = add.map((value, index) => resolveTargetValue(value, deletedItems[index])); target.splice(start, deleteCount, ...add); - } - else { + } else { target.splice(start, deleteCount); } return target; @@ -617,7 +675,9 @@ function patchConstruct(target: any, record: ConstructRecord): any { const { args, descriptor = defaultConstructDescriptor, Ctor, name, propertyRecords } = record; const value = new Ctor(...(args || [])); if (propertyRecords) { - propertyRecords.forEach((record) => isConstructRecord(record) ? patchConstruct(value, record) : patchPatch(value, record)); + propertyRecords.forEach( + (record) => (isConstructRecord(record) ? patchConstruct(value, record) : patchPatch(value, record)) + ); } defineProperty(target, name, assign({ value }, descriptor)); return target; @@ -629,15 +689,14 @@ function patchConstruct(target: any, record: ConstructRecord): any { */ function resolveTargetValue(patchValue: any, targetValue: any): any { const patchIsSpliceRecordArray = isSpliceRecordArray(patchValue); - return (patchIsSpliceRecordArray || isPatchRecordArray(patchValue)) ? - patch( - patchIsSpliceRecordArray ? - isArray(targetValue) ? - targetValue : [] : isPlainObject(targetValue) ? - targetValue : objectCreate(null), - patchValue - ) : - patchValue; + return patchIsSpliceRecordArray || isPatchRecordArray(patchValue) + ? patch( + patchIsSpliceRecordArray + ? isArray(targetValue) ? targetValue : [] + : isPlainObject(targetValue) ? targetValue : objectCreate(null), + patchValue + ) + : patchValue; } /** @@ -686,7 +745,8 @@ export function patch(target: any, records: (ConstructRecord | PatchRecord | Spl records.forEach((record) => { target = isSpliceRecord(record) ? patchSplice(isArray(target) ? target : [], record) /* patch arrays */ - : isConstructRecord(record) ? patchConstruct(target, record) /* patch complex object */ + : isConstructRecord(record) + ? patchConstruct(target, record) /* patch complex object */ : patchPatch(isPlainObject(target) ? target : {}, record); /* patch plain object */ }); return target; diff --git a/src/support/d.ts b/src/support/d.ts index 29cc771..bfc02aa 100644 --- a/src/support/d.ts +++ b/src/support/d.ts @@ -6,9 +6,9 @@ import { CustomDiff } from './compare'; export type RenderResults = DNode | DNode[]; -type FoundNodeInfo = { found?: T, parent?: WNode | HNode | undefined, index?: number }; +type FoundNodeInfo = { found?: T; parent?: WNode | HNode | undefined; index?: number }; -function assignChildPropertiesByKeyOrIndex( +function assignChildPropertiesByKeyOrIndex( target: WNode | HNode, keyOrIndex: string | number | object, properties: WidgetProperties | VirtualDomProperties, @@ -18,24 +18,42 @@ function assignChildPropertiesByKeyOrIndex( if (!node || !(isWNode(node) || isHNode(node))) { const keyOrIndexString = typeof keyOrIndex === 'object' ? JSON.stringify(keyOrIndex) : keyOrIndex; - throw new TypeError(`${(byKey || typeof keyOrIndex === 'object') ? 'Key' : 'Index'} of "${keyOrIndexString}" is not resolving to a valid target`); + throw new TypeError( + `${ + byKey || typeof keyOrIndex === 'object' ? 'Key' : 'Index' + } of "${keyOrIndexString}" is not resolving to a valid target` + ); } assignProperties(node, properties); return target; } -export function assignChildProperties(target: WNode | HNode, index: number | string, properties: WidgetProperties | VirtualDomProperties): WNode | HNode { - return assignChildPropertiesByKeyOrIndex(target, index, properties); +export function assignChildProperties( + target: WNode | HNode, + index: number | string, + properties: WidgetProperties | VirtualDomProperties +): WNode | HNode { + return assignChildPropertiesByKeyOrIndex(target, index, properties); } -export function assignChildPropertiesByKey(target: WNode | HNode, key: string | object, properties: WidgetProperties | VirtualDomProperties): WNode | HNode { +export function assignChildPropertiesByKey( + target: WNode | HNode, + key: string | object, + properties: WidgetProperties | VirtualDomProperties +): WNode | HNode { return assignChildPropertiesByKeyOrIndex(target, key, properties, true); } export function assignProperties(target: HNode, properties: VirtualDomProperties): HNode; export function assignProperties(target: WNode, properties: WidgetProperties): WNode; -export function assignProperties(target: WNode | HNode, properties: WidgetProperties | VirtualDomProperties): WNode | HNode; -export function assignProperties(target: WNode | HNode, properties: WidgetProperties | VirtualDomProperties): WNode | HNode { +export function assignProperties( + target: WNode | HNode, + properties: WidgetProperties | VirtualDomProperties +): WNode | HNode; +export function assignProperties( + target: WNode | HNode, + properties: WidgetProperties | VirtualDomProperties +): WNode | HNode { assign(target.properties, properties); return target; } @@ -45,7 +63,9 @@ export function assignProperties(target: WNode | HNode, properties: WidgetProper * of the property is considered equal, otherwise it is considered not equal and the expected render will fail. * @param callback A function that is invoked when comparing the property value */ -export function compareProperty(callback: (value: T, name: string | number, parent: WidgetProperties | VirtualDomProperties) => boolean): CustomDiff { +export function compareProperty( + callback: (value: T, name: string | number, parent: WidgetProperties | VirtualDomProperties) => boolean +): CustomDiff { function differ(value: T, name: string | number, parent: WidgetProperties | VirtualDomProperties) { if (!callback(value, name, parent)) { throw new AssertionError(`The value of property "${name}" is unexpected.`, {}, differ); @@ -68,13 +88,15 @@ function replaceChildByKeyOrIndex( if (!parent || typeof index === 'undefined' || !parent.children) { if (byKey || typeof indexOrKey === 'object') { - throw new TypeError(`Key of "${typeof indexOrKey === 'object' ? JSON.stringify(indexOrKey) : indexOrKey}" is not resolving to a valid target`); - } - else { + throw new TypeError( + `Key of "${ + typeof indexOrKey === 'object' ? JSON.stringify(indexOrKey) : indexOrKey + }" is not resolving to a valid target` + ); + } else { throw new TypeError(`Index of "${indexOrKey}" is not resolving to a valid target`); } - } - else { + } else { parent.children[index] = replacement; } @@ -112,9 +134,8 @@ function isNode(value: any): value is WNode | HNode { function findByKeyOrIndex(target: WNode | HNode, keyOrIndex: string | number | object, byKey = false) { if (byKey || typeof keyOrIndex === 'object') { - return findByKey(target, keyOrIndex); - } - else { + return findByKey(target, keyOrIndex); + } else { return findByIndex(target, keyOrIndex); } } @@ -132,28 +153,23 @@ function findByKey( return {}; } let nodeInfo: FoundNodeInfo | undefined; - target.children - .forEach((child, index) => { - if (isNode(child)) { - if (nodeInfo && nodeInfo.found) { - if (findByKey(child, key, target, index).found) { - console.warn(`Duplicate key of "${typeof key === 'object' ? JSON.stringify(key) : key }" found.`); - } - } - else { - nodeInfo = findByKey(child, key, target, index); + target.children.forEach((child, index) => { + if (isNode(child)) { + if (nodeInfo && nodeInfo.found) { + if (findByKey(child, key, target, index).found) { + console.warn(`Duplicate key of "${typeof key === 'object' ? JSON.stringify(key) : key}" found.`); } + } else { + nodeInfo = findByKey(child, key, target, index); } - }); + } + }); return nodeInfo || {}; } -function findByIndex( - target: WNode | HNode, - index: number | string -): FoundNodeInfo { +function findByIndex(target: WNode | HNode, index: number | string): FoundNodeInfo { if (typeof index === 'number') { - return target.children ? { parent: target, found: target.children[index], index } : {}; + return target.children ? { parent: target, found: target.children[index], index } : {}; } const indexes = index.split(',').map(Number); const lastIndex = indexes.pop()!; @@ -200,29 +216,46 @@ function replaceChildPropertiesByKeyOrIndex( if (!found || !(isWNode(found) || isHNode(found))) { if (byKey || typeof indexOrKey === 'object') { - throw new TypeError(`Key of "${typeof indexOrKey === 'object' ? JSON.stringify(indexOrKey) : indexOrKey}" is not resolving to a valid target`); - } - else { + throw new TypeError( + `Key of "${ + typeof indexOrKey === 'object' ? JSON.stringify(indexOrKey) : indexOrKey + }" is not resolving to a valid target` + ); + } else { throw new TypeError(`Index of "${indexOrKey}" is not resolving to a valid target`); } } - replaceProperties(found, properties); + replaceProperties(found, properties); return target; } -export function replaceChildProperties(target: WNode | HNode, index: number | string, properties: WidgetProperties | VirtualDomProperties): WNode | HNode { +export function replaceChildProperties( + target: WNode | HNode, + index: number | string, + properties: WidgetProperties | VirtualDomProperties +): WNode | HNode { return replaceChildPropertiesByKeyOrIndex(target, index, properties); } -export function replaceChildPropertiesByKey(target: WNode | HNode, key: string | object, properties: WidgetProperties | VirtualDomProperties): WNode | HNode { - return replaceChildPropertiesByKeyOrIndex(target, key, properties, true); +export function replaceChildPropertiesByKey( + target: WNode | HNode, + key: string | object, + properties: WidgetProperties | VirtualDomProperties +): WNode | HNode { + return replaceChildPropertiesByKeyOrIndex(target, key, properties, true); } export function replaceProperties(target: HNode, properties: VirtualDomProperties): HNode; export function replaceProperties(target: WNode, properties: WidgetProperties): WNode; -export function replaceProperties(target: WNode | HNode, properties: WidgetProperties | VirtualDomProperties): WNode | HNode; -export function replaceProperties(target: WNode | HNode, properties: WidgetProperties | VirtualDomProperties): WNode | HNode { +export function replaceProperties( + target: WNode | HNode, + properties: WidgetProperties | VirtualDomProperties +): WNode | HNode; +export function replaceProperties( + target: WNode | HNode, + properties: WidgetProperties | VirtualDomProperties +): WNode | HNode { target.properties = properties; return target; } diff --git a/src/support/interfaces.d.ts b/src/support/interfaces.d.ts index 75544a7..6405f9a 100644 --- a/src/support/interfaces.d.ts +++ b/src/support/interfaces.d.ts @@ -7,7 +7,9 @@ declare module 'assertion-error' { stack: string; } - module AssertionError { } + namespace AssertionError { + + } export = AssertionError; } diff --git a/src/support/loadJsdom.ts b/src/support/loadJsdom.ts index 78191ec..b28f013 100644 --- a/src/support/loadJsdom.ts +++ b/src/support/loadJsdom.ts @@ -28,16 +28,19 @@ if (!('document' in global)) { virtualConsole.sendTo(console); /* Create a new jsdom instance */ - const dom = new jsdom.JSDOM(` + const dom = new jsdom.JSDOM( + ` - `, { - virtualConsole, - runScripts: 'dangerously' - }); + `, + { + virtualConsole, + runScripts: 'dangerously' + } + ); /* Assign a global window */ global.window = dom.window; @@ -55,7 +58,7 @@ if (!('document' in global)) { Object.defineProperty( window.CSSStyleDeclaration.prototype, 'transition', - Object.getOwnPropertyDescriptor(( window).CSSStyleDeclaration.prototype, 'webkitTransition')! + Object.getOwnPropertyDescriptor((window).CSSStyleDeclaration.prototype, 'webkitTransition')! ); /* Polyfill requestAnimationFrame - this can never be called an *actual* polyfill */ @@ -68,8 +71,7 @@ if (!('document' in global)) { global.cancelAnimationFrame = () => {}; hasAdd('jsdom', true); -} -else { +} else { doc = document; /* istanbul ignore else */ if (!exists('jsdom')) { diff --git a/src/support/sendEvent.ts b/src/support/sendEvent.ts index bc47e13..b788737 100644 --- a/src/support/sendEvent.ts +++ b/src/support/sendEvent.ts @@ -5,64 +5,63 @@ hasAdd('customevent-constructor', () => { try { new window.CustomEvent('foo'); return true; - } - catch (e) { + } catch (e) { return false; } }); export type EventClass = - 'AnimationEvent' | - 'AudioProcessingEvent' | - 'BeforeInputEvent' | - 'BeforeUnloadEvent' | - 'BlobEvent' | - 'ClipboardEvent' | - 'CloseEvent' | - 'CompositionEvent' | - 'CSSFontFaceLoadEvent' | - 'CustomEvent' | - 'DeviceLightEvent' | - 'DeviceMotionEvent' | - 'DeviceOrientationEvent' | - 'DeviceProximityEvent' | - 'DOMTransactionEvent' | - 'DragEvent' | - 'EditingBeforeInputEvent' | - 'ErrorEvent' | - 'FetchEvent' | - 'FocusEvent' | - 'GamepadEvent' | - 'HashChangeEvent' | - 'IDBVersionChangeEvent' | - 'InputEvent' | - 'KeyboardEvent' | - 'MediaStreamEvent' | - 'MessageEvent' | - 'MouseEvent' | - 'MutationEvent' | - 'OfflineAudioCompletionEvent' | - 'PageTransitionEvent' | - 'PointerEvent' | - 'PopStateEvent' | - 'ProgressEvent' | - 'RelatedEvent' | - 'RTCDataChannelEvent' | - 'RTCIdentityErrorEvent' | - 'RTCIdentityEvent' | - 'RTCPeerConnectionIceEvent' | - 'SensorEvent' | - 'StorageEvent' | - 'SVGEvent' | - 'SVGZoomEvent' | - 'TimeEvent' | - 'TouchEvent' | - 'TrackEvent' | - 'TransitionEvent' | - 'UIEvent' | - 'UserProximityEvent' | - 'WebGLContextEvent' | - 'WheelEvent'; + | 'AnimationEvent' + | 'AudioProcessingEvent' + | 'BeforeInputEvent' + | 'BeforeUnloadEvent' + | 'BlobEvent' + | 'ClipboardEvent' + | 'CloseEvent' + | 'CompositionEvent' + | 'CSSFontFaceLoadEvent' + | 'CustomEvent' + | 'DeviceLightEvent' + | 'DeviceMotionEvent' + | 'DeviceOrientationEvent' + | 'DeviceProximityEvent' + | 'DOMTransactionEvent' + | 'DragEvent' + | 'EditingBeforeInputEvent' + | 'ErrorEvent' + | 'FetchEvent' + | 'FocusEvent' + | 'GamepadEvent' + | 'HashChangeEvent' + | 'IDBVersionChangeEvent' + | 'InputEvent' + | 'KeyboardEvent' + | 'MediaStreamEvent' + | 'MessageEvent' + | 'MouseEvent' + | 'MutationEvent' + | 'OfflineAudioCompletionEvent' + | 'PageTransitionEvent' + | 'PointerEvent' + | 'PopStateEvent' + | 'ProgressEvent' + | 'RelatedEvent' + | 'RTCDataChannelEvent' + | 'RTCIdentityErrorEvent' + | 'RTCIdentityEvent' + | 'RTCPeerConnectionIceEvent' + | 'SensorEvent' + | 'StorageEvent' + | 'SVGEvent' + | 'SVGZoomEvent' + | 'TimeEvent' + | 'TouchEvent' + | 'TrackEvent' + | 'TransitionEvent' + | 'UIEvent' + | 'UserProximityEvent' + | 'WebGLContextEvent' + | 'WheelEvent'; export interface SendEventOptions { /** @@ -91,8 +90,11 @@ export interface EventInitializer { * @param type The event type to dispatch * @param options A map of options to configure the event */ -export default function sendEvent(target: Element, type: string, options?: SendEventOptions): void { - +export default function sendEvent( + target: Element, + type: string, + options?: SendEventOptions +): void { function dispatchEvent(target: Element, event: Event) { let error: Error | undefined; @@ -110,22 +112,16 @@ export default function sendEvent(target: Element, type: st } } - const { - eventClass = 'CustomEvent', - eventInit = {} as EventInit, - selector = '' - } = options || {}; + const { eventClass = 'CustomEvent', eventInit = {} as EventInit, selector = '' } = options || {}; let dispatchTarget: Element | undefined; if (selector) { const selectorTarget = target.querySelector(selector); if (selectorTarget) { dispatchTarget = selectorTarget; - } - else { + } else { throw new Error(`Cannot resolve to an element with selector "${selector}"`); } - } - else { + } else { dispatchTarget = target; } if (dispatchTarget) { @@ -137,9 +133,8 @@ export default function sendEvent(target: Element, type: st const { bubbles, cancelable, ...initProps } = eventInit; if (has('customevent-constructor')) { const ctorName = eventClass in window ? eventClass : 'CustomEvent'; - event = new (( window)[ctorName] as typeof CustomEvent)(type, eventInit); - } - else { + event = new ((window)[ctorName] as typeof CustomEvent)(type, eventInit); + } else { /* because the arity varies too greatly to be able to properly call all the event types, we will * only support CustomEvent for those platforms that don't support event constructors, which is * essentially IE11 */ @@ -148,8 +143,9 @@ export default function sendEvent(target: Element, type: st } try { deepAssign(event, initProps); + } catch (e) { + /* swallowing assignment errors when trying to overwrite native event properties */ } - catch (e) { /* swallowing assignment errors when trying to overwrite native event properties */ } dispatchEvent(dispatchTarget, event); } } diff --git a/tests/support/NodeId.ts b/tests/support/NodeId.ts index bca3127..e38e2e3 100644 --- a/tests/support/NodeId.ts +++ b/tests/support/NodeId.ts @@ -7,4 +7,4 @@ export default class NodeId extends Base { return node.id; } } -}; +} diff --git a/tests/unit/harness.ts b/tests/unit/harness.ts index 0b17550..241e604 100644 --- a/tests/unit/harness.ts +++ b/tests/unit/harness.ts @@ -14,7 +14,7 @@ import assertRender from '../../src/support/assertRender'; const hasFunctionName = (() => { function foo() {} - return ( foo).name === 'foo'; + return (foo).name === 'foo'; })(); interface MockWidgetProperties extends WidgetProperties { @@ -26,15 +26,13 @@ interface MockWidgetProperties extends WidgetProperties { class MockWidget extends WidgetBase { render() { - return v('div', { classes: [ 'foo' ] }); + return v('div', { classes: ['foo'] }); } } class MockArrayWidget extends WidgetBase { render() { - return [ - v('div', { classes: [ 'foo' ] }) - ]; + return [v('div', { classes: ['foo'] })]; } } @@ -52,28 +50,33 @@ class RegistryWidgetChild extends WidgetBase { } } -class RegisterChildWidget extends WidgetBase { +class RegisterChildWidget extends WidgetBase { render() { const registry = new MockRegistry(); registry.tag = this.properties.tag; - return v('div', { - key: 'wrapper' - }, [ w(RegistryWidgetChild, { - key: 'child', - registry - }) ]); + return v( + 'div', + { + key: 'wrapper' + }, + [ + w(RegistryWidgetChild, { + key: 'child', + registry + }) + ] + ); } } class SubWidget extends WidgetBase { render() { - return v('div', { }, [ w(MockWidget, { key: 'first' }), w('widget', { key: 'second' }) ]); + return v('div', {}, [w(MockWidget, { key: 'first' }), w('widget', { key: 'second' })]); } } registerSuite('harness', { - - 'rendering': { + rendering: { 'nodes are added during rendering'() { const widget = harness(MockWidget); const dom = widget.getDom(); @@ -90,7 +93,11 @@ registerSuite('harness', { const widget = harness(MockWidget, div); const parentElement = widget.getDom().parentElement!; - assert.strictEqual(parentElement.parentElement, div, 'the root of the harness should be a child of the div'); + assert.strictEqual( + parentElement.parentElement, + div, + 'the root of the harness should be a child of the div' + ); widget.destroy(); document.body.removeChild(div); /* cleanup after test */ }, @@ -104,8 +111,7 @@ registerSuite('harness', { assert.strictEqual(dom.children[1].tagName, 'TEST--WIDGET-STUB'); if (hasFunctionName) { assert.strictEqual(dom.children[0].getAttribute('data--widget-name'), 'MockWidget'); - } - else { + } else { assert.strictEqual(dom.children[0].getAttribute('data--widget-name'), ''); } assert.strictEqual(dom.children[1].getAttribute('data--widget-name'), 'widget'); @@ -117,7 +123,11 @@ registerSuite('harness', { class CustomEventWidget extends WidgetBase { render() { - return v('div', { onfoo() { called = true; }}); + return v('div', { + onfoo() { + called = true; + } + }); } } @@ -166,9 +176,13 @@ registerSuite('harness', { const widget = harness(NullWidget); - assert.throws(() => { - widget.getDom(); - }, Error, 'No root node has been rendered'); + assert.throws( + () => { + widget.getDom(); + }, + Error, + 'No root node has been rendered' + ); widget.destroy(); } @@ -177,13 +191,13 @@ registerSuite('harness', { '.expectRender()': { 'HNode render - matches'() { const widget = harness(MockWidget); - widget.expectRender(v('div', { classes: [ 'foo' ] })); + widget.expectRender(v('div', { classes: ['foo'] })); widget.destroy(); }, 'HNode render array - matches'() { const widget = harness(MockArrayWidget); - widget.expectRender([ v('div', { classes: [ 'foo' ] }) ]); + widget.expectRender([v('div', { classes: ['foo'] })]); widget.destroy(); }, @@ -212,7 +226,7 @@ registerSuite('harness', { 'HNode render - does not match'() { const widget = harness(MockWidget); assert.throws(() => { - widget.expectRender(v('div', { classes: [ 'bar' ] })); + widget.expectRender(v('div', { classes: ['bar'] })); }); widget.destroy(); }, @@ -220,7 +234,7 @@ registerSuite('harness', { 'HNode render array - does not match'() { const widget = harness(MockWidget); assert.throws(() => { - widget.expectRender([ v('div', { classes: [ 'baz' ] }) ]); + widget.expectRender([v('div', { classes: ['baz'] })]); }); widget.destroy(); }, @@ -233,7 +247,7 @@ registerSuite('harness', { } const widget = harness(MockWidget); assert.throws(() => { - widget.expectRender([ v('div', { classes: [ 'baz' ] }) ]); + widget.expectRender([v('div', { classes: ['baz'] })]); }); widget.destroy(); }, @@ -246,39 +260,43 @@ registerSuite('harness', { } const widget = harness(MockWidget); assert.throws(() => { - widget.expectRender([ v('div', { classes: [ 'baz' ] }) ]); + widget.expectRender([v('div', { classes: ['baz'] })]); }); widget.destroy(); }, 'WNode children render - matches'() { const widget = harness(SubWidget); - widget.expectRender(v('div', { }, [ w(MockWidget, { key: 'first' }), w('widget', { key: 'second' }) ])); + widget.expectRender(v('div', {}, [w(MockWidget, { key: 'first' }), w('widget', { key: 'second' })])); widget.destroy(); }, 'WNode children render - does not match'() { const widget = harness(SubWidget); assert.throws(() => { - widget.expectRender(v('div', { }, [ w(MockWidget, { key: 'fist' }), w('widget', { key: 'second' }) ])); + widget.expectRender(v('div', {}, [w(MockWidget, { key: 'fist' }), w('widget', { key: 'second' })])); }); widget.destroy(); }, 'render does not occur'() { class BrokenRender { - addDecorator() { } - __setProperties__() { } - on() { } - own() { } - __setChildren__() { } - __render__() { } + addDecorator() {} + __setProperties__() {} + on() {} + own() {} + __setChildren__() {} + __render__() {} } const widget = harness(BrokenRender as any); - assert.throws(() => { - widget.expectRender(null); - }, Error, 'An expected render did not occur.'); + assert.throws( + () => { + widget.expectRender(null); + }, + Error, + 'An expected render did not occur.' + ); widget.destroy(); }, @@ -288,7 +306,7 @@ registerSuite('harness', { onClick = () => { called = true; this.invalidate(); - } + }; render() { return v('div', { @@ -300,9 +318,11 @@ registerSuite('harness', { const widget = harness(SelfInvalidateWidget); widget.callListener('onClick'); assert.isTrue(called); - widget.expectRender(v('div', { - onClick: widget.listener - })); + widget.expectRender( + v('div', { + onClick: widget.listener + }) + ); }, 'with comparison': { @@ -312,16 +332,20 @@ registerSuite('harness', { tag: 'foo' }); let called = false; - const compareRegistry = compareProperty((value: MockRegistry, name, properties: RegistryWidgetProperties | VirtualDomProperties) => { - called = true; - assert.instanceOf(value, MockRegistry); - assert.strictEqual(name, 'registry'); - assert.strictEqual(properties.key, 'child'); - return value.tag === 'foo'; - }); - widget.expectRender(v('div', { key: 'wrapper' }, [ - w(RegistryWidgetChild, { key: 'child', registry: compareRegistry }) - ])); + const compareRegistry = compareProperty( + (value: MockRegistry, name, properties: RegistryWidgetProperties | VirtualDomProperties) => { + called = true; + assert.instanceOf(value, MockRegistry); + assert.strictEqual(name, 'registry'); + assert.strictEqual(properties.key, 'child'); + return value.tag === 'foo'; + } + ); + widget.expectRender( + v('div', { key: 'wrapper' }, [ + w(RegistryWidgetChild, { key: 'child', registry: compareRegistry }) + ]) + ); assert.isTrue(called, 'comparer should have been called'); }, @@ -335,11 +359,17 @@ registerSuite('harness', { called = true; return value.tag === 'foo'; }); - assert.throws(() => { - widget.expectRender(v('div', { key: 'wrapper' }, [ - w(RegistryWidgetChild, { key: 'child', registry: compareRegistry }) - ])); - }, AssertionError, 'The value of property "registry" is unexpected.'); + assert.throws( + () => { + widget.expectRender( + v('div', { key: 'wrapper' }, [ + w(RegistryWidgetChild, { key: 'child', registry: compareRegistry }) + ]) + ); + }, + AssertionError, + 'The value of property "registry" is unexpected.' + ); assert.isTrue(called, 'comparer should have been called'); }, @@ -378,7 +408,7 @@ registerSuite('harness', { 'widget render - array value compare'() { class ArrayWidget extends WidgetBase { render() { - return v('div', { array: [ 3 ] }); + return v('div', { array: [3] }); } } const widget = harness(ArrayWidget); @@ -386,7 +416,7 @@ registerSuite('harness', { return array.length === 1 && array[0] === 3; }); const compareId = compareProperty(comparisonStub); - widget.expectRender(v('div', { array : compareId as any })); + widget.expectRender(v('div', { array: compareId as any })); assert.isTrue(comparisonStub.calledOnce, 'comparer should have been called'); } } @@ -402,12 +432,9 @@ registerSuite('harness', { const widget = harness(ParentWidget); - widget.setChildren([ v('span'), v('a', { href: 'http://dojo.io' }) ]); + widget.setChildren([v('span'), v('a', { href: 'http://dojo.io' })]); - widget.expectRender(v('div', {}, [ - v('span'), - v('a', { href: 'http://dojo.io' }) - ])); + widget.expectRender(v('div', {}, [v('span'), v('a', { href: 'http://dojo.io' })])); widget.destroy(); } @@ -421,19 +448,19 @@ registerSuite('harness', { class DynamicWidget extends WidgetBase { render() { - return this.properties.flag ? - v('div', { }, [ w(MockWidget, { key: 'first' }), w(MockWidget, { key: 'second' }) ]) : - v('div', { }, [ w(MockWidget, { key: 'first' }) ]); + return this.properties.flag + ? v('div', {}, [w(MockWidget, { key: 'first' }), w(MockWidget, { key: 'second' })]) + : v('div', {}, [w(MockWidget, { key: 'first' })]); } } const widget = harness(DynamicWidget); widget.setProperties({ flag: false }); - widget.expectRender(v('div', { }, [ w(MockWidget, { key: 'first' }) ])); + widget.expectRender(v('div', {}, [w(MockWidget, { key: 'first' })])); widget.setProperties({ flag: true }); - widget.expectRender(v('div', { }, [ w(MockWidget, { key: 'first' }), w(MockWidget, { key: 'second' }) ])); + widget.expectRender(v('div', {}, [w(MockWidget, { key: 'first' }), w(MockWidget, { key: 'second' })])); widget.destroy(); } @@ -497,7 +524,7 @@ registerSuite('harness', { } render() { - return v('div', { onclick: this.onClick }, [ v('button') ]); + return v('div', { onclick: this.onClick }, [v('button')]); } } @@ -536,7 +563,7 @@ registerSuite('harness', { } render() { - return v('div', { key: 'wrap', onclick: this.onClick }, [ v('button', { key: 'button' }) ]); + return v('div', { key: 'wrap', onclick: this.onClick }, [v('button', { key: 'button' })]); } } @@ -558,17 +585,21 @@ registerSuite('harness', { 'with key not found'() { class ButtonWidget extends WidgetBase { render() { - return v('div', { key: 'wrap' }, [ v('button', { key: 'button' }), 'foo', 'bar' ]); + return v('div', { key: 'wrap' }, [v('button', { key: 'button' }), 'foo', 'bar']); } } const widget = harness(ButtonWidget); - assert.throws(() => { - widget.sendEvent('click', { - key: 'foo' - }); - }, Error, 'Could not find key of "foo" to sendEvent'); + assert.throws( + () => { + widget.sendEvent('click', { + key: 'foo' + }); + }, + Error, + 'Could not find key of "foo" to sendEvent' + ); widget.destroy(); }, @@ -578,17 +609,9 @@ registerSuite('harness', { render() { return v('div', { key: 'foo' }, [ 'foo', - v('span', { key: 'parent1' }, [ - v('i', { key: 'icon', id: 'i1' }, [ 'bar' ]), - 'bar' - ]), - v('span', { key: 'parent2' }, [ - v('i', { key: 'super-icon', id: 'i1' }, [ 'bar' ]), - 'bar' - ]), - v('span', { key: 'parent3' }, [ - v('i', { key: 'icon', id: 'i2' }, [ 'bar' ]) - ]) + v('span', { key: 'parent1' }, [v('i', { key: 'icon', id: 'i1' }, ['bar']), 'bar']), + v('span', { key: 'parent2' }, [v('i', { key: 'super-icon', id: 'i1' }, ['bar']), 'bar']), + v('span', { key: 'parent3' }, [v('i', { key: 'icon', id: 'i2' }, ['bar'])]) ]); } } @@ -600,7 +623,11 @@ registerSuite('harness', { key: 'icon' }); assert.strictEqual(warnStub.callCount, 1, 'should have been called once'); - assert.strictEqual(warnStub.lastCall.args[0], 'Duplicate key of "icon" found.', 'should have logged duplicate key'); + assert.strictEqual( + warnStub.lastCall.args[0], + 'Duplicate key of "icon" found.', + 'should have logged duplicate key' + ); warnStub.restore(); }, @@ -615,31 +642,49 @@ registerSuite('harness', { const widget = harness(TextOnlyWidget); - assert.throws(() => { - widget.sendEvent('click', { - key: 'foo' - }); - }, Error, 'No root node has been rendered'); + assert.throws( + () => { + widget.sendEvent('click', { + key: 'foo' + }); + }, + Error, + 'No root node has been rendered' + ); widget.destroy(); } }, '.callListener()': { - 'defaults'() { + defaults() { let rootClick = 0; let firstClick = 0; let secondClick = 0; class ComplexSubWidget extends WidgetBase { render() { - return v('div', { - onclick() { - rootClick++; - } - }, [ - w(MockWidget, { onClick() { firstClick++; }, key: 'first' }), - w('widget', { onClick() { secondClick++; }, key: 'second' }) - ]); + return v( + 'div', + { + onclick() { + rootClick++; + } + }, + [ + w(MockWidget, { + onClick() { + firstClick++; + }, + key: 'first' + }), + w('widget', { + onClick() { + secondClick++; + }, + key: 'second' + }) + ] + ); } } @@ -657,24 +702,52 @@ registerSuite('harness', { class ComplexSubWidget extends WidgetBase { render() { return [ - v('div', { - key: 'parent1', - onclick() { - rootClick++; - } - }, [ - w(MockWidget, { onClick() { firstClick++; }, key: 'first' }), - w('widget', { onClick() { secondClick++; }, key: 'second' }) - ]), - v('div', { - key: 'parent2', - onclick() { - rootClick++; - } - }, [ - w(MockWidget, { onClick() { firstClick++; }, key: 'first' }), - w('widget', { onClick() { secondClick++; }, key: 'second' }) - ]) + v( + 'div', + { + key: 'parent1', + onclick() { + rootClick++; + } + }, + [ + w(MockWidget, { + onClick() { + firstClick++; + }, + key: 'first' + }), + w('widget', { + onClick() { + secondClick++; + }, + key: 'second' + }) + ] + ), + v( + 'div', + { + key: 'parent2', + onclick() { + rootClick++; + } + }, + [ + w(MockWidget, { + onClick() { + firstClick++; + }, + key: 'first' + }), + w('widget', { + onClick() { + secondClick++; + }, + key: 'second' + }) + ] + ) ]; } } @@ -692,14 +765,28 @@ registerSuite('harness', { let secondClick = 0; class ComplexSubWidget extends WidgetBase { render() { - return v('div', { - onclick() { - rootClick++; - } - }, [ - w(MockWidget, { onClick() { firstClick++; }, key: 'first' }), - w('widget', { onClick() { secondClick++; }, key: 'second' }) - ]); + return v( + 'div', + { + onclick() { + rootClick++; + } + }, + [ + w(MockWidget, { + onClick() { + firstClick++; + }, + key: 'first' + }), + w('widget', { + onClick() { + secondClick++; + }, + key: 'second' + }) + ] + ); } } @@ -717,18 +804,32 @@ registerSuite('harness', { class ComplexSubWidget extends WidgetBase { render() { return [ - v( 'div', { + v('div', { key: 'parent1' }), - v('div', { - key: 'parent2', - onclick() { - rootClick++; - } - }, [ - w(MockWidget, { onClick() { firstClick++; }, key: 'first' }), - w('widget', { onClick() { secondClick++; }, key: 'second' }) - ]) + v( + 'div', + { + key: 'parent2', + onclick() { + rootClick++; + } + }, + [ + w(MockWidget, { + onClick() { + firstClick++; + }, + key: 'first' + }), + w('widget', { + onClick() { + secondClick++; + }, + key: 'second' + }) + ] + ) ]; } } @@ -746,14 +847,28 @@ registerSuite('harness', { let secondClick = 0; class ComplexSubWidget extends WidgetBase { render() { - return v('div', { - onclick() { - rootClick++; - } - }, [ - w(MockWidget, { onClick() { firstClick++; }, key: 'first' }), - w('widget', { onClick() { secondClick++; }, key: 'second' }) - ]); + return v( + 'div', + { + onclick() { + rootClick++; + } + }, + [ + w(MockWidget, { + onClick() { + firstClick++; + }, + key: 'first' + }), + w('widget', { + onClick() { + secondClick++; + }, + key: 'second' + }) + ] + ); } } @@ -767,10 +882,13 @@ registerSuite('harness', { 'properties.bind'() { class ComplexSubWidget extends WidgetBase { render() { - return v('div', { }, [ - w(MockWidget, { onClick(this: any) { - assert.instanceOf(this, ComplexSubWidget, 'should call with bound scope'); - }, key: 'first' }) + return v('div', {}, [ + w(MockWidget, { + onClick(this: any) { + assert.instanceOf(this, ComplexSubWidget, 'should call with bound scope'); + }, + key: 'first' + }) ]); } } @@ -793,7 +911,7 @@ registerSuite('harness', { const widget = harness(BasicWidget); widget.callListener('onclick', { - args: [ event ] + args: [event] }); }, @@ -805,9 +923,13 @@ registerSuite('harness', { } const widget = harness(StringWidget); - assert.throws(() => { - widget.callListener('onclick'); - }, TypeError, 'Widget is not rendering an HNode or WNode'); + assert.throws( + () => { + widget.callListener('onclick'); + }, + TypeError, + 'Widget is not rendering an HNode or WNode' + ); }, 'widget renders null'() { @@ -818,27 +940,35 @@ registerSuite('harness', { } const widget = harness(NullWidget); - assert.throws(() => { - widget.callListener('onclick'); - }, TypeError, 'Widget is not rendering an HNode or WNode'); + assert.throws( + () => { + widget.callListener('onclick'); + }, + TypeError, + 'Widget is not rendering an HNode or WNode' + ); } }, '.getDom()'() { const widget = harness(MockWidget); const dom = widget.getDom(); - assert.strictEqual(dom.parentElement && dom.parentElement.innerHTML, '
', 'widget was rendered to the DOM as expected'); + assert.strictEqual( + dom.parentElement && dom.parentElement.innerHTML, + '
', + 'widget was rendered to the DOM as expected' + ); widget.destroy(); }, '.getRender()'() { class ChildTextWidget extends WidgetBase { render() { - return v('div', {}, [ 'foo' ]); + return v('div', {}, ['foo']); } } const widget = harness(ChildTextWidget); - assertRender(widget.getRender(), v('div', {}, [ 'foo' ])); + assertRender(widget.getRender(), v('div', {}, ['foo'])); widget.destroy(); }, @@ -846,7 +976,9 @@ registerSuite('harness', { 'handles premature removal from the dom'() { const widget = harness(MockWidget); const dom = widget.getDom(); - dom.parentElement && dom.parentElement.parentElement && dom.parentElement.parentElement.removeChild(dom.parentElement); + dom.parentElement && + dom.parentElement.parentElement && + dom.parentElement.parentElement.removeChild(dom.parentElement); widget.destroy(); }, @@ -874,10 +1006,14 @@ registerSuite('harness', { class IdWidget extends WidgetBase { render() { idStack.push(this.meta(NodeId).get('foo')); - return v('div', { - key: 'foo', - id: 'foo' - }, [ 'Hello world' ]); + return v( + 'div', + { + key: 'foo', + id: 'foo' + }, + ['Hello world'] + ); } } @@ -885,7 +1021,7 @@ registerSuite('harness', { widget.getRender(); - assert.deepEqual(idStack, [ undefined, 'foo' ]); + assert.deepEqual(idStack, [undefined, 'foo']); const handle = widget.mockMeta(NodeId, { get(key: string | number) { @@ -899,7 +1035,7 @@ registerSuite('harness', { widget.getRender(); - assert.deepEqual(idStack, [ undefined, 'foo', 'qat' ]); + assert.deepEqual(idStack, [undefined, 'foo', 'qat']); handle.destroy(); widget.setProperties({ @@ -908,7 +1044,7 @@ registerSuite('harness', { widget.getRender(); - assert.deepEqual(idStack, [ undefined, 'foo', 'qat', undefined ]); + assert.deepEqual(idStack, [undefined, 'foo', 'qat', undefined]); widget.destroy(); }, @@ -917,19 +1053,29 @@ registerSuite('harness', { class IdWidget extends WidgetBase<{ flush: boolean }> { render() { const content = this.meta(NodeId).get('foo'); - return v('div', { - key: 'foo', - id: 'foo' - }, [ content ? content : 'foo' ]); + return v( + 'div', + { + key: 'foo', + id: 'foo' + }, + [content ? content : 'foo'] + ); } } const widget = harness(IdWidget); - widget.expectRender(v('div', { - key: 'foo', - id: 'foo' - }, [ 'foo' ])); + widget.expectRender( + v( + 'div', + { + key: 'foo', + id: 'foo' + }, + ['foo'] + ) + ); widget.mockMeta(NodeId, { get(this: MetaMockContext, key: string | number) { @@ -940,10 +1086,16 @@ registerSuite('harness', { widget.setProperties({ flush: true }); - widget.expectRender(v('div', { - key: 'foo', - id: 'foo' - }, [ 'qat' ])); + widget.expectRender( + v( + 'div', + { + key: 'foo', + id: 'foo' + }, + ['qat'] + ) + ); widget.destroy(); }, @@ -954,10 +1106,14 @@ registerSuite('harness', { class IdWidget extends WidgetBase { render() { idStack.push(this.meta(NodeId).get('foo')); - return v('div', { - key: 'foo', - id: 'foo' - }, [ 'Hello world' ]); + return v( + 'div', + { + key: 'foo', + id: 'foo' + }, + ['Hello world'] + ); } } @@ -971,7 +1127,7 @@ registerSuite('harness', { widget.getRender(); - assert.deepEqual(idStack, [ 'qat' ]); + assert.deepEqual(idStack, ['qat']); const handle2 = widget.mockMeta(NodeId, { get(key: string | number) { @@ -987,7 +1143,7 @@ registerSuite('harness', { widget.getRender(); - assert.deepEqual(idStack, [ 'qat', 'baz' ]); + assert.deepEqual(idStack, ['qat', 'baz']); handle1.destroy(); @@ -995,7 +1151,7 @@ registerSuite('harness', { } }, - 'findDNodeByKey': { + findDNodeByKey: { 'should not error with string'() { findDNodeByKey('foo', 'bar'); } diff --git a/tests/unit/main.ts b/tests/unit/main.ts index 4fa1b50..90d0e7a 100644 --- a/tests/unit/main.ts +++ b/tests/unit/main.ts @@ -6,10 +6,17 @@ import harness from '../../src/harness'; import assertRender from '../../src/support/assertRender'; import callListener from '../../src/support/callListener'; import sendEvent from '../../src/support/sendEvent'; -import { assignChildProperties, assignProperties, findIndex, findKey, replaceChild, replaceChildProperties, replaceProperties } from '../../src/support/d'; +import { + assignChildProperties, + assignProperties, + findIndex, + findKey, + replaceChild, + replaceChildProperties, + replaceProperties +} from '../../src/support/d'; registerSuite('main', { - 'validate api'() { assert(main); diff --git a/tests/unit/resolvers.ts b/tests/unit/resolvers.ts index 2bd6088..9b8bcee 100644 --- a/tests/unit/resolvers.ts +++ b/tests/unit/resolvers.ts @@ -47,9 +47,12 @@ registerSuite('resolvers', { resolvers.restore(); const dfd = this.async(); - setTimeout(dfd.callback(() => { - assert.isTrue(callback.calledOnce); - }), 100); + setTimeout( + dfd.callback(() => { + assert.isTrue(callback.calledOnce); + }), + 100 + ); }, 'resolve idle callback'() { @@ -66,9 +69,12 @@ registerSuite('resolvers', { resolvers.restore(); const dfd = this.async(); - setTimeout(dfd.callback(() => { - assert.isTrue(callback.calledOnce); - }), 100); + setTimeout( + dfd.callback(() => { + assert.isTrue(callback.calledOnce); + }), + 100 + ); } } }); diff --git a/tests/unit/support/AssertionError.ts b/tests/unit/support/AssertionError.ts index 813286e..823fd15 100644 --- a/tests/unit/support/AssertionError.ts +++ b/tests/unit/support/AssertionError.ts @@ -4,22 +4,21 @@ const { assert } = intern.getPlugin('chai'); import AssertionError from '../../../src/support/AssertionError'; registerSuite('support/AssertionError', { - - 'construction'() { + construction() { const err = new AssertionError(); assert(err instanceof Error, 'instanceof Error'); assert(err instanceof AssertionError, 'instanceof AssertionError'); assert(err.name && err.name === 'AssertionError', 'name === "AssertionError"'); }, - 'message'() { + message() { const err = new AssertionError('Oops.'); const empty = new AssertionError(); assert(err.message === 'Oops.', 'w/ err.message'); assert(empty.message === 'Unspecified AssertionError', 'w/o err.message'); }, - 'stack'() { + stack() { assert(typeof new AssertionError().stack === 'string'); }, diff --git a/tests/unit/support/assertRender.ts b/tests/unit/support/assertRender.ts index 8350a6c..f963573 100644 --- a/tests/unit/support/assertRender.ts +++ b/tests/unit/support/assertRender.ts @@ -27,494 +27,493 @@ class OtherWidget extends WidgetBase { } registerSuite('support/assertRender', { - 'v()': { 'tag equal'() { - assertRender( - v('div'), - v('div') - ); + assertRender(v('div'), v('div')); }, 'array HNodes equal'() { - assertRender( - [ v('div'), v('span') ], - [ v('div'), v('span') ] - ); + assertRender([v('div'), v('span')], [v('div'), v('span')]); }, 'actual HNodes array and expected HNode not equal'() { - assert.throws(() => { - assertRender( - [ v('div'), v('span') ], - v('div') - ); - }, AssertionError, 'Render unexpected'); + assert.throws( + () => { + assertRender([v('div'), v('span')], v('div')); + }, + AssertionError, + 'Render unexpected' + ); }, 'expected HNode and expected HNode array not equal'() { - assert.throws(() => { - assertRender( - v('div'), - [ v('div'), v('span') ] - ); - }, AssertionError, 'Render unexpected'); + assert.throws( + () => { + assertRender(v('div'), [v('div'), v('span')]); + }, + AssertionError, + 'Render unexpected' + ); }, 'tag difference'() { - assert.throws(() => { - assertRender(v('div'), v('span')); - }, AssertionError, 'Render unexpected'); + assert.throws( + () => { + assertRender(v('div'), v('span')); + }, + AssertionError, + 'Render unexpected' + ); }, 'properties equal'() { - assertRender( - v('div', { styles: { 'color': 'black' } }), - v('div', { styles: { 'color': 'black' } }) - ); + assertRender(v('div', { styles: { color: 'black' } }), v('div', { styles: { color: 'black' } })); }, 'properties not equal'() { - assert.throws(() => { - assertRender( - v('div', { styles: { 'color': 'black' } }), - v('div', { styles: { 'color': 'white' } }) - ); - }, AssertionError, 'Render unexpected'); + assert.throws( + () => { + assertRender(v('div', { styles: { color: 'black' } }), v('div', { styles: { color: 'white' } })); + }, + AssertionError, + 'Render unexpected' + ); }, 'function properties equal'() { - assertRender( - v('div', { func() { } }), - v('div', { func() { } }) - ); + assertRender(v('div', { func() {} }), v('div', { func() {} })); }, 'unexpected function property'() { - assert.throws(() => { - assertRender( - v('div', { func() { } }), - v('div', { }) - ); - }, AssertionError, 'Render unexpected'); + assert.throws( + () => { + assertRender(v('div', { func() {} }), v('div', {})); + }, + AssertionError, + 'Render unexpected' + ); }, 'missing function property'() { - assert.throws(() => { - assertRender( - v('div', { }), - v('div', { func() { } }) - ); - }, AssertionError, 'Render unexpected'); + assert.throws( + () => { + assertRender(v('div', {}), v('div', { func() {} })); + }, + AssertionError, + 'Render unexpected' + ); }, 'empty children'() { - assertRender( - v('div', { }, []), - v('div', { }, []) - ); + assertRender(v('div', {}, []), v('div', {}, [])); }, 'missing children'() { - assert.throws(() => { - assertRender( - v('div', {}), - v('div', {}, []) - ); - }, AssertionError, 'Render unexpected: Expected children'); + assert.throws( + () => { + assertRender(v('div', {}), v('div', {}, [])); + }, + AssertionError, + 'Render unexpected: Expected children' + ); }, 'unexpected children'() { - assert.throws(() => { - assertRender( - v('div', {}, []), - v('div', {}) - ); - }, AssertionError, 'Render unexpected: Unxpected children'); + assert.throws( + () => { + assertRender(v('div', {}, []), v('div', {})); + }, + AssertionError, + 'Render unexpected: Unxpected children' + ); }, 'string children equal'() { - assertRender( - v('div', { }, [ 'foo' ]), - v('div', { }, [ 'foo' ]) - ); + assertRender(v('div', {}, ['foo']), v('div', {}, ['foo'])); }, 'string children unequal'() { - assert.throws(() => { - assertRender( - v('div', { }, [ 'foo' ]), - v('div', { }, [ 'bar' ]) - ); - }, AssertionError, 'Render unexpected: Unexpected string values'); + assert.throws( + () => { + assertRender(v('div', {}, ['foo']), v('div', {}, ['bar'])); + }, + AssertionError, + 'Render unexpected: Unexpected string values' + ); }, 'rendered string child equal'() { - const actual = v('div', { }, [ v('', { })] ); + const actual = v('div', {}, [v('', {})]); (actual.children![0] as any).text = 'foo'; - assertRender( - actual, - v('div', { }, [ 'foo' ]) - ); + assertRender(actual, v('div', {}, ['foo'])); }, 'rendered string child not equal'() { - const actual = v('div', { }, [ v('', { })] ); + const actual = v('div', {}, [v('', {})]); (actual.children![0] as any).text = 'foo'; - assert.throws(() => { - assertRender( - actual, - v('div', { }, [ 'bar' ]) - ); - }, AssertionError, 'Render unexpected: Expected text differs from rendered text: [0]'); + assert.throws( + () => { + assertRender(actual, v('div', {}, ['bar'])); + }, + AssertionError, + 'Render unexpected: Expected text differs from rendered text: [0]' + ); }, 'missing child'() { - assert.throws(() => { - assertRender( - v('div', { }, [ 'foo' ]), - v('div', { }, [ 'foo', 'bar' ]) - ); - }, AssertionError, 'Render unexpected'); + assert.throws( + () => { + assertRender(v('div', {}, ['foo']), v('div', {}, ['foo', 'bar'])); + }, + AssertionError, + 'Render unexpected' + ); }, 'extra child'() { - assert.throws(() => { - assertRender( - v('div', { }, [ 'foo', 'bar' ]), - v('div', { }, [ 'foo' ]) - ); - }, AssertionError, 'Render unexpected'); + assert.throws( + () => { + assertRender(v('div', {}, ['foo', 'bar']), v('div', {}, ['foo'])); + }, + AssertionError, + 'Render unexpected' + ); }, 'HNode children equal'() { - assertRender( - v('div', { }, [ v('span', {}, [ 'foo' ]) ]), - v('div', { }, [ v('span', {}, [ 'foo' ]) ]) - ); + assertRender(v('div', {}, [v('span', {}, ['foo'])]), v('div', {}, [v('span', {}, ['foo'])])); }, 'HNode children not equal'() { - assert.throws(() => { - assertRender( - v('div', { }, [ v('span', {}, [ 'foo' ]) ]), - v('div', { }, [ v('i', {}, [ 'foo' ]) ]) - ); - }, AssertionError, 'Render unexpected: Tags do not match: [0]'); + assert.throws( + () => { + assertRender(v('div', {}, [v('span', {}, ['foo'])]), v('div', {}, [v('i', {}, ['foo'])])); + }, + AssertionError, + 'Render unexpected: Tags do not match: [0]' + ); }, 'WNode children equal'() { assertRender( - v('div', { }, [ v('span', {}, [ w(MockWidget, { foo: 'bar', baz() { } }) ]) ]), - v('div', { }, [ v('span', {}, [ w(MockWidget, { foo: 'bar', baz() { } }) ]) ]) + v('div', {}, [v('span', {}, [w(MockWidget, { foo: 'bar', baz() {} })])]), + v('div', {}, [v('span', {}, [w(MockWidget, { foo: 'bar', baz() {} })])]) ); }, 'WNode children not equal'() { - assert.throws(() => { - assertRender( - v('div', { }, [ v('span', {}, [ w(MockWidget, { foo: 'bar', baz() { } }) ]) ]), - v('div', { }, [ v('span', {}, [ w(MockWidget, { foo: 'baz', baz() { } }) ]) ]) - ); - }, AssertionError, 'Render unexpected'); + assert.throws( + () => { + assertRender( + v('div', {}, [v('span', {}, [w(MockWidget, { foo: 'bar', baz() {} })])]), + v('div', {}, [v('span', {}, [w(MockWidget, { foo: 'baz', baz() {} })])]) + ); + }, + AssertionError, + 'Render unexpected' + ); }, 'compare unique classes only'() { assertRender( - v('div', { classes: [ 'foo', null, 'bar' ] }), - v('div', { classes: [ null, 'bar', 'foo', undefined ] }) + v('div', { classes: ['foo', null, 'bar'] }), + v('div', { classes: [null, 'bar', 'foo', undefined] }) ); - assertRender( - v('div', { classes: null }), - v('div', { classes: [] }) - ); + assertRender(v('div', { classes: null }), v('div', { classes: [] })); - assertRender( - v('div', { classes: 'foo' }), - v('div', { classes: [ 'foo' ] }) - ); + assertRender(v('div', { classes: 'foo' }), v('div', { classes: ['foo'] })); - assertRender( - v('div', { classes: 'foo' }), - v('div', { classes: 'foo' }) - ); + assertRender(v('div', { classes: 'foo' }), v('div', { classes: 'foo' })); - assert.throws(() => { - assertRender( - v('div', { classes: 'foo' }), - v('div', { classes: [ 'bar' ] }) - ); - }, AssertionError, 'The value of property "classes" is unexpected.'); + assert.throws( + () => { + assertRender(v('div', { classes: 'foo' }), v('div', { classes: ['bar'] })); + }, + AssertionError, + 'The value of property "classes" is unexpected.' + ); - assert.throws(() => { - assertRender( - v('div', { classes: [ 'foo', null, 'bar' ] }), - v('div', { classes: [ 'foo', null, 'baz' ] }) - ); - }, AssertionError, 'The value of property "classes" is unexpected.'); + assert.throws( + () => { + assertRender( + v('div', { classes: ['foo', null, 'bar'] }), + v('div', { classes: ['foo', null, 'baz'] }) + ); + }, + AssertionError, + 'The value of property "classes" is unexpected.' + ); - assert.throws(() => { - assertRender( - v('div', { classes: [ 'foo', 'bar', 'baz' ] }), - v('div', { classes: [ 'foo', 'bar' ] }) - ); - }, AssertionError, 'The value of property "classes" is unexpected.'); + assert.throws( + () => { + assertRender(v('div', { classes: ['foo', 'bar', 'baz'] }), v('div', { classes: ['foo', 'bar'] })); + }, + AssertionError, + 'The value of property "classes" is unexpected.' + ); } }, 'w()': { 'class equal'() { - assertRender( - w(MockWidget, {}), - w(MockWidget, {}) - ); + assertRender(w(MockWidget, {}), w(MockWidget, {})); }, 'WNode array equal'() { - assertRender( - [ w(MockWidget, {}) ], - [ w(MockWidget, {}) ] - ); + assertRender([w(MockWidget, {})], [w(MockWidget, {})]); }, 'string constructors equal'() { - assertRender( - w('foo', {}), - w('foo', {}) - ); + assertRender(w('foo', {}), w('foo', {})); }, 'class equal, different properties'() { - assert.throws(() => { - assertRender( - w(MockWidget, { foo: 'bar' }), - w(MockWidget, { bar: 2 }) - ); - }, AssertionError, 'Render unexpected'); + assert.throws( + () => { + assertRender(w(MockWidget, { foo: 'bar' }), w(MockWidget, { bar: 2 })); + }, + AssertionError, + 'Render unexpected' + ); }, 'property missing'() { - assert.throws(() => { - assertRender( - w(MockWidget, { foo: 'bar' }), - w(MockWidget, { }) - ); - }, AssertionError, 'Render unexpected'); + assert.throws( + () => { + assertRender(w(MockWidget, { foo: 'bar' }), w(MockWidget, {})); + }, + AssertionError, + 'Render unexpected' + ); }, 'property different'() { - assert.throws(() => { - assertRender( - w(MockWidget, { foo: 'bar' }), - w(MockWidget, { foo: 'baz' }) - ); - }, AssertionError, 'Render unexpected'); + assert.throws( + () => { + assertRender(w(MockWidget, { foo: 'bar' }), w(MockWidget, { foo: 'baz' })); + }, + AssertionError, + 'Render unexpected' + ); }, 'property extra'() { - assert.throws(() => { - assertRender( - w(MockWidget, { foo: 'bar' }), - w(MockWidget, { foo: 'bar', bar: 2 }) - ); - }, AssertionError, 'Render unexpected'); + assert.throws( + () => { + assertRender(w(MockWidget, { foo: 'bar' }), w(MockWidget, { foo: 'bar', bar: 2 })); + }, + AssertionError, + 'Render unexpected' + ); }, 'properties have functions'() { - assertRender( - w(MockWidget, { baz() {} }), - w(MockWidget, { baz() {} }) - ); + assertRender(w(MockWidget, { baz() {} }), w(MockWidget, { baz() {} })); }, 'added function'() { - assert.throws(() => { - assertRender( - w(MockWidget, { baz() {} }), - w(MockWidget, { }) - ); - }, AssertionError, 'Render unexpected'); + assert.throws( + () => { + assertRender(w(MockWidget, { baz() {} }), w(MockWidget, {})); + }, + AssertionError, + 'Render unexpected' + ); }, 'missing function'() { - assert.throws(() => { - assertRender( - w(MockWidget, { }), - w(MockWidget, { baz() {} }) - ); - }, AssertionError, 'Render unexpected'); + assert.throws( + () => { + assertRender(w(MockWidget, {}), w(MockWidget, { baz() {} })); + }, + AssertionError, + 'Render unexpected' + ); }, 'class unequal'() { - assert.throws(() => { - assertRender( - w(MockWidget, {}), - w(OtherWidget, {}) - ); - }, AssertionError, 'Render unexpected'); + assert.throws( + () => { + assertRender(w(MockWidget, {}), w(OtherWidget, {})); + }, + AssertionError, + 'Render unexpected' + ); }, 'string constructor unequal'() { - assert.throws(() => { - assertRender( - w('foo', {}), - w('bar', {}) - ); - }, AssertionError, 'Render unexpected'); + assert.throws( + () => { + assertRender(w('foo', {}), w('bar', {})); + }, + AssertionError, + 'Render unexpected' + ); }, 'empty children'() { - assertRender( - w(MockWidget, {}, []), - w(MockWidget, {}, []) - ); + assertRender(w(MockWidget, {}, []), w(MockWidget, {}, [])); }, 'string children equal'() { - assertRender( - w(MockWidget, {}, [ 'foo' ]), - w(MockWidget, {}, [ 'foo' ]) - ); + assertRender(w(MockWidget, {}, ['foo']), w(MockWidget, {}, ['foo'])); }, 'HNode children equal'() { - assertRender( - w(MockWidget, {}, [ v('div') ]), - w(MockWidget, {}, [ v('div') ]) - ); + assertRender(w(MockWidget, {}, [v('div')]), w(MockWidget, {}, [v('div')])); }, 'WNode children equal'() { - assertRender( - w(MockWidget, {}, [ w(OtherWidget, {}) ]), - w(MockWidget, {}, [ w(OtherWidget, {}) ]) - ); + assertRender(w(MockWidget, {}, [w(OtherWidget, {})]), w(MockWidget, {}, [w(OtherWidget, {})])); }, 'unexpected children'() { - assert.throws(() => { - assertRender( - w(MockWidget, { }, [ w(OtherWidget, {}) ]), - w(MockWidget, { }) - ); - }, AssertionError, 'Render unexpected'); + assert.throws( + () => { + assertRender(w(MockWidget, {}, [w(OtherWidget, {})]), w(MockWidget, {})); + }, + AssertionError, + 'Render unexpected' + ); }, 'missing children'() { - assert.throws(() => { - assertRender( - w(MockWidget, { }), - w(MockWidget, { }, [ w(OtherWidget, {}) ]) - ); - }, AssertionError, 'Render unexpected'); + assert.throws( + () => { + assertRender(w(MockWidget, {}), w(MockWidget, {}, [w(OtherWidget, {})])); + }, + AssertionError, + 'Render unexpected' + ); }, 'extra child'() { - assert.throws(() => { - assertRender( - w(MockWidget, { }, [ w(OtherWidget, {}), w(OtherWidget, {}) ]), - w(MockWidget, { }, [ w(OtherWidget, {}) ]) - ); - }, AssertionError, 'Render unexpected'); + assert.throws( + () => { + assertRender( + w(MockWidget, {}, [w(OtherWidget, {}), w(OtherWidget, {})]), + w(MockWidget, {}, [w(OtherWidget, {})]) + ); + }, + AssertionError, + 'Render unexpected' + ); }, 'missing child'() { - assert.throws(() => { - assertRender( - w(MockWidget, { }, [ w(OtherWidget, {}) ]), - w(MockWidget, { }, [ w(OtherWidget, {}), w(OtherWidget, {}) ]) - ); - }, AssertionError, 'Render unexpected'); + assert.throws( + () => { + assertRender( + w(MockWidget, {}, [w(OtherWidget, {})]), + w(MockWidget, {}, [w(OtherWidget, {}), w(OtherWidget, {})]) + ); + }, + AssertionError, + 'Render unexpected' + ); }, 'bind property ignored'() { const bind = new MockWidget(); - assertRender( - w(MockWidget, { bind }), - w(MockWidget, { }) - ); + assertRender(w(MockWidget, { bind }), w(MockWidget, {})); }, 'compare unique classes only'() { assertRender( - w(MockWidget, { classes: [ 'foo', null, 'bar' ] }), - w(MockWidget, { classes: [ null, 'bar', 'foo', undefined ] }) + w(MockWidget, { classes: ['foo', null, 'bar'] }), + w(MockWidget, { classes: [null, 'bar', 'foo', undefined] }) ); - assertRender( - w(MockWidget, { classes: null }), - w(MockWidget, { classes: [] }) - ); + assertRender(w(MockWidget, { classes: null }), w(MockWidget, { classes: [] })); - assertRender( - w(MockWidget, { classes: 'foo' }), - w(MockWidget, { classes: [ 'foo' ] }) - ); + assertRender(w(MockWidget, { classes: 'foo' }), w(MockWidget, { classes: ['foo'] })); - assertRender( - w(MockWidget, { classes: 'foo' }), - w(MockWidget, { classes: 'foo' }) - ); + assertRender(w(MockWidget, { classes: 'foo' }), w(MockWidget, { classes: 'foo' })); - assert.throws(() => { - assertRender( - w(MockWidget, { classes: 'foo' }), - w(MockWidget, { classes: [ 'bar' ] }) - ); - }, AssertionError, 'The value of property "classes" is unexpected.'); + assert.throws( + () => { + assertRender(w(MockWidget, { classes: 'foo' }), w(MockWidget, { classes: ['bar'] })); + }, + AssertionError, + 'The value of property "classes" is unexpected.' + ); - assert.throws(() => { - assertRender( - w(MockWidget, { classes: [ 'foo', null, 'bar' ] }), - w(MockWidget, { classes: [ 'foo', null, 'baz' ] }) - ); - }, AssertionError, 'The value of property "classes" is unexpected.'); + assert.throws( + () => { + assertRender( + w(MockWidget, { classes: ['foo', null, 'bar'] }), + w(MockWidget, { classes: ['foo', null, 'baz'] }) + ); + }, + AssertionError, + 'The value of property "classes" is unexpected.' + ); - assert.throws(() => { - assertRender( - w(MockWidget, { classes: [ 'foo', 'bar', 'baz' ] }), - w(MockWidget, { classes: [ 'foo', 'bar' ] }) - ); - }, AssertionError, 'The value of property "classes" is unexpected.'); + assert.throws( + () => { + assertRender( + w(MockWidget, { classes: ['foo', 'bar', 'baz'] }), + w(MockWidget, { classes: ['foo', 'bar'] }) + ); + }, + AssertionError, + 'The value of property "classes" is unexpected.' + ); } }, - 'strings': { - 'equal'() { + strings: { + equal() { assertRender('foo', 'foo'); }, - 'unequal'() { - assert.throws(() => { - assertRender('foo', 'bar'); - }, AssertionError, 'Render unexpected'); + unequal() { + assert.throws( + () => { + assertRender('foo', 'bar'); + }, + AssertionError, + 'Render unexpected' + ); } }, - 'null': { - 'equal'() { + null: { + equal() { assertRender(null, null); }, - 'unequal'() { - assert.throws(() => { - assertRender(null, 'bar'); - }, AssertionError, 'Render unexpected'); + unequal() { + assert.throws( + () => { + assertRender(null, 'bar'); + }, + AssertionError, + 'Render unexpected' + ); } }, 'throws with message'() { - assert.throws(() => { - assertRender(null, 'bar', 'foo'); - }, AssertionError, 'Render unexpected: DNode type mismatch, expected "string" actual "null": foo'); - assert.throws(() => { - assertRender('bar', null, 'foo'); - }, AssertionError, 'Render unexpected: DNode type mismatch, expected "null" actual "string": foo'); + assert.throws( + () => { + assertRender(null, 'bar', 'foo'); + }, + AssertionError, + 'Render unexpected: DNode type mismatch, expected "string" actual "null": foo' + ); + assert.throws( + () => { + assertRender('bar', null, 'foo'); + }, + AssertionError, + 'Render unexpected: DNode type mismatch, expected "null" actual "string": foo' + ); }, - 'options': { - 'isWNode'() { + options: { + isWNode() { let called = false; assertRender(w(MockWidget, {}), w(MockWidget, {}), { isWNode(node: any): node is WNode { @@ -525,7 +524,7 @@ registerSuite('support/assertRender', { assert.isTrue(called, 'isWNode should have been called'); }, - 'isHNode'() { + isHNode() { let called = false; assertRender(v('div'), v('div'), { isHNode(node: any): node is HNode { @@ -536,15 +535,19 @@ registerSuite('support/assertRender', { assert.isTrue(called, 'isHNode should have been called'); }, - 'allowFunctionValues'() { - assert.throws(() => { - assertRender(w(MockWidget, { baz() { } }), w(MockWidget, { baz() { } }), { - allowFunctionValues: false - }); - }, TypeError, 'Value of property named "baz" from first argument is not a primative, plain Object, or Array.'); + allowFunctionValues() { + assert.throws( + () => { + assertRender(w(MockWidget, { baz() {} }), w(MockWidget, { baz() {} }), { + allowFunctionValues: false + }); + }, + TypeError, + 'Value of property named "baz" from first argument is not a primative, plain Object, or Array.' + ); }, - 'ignoreProperties'() { + ignoreProperties() { assertRender(v('div', { foo: 'bar', bar: 2 }), v('div', { foo: 'bar' }), { ignoreProperties(prop): boolean { return prop === 'bar'; @@ -552,7 +555,7 @@ registerSuite('support/assertRender', { }); }, - 'ignorePropertyValues': { + ignorePropertyValues: { 'is passed'() { assertRender(v('div', { foo: 'bar', bar: 2 }), v('div', { foo: 'bar', bar: 3 }), { ignorePropertyValues(prop): boolean { @@ -563,11 +566,15 @@ registerSuite('support/assertRender', { 'overrides defaults'() { const bind = new MockWidget(); - assert.throws(() => { - assertRender(w(MockWidget, { bind }), w(MockWidget, { bind: true }), { - ignoreProperties: [ 'foo' ] - }); - }, TypeError, 'Value of property named "bind" from first argument is not a primative, plain Object, or Array.'); + assert.throws( + () => { + assertRender(w(MockWidget, { bind }), w(MockWidget, { bind: true }), { + ignoreProperties: ['foo'] + }); + }, + TypeError, + 'Value of property named "bind" from first argument is not a primative, plain Object, or Array.' + ); } }, @@ -583,10 +590,14 @@ registerSuite('support/assertRender', { }); } catch (err) { assert.deepEqual( - err.actual, { foo: 'bar' }, 'Should have excluded ignored properties from "actual" value' + err.actual, + { foo: 'bar' }, + 'Should have excluded ignored properties from "actual" value' ); assert.deepEqual( - err.expected, { foo: 'baz' }, 'Should have excluded ignored properties from "expected" value' + err.expected, + { foo: 'baz' }, + 'Should have excluded ignored properties from "expected" value' ); } } diff --git a/tests/unit/support/callListener.ts b/tests/unit/support/callListener.ts index ed3a361..4c6223a 100644 --- a/tests/unit/support/callListener.ts +++ b/tests/unit/support/callListener.ts @@ -6,7 +6,6 @@ import callListener from '../../../src/support/callListener'; import { v, w } from '@dojo/widget-core/d'; registerSuite('support/callListener', { - 'should call listener'() { let count = 0; const vnode = w('widget', { @@ -45,7 +44,7 @@ registerSuite('support/callListener', { }, 'should pass args when specified'() { - const args = [ 1, 2, 3 ]; + const args = [1, 2, 3]; const vnode = w('widget', { onClick(...calledArgs: any[]) { assert.deepEqual(calledArgs, args); @@ -79,14 +78,28 @@ registerSuite('support/callListener', { 'should target key when passed'() { let keyCount = 0; let count = 0; - const vnode = w('widget', { - onClick() { - count++; - } - }, [ - w('sub-widget', { key: 'foo', onClick() { keyCount++; } }), - w('sub-widget', { key: 'bar', onClick() { count++; } }) - ]); + const vnode = w( + 'widget', + { + onClick() { + count++; + } + }, + [ + w('sub-widget', { + key: 'foo', + onClick() { + keyCount++; + } + }), + w('sub-widget', { + key: 'bar', + onClick() { + count++; + } + }) + ] + ); callListener(vnode, 'onClick', { key: 'foo' }); @@ -97,14 +110,28 @@ registerSuite('support/callListener', { 'should target when index is passed'() { let indexCount = 0; let count = 0; - const vnode = v('div', { - onClick() { - count++; - } - }, [ - w('sub-widget', { key: 'foo', onClick() { indexCount++; } }), - w('sub-widget', { key: 'bar', onClick() { count++; } }) - ]); + const vnode = v( + 'div', + { + onClick() { + count++; + } + }, + [ + w('sub-widget', { + key: 'foo', + onClick() { + indexCount++; + } + }), + w('sub-widget', { + key: 'bar', + onClick() { + count++; + } + }) + ] + ); callListener(vnode, 'onClick', { index: 0 }); @@ -125,36 +152,52 @@ registerSuite('support/callListener', { 'error conditions': { 'method is not found'() { - const vnode = w('widget', { onClick() { } }); - assert.throws(() => { - callListener(vnode, 'onFoo'); - }, TypeError, 'Cannot resolve listener: "onFoo"'); + const vnode = w('widget', { onClick() {} }); + assert.throws( + () => { + callListener(vnode, 'onFoo'); + }, + TypeError, + 'Cannot resolve listener: "onFoo"' + ); }, 'key is not found'() { const vnode = v('div', {}, [ - w('sub-widget', { key: 'foo', onClick() { } }), - w('sub-widget', { key: 'bar', onClick() { } }) + w('sub-widget', { key: 'foo', onClick() {} }), + w('sub-widget', { key: 'bar', onClick() {} }) ]); - assert.throws(() => { - callListener(vnode, 'onClick', { key: 'baz' }); - }, TypeError, 'Cannot resolve target'); + assert.throws( + () => { + callListener(vnode, 'onClick', { key: 'baz' }); + }, + TypeError, + 'Cannot resolve target' + ); }, 'index is not found'() { const vnode = v('div', {}, [ - w('sub-widget', { key: 'foo', onClick() { } }), - w('sub-widget', { key: 'bar', onClick() { } }) + w('sub-widget', { key: 'foo', onClick() {} }), + w('sub-widget', { key: 'bar', onClick() {} }) ]); - assert.throws(() => { - callListener(vnode, 'onClick', { index: 2 }); - }, TypeError, 'Cannot resolve target'); + assert.throws( + () => { + callListener(vnode, 'onClick', { index: 2 }); + }, + TypeError, + 'Cannot resolve target' + ); }, 'string is not supported'() { - assert.throws(() => { - callListener('testString', 'onclick'); - }, TypeError, 'Cannot resolve target'); + assert.throws( + () => { + callListener('testString', 'onclick'); + }, + TypeError, + 'Cannot resolve target' + ); } } }); diff --git a/tests/unit/support/compare.ts b/tests/unit/support/compare.ts index 1d280e6..c3266a6 100644 --- a/tests/unit/support/compare.ts +++ b/tests/unit/support/compare.ts @@ -4,13 +4,15 @@ const { assert } = intern.getPlugin('chai'); import { createConstructRecord, diff, patch, CustomDiff } from '../../../src/support/compare'; registerSuite('compare', { - diff: { 'plain object': { 'add property'() { - const patchRecords = diff({ - foo: 'bar' - }, {}); + const patchRecords = diff( + { + foo: 'bar' + }, + {} + ); assert.deepEqual(patchRecords, [ { @@ -22,11 +24,14 @@ registerSuite('compare', { }, 'update property'() { - const patchRecords = diff({ - foo: 'bar' - }, { - foo: 'qat' - }); + const patchRecords = diff( + { + foo: 'bar' + }, + { + foo: 'qat' + } + ); assert.deepEqual(patchRecords, [ { @@ -38,9 +43,12 @@ registerSuite('compare', { }, 'delete property'() { - const patchRecords = diff({}, { - foo: 'qat' - }); + const patchRecords = diff( + {}, + { + foo: 'qat' + } + ); assert.deepEqual(patchRecords, [ { @@ -51,20 +59,28 @@ registerSuite('compare', { }, 'allowFunctionValues - equal'() { - const patchRecords = diff({ - foo() { } - }, { - foo() { } - }, { allowFunctionValues: true }); + const patchRecords = diff( + { + foo() {} + }, + { + foo() {} + }, + { allowFunctionValues: true } + ); assert.strictEqual(patchRecords.length, 0, 'should not see a difference'); }, 'allowFunctionValues - add property'() { function foo() {} - const patchRecords = diff({ - foo - }, { }, { allowFunctionValues: true }); + const patchRecords = diff( + { + foo + }, + {}, + { allowFunctionValues: true } + ); assert.deepEqual(patchRecords, [ { @@ -81,32 +97,39 @@ registerSuite('compare', { }, 'primative values'() { - const patchRecords = diff({ - foo: undefined, - bar: null, - baz: '', - qat: 0, - qux: false - }, {}); + const patchRecords = diff( + { + foo: undefined, + bar: null, + baz: '', + qat: 0, + qux: false + }, + {} + ); assert.deepEqual(patchRecords, [ { descriptor: { configurable: true, enumerable: true, value: undefined, writable: true }, name: 'foo', type: 'add' - }, { + }, + { descriptor: { configurable: true, enumerable: true, value: null, writable: true }, name: 'bar', type: 'add' - }, { + }, + { descriptor: { configurable: true, enumerable: true, value: '', writable: true }, name: 'baz', type: 'add' - }, { + }, + { descriptor: { configurable: true, enumerable: true, value: 0, writable: true }, name: 'qat', type: 'add' - }, { + }, + { descriptor: { configurable: true, enumerable: true, value: false, writable: true }, name: 'qux', type: 'add' @@ -115,15 +138,18 @@ registerSuite('compare', { }, 'deep add value'() { - const patchRecords = diff({ - foo: { - bar: 'baz' - } - }, {}); + const patchRecords = diff( + { + foo: { + bar: 'baz' + } + }, + {} + ); assert.deepEqual(patchRecords, [ { - descriptor: { configurable: true, enumerable: true, value: { }, writable: true }, + descriptor: { configurable: true, enumerable: true, value: {}, writable: true }, name: 'foo', type: 'add', valueRecords: [ @@ -138,15 +164,18 @@ registerSuite('compare', { }, 'deep update value'() { - const patchRecords = diff({ - foo: { - bar: 'baz' - } - }, { - foo: { - bar: 1 + const patchRecords = diff( + { + foo: { + bar: 'baz' + } + }, + { + foo: { + bar: 1 + } } - }); + ); assert.deepEqual(patchRecords, [ { @@ -165,32 +194,40 @@ registerSuite('compare', { }, 'complex diff'() { - const patchRecords = diff({ - foo: { - bar: 'qat' - }, - baz: { - qat: { - qux: true - } - }, - qat: 'foo' - }, { - foo: { - bar: { - qat: true + const patchRecords = diff( + { + foo: { + bar: 'qat' }, - baz: undefined + baz: { + qat: { + qux: true + } + }, + qat: 'foo' }, - baz: 1, - qux: { - baz: 2 + { + foo: { + bar: { + qat: true + }, + baz: undefined + }, + baz: 1, + qux: { + baz: 2 + } } - }); + ); assert.deepEqual(patchRecords, [ { - descriptor: { configurable: true, enumerable: true, value: { bar: { qat: true }, baz: undefined }, writable: true }, + descriptor: { + configurable: true, + enumerable: true, + value: { bar: { qat: true }, baz: undefined }, + writable: true + }, name: 'foo', type: 'update', valueRecords: [ @@ -204,29 +241,37 @@ registerSuite('compare', { type: 'delete' } ] - }, { - descriptor: { configurable: true, enumerable: true, value: { }, writable: true }, + }, + { + descriptor: { configurable: true, enumerable: true, value: {}, writable: true }, name: 'baz', type: 'update', valueRecords: [ { - descriptor: { configurable: true, enumerable: true, value: { }, writable: true }, + descriptor: { configurable: true, enumerable: true, value: {}, writable: true }, name: 'qat', type: 'add', valueRecords: [ { - descriptor: { configurable: true, enumerable: true, value: true, writable: true }, + descriptor: { + configurable: true, + enumerable: true, + value: true, + writable: true + }, name: 'qux', type: 'add' } ] } ] - }, { + }, + { descriptor: { configurable: true, enumerable: true, value: 'foo', writable: true }, name: 'qat', type: 'add' - }, { + }, + { name: 'qux', type: 'delete' } @@ -234,30 +279,39 @@ registerSuite('compare', { }, 'no differences'() { - const patchRecords = diff({ - foo: 'bar' - }, { - foo: 'bar' - }); + const patchRecords = diff( + { + foo: 'bar' + }, + { + foo: 'bar' + } + ); assert.deepEqual(patchRecords, []); }, 'deep no differences'() { - const patchRecords = diff({ - foo: { bar: 1 } - }, { - foo: { bar: 1 } - }); + const patchRecords = diff( + { + foo: { bar: 1 } + }, + { + foo: { bar: 1 } + } + ); assert.deepEqual(patchRecords, []); }, 'symbols are ignored'() { - const patchRecords = diff({ - foo: 'bar', - [Symbol.iterator]() { } - }, {}); + const patchRecords = diff( + { + foo: 'bar', + [Symbol.iterator]() {} + }, + {} + ); assert.deepEqual(patchRecords, [ { @@ -325,7 +379,7 @@ registerSuite('compare', { assert.deepEqual(patchRecords, [], 'should have found no differences'); }, - 'difference'() { + difference() { const a = { foo: /foo/ }; @@ -333,9 +387,11 @@ registerSuite('compare', { return createConstructRecord(RegExp); }); const patchRecords = diff(a, { foo: customDiff }); - assert.deepEqual(patchRecords, [ - { Ctor: RegExp, name: 'foo' } - ], 'should have expected patch records'); + assert.deepEqual( + patchRecords, + [{ Ctor: RegExp, name: 'foo' }], + 'should have expected patch records' + ); }, 'difference with arguments'() { @@ -343,12 +399,14 @@ registerSuite('compare', { foo: /foo/ }; const customDiff = new CustomDiff(() => { - return createConstructRecord(RegExp, [ '/bar/' ]); + return createConstructRecord(RegExp, ['/bar/']); }); const patchRecords = diff(a, { foo: customDiff }); - assert.deepEqual(patchRecords, [ - { args: [ '/bar/' ], Ctor: RegExp, name: 'foo' } - ], 'should have expected patch records'); + assert.deepEqual( + patchRecords, + [{ args: ['/bar/'], Ctor: RegExp, name: 'foo' }], + 'should have expected patch records' + ); }, 'difference with descriptor'() { @@ -359,29 +417,35 @@ registerSuite('compare', { return createConstructRecord(RegExp, undefined, { writable: true }); }); const patchRecords = diff(a, { foo: customDiff }); - assert.deepEqual(patchRecords, [ - { Ctor: RegExp, descriptor: { writable: true }, name: 'foo' } - ], 'should have expected patch records'); + assert.deepEqual( + patchRecords, + [{ Ctor: RegExp, descriptor: { writable: true }, name: 'foo' }], + 'should have expected patch records' + ); }, 'deleted property'() { const customDiff = new CustomDiff(() => { return createConstructRecord(RegExp); }); - const patchRecords = diff({ }, { foo: customDiff }); - assert.deepEqual(patchRecords, [ - { name: 'foo', type: 'delete' } - ], 'should have expected patch records'); + const patchRecords = diff({}, { foo: customDiff }); + assert.deepEqual( + patchRecords, + [{ name: 'foo', type: 'delete' }], + 'should have expected patch records' + ); }, 'added property'() { const customDiff = new CustomDiff(() => { return createConstructRecord(RegExp); }); - const patchRecords = diff({ foo: customDiff }, { }); - assert.deepEqual(patchRecords, [ - { Ctor: RegExp, name: 'foo' } - ], 'should have expected patch records'); + const patchRecords = diff({ foo: customDiff }, {}); + assert.deepEqual( + patchRecords, + [{ Ctor: RegExp, name: 'foo' }], + 'should have expected patch records' + ); } }, @@ -392,7 +456,7 @@ registerSuite('compare', { bar: 1 }; - const patchRecords = diff(a, {}, { ignoreProperties: [ 'bar' ] }); + const patchRecords = diff(a, {}, { ignoreProperties: ['bar'] }); assert.deepEqual(patchRecords, [ { @@ -409,7 +473,7 @@ registerSuite('compare', { bar: 1 }; - const patchRecords = diff({}, b, { ignoreProperties: [ 'bar' ] }); + const patchRecords = diff({}, b, { ignoreProperties: ['bar'] }); assert.deepEqual(patchRecords, [ { @@ -425,7 +489,7 @@ registerSuite('compare', { _bar: 1 }; - const patchRecords = diff(a, {}, { ignoreProperties: [ /^_/ ] }); + const patchRecords = diff(a, {}, { ignoreProperties: [/^_/] }); assert.deepEqual(patchRecords, [ { @@ -442,7 +506,7 @@ registerSuite('compare', { _bar: 1 }; - const patchRecords = diff({}, b, { ignoreProperties: [ /^_/ ] }); + const patchRecords = diff({}, b, { ignoreProperties: [/^_/] }); assert.deepEqual(patchRecords, [ { @@ -459,7 +523,7 @@ registerSuite('compare', { _bar: 1 }; - const patchRecords = diff(a, {}, { ignoreProperties: [ 'bar', /^_/ ] }); + const patchRecords = diff(a, {}, { ignoreProperties: ['bar', /^_/] }); assert.deepEqual(patchRecords, [ { @@ -477,7 +541,7 @@ registerSuite('compare', { _bar: 1 }; - const patchRecords = diff({}, b, { ignoreProperties: [ 'bar', /^_/ ] }); + const patchRecords = diff({}, b, { ignoreProperties: ['bar', /^_/] }); assert.deepEqual(patchRecords, [ { @@ -520,7 +584,7 @@ registerSuite('compare', { ]); }, - 'function'() { + function() { const propertyStack: string[] = []; const a = { @@ -535,15 +599,17 @@ registerSuite('compare', { baz: false }; - const patchRecords = diff(a, b, { ignoreProperties(name, first, second) { - propertyStack.push(name); - assert.strictEqual(first, a); - assert.strictEqual(second, b); - return false; - } }); + const patchRecords = diff(a, b, { + ignoreProperties(name, first, second) { + propertyStack.push(name); + assert.strictEqual(first, a); + assert.strictEqual(second, b); + return false; + } + }); assert.deepEqual(patchRecords, [], 'should be no differences'); - assert.deepEqual(propertyStack, [ 'foo', 'bar', 'baz' ]); + assert.deepEqual(propertyStack, ['foo', 'bar', 'baz']); }, 'function and ignored'() { @@ -561,15 +627,17 @@ registerSuite('compare', { baz: false }; - const patchRecords = diff(a, b, { ignoreProperties(name, first, second) { - propertyStack.push(name); - assert.strictEqual(first, a); - assert.strictEqual(second, b); - return true; - } }); + const patchRecords = diff(a, b, { + ignoreProperties(name, first, second) { + propertyStack.push(name); + assert.strictEqual(first, a); + assert.strictEqual(second, b); + return true; + } + }); assert.deepEqual(patchRecords, [], 'should be no differences'); - assert.deepEqual(propertyStack, [ 'foo', 'bar', 'baz' ]); + assert.deepEqual(propertyStack, ['foo', 'bar', 'baz']); } }, @@ -583,7 +651,7 @@ registerSuite('compare', { foo: new Error('foo') }; - const patchRecords = diff(a, b, { ignorePropertyValues: [ 'foo' ] }); + const patchRecords = diff(a, b, { ignorePropertyValues: ['foo'] }); assert.deepEqual(patchRecords, []); }, @@ -594,7 +662,7 @@ registerSuite('compare', { foo }; - const patchRecords = diff(a, { }, { ignorePropertyValues: [ 'foo' ] }); + const patchRecords = diff(a, {}, { ignorePropertyValues: ['foo'] }); assert.deepEqual(patchRecords, [ { @@ -610,7 +678,7 @@ registerSuite('compare', { foo: new Error('foo') }; - const patchRecords = diff({ }, b, { ignorePropertyValues: [ 'foo' ] }); + const patchRecords = diff({}, b, { ignorePropertyValues: ['foo'] }); assert.deepEqual(patchRecords, [ { @@ -629,7 +697,7 @@ registerSuite('compare', { foo: new Error('foo') }; - const patchRecords = diff(a, b, { ignorePropertyValues: [ /^foo$/ ] }); + const patchRecords = diff(a, b, { ignorePropertyValues: [/^foo$/] }); assert.deepEqual(patchRecords, []); }, @@ -640,7 +708,7 @@ registerSuite('compare', { foo }; - const patchRecords = diff(a, { }, { ignorePropertyValues: [ /^foo$/ ] }); + const patchRecords = diff(a, {}, { ignorePropertyValues: [/^foo$/] }); assert.deepEqual(patchRecords, [ { @@ -656,7 +724,7 @@ registerSuite('compare', { foo: new Error('foo') }; - const patchRecords = diff({ }, b, { ignorePropertyValues: [ /^foo$/ ] }); + const patchRecords = diff({}, b, { ignorePropertyValues: [/^foo$/] }); assert.deepEqual(patchRecords, [ { @@ -677,7 +745,7 @@ registerSuite('compare', { bar: new Error('bar') }; - const patchRecords = diff(a, b, { ignorePropertyValues: [ 'bar', /^foo$/ ] }); + const patchRecords = diff(a, b, { ignorePropertyValues: ['bar', /^foo$/] }); assert.deepEqual(patchRecords, []); }, @@ -690,14 +758,15 @@ registerSuite('compare', { bar }; - const patchRecords = diff(a, { }, { ignorePropertyValues: [ 'bar', /^foo$/ ] }); + const patchRecords = diff(a, {}, { ignorePropertyValues: ['bar', /^foo$/] }); assert.deepEqual(patchRecords, [ { descriptor: { configurable: true, enumerable: true, value: foo, writable: true }, name: 'foo', type: 'add' - }, { + }, + { descriptor: { configurable: true, enumerable: true, value: bar, writable: true }, name: 'bar', type: 'add' @@ -711,13 +780,14 @@ registerSuite('compare', { bar: new Error('bar') }; - const patchRecords = diff({ }, b, { ignorePropertyValues: [ 'bar', /^foo$/ ] }); + const patchRecords = diff({}, b, { ignorePropertyValues: ['bar', /^foo$/] }); assert.deepEqual(patchRecords, [ { name: 'foo', type: 'delete' - }, { + }, + { name: 'bar', type: 'delete' } @@ -744,7 +814,7 @@ registerSuite('compare', { foo }; - const patchRecords = diff(a, { }, { ignorePropertyValues: (name) => /^foo$/.test(name) }); + const patchRecords = diff(a, {}, { ignorePropertyValues: (name) => /^foo$/.test(name) }); assert.deepEqual(patchRecords, [ { @@ -760,7 +830,7 @@ registerSuite('compare', { foo: new Error('foo') }; - const patchRecords = diff({ }, b, { ignorePropertyValues: (name) => /^foo$/.test(name) }); + const patchRecords = diff({}, b, { ignorePropertyValues: (name) => /^foo$/.test(name) }); assert.deepEqual(patchRecords, [ { @@ -772,15 +842,15 @@ registerSuite('compare', { } }, - 'array': { - 'same'() { - const patchRecords = diff([ 1, 2, 3 ], [ 1, 2, 3 ]); + array: { + same() { + const patchRecords = diff([1, 2, 3], [1, 2, 3]); - assert.deepEqual(patchRecords, [ ]); + assert.deepEqual(patchRecords, []); }, - 'shorter'() { - const patchRecords = diff([ 1, 2, 3 ], [ 1, 2, 3, 4, 5 ]); + shorter() { + const patchRecords = diff([1, 2, 3], [1, 2, 3, 4, 5]); assert.deepEqual(patchRecords, [ { @@ -791,12 +861,12 @@ registerSuite('compare', { ]); }, - 'longer'() { - const patchRecords = diff([ 1, 2, 3, 4, 5 ], [ 1, 2, 3 ]); + longer() { + const patchRecords = diff([1, 2, 3, 4, 5], [1, 2, 3]); assert.deepEqual(patchRecords, [ { - add: [ 4, 5 ], + add: [4, 5], deleteCount: 0, start: 3, type: 'splice' @@ -805,11 +875,11 @@ registerSuite('compare', { }, 'first element changed'() { - const patchRecords = diff([ 1, 2, 3 ], [ false, 2, 3 ]); + const patchRecords = diff([1, 2, 3], [false, 2, 3]); assert.deepEqual(patchRecords, [ { - add: [ 1 ], + add: [1], deleteCount: 1, start: 0, type: 'splice' @@ -818,11 +888,11 @@ registerSuite('compare', { }, 'middle element changed'() { - const patchRecords = diff([ 1, 2, 3 ], [ 1, false, 3 ]); + const patchRecords = diff([1, 2, 3], [1, false, 3]); assert.deepEqual(patchRecords, [ { - add: [ 2 ], + add: [2], deleteCount: 1, start: 1, type: 'splice' @@ -830,12 +900,12 @@ registerSuite('compare', { ]); }, - 'last element changed' () { - const patchRecords = diff([ 1, 2, 3 ], [ 1, 2, false ]); + 'last element changed'() { + const patchRecords = diff([1, 2, 3], [1, 2, false]); assert.deepEqual(patchRecords, [ { - add: [ 3 ], + add: [3], deleteCount: 1, start: 2, type: 'splice' @@ -844,11 +914,11 @@ registerSuite('compare', { }, 'tail changed plus shorter'() { - const patchRecords = diff([ 1, 2, 3 ], [ 1, 2, false, 4, 5 ]); + const patchRecords = diff([1, 2, 3], [1, 2, false, 4, 5]); assert.deepEqual(patchRecords, [ { - add: [ 3 ], + add: [3], deleteCount: 3, start: 2, type: 'splice' @@ -857,11 +927,11 @@ registerSuite('compare', { }, 'tail changed plug longer'() { - const patchRecords = diff([ 1, 2, 3, 4, 5 ], [ 1, 2, false ]); + const patchRecords = diff([1, 2, 3, 4, 5], [1, 2, false]); assert.deepEqual(patchRecords, [ { - add: [ 3, 4, 5 ], + add: [3, 4, 5], deleteCount: 1, start: 2, type: 'splice' @@ -870,16 +940,17 @@ registerSuite('compare', { }, 'multiple changes'() { - const patchRecords = diff([ 1, 2, 3, 4, 5 ], [ 1, false, 3, 4, false, 6, 7 ]); + const patchRecords = diff([1, 2, 3, 4, 5], [1, false, 3, 4, false, 6, 7]); assert.deepEqual(patchRecords, [ { - add: [ 2 ], + add: [2], deleteCount: 1, start: 1, type: 'splice' - }, { - add: [ 5 ], + }, + { + add: [5], deleteCount: 3, start: 4, type: 'splice' @@ -888,11 +959,11 @@ registerSuite('compare', { }, 'primative values array'() { - const patchRecords = diff([ '', 0, false, undefined, null ], []); + const patchRecords = diff(['', 0, false, undefined, null], []); assert.deepEqual(patchRecords, [ { - add: [ '', 0, false, undefined, null ], + add: ['', 0, false, undefined, null], deleteCount: 0, start: 0, type: 'splice' @@ -901,18 +972,18 @@ registerSuite('compare', { }, 'allowFunctionValues - equal'() { - const patchRecords = diff([ function foo () { } ], [ () => undefined ], { allowFunctionValues: true }); + const patchRecords = diff([function foo() {}], [() => undefined], { allowFunctionValues: true }); assert.lengthOf(patchRecords, 0, 'should have no differences'); }, 'allowFunctionValues - add'() { function foo() {} - const patchRecords = diff([ foo ], [], { allowFunctionValues: true }); + const patchRecords = diff([foo], [], { allowFunctionValues: true }); assert.deepEqual(patchRecords, [ { - add: [ foo ], + add: [foo], deleteCount: 0, start: 0, type: 'splice' @@ -922,8 +993,8 @@ registerSuite('compare', { 'array of arrays'() { const patchRecords = diff( - [ [ 1, 2, 3 ], [ 'foo', 'bar', 'baz' ], [ true, false ] ], - [ [ 1, false, 3], [ 'bar', 'baz' ] ] + [[1, 2, 3], ['foo', 'bar', 'baz'], [true, false]], + [[1, false, 3], ['bar', 'baz']] ); assert.deepEqual(patchRecords, [ @@ -931,21 +1002,23 @@ registerSuite('compare', { add: [ [ { - add: [ 2 ], + add: [2], deleteCount: 1, start: 1, type: 'splice' } - ], [ + ], + [ { - add: [ 'foo', 'bar', 'baz' ], + add: ['foo', 'bar', 'baz'], deleteCount: 2, start: 0, type: 'splice' } - ], [ + ], + [ { - add: [ true, false ], + add: [true, false], deleteCount: 0, start: 0, type: 'splice' @@ -961,30 +1034,33 @@ registerSuite('compare', { 'deep no changes'() { const patchRecords = diff( - [ [ 1, 2, 3 ], [ 'foo', 'bar', 'baz' ], [ true, false ] ], - [ [ 1, 2, 3 ], [ 'foo', 'bar', 'baz' ], [ true, false ] ] + [[1, 2, 3], ['foo', 'bar', 'baz'], [true, false]], + [[1, 2, 3], ['foo', 'bar', 'baz'], [true, false]] ); - assert.deepEqual(patchRecords, [ ]); + assert.deepEqual(patchRecords, []); } }, 'mixed object/arrays': { 'object with array'() { - const patchRecords = diff({ - foo: [ 1, 2, 3 ] - }, { - foo: [ 1, false, 3 ] - }); + const patchRecords = diff( + { + foo: [1, 2, 3] + }, + { + foo: [1, false, 3] + } + ); assert.deepEqual(patchRecords, [ { - descriptor: { configurable: true, enumerable: true, value: [ 1, false, 3 ], writable: true }, + descriptor: { configurable: true, enumerable: true, value: [1, false, 3], writable: true }, name: 'foo', type: 'update', valueRecords: [ { - add: [ 2 ], + add: [2], deleteCount: 1, start: 1, type: 'splice' @@ -996,8 +1072,8 @@ registerSuite('compare', { 'array with objects'() { const patchRecords = diff( - [ { bar: 1 }, { foo: 'bar' }, { baz: 1, qat: false }, { qux: null }, { } ], - [ { bar: 1 }, { foo: 'baz' }, { baz: 1 }, { }, { qux: null } ] + [{ bar: 1 }, { foo: 'bar' }, { baz: 1, qat: false }, { qux: null }, {}], + [{ bar: 1 }, { foo: 'baz' }, { baz: 1 }, {}, { qux: null }] ); assert.deepEqual(patchRecords, [ @@ -1009,19 +1085,22 @@ registerSuite('compare', { name: 'foo', type: 'update' } - ], [ + ], + [ { descriptor: { configurable: true, enumerable: true, value: false, writable: true }, name: 'qat', type: 'add' } - ], [ + ], + [ { descriptor: { configurable: true, enumerable: true, value: null, writable: true }, name: 'qux', type: 'add' } - ], [ + ], + [ { name: 'qux', type: 'delete' @@ -1036,20 +1115,23 @@ registerSuite('compare', { }, 'object array value to object value'() { - const patchRecords = diff({ - foo: [ 1, 2, 3 ] - }, { - foo: { bar: 1 } - }); + const patchRecords = diff( + { + foo: [1, 2, 3] + }, + { + foo: { bar: 1 } + } + ); assert.deepEqual(patchRecords, [ { - descriptor: { configurable: true, enumerable: true, value: [ ], writable: true }, + descriptor: { configurable: true, enumerable: true, value: [], writable: true }, name: 'foo', type: 'update', valueRecords: [ { - add: [ 1, 2, 3 ], + add: [1, 2, 3], deleteCount: 0, start: 0, type: 'splice' @@ -1060,15 +1142,18 @@ registerSuite('compare', { }, 'object object value to array value'() { - const patchRecords = diff({ - foo: { bar: 1 } - }, { - foo: [ 1, 2, 3 ] - }); + const patchRecords = diff( + { + foo: { bar: 1 } + }, + { + foo: [1, 2, 3] + } + ); assert.deepEqual(patchRecords, [ { - descriptor: { configurable: true, enumerable: true, value: { }, writable: true }, + descriptor: { configurable: true, enumerable: true, value: {}, writable: true }, name: 'foo', type: 'update', valueRecords: [ @@ -1083,16 +1168,21 @@ registerSuite('compare', { }, 'array array value to object value'() { - const patchRecords = diff([ [ 1, 2, 3 ] ], [ { - foo: 1 - } ]); + const patchRecords = diff( + [[1, 2, 3]], + [ + { + foo: 1 + } + ] + ); assert.deepEqual(patchRecords, [ { add: [ [ { - add: [ 1, 2, 3 ], + add: [1, 2, 3], deleteCount: 0, start: 0, type: 'splice' @@ -1107,9 +1197,14 @@ registerSuite('compare', { }, 'array object value to array value'() { - const patchRecords = diff([ { - foo: 1 - } ], [ [ 1, 2, 3 ] ]); + const patchRecords = diff( + [ + { + foo: 1 + } + ], + [[1, 2, 3]] + ); assert.deepEqual(patchRecords, [ { @@ -1130,13 +1225,13 @@ registerSuite('compare', { }, 'array to object'() { - const patchRecords = diff([ 1, 2, 3 ], { + const patchRecords = diff([1, 2, 3], { foo: 'bar' }); assert.deepEqual(patchRecords, [ { - add: [ 1, 2, 3 ], + add: [1, 2, 3], deleteCount: 0, start: 0, type: 'splice' @@ -1145,9 +1240,12 @@ registerSuite('compare', { }, 'object to array'() { - const patchRecords = diff({ - foo: 'bar' - }, [ 1, 2, 3 ]); + const patchRecords = diff( + { + foo: 'bar' + }, + [1, 2, 3] + ); assert.deepEqual(patchRecords, [ { @@ -1160,26 +1258,45 @@ registerSuite('compare', { }, 'negative tests'() { - assert.throws(() => { - diff({}, 'foo'); - }, TypeError, 'Arguments are not of type object.'); + assert.throws( + () => { + diff({}, 'foo'); + }, + TypeError, + 'Arguments are not of type object.' + ); - assert.throws(() => { - diff('foo', {}); - }, TypeError, 'Arguments are not of type object.'); + assert.throws( + () => { + diff('foo', {}); + }, + TypeError, + 'Arguments are not of type object.' + ); - assert.throws(() => { - diff({ - foo: /bar/ - }, {}); - }, TypeError, 'Value of property named "foo" from first argument is not a primative, plain Object, or Array.'); + assert.throws( + () => { + diff( + { + foo: /bar/ + }, + {} + ); + }, + TypeError, + 'Value of property named "foo" from first argument is not a primative, plain Object, or Array.' + ); - assert.throws(() => { - diff([ /foo/ ], []); - }, TypeError, 'Value of array element "0" from first argument is not a primative, plain Object, or Array.'); + assert.throws( + () => { + diff([/foo/], []); + }, + TypeError, + 'Value of array element "0" from first argument is not a primative, plain Object, or Array.' + ); assert.doesNotThrow(() => { - diff([ ], [ /foo/ ]); + diff([], [/foo/]); }); class Foo { @@ -1188,17 +1305,25 @@ registerSuite('compare', { const foo = new Foo(); - assert.throws(() => { - diff(foo, {}); - }, TypeError, 'Arguments are not plain Objects or Arrays.'); + assert.throws( + () => { + diff(foo, {}); + }, + TypeError, + 'Arguments are not plain Objects or Arrays.' + ); - assert.throws(() => { - diff({}, foo); - }, TypeError, 'Arguments are not plain Objects or Arrays.'); + assert.throws( + () => { + diff({}, foo); + }, + TypeError, + 'Arguments are not plain Objects or Arrays.' + ); } }, - 'patch': { + patch: { 'plain object': { 'add property'() { const target = {}; @@ -1217,15 +1342,18 @@ registerSuite('compare', { }, 'update property'() { - const result = patch({ - foo: 'qat' - }, [ + const result = patch( { - descriptor: { configurable: true, enumerable: true, value: 'bar', writable: true }, - name: 'foo', - type: 'update' - } - ]); + foo: 'qat' + }, + [ + { + descriptor: { configurable: true, enumerable: true, value: 'bar', writable: true }, + name: 'foo', + type: 'update' + } + ] + ); assert.deepEqual(result, { foo: 'bar' @@ -1233,14 +1361,17 @@ registerSuite('compare', { }, 'delete property'() { - const result = patch({ - foo: 'qat' - }, [ + const result = patch( { - name: 'foo', - type: 'delete' - } - ]); + foo: 'qat' + }, + [ + { + name: 'foo', + type: 'delete' + } + ] + ); assert.deepEqual(result, {}); }, @@ -1251,19 +1382,23 @@ registerSuite('compare', { descriptor: { configurable: true, enumerable: true, value: undefined, writable: true }, name: 'foo', type: 'add' - }, { + }, + { descriptor: { configurable: true, enumerable: true, value: null, writable: true }, name: 'bar', type: 'add' - }, { + }, + { descriptor: { configurable: true, enumerable: true, value: '', writable: true }, name: 'baz', type: 'add' - }, { + }, + { descriptor: { configurable: true, enumerable: true, value: 0, writable: true }, name: 'qat', type: 'add' - }, { + }, + { descriptor: { configurable: true, enumerable: true, value: false, writable: true }, name: 'qux', type: 'add' @@ -1282,7 +1417,7 @@ registerSuite('compare', { 'deep add value'() { const result = patch({}, [ { - descriptor: { configurable: true, enumerable: true, value: { }, writable: true }, + descriptor: { configurable: true, enumerable: true, value: {}, writable: true }, name: 'foo', type: 'add', valueRecords: [ @@ -1362,29 +1497,37 @@ registerSuite('compare', { type: 'delete' } ] - }, { - descriptor: { configurable: true, enumerable: true, value: { }, writable: true }, + }, + { + descriptor: { configurable: true, enumerable: true, value: {}, writable: true }, name: 'baz', type: 'update', valueRecords: [ { - descriptor: { configurable: true, enumerable: true, value: { }, writable: true }, + descriptor: { configurable: true, enumerable: true, value: {}, writable: true }, name: 'qat', type: 'add', valueRecords: [ { - descriptor: { configurable: true, enumerable: true, value: true, writable: true }, + descriptor: { + configurable: true, + enumerable: true, + value: true, + writable: true + }, name: 'qux', type: 'add' } ] } ] - }, { + }, + { descriptor: { configurable: true, enumerable: true, value: 'foo', writable: true }, name: 'qat', type: 'add' - }, { + }, + { name: 'qux', type: 'delete' } @@ -1409,25 +1552,25 @@ registerSuite('compare', { 'empty patch'() { const target = {}; - const result = patch(target, [ ]); + const result = patch(target, []); assert.deepEqual(result, {}); assert.strictEqual(result, target); } }, - 'array': { - 'same'() { - const target = [ 1, 2, 3 ]; - const result = patch(target, [ ]); + array: { + same() { + const target = [1, 2, 3]; + const result = patch(target, []); - assert.deepEqual(result, [ 1, 2, 3 ]); + assert.deepEqual(result, [1, 2, 3]); assert.deepEqual(result, target); assert.strictEqual(target, result); }, - 'shorter'() { - const target = [ 1, 2, 3, 4, 5 ]; + shorter() { + const target = [1, 2, 3, 4, 5]; const result = patch(target, [ { deleteCount: 2, @@ -1436,162 +1579,189 @@ registerSuite('compare', { } ]); - assert.deepEqual(result, [ 1, 2, 3 ]); + assert.deepEqual(result, [1, 2, 3]); assert.strictEqual(target, result); }, - 'longer'() { - const target = [ 1, 2, 3 ]; + longer() { + const target = [1, 2, 3]; const result = patch(target, [ { - add: [ 4, 5 ], + add: [4, 5], deleteCount: 0, start: 3, type: 'splice' } ]); - assert.deepEqual(result, [ 1, 2, 3, 4, 5 ]); + assert.deepEqual(result, [1, 2, 3, 4, 5]); assert.strictEqual(result, target); }, 'first element changed'() { - const result = patch([ false, 2, 3 ], [ - { - add: [ 1 ], - deleteCount: 1, - start: 0, - type: 'splice' - } - ]); + const result = patch( + [false, 2, 3], + [ + { + add: [1], + deleteCount: 1, + start: 0, + type: 'splice' + } + ] + ); - assert.deepEqual(result, [ 1, 2, 3 ]); + assert.deepEqual(result, [1, 2, 3]); }, 'middle element changed'() { - const result = patch([ 1, false, 3 ], [ - { - add: [ 2 ], - deleteCount: 1, - start: 1, - type: 'splice' - } - ]); + const result = patch( + [1, false, 3], + [ + { + add: [2], + deleteCount: 1, + start: 1, + type: 'splice' + } + ] + ); - assert.deepEqual(result, [ 1, 2, 3 ]); + assert.deepEqual(result, [1, 2, 3]); }, - 'last element changed' () { - const result = patch([ 1, 2, false ], [ - { - add: [ 3 ], - deleteCount: 1, - start: 2, - type: 'splice' - } - ]); + 'last element changed'() { + const result = patch( + [1, 2, false], + [ + { + add: [3], + deleteCount: 1, + start: 2, + type: 'splice' + } + ] + ); - assert.deepEqual(result, [ 1, 2, 3 ]); + assert.deepEqual(result, [1, 2, 3]); }, 'tail changed plus shorter'() { - const result = patch([ 1, 2, false, 4, 5 ], [ - { - add: [ 3 ], - deleteCount: 3, - start: 2, - type: 'splice' - } - ]); + const result = patch( + [1, 2, false, 4, 5], + [ + { + add: [3], + deleteCount: 3, + start: 2, + type: 'splice' + } + ] + ); - assert.deepEqual(result, [ 1, 2, 3 ]); + assert.deepEqual(result, [1, 2, 3]); }, 'tail changed plug longer'() { - const result = patch([ 1, 2, false ], [ - { - add: [ 3, 4, 5 ], - deleteCount: 1, - start: 2, - type: 'splice' - } - ]); + const result = patch( + [1, 2, false], + [ + { + add: [3, 4, 5], + deleteCount: 1, + start: 2, + type: 'splice' + } + ] + ); - assert.deepEqual(result, [ 1, 2, 3, 4, 5 ]); + assert.deepEqual(result, [1, 2, 3, 4, 5]); }, 'multiple changes'() { - const result = patch([ 1, false, 3, 4, false, 6, 7 ], [ - { - add: [ 2 ], - deleteCount: 1, - start: 1, - type: 'splice' - }, { - add: [ 5 ], - deleteCount: 3, - start: 4, - type: 'splice' - } - ]); + const result = patch( + [1, false, 3, 4, false, 6, 7], + [ + { + add: [2], + deleteCount: 1, + start: 1, + type: 'splice' + }, + { + add: [5], + deleteCount: 3, + start: 4, + type: 'splice' + } + ] + ); - assert.deepEqual(result, [ 1, 2, 3, 4, 5 ]); + assert.deepEqual(result, [1, 2, 3, 4, 5]); }, 'primative values array'() { - const result = patch([], [ - { - add: [ '', 0, false, undefined, null ], - deleteCount: 0, - start: 0, - type: 'splice' - } - ]); + const result = patch( + [], + [ + { + add: ['', 0, false, undefined, null], + deleteCount: 0, + start: 0, + type: 'splice' + } + ] + ); - assert.deepEqual(result, [ '', 0, false, undefined, null ]); + assert.deepEqual(result, ['', 0, false, undefined, null]); }, 'array of arrays'() { - const result = patch([ [ 1, false, 3], [ 'bar', 'baz' ] ], [ - { - add: [ - [ - { - add: [ 2 ], - deleteCount: 1, - start: 1, - type: 'splice' - } - ], [ - { - add: [ 'foo', 'bar', 'baz' ], - deleteCount: 2, - start: 0, - type: 'splice' - } - ], [ - { - add: [ true, false ], - deleteCount: 0, - start: 0, - type: 'splice' - } - ] - ], - deleteCount: 2, - start: 0, - type: 'splice' - } - ]); + const result = patch( + [[1, false, 3], ['bar', 'baz']], + [ + { + add: [ + [ + { + add: [2], + deleteCount: 1, + start: 1, + type: 'splice' + } + ], + [ + { + add: ['foo', 'bar', 'baz'], + deleteCount: 2, + start: 0, + type: 'splice' + } + ], + [ + { + add: [true, false], + deleteCount: 0, + start: 0, + type: 'splice' + } + ] + ], + deleteCount: 2, + start: 0, + type: 'splice' + } + ] + ); - assert.deepEqual(result, [ [ 1, 2, 3 ], [ 'foo', 'bar', 'baz' ], [ true, false ] ]); + assert.deepEqual(result, [[1, 2, 3], ['foo', 'bar', 'baz'], [true, false]]); } }, 'mixed object/arrays': { 'object with array'() { const target = { - foo: [ 1, false, 3 ] + foo: [1, false, 3] }; const result = patch(target, [ @@ -1601,7 +1771,7 @@ registerSuite('compare', { type: 'update', valueRecords: [ { - add: [ 2 ], + add: [2], deleteCount: 1, start: 1, type: 'splice' @@ -1611,14 +1781,14 @@ registerSuite('compare', { ]); assert.deepEqual(result, { - foo: [ 1, 2, 3 ] + foo: [1, 2, 3] }); assert.strictEqual(target, result); assert.strictEqual(target.foo, result.foo); }, 'array with objects'() { - const target = [ { bar: 1 }, { foo: 'baz' }, { baz: 1 }, { }, { qux: null } ]; + const target = [{ bar: 1 }, { foo: 'baz' }, { baz: 1 }, {}, { qux: null }]; const result = patch(target, [ { @@ -1629,19 +1799,22 @@ registerSuite('compare', { name: 'foo', type: 'update' } - ], [ + ], + [ { descriptor: { configurable: true, enumerable: true, value: false, writable: true }, name: 'qat', type: 'add' } - ], [ + ], + [ { descriptor: { configurable: true, enumerable: true, value: null, writable: true }, name: 'qux', type: 'add' } - ], [ + ], + [ { name: 'qux', type: 'delete' @@ -1654,7 +1827,7 @@ registerSuite('compare', { } ]); - assert.deepEqual(result, [ { bar: 1 }, { foo: 'bar' }, { baz: 1, qat: false }, { qux: null }, { } ]); + assert.deepEqual(result, [{ bar: 1 }, { foo: 'bar' }, { baz: 1, qat: false }, { qux: null }, {}]); assert.strictEqual(target, result); target.forEach((item, index) => { assert.strictEqual(item, result[index]); @@ -1662,46 +1835,52 @@ registerSuite('compare', { }, 'object array value to object value'() { - const result = patch({ - foo: { bar: 1 } - }, [ + const result = patch( { - descriptor: { configurable: true, enumerable: true, value: [ ], writable: true }, - name: 'foo', - type: 'update', - valueRecords: [ - { - add: [ 1, 2, 3 ], - deleteCount: 0, - start: 0, - type: 'splice' - } - ] - } - ]); + foo: { bar: 1 } + }, + [ + { + descriptor: { configurable: true, enumerable: true, value: [], writable: true }, + name: 'foo', + type: 'update', + valueRecords: [ + { + add: [1, 2, 3], + deleteCount: 0, + start: 0, + type: 'splice' + } + ] + } + ] + ); assert.deepEqual(result, { - foo: [ 1, 2, 3 ] + foo: [1, 2, 3] }); }, 'object object value to array value'() { - const result = patch({ - foo: [ 1, 2, 3 ] - }, [ + const result = patch( { - descriptor: { configurable: true, enumerable: true, value: { }, writable: true }, - name: 'foo', - type: 'update', - valueRecords: [ - { - descriptor: { configurable: true, enumerable: true, value: 1, writable: true }, - name: 'bar', - type: 'add' - } - ] - } - ]); + foo: [1, 2, 3] + }, + [ + { + descriptor: { configurable: true, enumerable: true, value: {}, writable: true }, + name: 'foo', + type: 'update', + valueRecords: [ + { + descriptor: { configurable: true, enumerable: true, value: 1, writable: true }, + name: 'bar', + type: 'add' + } + ] + } + ] + ); assert.deepEqual(result, { foo: { bar: 1 } @@ -1709,75 +1888,91 @@ registerSuite('compare', { }, 'array array value to object value'() { - const result = patch([ { - foo: 1 - } ], [ - { - add: [ - [ - { - add: [ 1, 2, 3 ], - deleteCount: 0, - start: 0, - type: 'splice' - } - ] - ], - deleteCount: 1, - start: 0, - type: 'splice' - } - ]); + const result = patch( + [ + { + foo: 1 + } + ], + [ + { + add: [ + [ + { + add: [1, 2, 3], + deleteCount: 0, + start: 0, + type: 'splice' + } + ] + ], + deleteCount: 1, + start: 0, + type: 'splice' + } + ] + ); - assert.deepEqual(result, [ [ 1, 2, 3 ] ]); + assert.deepEqual(result, [[1, 2, 3]]); }, 'array object value to array value'() { - const result = patch([ [ 1, 2, 3 ] ], [ + const result = patch( + [[1, 2, 3]], + [ + { + add: [ + [ + { + descriptor: { configurable: true, enumerable: true, value: 1, writable: true }, + name: 'foo', + type: 'add' + } + ] + ], + deleteCount: 1, + start: 0, + type: 'splice' + } + ] + ); + + assert.deepEqual(result, [ { - add: [ - [ - { - descriptor: { configurable: true, enumerable: true, value: 1, writable: true }, - name: 'foo', - type: 'add' - } - ] - ], - deleteCount: 1, - start: 0, - type: 'splice' + foo: 1 } ]); - - assert.deepEqual(result, [ { - foo: 1 - } ]); }, 'array to object'() { - const result = patch({ - foo: 'bar' - }, [ + const result = patch( { - add: [ 1, 2, 3 ], - deleteCount: 0, - start: 0, - type: 'splice' - } - ]); + foo: 'bar' + }, + [ + { + add: [1, 2, 3], + deleteCount: 0, + start: 0, + type: 'splice' + } + ] + ); - assert.deepEqual(result, [ 1, 2, 3 ]); + assert.deepEqual(result, [1, 2, 3]); }, 'object to array'() { - const result = patch([ 1, 2, 3 ], [ - { - descriptor: { configurable: true, enumerable: true, value: 'bar', writable: true }, - name: 'foo', - type: 'add' - } - ]); + const result = patch( + [1, 2, 3], + [ + { + descriptor: { configurable: true, enumerable: true, value: 'bar', writable: true }, + name: 'foo', + type: 'add' + } + ] + ); assert.deepEqual(result, { foo: 'bar' @@ -1787,9 +1982,7 @@ registerSuite('compare', { 'plain object with construct records': { 'basic property construct'() { - const result = patch({}, [ - { args: [ 'foo' ], Ctor: RegExp, name: 'foo' } - ]); + const result = patch({}, [{ args: ['foo'], Ctor: RegExp, name: 'foo' }]); assert.instanceOf(result.foo, RegExp, 'should be a regular expression'); assert.strictEqual(result.foo.toString(), '/foo/', 'should have a pattern of foo'); @@ -1797,8 +1990,13 @@ registerSuite('compare', { 'property construct with descriptor'() { const result = patch({}, [ - { args: [ 'foo' ], Ctor: RegExp, name: 'foo', descriptor: { writable: false, enumerable: false, configurable: false } }, - { args: [ 'foo' ], Ctor: RegExp, name: 'bar' } + { + args: ['foo'], + Ctor: RegExp, + name: 'foo', + descriptor: { writable: false, enumerable: false, configurable: false } + }, + { args: ['foo'], Ctor: RegExp, name: 'bar' } ]); const descriptorFoo = Object.getOwnPropertyDescriptor(result, 'foo')!; @@ -1820,13 +2018,16 @@ registerSuite('compare', { } const result = patch({}, [ - { Ctor: Foo, name: 'foo', propertyRecords: - [ + { + Ctor: Foo, + name: 'foo', + propertyRecords: [ { descriptor: { configurable: true, enumerable: true, value: 1, writable: true }, name: 'foo', type: 'add' - }, { + }, + { descriptor: { configurable: true, enumerable: true, value: 'baz', writable: true }, name: 'bar', type: 'add' @@ -1846,7 +2047,10 @@ registerSuite('compare', { } const result = patch({}, [ - { Ctor: Foo, name: 'foo', propertyRecords: [ + { + Ctor: Foo, + name: 'foo', + propertyRecords: [ { Ctor: Foo, name: 'foo' @@ -1860,22 +2064,25 @@ registerSuite('compare', { }, 'plain object has complex property'() { - const result = patch({ - foo: [] - }, [ + const result = patch( { - descriptor: { configurable: true, enumerable: true, value: { }, writable: true }, - name: 'foo', - type: 'update', - valueRecords: [ - { - args: [ 'foo' ], - Ctor: RegExp, - name: 'bar' - } - ] - } - ]); + foo: [] + }, + [ + { + descriptor: { configurable: true, enumerable: true, value: {}, writable: true }, + name: 'foo', + type: 'update', + valueRecords: [ + { + args: ['foo'], + Ctor: RegExp, + name: 'bar' + } + ] + } + ] + ); assert.instanceOf(result.foo.bar, RegExp); assert.strictEqual(result.foo.bar.toString(), '/foo/'); @@ -1883,31 +2090,47 @@ registerSuite('compare', { }, 'negative tests'() { - assert.throws(() => { - patch(/foo/, [ ]); - }, TypeError, 'A target for a patch must be either an array or a plain object.'); + assert.throws( + () => { + patch(/foo/, []); + }, + TypeError, + 'A target for a patch must be either an array or a plain object.' + ); class Foo { bar: 'bar'; } - assert.throws(() => { - patch(new Foo(), [ ]); - }, TypeError, 'A target for a patch must be either an array or a plain object.'); + assert.throws( + () => { + patch(new Foo(), []); + }, + TypeError, + 'A target for a patch must be either an array or a plain object.' + ); const foo = {}; Object.freeze(foo); - assert.throws(() => { - patch(foo, []); - }, TypeError, 'Cannot patch sealed or frozen objects.'); + assert.throws( + () => { + patch(foo, []); + }, + TypeError, + 'Cannot patch sealed or frozen objects.' + ); const bar = {}; Object.seal(bar); - assert.throws(() => { - patch(bar, []); - }, TypeError, 'Cannot patch sealed or frozen objects.'); + assert.throws( + () => { + patch(bar, []); + }, + TypeError, + 'Cannot patch sealed or frozen objects.' + ); } } }); diff --git a/tests/unit/support/d.ts b/tests/unit/support/d.ts index c3c82c8..8334e82 100644 --- a/tests/unit/support/d.ts +++ b/tests/unit/support/d.ts @@ -21,101 +21,118 @@ import AssertionError from '../../../src/support/AssertionError'; import assertRender from '../../../src/support/assertRender'; registerSuite('support/virtualDom', { - 'assignChildProperties()': { 'by index'() { - const actual = v('div', {}, [ null, v('a', { href: '#link' }) ]); + const actual = v('div', {}, [null, v('a', { href: '#link' })]); - assertRender(actual, v('div', {}, [ null, v('a', { href: '#link' }) ])); + assertRender(actual, v('div', {}, [null, v('a', { href: '#link' })])); assignChildProperties(actual, 1, { target: '_blank' }); - assertRender(actual, v('div', {}, [ null, v('a', { href: '#link', target: '_blank' }) ])); + assertRender(actual, v('div', {}, [null, v('a', { href: '#link', target: '_blank' })])); }, 'does not resolve'() { - const actual = v('div', {}, [ null, v('a', { href: '#link' }) ]); - - assert.throws(() => { - assignChildProperties(actual, 0, { target: '_blank' }); - }, TypeError, 'Index of "0" is not resolving to a valid target'); + const actual = v('div', {}, [null, v('a', { href: '#link' })]); + + assert.throws( + () => { + assignChildProperties(actual, 0, { target: '_blank' }); + }, + TypeError, + 'Index of "0" is not resolving to a valid target' + ); } }, 'assignChildPropertiesByKey()': { 'by string key'() { - const actual = v('div', { key: 'a' }, [ null, v('a', { key: 'b', href: '#link' }) ]); + const actual = v('div', { key: 'a' }, [null, v('a', { key: 'b', href: '#link' })]); - assertRender(actual, v('div', { key: 'a' }, [ null, v('a', { key: 'b', href: '#link' }) ])); + assertRender(actual, v('div', { key: 'a' }, [null, v('a', { key: 'b', href: '#link' })])); assignChildPropertiesByKey(actual, 'b', { target: '_blank' }); - assertRender(actual, v('div', { key: 'a' }, [ null, v('a', { key: 'b', href: '#link', target: '_blank' }) ])); + assertRender(actual, v('div', { key: 'a' }, [null, v('a', { key: 'b', href: '#link', target: '_blank' })])); }, 'by object key'() { const key: any = {}; - const actual = v('div', { key: 'a' }, [ null, v('a', { key, href: '#link' }) ]); + const actual = v('div', { key: 'a' }, [null, v('a', { key, href: '#link' })]); - assertRender(actual, v('div', { key: 'a' }, [ null, v('a', { key, href: '#link' }) ])); + assertRender(actual, v('div', { key: 'a' }, [null, v('a', { key, href: '#link' })])); assignChildPropertiesByKey(actual, key, { target: '_blank' }); - assertRender(actual, v('div', { key: 'a' }, [ null, v('a', { key, href: '#link', target: '_blank' }) ])); + assertRender(actual, v('div', { key: 'a' }, [null, v('a', { key, href: '#link', target: '_blank' })])); }, 'does not resolve - string'() { - const actual = v('div', {}, [ v('a', { href: '#link' }) ]); + const actual = v('div', {}, [v('a', { href: '#link' })]); - assert.throws(() => { - assignChildPropertiesByKey(actual, 'a', { target: '_blank' }); - }, TypeError, 'Key of "a" is not resolving to a valid target'); + assert.throws( + () => { + assignChildPropertiesByKey(actual, 'a', { target: '_blank' }); + }, + TypeError, + 'Key of "a" is not resolving to a valid target' + ); }, 'does not resolve - object'() { - const actual = v('div', {}, [ v('a', { href: '#link' }) ]); + const actual = v('div', {}, [v('a', { href: '#link' })]); - assert.throws(() => { - assignChildPropertiesByKey(actual, {}, { target: '_blank' }); - }, TypeError, 'Key of "{}" is not resolving to a valid target'); + assert.throws( + () => { + assignChildPropertiesByKey(actual, {}, { target: '_blank' }); + }, + TypeError, + 'Key of "{}" is not resolving to a valid target' + ); }, 'duplicate key'() { - const actual = v('div', {}, [ v('a', { key: 'a' }), v('a', { key: 'a', href: '#link' }) ]); + const actual = v('div', {}, [v('a', { key: 'a' }), v('a', { key: 'a', href: '#link' })]); const warnStub = stub(console, 'warn'); assignChildPropertiesByKey(actual, 'a', { target: '_blank' }); warnStub.restore(); - assertRender(actual, v('div', {}, [ v('a', { target: '_blank', key: 'a' }), v('a', { key: 'a', href: '#link' }) ])); + assertRender( + actual, + v('div', {}, [v('a', { target: '_blank', key: 'a' }), v('a', { key: 'a', href: '#link' })]) + ); assert.isTrue(warnStub.calledOnce); - assert.deepEqual(warnStub.args, [ [ 'Duplicate key of "a" found.' ] ]); + assert.deepEqual(warnStub.args, [['Duplicate key of "a" found.']]); } }, 'assignProperties()': { - 'basic'() { - const actual = v('div', { styles: { 'color': 'blue' } }, [ null, v('a', { href: '#link' }) ]); + basic() { + const actual = v('div', { styles: { color: 'blue' } }, [null, v('a', { href: '#link' })]); - assertRender(actual, v('div', { styles: { 'color': 'blue' } }, [ null, v('a', { href: '#link' }) ])); + assertRender(actual, v('div', { styles: { color: 'blue' } }, [null, v('a', { href: '#link' })])); assignProperties(actual, { styles: { 'font-weight': 'bold' } }); - assertRender(actual, v('div', { styles: { 'font-weight': 'bold' } }, [ null, v('a', { href: '#link' }) ])); + assertRender(actual, v('div', { styles: { 'font-weight': 'bold' } }, [null, v('a', { href: '#link' })])); }, 'with class function'() { - const actual = v('div', { styles: { 'color': 'blue' } }, [ null, v('a', { href: '#link' }) ]); + const actual = v('div', { styles: { color: 'blue' } }, [null, v('a', { href: '#link' })]); - assertRender(actual, v('div', { styles: { 'color': 'blue' } }, [ null, v('a', { href: '#link' }) ])); + assertRender(actual, v('div', { styles: { color: 'blue' } }, [null, v('a', { href: '#link' })])); - assignProperties(actual, { classes: [ 'testClass' ] }); + assignProperties(actual, { classes: ['testClass'] }); - assertRender(actual, v('div', { styles: { 'color': 'blue' }, classes: [ 'testClass' ] }, [ null, v('a', { href: '#link' }) ])); + assertRender( + actual, + v('div', { styles: { color: 'blue' }, classes: ['testClass'] }, [null, v('a', { href: '#link' })]) + ); } }, 'compareProperty()': { - 'equals'() { + equals() { let called = false; const obj = {}; const compareString = compareProperty((value: string, name, parent) => { @@ -128,38 +145,42 @@ registerSuite('support/virtualDom', { assert.isTrue(called); }, - 'unequal'() { + unequal() { let called = false; const compareNothing = compareProperty(() => { called = true; return false; }); - assert.throws(() => { - compareNothing.diff('foo', 'bar', {}); - }, AssertionError, 'The value of property "bar" is unexpected.'); + assert.throws( + () => { + compareNothing.diff('foo', 'bar', {}); + }, + AssertionError, + 'The value of property "bar" is unexpected.' + ); assert.isTrue(called); } }, 'replaceChild()': { 'by index'() { - const actual = v('div', {}, [ null, v('a', { href: '#link' }) ]); + const actual = v('div', {}, [null, v('a', { href: '#link' })]); - assertRender(actual, v('div', {}, [ null, v('a', { href: '#link' }) ])); + assertRender(actual, v('div', {}, [null, v('a', { href: '#link' })])); replaceChild(actual, 0, v('dfn')); - assertRender(actual, v('div', {}, [ v('dfn'), v('a', { href: '#link' }) ])); + assertRender(actual, v('div', {}, [v('dfn'), v('a', { href: '#link' })])); }, 'by string index'() { - const actual = v('div', {}, [ null, v('a', { href: '#link' }) ]); + const actual = v('div', {}, [null, v('a', { href: '#link' })]); - assertRender(actual, v('div', {}, [ null, v('a', { href: '#link' }) ])); + assertRender(actual, v('div', {}, [null, v('a', { href: '#link' })])); replaceChild(actual, '0', v('dfn')); - assertRender(actual, v('div', {}, [ v('dfn'), v('a', { href: '#link' }) ])); + assertRender(actual, v('div', {}, [v('dfn'), v('a', { href: '#link' })])); }, 'no children'() { @@ -169,196 +190,230 @@ registerSuite('support/virtualDom', { replaceChild(actual, 0, v('span')); - assertRender(actual, w('widget', {}, [ v('span') ])); + assertRender(actual, w('widget', {}, [v('span')])); }, 'by string deep index'() { - const actual = v('div', {}, [ v('span', {}, [ 'foobar' ]), v('a', { href: '#link' }) ]); + const actual = v('div', {}, [v('span', {}, ['foobar']), v('a', { href: '#link' })]); - assertRender(actual, v('div', {}, [ v('span', {}, [ 'foobar' ]), v('a', { href: '#link' }) ])); + assertRender(actual, v('div', {}, [v('span', {}, ['foobar']), v('a', { href: '#link' })])); replaceChild(actual, '0,0', 'baz'); - assertRender(actual, v('div', {}, [ v('span', {}, [ 'baz' ]), v('a', { href: '#link' }) ])); + assertRender(actual, v('div', {}, [v('span', {}, ['baz']), v('a', { href: '#link' })])); }, 'final item missing children'() { - const actual = v('div', [ v('span', [ w('widget', { }) ]) ]); + const actual = v('div', [v('span', [w('widget', {})])]); - assertRender(actual, v('div', [ v('span', [ w('widget', { }) ]) ])); + assertRender(actual, v('div', [v('span', [w('widget', {})])])); replaceChild(actual, '0,0,0', 'foo'); - assertRender(actual, v('div', [ v('span', [ w('widget', { }, [ 'foo' ]) ]) ])); + assertRender(actual, v('div', [v('span', [w('widget', {}, ['foo'])])])); }, 'string index resolving to a non child node throws'() { - const actual = v('div', {}, [ v('span', {}, [ 'foobar' ]), v('a', { href: '#link' }) ]); + const actual = v('div', {}, [v('span', {}, ['foobar']), v('a', { href: '#link' })]); - assert.throws(() => { - replaceChild(actual, '0,0,0', 'bar'); - }, TypeError, 'Index of "0,0,0" is not resolving to a valid target'); + assert.throws( + () => { + replaceChild(actual, '0,0,0', 'bar'); + }, + TypeError, + 'Index of "0,0,0" is not resolving to a valid target' + ); }, 'string index resolve to an earlier non child node throws'() { - const actual = v('div', {}, [ v('span', {}, [ 'foobar' ]), v('a', { href: '#link' }) ]); - - assert.throws(() => { - replaceChild(actual, '3,0,0', 'bar'); - }, TypeError, 'Index of "3,0,0" is not resolving to a valid target'); + const actual = v('div', {}, [v('span', {}, ['foobar']), v('a', { href: '#link' })]); + + assert.throws( + () => { + replaceChild(actual, '3,0,0', 'bar'); + }, + TypeError, + 'Index of "3,0,0" is not resolving to a valid target' + ); } }, 'replaceChildByKey()': { 'by key'() { - const actual = v('div', { key: 'a' }, [ null, v('a', { key: 'b', href: '#link' }) ]); + const actual = v('div', { key: 'a' }, [null, v('a', { key: 'b', href: '#link' })]); - assertRender(actual, v('div', { key: 'a' }, [ null, v('a', { key: 'b', href: '#link' }) ])); + assertRender(actual, v('div', { key: 'a' }, [null, v('a', { key: 'b', href: '#link' })])); replaceChildByKey(actual, 'b', v('dfn')); - assertRender(actual, v('div', { key: 'a' }, [ null, v('dfn') ]), 'Didnt render correct vdom'); + assertRender(actual, v('div', { key: 'a' }, [null, v('dfn')]), 'Didnt render correct vdom'); }, 'by object key'() { const key: any = {}; - const actual = v('div', { key: 'a' }, [ null, v('a', { key, href: '#link' }) ]); + const actual = v('div', { key: 'a' }, [null, v('a', { key, href: '#link' })]); - assertRender(actual, v('div', { key: 'a' }, [ null, v('a', { key, href: '#link' }) ])); + assertRender(actual, v('div', { key: 'a' }, [null, v('a', { key, href: '#link' })])); replaceChildByKey(actual, key, v('dfn')); - assertRender(actual, v('div', { key: 'a' }, [ null, v('dfn') ])); + assertRender(actual, v('div', { key: 'a' }, [null, v('dfn')])); }, 'nested child'() { - const actual = v('div', { key: 'a' }, [ v('div', {}, [ v('div', { key: 'b' }) ]), v('a', { href: '#link' }) ]); + const actual = v('div', { key: 'a' }, [v('div', {}, [v('div', { key: 'b' })]), v('a', { href: '#link' })]); - assertRender(actual, v('div', { key: 'a' }, [ v('div', {}, [ v('div', { key: 'b' }) ]), v('a', { href: '#link' }) ])); + assertRender( + actual, + v('div', { key: 'a' }, [v('div', {}, [v('div', { key: 'b' })]), v('a', { href: '#link' })]) + ); replaceChildByKey(actual, 'b', 'baz'); - assertRender(actual, v('div', { key: 'a' }, [ v('div', {}, [ 'baz' ]), v('a', { href: '#link' }) ])); + assertRender(actual, v('div', { key: 'a' }, [v('div', {}, ['baz']), v('a', { href: '#link' })])); }, 'duplicate key'() { - const actual = v('div', {}, [ v('a', { key: 'a' }), v('a', { key: 'a', href: '#link' }) ]); + const actual = v('div', {}, [v('a', { key: 'a' }), v('a', { key: 'a', href: '#link' })]); const warnStub = stub(console, 'warn'); replaceChildByKey(actual, 'a', 'foo'); warnStub.restore(); - assertRender(actual, v('div', {}, [ 'foo', v('a', { key: 'a', href: '#link' }) ])); + assertRender(actual, v('div', {}, ['foo', v('a', { key: 'a', href: '#link' })])); assert.isTrue(warnStub.calledOnce); assert.isTrue(warnStub.calledWith('Duplicate key of "a" found.')); }, 'string key resolving to a non child node throws'() { - const actual = v('div', {}, [ v('span', {}, [ 'foobar' ]), v('a', { href: '#link' }) ]); + const actual = v('div', {}, [v('span', {}, ['foobar']), v('a', { href: '#link' })]); - assert.throws(() => { - replaceChildByKey(actual, 'a', 'bar'); - }, TypeError, 'Key of "a" is not resolving to a valid target'); + assert.throws( + () => { + replaceChildByKey(actual, 'a', 'bar'); + }, + TypeError, + 'Key of "a" is not resolving to a valid target' + ); }, 'object key resolve to a non child node throws'() { - const actual = v('div', {}, [ v('span', {}, [ 'foobar' ]), v('a', { href: '#link' }) ]); + const actual = v('div', {}, [v('span', {}, ['foobar']), v('a', { href: '#link' })]); - assert.throws(() => { - replaceChildByKey(actual, {}, 'bar'); - }, TypeError, 'Key of "{}" is not resolving to a valid target'); + assert.throws( + () => { + replaceChildByKey(actual, {}, 'bar'); + }, + TypeError, + 'Key of "{}" is not resolving to a valid target' + ); }, 'no children - should throw'() { const actual = v('div', {}); - assert.throws(() => { - replaceChildByKey(actual, 'key', 'foo'); - }, TypeError, 'Target does not have children.'); + assert.throws( + () => { + replaceChildByKey(actual, 'key', 'foo'); + }, + TypeError, + 'Target does not have children.' + ); } }, 'replaceChildProperties()': { 'by index'() { - const actual = v('div', {}, [ null, v('a', { href: '#link' }) ]); + const actual = v('div', {}, [null, v('a', { href: '#link' })]); - assertRender(actual, v('div', {}, [ null, v('a', { href: '#link' }) ])); + assertRender(actual, v('div', {}, [null, v('a', { href: '#link' })])); replaceChildProperties(actual, 1, { target: '_blank' }); - assertRender(actual, v('div', {}, [ null, v('a', { target: '_blank' }) ])); + assertRender(actual, v('div', {}, [null, v('a', { target: '_blank' })])); }, - 'throws when final child can\'t have properties'() { - const actual = v('div', {}, [ null, v('a', { href: '#link' }) ]); + "throws when final child can't have properties"() { + const actual = v('div', {}, [null, v('a', { href: '#link' })]); - assertRender(actual, v('div', {}, [ null, v('a', { href: '#link' }) ])); + assertRender(actual, v('div', {}, [null, v('a', { href: '#link' })])); - assert.throws(() => { - replaceChildProperties(actual, 0, { target: '_blank' }); - }, TypeError, 'Index of "0" is not resolving to a valid target'); + assert.throws( + () => { + replaceChildProperties(actual, 0, { target: '_blank' }); + }, + TypeError, + 'Index of "0" is not resolving to a valid target' + ); } }, 'replaceChildPropertiesByKey()': { 'by string key'() { - const actual = v('div', { key: 'a' }, [ null, v('a', { key: 'b', href: '#link' }) ]); + const actual = v('div', { key: 'a' }, [null, v('a', { key: 'b', href: '#link' })]); - assertRender(actual, v('div', { key: 'a' }, [ null, v('a', { key: 'b', href: '#link' }) ])); + assertRender(actual, v('div', { key: 'a' }, [null, v('a', { key: 'b', href: '#link' })])); replaceChildPropertiesByKey(actual, 'b', { key: 'b', target: '_blank' }); - assertRender(actual, v('div', { key: 'a' }, [ null, v('a', { key: 'b', target: '_blank' }) ])); + assertRender(actual, v('div', { key: 'a' }, [null, v('a', { key: 'b', target: '_blank' })])); }, 'by object key'() { const key: any = {}; - const actual = v('div', { key: 'a' }, [ null, v('a', { key, href: '#link' }) ]); + const actual = v('div', { key: 'a' }, [null, v('a', { key, href: '#link' })]); - assertRender(actual, v('div', { key: 'a' }, [ null, v('a', { key, href: '#link' }) ])); + assertRender(actual, v('div', { key: 'a' }, [null, v('a', { key, href: '#link' })])); replaceChildPropertiesByKey(actual, key, { key, target: '_blank' }); - assertRender(actual, v('div', { key: 'a' }, [ null, v('a', { key, target: '_blank' }) ])); + assertRender(actual, v('div', { key: 'a' }, [null, v('a', { key, target: '_blank' })])); }, 'duplicate key'() { - const actual = v('div', {}, [ v('a', { key: 'a' }), v('a', { key: 'a', href: '#link' }) ]); + const actual = v('div', {}, [v('a', { key: 'a' }), v('a', { key: 'a', href: '#link' })]); const warnStub = stub(console, 'warn'); replaceChildPropertiesByKey(actual, 'a', { key: 'a', prop: 'b' }); warnStub.restore(); - assertRender(actual, v('div', {}, [ v('a', { key: 'a', prop: 'b' }), v('a', { key: 'a', href: '#link' }) ])); + assertRender(actual, v('div', {}, [v('a', { key: 'a', prop: 'b' }), v('a', { key: 'a', href: '#link' })])); assert.isTrue(warnStub.calledOnce); assert.isTrue(warnStub.calledWith('Duplicate key of "a" found.')); }, 'string key resolving to a non child node throws'() { - const actual = v('div', {}, [ v('span', {}, [ 'foobar' ]), v('a', { href: '#link' }) ]); + const actual = v('div', {}, [v('span', {}, ['foobar']), v('a', { href: '#link' })]); - assert.throws(() => { - replaceChildPropertiesByKey(actual, 'a', {}); - }, TypeError, 'Key of "a" is not resolving to a valid target'); + assert.throws( + () => { + replaceChildPropertiesByKey(actual, 'a', {}); + }, + TypeError, + 'Key of "a" is not resolving to a valid target' + ); }, 'object key resolve to a non child node throws'() { - const actual = v('div', {}, [ v('span', {}, [ 'foobar' ]), v('a', { href: '#link' }) ]); - - assert.throws(() => { - replaceChildPropertiesByKey(actual, {}, {}); - }, TypeError, 'Key of "{}" is not resolving to a valid target'); + const actual = v('div', {}, [v('span', {}, ['foobar']), v('a', { href: '#link' })]); + + assert.throws( + () => { + replaceChildPropertiesByKey(actual, {}, {}); + }, + TypeError, + 'Key of "{}" is not resolving to a valid target' + ); } - }, 'replaceProperties()': { - 'basic'() { - const actual = v('div', { styles: { 'color': 'blue' } }, [ null, v('a', { href: '#link' }) ]); + basic() { + const actual = v('div', { styles: { color: 'blue' } }, [null, v('a', { href: '#link' })]); - assertRender(actual, v('div', { styles: { 'color': 'blue' } }, [ null, v('a', { href: '#link' }) ])); + assertRender(actual, v('div', { styles: { color: 'blue' } }, [null, v('a', { href: '#link' })])); - replaceProperties(actual, { classes: [ 'foo' ] }); + replaceProperties(actual, { classes: ['foo'] }); - assertRender(actual, v('div', { classes: [ 'foo' ] }, [ null, v('a', { href: '#link' }) ])); + assertRender(actual, v('div', { classes: ['foo'] }, [null, v('a', { href: '#link' })])); } }, @@ -368,7 +423,10 @@ registerSuite('support/virtualDom', { }, 'key not found with children'() { - assert.isUndefined(findKey(v('div', [ v('span', { key: 'bar' }), 'foo', null ]), 'foo'), 'should not find key'); + assert.isUndefined( + findKey(v('div', [v('span', { key: 'bar' }), 'foo', null]), 'foo'), + 'should not find key' + ); }, 'key is in root node'() { @@ -376,41 +434,61 @@ registerSuite('support/virtualDom', { }, 'key is in child'() { - assertRender(findKey(v('div', { key: 'bar' }, [ v('span', { key: 'foo' }), 'foo', null ]), 'foo')!, v('span', { key: 'foo' }), 'should find child node'); - assertRender(findKey(v('div', { key: 'bar' }, [ v('span', { key: 'foo' }), v('span', { key: 'baz' }), 'foo', null ]), 'baz')!, v('span', { key: 'baz' }), 'should find child node'); + assertRender( + findKey(v('div', { key: 'bar' }, [v('span', { key: 'foo' }), 'foo', null]), 'foo')!, + v('span', { key: 'foo' }), + 'should find child node' + ); + assertRender( + findKey( + v('div', { key: 'bar' }, [v('span', { key: 'foo' }), v('span', { key: 'baz' }), 'foo', null]), + 'baz' + )!, + v('span', { key: 'baz' }), + 'should find child node' + ); }, 'key is object'() { const obj = {}; - assertRender(findKey(v('div', { key: 'bar' }, [ v('span', { key: obj } as any), 'foo', null ]), obj)!, v('span', { key: obj } as any), 'should find child node'); + assertRender( + findKey(v('div', { key: 'bar' }, [v('span', { key: obj } as any), 'foo', null]), obj)!, + v('span', { key: obj } as any), + 'should find child node' + ); }, 'value is WNode'() { - const vnode = w('widget', { - onClick() { } - }, [ - w('sub-widget', { key: 'foo', onClick() { } }), - w('sub-widget', { key: 'bar', onClick() { } }) - ]); + const vnode = w( + 'widget', + { + onClick() {} + }, + [w('sub-widget', { key: 'foo', onClick() {} }), w('sub-widget', { key: 'bar', onClick() {} })] + ); - assertRender(findKey(vnode, 'foo')!, w('sub-widget', { key: 'foo', onClick() { } }), 'should find widget'); + assertRender( + findKey(vnode, 'foo')!, + w('sub-widget', { key: 'foo', onClick() {} }), + 'should find widget' + ); }, 'duplicate string keys warn'() { const warnStub = stub(console, 'warn'); const fixture = v('div', { key: 'foo' }, [ - v('span', { key: 'parent1' }, [ - v('i', { key: 'icon', id: 'i1' }) - ]), - v('span', { key: 'parent2' }, [ - v('i', { key: 'icon', id: 'i2' }) - ]) + v('span', { key: 'parent1' }, [v('i', { key: 'icon', id: 'i1' })]), + v('span', { key: 'parent2' }, [v('i', { key: 'icon', id: 'i2' })]) ]); assertRender(findKey(fixture, 'icon')!, v('i', { key: 'icon', id: 'i1' }), 'should find first key'); assert.strictEqual(warnStub.callCount, 1, 'should have been called once'); - assert.strictEqual(warnStub.lastCall.args[0], 'Duplicate key of "icon" found.', 'should have logged duplicate key'); + assert.strictEqual( + warnStub.lastCall.args[0], + 'Duplicate key of "icon" found.', + 'should have logged duplicate key' + ); warnStub.restore(); }, @@ -419,12 +497,8 @@ registerSuite('support/virtualDom', { const key: any = {}; const fixture = v('div', { key: 'foo' }, [ - v('span', { key: 'parent1' }, [ - v('i', { key, id: 'i1' }) - ]), - v('span', { key: 'parent2' }, [ - v('i', { key, id: 'i2' }) - ]) + v('span', { key: 'parent1' }, [v('i', { key, id: 'i1' })]), + v('span', { key: 'parent2' }, [v('i', { key, id: 'i2' })]) ]); const noDuplicates = v('div', { key: 'foo' }, [ @@ -435,14 +509,18 @@ registerSuite('support/virtualDom', { assertRender(findKey(fixture, key)!, v('i', { key, id: 'i1' }), 'should find first key'); assertRender(findKey(noDuplicates, 'parent2')!, v('span', { key: 'parent2' }), 'should find key'); assert.strictEqual(warnStub.callCount, 1, 'should have been called once'); - assert.strictEqual(warnStub.lastCall.args[0], 'Duplicate key of "{}" found.', 'should have logged duplicate key'); + assert.strictEqual( + warnStub.lastCall.args[0], + 'Duplicate key of "{}" found.', + 'should have logged duplicate key' + ); warnStub.restore(); } }, 'findIndex()': { 'by string index'() { - const actual = v('div', {}, [ null, v('a', { href: '#link' }) ]); + const actual = v('div', {}, [null, v('a', { href: '#link' })]); assertRender(findIndex(actual, '1')!, v('a', { href: '#link' })); }, @@ -452,22 +530,22 @@ registerSuite('support/virtualDom', { }, 'by string deep index'() { - const actual = v('div', {}, [ v('span', {}, [ v('a', { href: '#link' }) ]) ]); + const actual = v('div', {}, [v('span', {}, [v('a', { href: '#link' })])]); assertRender(findIndex(actual, '0,0')!, v('a', { href: '#link' })); }, 'final item missing children returns undefined'() { - const actual = v('div', [ v('span', [ w('widget', { }) ]) ]); + const actual = v('div', [v('span', [w('widget', {})])]); assert.isUndefined(findIndex(actual, '0,0,0')); }, 'string index resolving to a non child returns undefined'() { - const actual = v('div', {}, [ v('span', {}, [ 'foobar' ]), v('a', { href: '#link' }) ]); + const actual = v('div', {}, [v('span', {}, ['foobar']), v('a', { href: '#link' })]); assert.isUndefined(findIndex(actual, '0,0,0')); }, 'string index resolve to an earlier non child node returns undefined'() { - const actual = v('div', {}, [ v('span', {}, [ 'foobar' ]), v('a', { href: '#link' }) ]); + const actual = v('div', {}, [v('span', {}, ['foobar']), v('a', { href: '#link' })]); assert.isUndefined(findIndex(actual, '3,0,0')); } } diff --git a/tests/unit/support/loadJsdom.ts b/tests/unit/support/loadJsdom.ts index 2fe1562..ae51481 100644 --- a/tests/unit/support/loadJsdom.ts +++ b/tests/unit/support/loadJsdom.ts @@ -6,7 +6,6 @@ import global from '@dojo/shim/global'; import doc from '../../../src/support/loadJsdom'; registerSuite('support/loadJsdom', { - 'document is global and matches export'() { assert(document, 'document should be in the global scope'); assert.strictEqual(document, doc, 'document should equal default export of module'); diff --git a/tests/unit/support/sendEvent.ts b/tests/unit/support/sendEvent.ts index 6987107..3ddf64e 100644 --- a/tests/unit/support/sendEvent.ts +++ b/tests/unit/support/sendEvent.ts @@ -5,7 +5,6 @@ import has from '@dojo/has/has'; import sendEvent from '../../../src/support/sendEvent'; registerSuite('support/sendEvent', { - 'custom event'() { const target = document.createElement('div'); document.body.appendChild(target); @@ -47,16 +46,15 @@ registerSuite('support/sendEvent', { }); }, - 'MouseEvents'() { + MouseEvents() { const target = document.createElement('button'); document.body.appendChild(target); function listener(evt: MouseEvent) { assert.strictEqual(evt.type, 'click', 'event type should be "click"'); if (has('customevent-constructor')) { - assert(evt instanceof ( window).MouseEvent, 'event should be an instance of MouseEvent'); - } - else { + assert(evt instanceof (window).MouseEvent, 'event should be an instance of MouseEvent'); + } else { assert.instanceOf(evt, window['CustomEvent'], 'event should be an instance of CustomEvent'); } assert.strictEqual(evt.clientX, 50); @@ -97,7 +95,7 @@ registerSuite('support/sendEvent', { target.addEventListener('deviceproximity', listener); - const eventInit: EventInit & { max: number, min: number, value: number } = { + const eventInit: EventInit & { max: number; min: number; value: number } = { max: 0, min: 0, value: 0 @@ -109,7 +107,7 @@ registerSuite('support/sendEvent', { }); }, - 'selector'() { + selector() { const target = document.createElement('div'); const button = document.createElement('button'); target.appendChild(button); @@ -139,11 +137,15 @@ registerSuite('support/sendEvent', { const target = document.createElement('div'); document.body.appendChild(target); - assert.throws(() => { - sendEvent(target, 'foo', { - selector: 'button' - }); - }, Error, 'Cannot resolve to an element with selector'); + assert.throws( + () => { + sendEvent(target, 'foo', { + selector: 'button' + }); + }, + Error, + 'Cannot resolve to an element with selector' + ); document.body.removeChild(target); }, @@ -161,9 +163,13 @@ registerSuite('support/sendEvent', { } target.addEventListener('click', thrower); - assert.throws(() => { - sendEvent(target, 'click'); - }, Error, 'foo'); + assert.throws( + () => { + sendEvent(target, 'click'); + }, + Error, + 'foo' + ); target.removeEventListener('click', thrower); document.body.removeChild(target); diff --git a/tsconfig.json b/tsconfig.json index 3d57c80..a7a4d29 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -6,6 +6,7 @@ "moduleResolution": "node", "noImplicitAny": true, "noImplicitThis": true, + "noUnusedLocals": true, "outDir": "_build/", "removeComments": false, "sourceMap": true, diff --git a/tslint.json b/tslint.json index 855e134..1019fb0 100644 --- a/tslint.json +++ b/tslint.json @@ -1,5 +1,7 @@ { + "rulesDirectory": ["tslint-plugin-prettier"], "rules": { + "prettier": true, "align": false, "ban": [], "class-name": true, @@ -30,15 +32,12 @@ "no-switch-case-fall-through": false, "no-trailing-whitespace": true, "no-unused-expression": false, - "no-unused-variable": true, "no-use-before-declare": false, "no-var-keyword": true, "no-var-requires": false, "object-literal-sort-keys": false, "one-line": [ true, "check-open-brace", "check-whitespace" ], - "quotemark": [ true, "single" ], "radix": true, - "semicolon": [ true, "always" ], "trailing-comma": [ true, { "multiline": "never", "singleline": "never" @@ -58,8 +57,6 @@ "property-declaration": "onespace", "variable-declaration": "onespace" } ], - "use-strict": false, - "variable-name": [ true, "check-format", "allow-leading-underscore", "ban-keywords" ], - "whitespace": [ true, "check-branch", "check-decl", "check-operator", "check-module", "check-separator", "check-type", "check-typecast" ] + "variable-name": [ true, "check-format", "allow-leading-underscore", "ban-keywords" ] } }