From 87bc1115da8cbe270c685b276aa1446e6cb92a4e Mon Sep 17 00:00:00 2001 From: Martin Helmut Fieber Date: Sat, 22 Jun 2019 21:02:06 +0200 Subject: [PATCH] feat: implement first draft for snapshot testing --- .babelrc | 3 + .eslintrc.js | 13 +- .gitignore | 1 + package.json | 17 +- pnpm-lock.yaml | 412 ++++++++++++++---- .../__snapshots__/snapshot.test.jsx.snap | 18 + src/__tests__/runner.test.js | 31 ++ src/__tests__/snapshot.test.jsx | 27 ++ src/cli.js | 12 +- src/runner.js | 78 +++- 10 files changed, 514 insertions(+), 98 deletions(-) create mode 100644 .babelrc create mode 100644 src/__tests__/__snapshots__/snapshot.test.jsx.snap create mode 100644 src/__tests__/snapshot.test.jsx diff --git a/.babelrc b/.babelrc new file mode 100644 index 0000000..bfc8964 --- /dev/null +++ b/.babelrc @@ -0,0 +1,3 @@ +{ + "plugins": ["@babel/plugin-transform-react-jsx"] +} diff --git a/.eslintrc.js b/.eslintrc.js index 189fd66..129fe71 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -2,20 +2,23 @@ module.exports = { root: true, - extends: ["eslint:recommended", "prettier"], - // plugins: ["compat"], + extends: ["eslint:recommended", "prettier", "plugin:react/recommended"], parserOptions: { ecmaVersion: 2018, - impliedStrict: false + impliedStrict: false, + jsx: true }, env: { node: true, es6: true }, settings: { - browsers: ["maintained node versions"] + browsers: ["maintained node versions"], + react: { + version: "detect" + } }, rules: { - // "compat/compat": "error" + "no-prototype-builtins": 0 } }; diff --git a/.gitignore b/.gitignore index 2f24c57..d973174 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ node_modules/ coverage/ .nyc_output/ +*.log diff --git a/package.json b/package.json index 1e234bf..53d537c 100644 --- a/package.json +++ b/package.json @@ -7,11 +7,11 @@ "natr": "./src/cli.js" }, "scripts": { - "test": "./src/cli.js src/__tests__/*.test.js | tap-color", + "test": "./src/cli.js \"src/__tests__/*.test.@(js|jsx)\" -r @babel/register | tap-color", "coverage": "nyc --reporter=html --reporter=text ./src/cli.js src/__tests__/*.test.js | tap-nyc", - "lint": "eslint --ignore-path .gitignore --ext .js .", - "format": "prettier --ignore-path .gitignore --write \"**/*.{js,md,json,yml}\"", - "format:check": "prettier --ignore-path .gitignore --list-different \"**/*.{js,md,json,yml}\"" + "lint": "eslint --ignore-path .gitignore --ext .js --ext .jsx .", + "format": "prettier --ignore-path .gitignore --write \"**/*.{js,jsx,md,json,yml}\"", + "format:check": "prettier --ignore-path .gitignore --list-different \"**/*.{js,jsx,md,json,yml}\"" }, "keywords": [ "natr", @@ -44,14 +44,19 @@ "stack-utils": "1.0.2" }, "devDependencies": { + "@babel/core": "7.4.5", + "@babel/plugin-transform-react-jsx": "7.3.0", + "@babel/register": "7.4.4", "commitizen": "3.1.1", "concat-stream": "2.0.0", "cz-conventional-changelog": "2.1.0", - "eslint": "5.16.0", + "eslint": "6.0.0", "eslint-config-prettier": "5.0.0", - "eslint-plugin-compat": "3.1.2", + "eslint-plugin-react": "7.13.0", "nyc": "14.1.1", "prettier": "1.18.2", + "react": "16.8.6", + "react-test-renderer": "16.8.6", "stream-spec": "0.3.6", "tap-color": "1.1.0", "tap-nirvana": "1.1.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index fa46806..14947df 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -5,14 +5,19 @@ dependencies: object-inspect: 1.6.0 stack-utils: 1.0.2 devDependencies: + '@babel/core': 7.4.5 + '@babel/plugin-transform-react-jsx': 7.3.0_@babel+core@7.4.5 + '@babel/register': 7.4.4_@babel+core@7.4.5 commitizen: 3.1.1 concat-stream: 2.0.0 cz-conventional-changelog: 2.1.0 - eslint: 5.16.0 - eslint-config-prettier: 5.0.0_eslint@5.16.0 - eslint-plugin-compat: 3.1.2_eslint@5.16.0 + eslint: 6.0.0 + eslint-config-prettier: 5.0.0_eslint@6.0.0 + eslint-plugin-react: 7.13.0_eslint@6.0.0 nyc: 14.1.1 prettier: 1.18.2 + react: 16.8.6 + react-test-renderer: 16.8.6_react@16.8.6 stream-spec: 0.3.6 tap-color: 1.1.0 tap-nirvana: 1.1.0 @@ -25,6 +30,27 @@ packages: dev: true resolution: integrity: sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA== + /@babel/core/7.4.5: + dependencies: + '@babel/code-frame': 7.0.0 + '@babel/generator': 7.4.4 + '@babel/helpers': 7.4.4 + '@babel/parser': 7.4.5 + '@babel/template': 7.4.4 + '@babel/traverse': 7.4.5 + '@babel/types': 7.4.4 + convert-source-map: 1.6.0 + debug: 4.1.1 + json5: 2.1.0 + lodash: 4.17.11 + resolve: 1.11.1 + semver: 5.7.0 + source-map: 0.5.7 + dev: true + engines: + node: '>=6.9.0' + resolution: + integrity: sha512-OvjIh6aqXtlsA8ujtGKfC7LYWksYSX8yQcM8Ay3LuvVeQ63lcOKgoZWVqcpFwkd29aYU9rVx7jxhfhiEDV9MZA== /@babel/generator/7.4.4: dependencies: '@babel/types': 7.4.4 @@ -35,6 +61,13 @@ packages: dev: true resolution: integrity: sha512-53UOLK6TVNqKxf7RUh8NE851EHRxOOeVXKbK2bivdb+iziMyk03Sr4eaE9OELCbyZAAafAKPDwF2TPUES5QbxQ== + /@babel/helper-builder-react-jsx/7.3.0: + dependencies: + '@babel/types': 7.4.4 + esutils: 2.0.2 + dev: true + resolution: + integrity: sha512-MjA9KgwCuPEkQd9ncSXvSyJ5y+j2sICHyrI0M3L+6fnS4wMSNDc1ARXsbTfbb2cXHn17VisSnU/sHFTCxVxSMw== /@babel/helper-function-name/7.1.0: dependencies: '@babel/helper-get-function-arity': 7.0.0 @@ -49,12 +82,24 @@ packages: dev: true resolution: integrity: sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ== + /@babel/helper-plugin-utils/7.0.0: + dev: true + resolution: + integrity: sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA== /@babel/helper-split-export-declaration/7.4.4: dependencies: '@babel/types': 7.4.4 dev: true resolution: integrity: sha512-Ro/XkzLf3JFITkW6b+hNxzZ1n5OQ80NvIUdmHspih1XAhtN3vPTuUFT4eQnela+2MaZ5ulH+iyP513KJrxbN7Q== + /@babel/helpers/7.4.4: + dependencies: + '@babel/template': 7.4.4 + '@babel/traverse': 7.4.5 + '@babel/types': 7.4.4 + dev: true + resolution: + integrity: sha512-igczbR/0SeuPR8RFfC7tGrbdTbFL3QTvH6D+Z6zNxnTe//GyqmtHmDkzrqDmyZ3eSwPqB/LhyKoU5DXsp+Vp2A== /@babel/highlight/7.0.0: dependencies: chalk: 2.4.2 @@ -70,12 +115,40 @@ packages: hasBin: true resolution: integrity: sha512-9mUqkL1FF5T7f0WDFfAoDdiMVPWsdD1gZYzSnaXsxUCUqzuch/8of9G3VUSNiZmMBoRxT3neyVsqeiL/ZPcjew== - /@babel/runtime/7.4.5: + /@babel/plugin-syntax-jsx/7.2.0_@babel+core@7.4.5: + dependencies: + '@babel/core': 7.4.5 + '@babel/helper-plugin-utils': 7.0.0 + dev: true + peerDependencies: + '@babel/core': ^7.0.0-0 + resolution: + integrity: sha512-VyN4QANJkRW6lDBmENzRszvZf3/4AXaj9YR7GwrWeeN9tEBPuXbmDYVU9bYBN0D70zCWVwUy0HWq2553VCb6Hw== + /@babel/plugin-transform-react-jsx/7.3.0_@babel+core@7.4.5: + dependencies: + '@babel/core': 7.4.5 + '@babel/helper-builder-react-jsx': 7.3.0 + '@babel/helper-plugin-utils': 7.0.0 + '@babel/plugin-syntax-jsx': 7.2.0_@babel+core@7.4.5 + dev: true + peerDependencies: + '@babel/core': ^7.0.0-0 + resolution: + integrity: sha512-a/+aRb7R06WcKvQLOu4/TpjKOdvVEKRLWFpKcNuHhiREPgGRB4TQJxq07+EZLS8LFVYpfq1a5lDUnuMdcCpBKg== + /@babel/register/7.4.4_@babel+core@7.4.5: dependencies: - regenerator-runtime: 0.13.2 + '@babel/core': 7.4.5 + core-js: 3.1.4 + find-cache-dir: 2.1.0 + lodash: 4.17.11 + mkdirp: 0.5.1 + pirates: 4.0.1 + source-map-support: 0.5.12 dev: true + peerDependencies: + '@babel/core': ^7.0.0-0 resolution: - integrity: sha512-TuI4qpWZP6lGOGIuGWtp9sPluqYICmbk8T/1vpSysqJxRPkudh/ofFWyqdcMsDf2s7KvDL4/YHgKyvcS3g9CJQ== + integrity: sha512-sn51H88GRa00+ZoMqCVgOphmswG4b7mhf9VOB0LUBAieykq2GnRFerlN+JQkO/ntT7wz4jaHNSRPg9IdMPEUkA== /@babel/template/7.4.4: dependencies: '@babel/code-frame': 7.0.0 @@ -228,6 +301,15 @@ packages: node: '>=0.10.0' resolution: integrity: sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= + /array-includes/3.0.3: + dependencies: + define-properties: 1.1.3 + es-abstract: 1.13.0 + dev: true + engines: + node: '>= 0.4' + resolution: + integrity: sha1-GEtI9i2S10UrsxsyMWXH+L0CJm0= /array-unique/0.3.2: dev: true engines: @@ -240,10 +322,6 @@ packages: node: '>=0.10.0' resolution: integrity: sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= - /ast-metadata-inferer/0.1.1: - dev: true - resolution: - integrity: sha512-hc9w8Qrgg9Lf9iFcZVhNjUnhrd2BBpTlyCnegPVvCe6O0yMrF57a6Cmh7k+xUsfUOMh9wajOL5AsGOBNEyTCcw== /astral-regex/1.0.0: dev: true engines: @@ -307,15 +385,6 @@ packages: node: '>=8' resolution: integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== - /browserslist/4.6.3: - dependencies: - caniuse-lite: 1.0.30000976 - electron-to-chromium: 1.3.167 - node-releases: 1.1.23 - dev: true - hasBin: true - resolution: - integrity: sha512-CNBqTCq22RKM8wKJNowcqihHJ4SkI8CGeK7KOR9tPboXUuS5Zk5lQgzzTbs4oxD8x+6HUshZUa2OyNI9lR93bQ== /buffer-from/1.1.1: dev: true resolution: @@ -375,14 +444,6 @@ packages: node: '>=6' resolution: integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== - /caniuse-db/1.0.30000976: - dev: true - resolution: - integrity: sha512-QvzPHBh2cYmilQAiiamun3ooHRGKFKtVwLzzx0RG7avjpj7Gii89Yzs92EKeHNqbAA2rlcFXg4GzP/tC68OGuw== - /caniuse-lite/1.0.30000976: - dev: true - resolution: - integrity: sha512-tleNB1IwPRqZiod6nUNum63xQCMN96BUO2JTeiwuRM7p9d616EHsMBjBWJMudX39qCaPuWY8KEWzMZq7A9XQMQ== /chalk/1.1.3: dependencies: ansi-styles: 2.2.1 @@ -526,6 +587,11 @@ packages: node: '>=0.10.0' resolution: integrity: sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= + /core-js/3.1.4: + dev: true + requiresBuild: true + resolution: + integrity: sha512-YNZN8lt82XIMLnLirj9MhKDFZHalwzzrL9YLt6eb0T5D0EDl4IQ90IGkua8mHbnxNrkj1d8hbdizMc0Qmg1WnQ== /core-util-is/1.0.2: dev: true resolution: @@ -611,6 +677,14 @@ packages: node: '>=4' resolution: integrity: sha1-9fj7sYp9bVCyH2QfZJ67Uiz+JPc= + /define-properties/1.1.3: + dependencies: + object-keys: 1.1.1 + dev: true + engines: + node: '>= 0.4' + resolution: + integrity: sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== /define-property/0.2.5: dependencies: is-descriptor: 0.1.6 @@ -648,6 +722,14 @@ packages: node: '>=4' resolution: integrity: sha1-OHHMCmoALow+Wzz38zYmRnXwa50= + /doctrine/2.1.0: + dependencies: + esutils: 2.0.2 + dev: true + engines: + node: '>=0.10.0' + resolution: + integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw== /doctrine/3.0.0: dependencies: esutils: 2.0.2 @@ -666,10 +748,6 @@ packages: dev: true resolution: integrity: sha1-ixLauHjA1p4+eJEFFmKjL8a93ME= - /electron-to-chromium/1.3.167: - dev: true - resolution: - integrity: sha512-84IjpeRudjP43Q0+K7tlS7ESoHOl0W6CIdzs5reS9p+sAjCQEDiaAyiXN2v1qLUdL+Of6ZSaH4Cq6bl+sfzy8A== /emoji-regex/7.0.3: dev: true resolution: @@ -686,6 +764,29 @@ packages: dev: true resolution: integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== + /es-abstract/1.13.0: + dependencies: + es-to-primitive: 1.2.0 + function-bind: 1.1.1 + has: 1.0.3 + is-callable: 1.1.4 + is-regex: 1.0.4 + object-keys: 1.1.1 + dev: true + engines: + node: '>= 0.4' + resolution: + integrity: sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg== + /es-to-primitive/1.2.0: + dependencies: + is-callable: 1.1.4 + is-date-object: 1.0.1 + is-symbol: 1.0.2 + dev: true + engines: + node: '>= 0.4' + resolution: + integrity: sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg== /es6-error/4.1.1: dev: true resolution: @@ -696,9 +797,9 @@ packages: node: '>=0.8.0' resolution: integrity: sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= - /eslint-config-prettier/5.0.0_eslint@5.16.0: + /eslint-config-prettier/5.0.0_eslint@6.0.0: dependencies: - eslint: 5.16.0 + eslint: 6.0.0 get-stdin: 6.0.0 dev: true hasBin: true @@ -706,22 +807,23 @@ packages: eslint: '>=3.14.1' resolution: integrity: sha512-c17Aqiz5e8LEqoc/QPmYnaxQFAHTx2KlCZBPxXXjEMmNchOLnV/7j0HoPZuC+rL/tDC9bazUYOKJW9bOhftI/w== - /eslint-plugin-compat/3.1.2_eslint@5.16.0: - dependencies: - '@babel/runtime': 7.4.5 - ast-metadata-inferer: 0.1.1 - browserslist: 4.6.3 - caniuse-db: 1.0.30000976 - eslint: 5.16.0 - mdn-browser-compat-data: 0.0.74 - semver: 6.1.1 + /eslint-plugin-react/7.13.0_eslint@6.0.0: + dependencies: + array-includes: 3.0.3 + doctrine: 2.1.0 + eslint: 6.0.0 + has: 1.0.3 + jsx-ast-utils: 2.1.0 + object.fromentries: 2.0.0 + prop-types: 15.7.2 + resolve: 1.11.1 dev: true engines: - node: '>=8.x' + node: '>=4' peerDependencies: eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 resolution: - integrity: sha512-10XuVdl1RG53EvXNep6VwVsIbXsJM/g+M2fCvMTuw5CSVeITAw108HjC79+NPwrBbYFpdOfeIR08CviBDZQDKg== + integrity: sha512-uA5LrHylu8lW/eAH3bEQe9YdzpPaFd9yAJTwTi/i/BKTD7j6aQMKVAdGM/ML72zD6womuSK7EiGtMKuK06lWjQ== /eslint-scope/4.0.3: dependencies: esrecurse: 4.2.1 @@ -743,7 +845,7 @@ packages: node: '>=4' resolution: integrity: sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ== - /eslint/5.16.0: + /eslint/6.0.0: dependencies: '@babel/code-frame': 7.0.0 ajv: 6.10.0 @@ -754,17 +856,18 @@ packages: eslint-scope: 4.0.3 eslint-utils: 1.3.1 eslint-visitor-keys: 1.0.0 - espree: 5.0.1 + espree: 6.0.0 esquery: 1.0.1 esutils: 2.0.2 file-entry-cache: 5.0.1 functional-red-black-tree: 1.0.1 - glob: 7.1.4 + glob-parent: 3.1.0 globals: 11.12.0 ignore: 4.0.6 import-fresh: 3.0.0 imurmurhash: 0.1.4 inquirer: 6.4.1 + is-glob: 4.0.1 js-yaml: 3.13.1 json-stable-stringify-without-jsonify: 1.0.1 levn: 0.3.0 @@ -773,7 +876,6 @@ packages: mkdirp: 0.5.1 natural-compare: 1.4.0 optionator: 0.8.2 - path-is-inside: 1.0.2 progress: 2.0.3 regexpp: 2.0.1 semver: 5.7.0 @@ -783,11 +885,11 @@ packages: text-table: 0.2.0 dev: true engines: - node: ^6.14.0 || ^8.10.0 || >=9.10.0 + node: ^8.10.0 || ^10.13.0 || >=11.10.1 hasBin: true resolution: - integrity: sha512-S3Rz11i7c8AA5JPv7xAH+dOyq/Cu/VXHiHXBPOU1k/JAM5dXqQPt3qcrhpHSorXmrpu2g0gkIBVXAqCpzfoZIg== - /espree/5.0.1: + integrity: sha512-SrrIfcd4tOgsspOKTSwamuTOAMZOUigHQhVMrzNjz4/B9Za6SHQDIocMIyIDfwDgx6MhS15nS6HC8kumCV2qBQ== + /espree/6.0.0: dependencies: acorn: 6.1.1 acorn-jsx: 5.0.1_acorn@6.1.1 @@ -796,7 +898,7 @@ packages: engines: node: '>=6.0.0' resolution: - integrity: sha512-qWAZcWh4XE/RwzLJejfcofscgMc9CamR6Tn1+XRXNzrvUSSbiAjGOI/fggztjIi7y9VLPqnICMIPiGyr8JaZ0A== + integrity: sha512-lJvCS6YbCn3ImT3yKkPe0+tJ+mH6ljhGNjHQH9mRtiO6gjhVAOhVXW1yjnwqGwTkK3bGbye+hb00nFNmu0l/1Q== /esprima/4.0.1: dev: true engines: @@ -885,10 +987,6 @@ packages: node: '>=0.10.0' resolution: integrity: sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg= - /extend/3.0.2: - dev: true - resolution: - integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== /external-editor/3.0.3: dependencies: chardet: 0.7.0 @@ -1077,6 +1175,10 @@ packages: dev: true resolution: integrity: sha1-FQStJSMVjKpA20onh8sBQRmU6k8= + /function-bind/1.1.1: + dev: true + resolution: + integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== /functional-red-black-tree/1.0.1: dev: true resolution: @@ -1107,6 +1209,13 @@ packages: node: '>=0.10.0' resolution: integrity: sha1-3BXKHGcjh8p2vTesCjlbogQqLCg= + /glob-parent/3.1.0: + dependencies: + is-glob: 3.1.0 + path-dirname: 1.0.2 + dev: true + resolution: + integrity: sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4= /glob-parent/5.0.0: dependencies: is-glob: 4.0.1 @@ -1196,6 +1305,12 @@ packages: node: '>=4' resolution: integrity: sha1-tdRU3CGZriJWmfNGfloH87lVuv0= + /has-symbols/1.0.0: + dev: true + engines: + node: '>= 0.4' + resolution: + integrity: sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q= /has-value/0.3.1: dependencies: get-value: 2.0.6 @@ -1231,6 +1346,14 @@ packages: node: '>=0.10.0' resolution: integrity: sha1-lbC2P+whRmGab+V/51Yo1aOe/k8= + /has/1.0.3: + dependencies: + function-bind: 1.1.1 + dev: true + engines: + node: '>= 0.4.0' + resolution: + integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== /hasha/3.0.0: dependencies: is-stream: 1.1.0 @@ -1371,6 +1494,12 @@ packages: dev: true resolution: integrity: sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== + /is-callable/1.1.4: + dev: true + engines: + node: '>= 0.4' + resolution: + integrity: sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA== /is-data-descriptor/0.1.4: dependencies: kind-of: 3.2.2 @@ -1387,6 +1516,12 @@ packages: node: '>=0.10.0' resolution: integrity: sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ== + /is-date-object/1.0.1: + dev: true + engines: + node: '>= 0.4' + resolution: + integrity: sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY= /is-descriptor/0.1.6: dependencies: is-accessor-descriptor: 0.1.6 @@ -1440,6 +1575,14 @@ packages: node: '>=4' resolution: integrity: sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= + /is-glob/3.1.0: + dependencies: + is-extglob: 2.1.1 + dev: true + engines: + node: '>=0.10.0' + resolution: + integrity: sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo= /is-glob/4.0.1: dependencies: is-extglob: 2.1.1 @@ -1473,12 +1616,28 @@ packages: dev: true resolution: integrity: sha1-eaKp7OfwlugPNtKy87wWwf9L8/o= + /is-regex/1.0.4: + dependencies: + has: 1.0.3 + dev: true + engines: + node: '>= 0.4' + resolution: + integrity: sha1-VRdIm1RwkbCTDglWVM7SXul+lJE= /is-stream/1.1.0: dev: true engines: node: '>=0.10.0' resolution: integrity: sha1-EtSj3U5o4Lec6428hBc66A2RykQ= + /is-symbol/1.0.2: + dependencies: + has-symbols: 1.0.0 + dev: true + engines: + node: '>= 0.4' + resolution: + integrity: sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw== /is-utf8/0.2.1: dev: true resolution: @@ -1604,12 +1763,29 @@ packages: dev: true resolution: integrity: sha512-/11Pj1OyX814QMKO7K8l85SHPTr/KsFxHp8GE2zVa0BtJgGimDjXHfM3FhC7keQdWDea7+nXf+f1de7ATZcZkQ== + /json5/2.1.0: + dependencies: + minimist: 1.2.0 + dev: true + engines: + node: '>=6' + hasBin: true + resolution: + integrity: sha512-8Mh9h6xViijj36g7Dxi+Y4S6hNGV96vcJZr/SrlHh1LR/pEn/8j/+qIBbs44YKl69Lrfctp4QD+AdWLTMqEZAQ== /jsonfile/4.0.0: dev: true optionalDependencies: graceful-fs: 4.1.15 resolution: integrity: sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss= + /jsx-ast-utils/2.1.0: + dependencies: + array-includes: 3.0.3 + dev: true + engines: + node: '>=4.0' + resolution: + integrity: sha512-yDGDG2DS4JcqhA6blsuYbtsT09xL8AoLuUR2Gb5exrw7UEM19sBcOTq+YBBhrNbl0PUC4R4LnFu+dHg2HKeVvA== /kind-of/3.2.2: dependencies: is-buffer: 1.1.6 @@ -1693,6 +1869,13 @@ packages: node: '>=0.10.0' resolution: integrity: sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc= + /loose-envify/1.4.0: + dependencies: + js-tokens: 4.0.0 + dev: true + hasBin: true + resolution: + integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== /lru-cache/4.1.5: dependencies: pseudomap: 1.0.2 @@ -1735,14 +1918,6 @@ packages: node: '>=0.10.0' resolution: integrity: sha1-7Nyo8TFE5mDxtb1B8S80edmN+48= - /mdn-browser-compat-data/0.0.74: - dependencies: - extend: 3.0.2 - dev: true - engines: - node: '>=6.0.0' - resolution: - integrity: sha512-d/pTMwk3tMxdBb5ziOr3wHLFJRfYqSgGMt5aKLpCDBFYu6gk/uLGibkikv/HmMJyU3GEb9R1VvkVkCw75hVMvg== /mem/4.3.0: dependencies: map-age-cleaner: 0.1.3 @@ -1890,12 +2065,12 @@ packages: dev: true resolution: integrity: sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== - /node-releases/1.1.23: - dependencies: - semver: 5.7.0 + /node-modules-regexp/1.0.0: dev: true + engines: + node: '>=0.10.0' resolution: - integrity: sha512-uq1iL79YjfYC0WXoHbC/z28q/9pOl8kSHaXdWmAAc8No+bDwqkZbzIJz55g/MUsPgSGm9LZ7QSUbzTcH5tz47w== + integrity: sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA= /normalize-package-data/2.5.0: dependencies: hosted-git-info: 2.7.1 @@ -1972,6 +2147,12 @@ packages: dev: false resolution: integrity: sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ== + /object-keys/1.1.1: + dev: true + engines: + node: '>= 0.4' + resolution: + integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== /object-visit/1.0.1: dependencies: isobject: 3.0.1 @@ -1980,6 +2161,17 @@ packages: node: '>=0.10.0' resolution: integrity: sha1-95xEk68MU3e1n+OdOV5BBC3QRbs= + /object.fromentries/2.0.0: + dependencies: + define-properties: 1.1.3 + es-abstract: 1.13.0 + function-bind: 1.1.1 + has: 1.0.3 + dev: true + engines: + node: '>= 0.4' + resolution: + integrity: sha512-9iLiI6H083uiqUuvzyY6qrlmc/Gz8hLQFOcb/Ri/0xXFkSNS3ctV+CbE6yM2+AnkYfOB3dGjdzC0wrMLIhQICA== /object.pick/1.3.0: dependencies: isobject: 3.0.1 @@ -2130,6 +2322,10 @@ packages: node: '>=0.10.0' resolution: integrity: sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= + /path-dirname/1.0.2: + dev: true + resolution: + integrity: sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA= /path-exists/3.0.0: dev: true engines: @@ -2142,10 +2338,6 @@ packages: node: '>=0.10.0' resolution: integrity: sha1-F0uSaHNVNP+8es5r9TpanhtcX18= - /path-is-inside/1.0.2: - dev: true - resolution: - integrity: sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM= /path-key/2.0.1: dev: true engines: @@ -2182,6 +2374,14 @@ packages: node: '>=6' resolution: integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== + /pirates/4.0.1: + dependencies: + node-modules-regexp: 1.0.0 + dev: true + engines: + node: '>= 6' + resolution: + integrity: sha512-WuNqLTbMI3tmfef2TKxlQmAiLHKtFhlsCZnPIpuv2Ow0RDVO8lfy1Opf4NUzlMXLjPl+Men7AuVdX6TA+s+uGA== /pkg-dir/3.0.0: dependencies: find-up: 3.0.0 @@ -2247,6 +2447,14 @@ packages: node: '>=0.4.0' resolution: integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== + /prop-types/15.7.2: + dependencies: + loose-envify: 1.4.0 + object-assign: 4.1.1 + react-is: 16.8.6 + dev: true + resolution: + integrity: sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ== /pseudomap/1.0.2: dev: true resolution: @@ -2268,6 +2476,33 @@ packages: dev: true resolution: integrity: sha1-+p4xn/3u6zWycpbvDz03TawvUqc= + /react-is/16.8.6: + dev: true + resolution: + integrity: sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA== + /react-test-renderer/16.8.6_react@16.8.6: + dependencies: + object-assign: 4.1.1 + prop-types: 15.7.2 + react: 16.8.6 + react-is: 16.8.6 + scheduler: 0.13.6 + dev: true + peerDependencies: + react: ^16.0.0 + resolution: + integrity: sha512-H2srzU5IWYT6cZXof6AhUcx/wEyJddQ8l7cLM/F7gDXYyPr4oq+vCIxJYXVGhId1J706sqziAjuOEjyNkfgoEw== + /react/16.8.6: + dependencies: + loose-envify: 1.4.0 + object-assign: 4.1.1 + prop-types: 15.7.2 + scheduler: 0.13.6 + dev: true + engines: + node: '>=0.10.0' + resolution: + integrity: sha512-pC0uMkhLaHm11ZSJULfOBqV4tIZkx87ZLvbbQYunNixAAvjnC+snJCg0XQXn9VIsttVsbZP/H/ewzgsd5fxKXw== /read-pkg-up/4.0.0: dependencies: find-up: 3.0.0 @@ -2329,10 +2564,6 @@ packages: node: '>= 0.10' resolution: integrity: sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q= - /regenerator-runtime/0.13.2: - dev: true - resolution: - integrity: sha512-S/TQAZJO+D3m9xeN1WTI8dLKBBiRgXBlTJvbWjCThHWZj9EvHK70Ff50/tYj2J/fvBY6JtFVwRuazHN2E7M9BA== /regex-not/1.0.2: dependencies: extend-shallow: 3.0.2 @@ -2403,6 +2634,12 @@ packages: dev: true resolution: integrity: sha512-WL2pBDjqT6pGUNSUzMw00o4T7If+z4H2x3Gz893WoUQ5KW8Vr9txp00ykiP16VBaZF5+j/OcXJHZ9+PCvdiDKw== + /resolve/1.11.1: + dependencies: + path-parse: 1.0.6 + dev: true + resolution: + integrity: sha512-vIpgF6wfuJOZI7KKKSP+HmiKggadPQAdsp5HiC1mvqnfp0gF1vdwgBWZIdrVft9pgqoMFQN+R7BSWZiBxx+BBw== /restore-cursor/2.0.0: dependencies: onetime: 2.0.1 @@ -2472,6 +2709,13 @@ packages: dev: true resolution: integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + /scheduler/0.13.6: + dependencies: + loose-envify: 1.4.0 + object-assign: 4.1.1 + dev: true + resolution: + integrity: sha512-IWnObHt413ucAYKsD9J1QShUKkbKLQQHdxRyw73sw4FN26iWr3DY/H34xGPe4nmL1DwXyWmSWmMrA9TfQbE/XQ== /semver/5.7.0: dev: true hasBin: true @@ -2592,6 +2836,13 @@ packages: dev: true resolution: integrity: sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA== + /source-map-support/0.5.12: + dependencies: + buffer-from: 1.1.1 + source-map: 0.6.1 + dev: true + resolution: + integrity: sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ== /source-map-url/0.4.0: dev: true resolution: @@ -3130,18 +3381,23 @@ packages: resolution: integrity: sha512-HG/DWAJa1PAnHT9JAhNa8AbAv3FPaiLzioSjCcmuXXhP8MlpHO5vwls4g4j6n30Z74GVQj8Xa62dWVx1QCGklg== specifiers: + '@babel/core': 7.4.5 + '@babel/plugin-transform-react-jsx': 7.3.0 + '@babel/register': 7.4.4 commitizen: 3.1.1 concat-stream: 2.0.0 cz-conventional-changelog: 2.1.0 - eslint: 5.16.0 + eslint: 6.0.0 eslint-config-prettier: 5.0.0 - eslint-plugin-compat: 3.1.2 + eslint-plugin-react: 7.13.0 fast-deep-equal: 2.0.1 fast-glob: 3.0.1 minimist: 1.2.0 nyc: 14.1.1 object-inspect: 1.6.0 prettier: 1.18.2 + react: 16.8.6 + react-test-renderer: 16.8.6 stack-utils: 1.0.2 stream-spec: 0.3.6 tap-color: 1.1.0 diff --git a/src/__tests__/__snapshots__/snapshot.test.jsx.snap b/src/__tests__/__snapshots__/snapshot.test.jsx.snap new file mode 100644 index 0000000..50ccf1b --- /dev/null +++ b/src/__tests__/__snapshots__/snapshot.test.jsx.snap @@ -0,0 +1,18 @@ +{ + "toMatchSnapshot, Given an object: should match a specific snapshot": { + "id": 1, + "name": "Mary" + }, + "toMatchSnapshot, Given a different object: should match a specific snapshot": { + "id": 2, + "name": "Martin", + "active": true + }, + "toMatchSnapshot, Given a React component: should match a specific snapshot": { + "type": "div", + "props": {}, + "children": [ + "Hello World" + ] + } +} \ No newline at end of file diff --git a/src/__tests__/runner.test.js b/src/__tests__/runner.test.js index 90dae10..336d822 100644 --- a/src/__tests__/runner.test.js +++ b/src/__tests__/runner.test.js @@ -41,4 +41,35 @@ describe("runner", async assert => { }), expected: new Error("check() in execute() didn't match: true with false") }); + + assert({ + given: "a promise", + should: "resolve", + actual: await execute(() => { + return Promise.resolve(23); + }), + expected: 23 + }); + + assert({ + given: "user object", + should: "have the correct user id and structure", + actual: await execute(check => { + const user = { id: 1, name: "Helga" }; + + check(user, { id: 1, name: "Helga" }); + + return user.id; + }), + expected: 1 + }); +}); + +describe("multiple describe in one file", async assert => { + assert({ + given: "some string concatenation", + should: "resolve to the string", + actual: "Hello" + " " + "World", + expected: "Hello World" + }); }); diff --git a/src/__tests__/snapshot.test.jsx b/src/__tests__/snapshot.test.jsx new file mode 100644 index 0000000..9d2c495 --- /dev/null +++ b/src/__tests__/snapshot.test.jsx @@ -0,0 +1,27 @@ +const React = require("react"); +const renderer = require("react-test-renderer"); + +const { describe, toMatchSnapshot } = require("../runner"); + +describe("toMatchSnapshot", async assert => { + assert({ + given: "an object", + should: "match a specific snapshot", + actual: { id: 1, name: "Mary" }, + expected: toMatchSnapshot() + }); + + assert({ + given: "a different object", + should: "match a specific snapshot", + actual: { id: 2, name: "Martin", active: true }, + expected: toMatchSnapshot() + }); + + assert({ + given: "a React component", + should: "match a specific snapshot", + actual: renderer.create(
Hello World
).toJSON(), + expected: toMatchSnapshot() + }); +}); diff --git a/src/cli.js b/src/cli.js index 8a5f23b..962a827 100755 --- a/src/cli.js +++ b/src/cli.js @@ -3,11 +3,13 @@ const glob = require("fast-glob"); const parseOpts = require("minimist"); const { resolve } = require("path"); +const { unlinkSync } = require("fs"); const opts = parseOpts(process.argv.slice(2), { - alias: { r: "require" }, + alias: { r: "require", u: "update-snapshot" }, string: "require", - default: { r: [] } + boolean: "updateSnapshot", + default: { r: [], u: false } }); const cwd = process.cwd(); @@ -24,6 +26,12 @@ opts.require.forEach(module => { } }); +if (opts["updateSnapshot"]) { + const snapshotFiles = glob.sync(`${process.cwd()}/**/*.snap`); + + snapshotFiles.forEach(unlinkSync); +} + opts._.forEach(arg => { const files = glob.sync(arg).map(String); diff --git a/src/runner.js b/src/runner.js index 2fd4165..e7bd4dc 100644 --- a/src/runner.js +++ b/src/runner.js @@ -1,4 +1,6 @@ const deepEqual = require("fast-deep-equal"); +const fs = require("fs"); +const path = require("path"); const createDefaultStream = require("./default-stream"); const duplexStream = require("./duplex-stream"); @@ -7,6 +9,8 @@ const messaging = require("./messaging"); const Results = require("./results"); const Test = require("./test"); +const FS_OPTIONS = { encoding: "utf8" }; + function createExitHarness(conf = {}) { const harness = createHarness(); const stream = harness.createStream(); @@ -106,10 +110,70 @@ function catchPromise(value) { return isPromise(value) ? catchAndReturn(value) : value; } -function resolveSnapshot(name) { - const obj = {}; +function getTestFile() { + const originalFunc = Error.prepareStackTrace; + let callerFile; + + try { + const err = new Error(); + + Error.prepareStackTrace = (_, stack) => stack; + + const currentFile = err.stack.shift().getFileName(); + + while (err.stack.length) { + callerFile = err.stack.shift().getFileName(); + + if (currentFile !== callerFile) { + break; + } + } + } catch (e) { + // Ignore exception + } + + Error.prepareStackTrace = originalFunc; + + return callerFile; +} + +function writeFormattedObjectFile(file, obj) { + const data = JSON.stringify(obj, null, 2); + + fs.writeFileSync(file, data, FS_OPTIONS); +} + +function readFormattedObjectFile(file) { + return JSON.parse(fs.readFileSync(file, FS_OPTIONS)); +} + +function resolveSnapshot(name, value) { + const testFile = getTestFile(); + const snapshotDir = `${path.dirname(testFile)}${path.sep}__snapshots__`; + const snapshotFile = `${snapshotDir}${path.sep}${path.basename( + testFile + )}.snap`; + + if (!fs.existsSync(snapshotDir)) { + fs.mkdirSync(snapshotDir); + } + + if (!fs.existsSync(snapshotFile)) { + writeFormattedObjectFile(snapshotFile, { [name]: value }); + + return value; + } + + const snapshots = readFormattedObjectFile(snapshotFile); + + if (!snapshots[name]) { + snapshots[name] = value; + writeFormattedObjectFile(snapshotFile, snapshots); + + return value; + } - return obj[name]; + return snapshots[name]; } function isValidTestDescriptor(descriptor) { @@ -142,7 +206,7 @@ function createAssert(description, test) { if (expected === resolveSnapshot) { test.deepEqual( actual, - resolveSnapshot(`${description}, ${message}`), + resolveSnapshot(`${description}, ${message}`, actual), message ); return; @@ -155,9 +219,9 @@ function createAssert(description, test) { function check(a, b) { if (!deepEqual(a, b)) { throw new Error( - `check() in execute() didn't match: ${inspectObject( + `check() in execute() didn't match:\n${inspectObject( a - )} with ${inspectObject(b)}` + )}\nwith:\n${inspectObject(b)}` ); } } @@ -187,7 +251,7 @@ function describe(description, unit) { * * @public * @param {Function} fn Execution wrapper - * @returns {Promise} Returns resolved return value or thrown error + * @returns {Promise<*>} Returns resolved return value or thrown error */ async function execute(fn) { try {