From e1ef76a214df23bca30325a8e23737f3e89ec51f Mon Sep 17 00:00:00 2001 From: Daniel Azevedo Date: Mon, 7 Nov 2022 22:46:00 +0000 Subject: [PATCH 01/24] fix #2024 - Accessing `HTMLElement` and `SVGElement` through `window` (#2025) * fix: accessing `HTMLElement` and `SVGElement` through `window` * chore: revert changes in dist files --- packages/shared/is-visible.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/shared/is-visible.js b/packages/shared/is-visible.js index a7d52f379..5d837c5f1 100644 --- a/packages/shared/is-visible.js +++ b/packages/shared/is-visible.js @@ -5,7 +5,10 @@ */ function isStyleVisible(element) { - if (!(element instanceof HTMLElement) && !(element instanceof SVGElement)) { + if ( + !(element instanceof window.HTMLElement) && + !(element instanceof window.SVGElement) + ) { return false } From b9f9bc738d48d5ad29332f79dbe858140cfefae6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 18 Jan 2023 09:54:11 +1000 Subject: [PATCH 02/24] build(deps): bump socket.io-parser from 3.3.2 to 3.3.3 (#2027) Bumps [socket.io-parser](https://github.com/socketio/socket.io-parser) from 3.3.2 to 3.3.3. - [Release notes](https://github.com/socketio/socket.io-parser/releases) - [Changelog](https://github.com/socketio/socket.io-parser/blob/main/CHANGELOG.md) - [Commits](https://github.com/socketio/socket.io-parser/compare/3.3.2...3.3.3) --- updated-dependencies: - dependency-name: socket.io-parser dependency-type: indirect ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/yarn.lock b/yarn.lock index 3ff2af80f..6f8ecbdff 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7937,7 +7937,7 @@ isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: isarray@2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.1.tgz#a37d94ed9cda2d59865c9f76fe596ee1f338741e" - integrity sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4= + integrity sha512-c2cu3UxbI+b6kR3fy0nRnAhodsvR9dx7U5+znCOzdj6IfP3upFURTr0Xl5BlQZNKZjEtxrmVyfSdeE3O57smoQ== isarray@^2.0.1: version "2.0.4" @@ -9501,7 +9501,7 @@ move-concurrently@^1.0.1: ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= + integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== ms@2.1.1: version "2.1.1" @@ -12107,9 +12107,9 @@ socket.io-client@2.4.0: to-array "0.1.4" socket.io-parser@~3.3.0: - version "3.3.2" - resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-3.3.2.tgz#ef872009d0adcf704f2fbe830191a14752ad50b6" - integrity sha512-FJvDBuOALxdCI9qwRrO/Rfp9yfndRtc1jSgVgV8FDraihmSP/MLGD5PEuJrNfjALvcQ+vMDM/33AWOYP/JSjDg== + version "3.3.3" + resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-3.3.3.tgz#3a8b84823eba87f3f7624e64a8aaab6d6318a72f" + integrity sha512-qOg87q1PMWWTeO01768Yh9ogn7chB9zkKtQnya41Y355S0UmpXgpcrFwAgjYJxu9BdKug5r5e9YtVSeWhKBUZg== dependencies: component-emitter "~1.3.0" debug "~3.1.0" From b7933e311f28cd959fe1aec5cade028ad7a349f4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 18 Jan 2023 09:54:20 +1000 Subject: [PATCH 03/24] build(deps): bump decode-uri-component from 0.2.0 to 0.2.2 (#2039) Bumps [decode-uri-component](https://github.com/SamVerschueren/decode-uri-component) from 0.2.0 to 0.2.2. - [Release notes](https://github.com/SamVerschueren/decode-uri-component/releases) - [Commits](https://github.com/SamVerschueren/decode-uri-component/compare/v0.2.0...v0.2.2) --- updated-dependencies: - dependency-name: decode-uri-component dependency-type: indirect ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/yarn.lock b/yarn.lock index 6f8ecbdff..a0dfc2b0d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5120,8 +5120,9 @@ decimal.js@^10.2.0: integrity sha512-vDPw+rDgn3bZe1+F/pyEwb1oMG2XTlRVgAa6B4KccTEpYgF8w6eQllVbQcfIJnZyvzFtFpxnpGtx8dd7DJp/Rw== decode-uri-component@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" + version "0.2.2" + resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.2.tgz#e69dbe25d37941171dd540e024c444cd5188e1e9" + integrity sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ== decompress-response@^3.3.0: version "3.3.0" From 1b41ff2a130cdb3ebee45f8e8f4c05edaf2ef150 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 18 Jan 2023 09:54:31 +1000 Subject: [PATCH 04/24] build(deps): bump qs from 6.5.2 to 6.5.3 (#2042) Bumps [qs](https://github.com/ljharb/qs) from 6.5.2 to 6.5.3. - [Release notes](https://github.com/ljharb/qs/releases) - [Changelog](https://github.com/ljharb/qs/blob/main/CHANGELOG.md) - [Commits](https://github.com/ljharb/qs/compare/v6.5.2...v6.5.3) --- updated-dependencies: - dependency-name: qs dependency-type: indirect ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/yarn.lock b/yarn.lock index a0dfc2b0d..4822b72ee 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11064,8 +11064,9 @@ qs@6.7.0: integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ== qs@~6.5.2: - version "6.5.2" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" + version "6.5.3" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.3.tgz#3aeeffc91967ef6e35c0e488ef46fb296ab76aad" + integrity sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA== query-string@^5.0.1: version "5.1.1" From d5a4ac2f639393237168a993f4923483a29968b0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 18 Jan 2023 09:55:02 +1000 Subject: [PATCH 05/24] build(deps): bump css-what from 2.1.0 to 2.1.3 (#2015) Bumps [css-what](https://github.com/fb55/css-what) from 2.1.0 to 2.1.3. - [Release notes](https://github.com/fb55/css-what/releases) - [Commits](https://github.com/fb55/css-what/compare/v2.1.0...v2.1.3) --- updated-dependencies: - dependency-name: css-what dependency-type: indirect ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/yarn.lock b/yarn.lock index 4822b72ee..817506336 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4862,8 +4862,9 @@ css-tree@1.0.0-alpha.39: source-map "^0.6.1" css-what@2.1: - version "2.1.0" - resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.0.tgz#9467d032c38cfaefb9f2d79501253062f87fa1bd" + version "2.1.3" + resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.3.tgz#a6d7604573365fe74686c3f311c56513d88285f2" + integrity sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg== css-what@^3.2.1: version "3.3.0" From 32afb3256076cd25c686759d2d4ca369a10a98b3 Mon Sep 17 00:00:00 2001 From: Ctibor Laky Date: Wed, 18 Jan 2023 00:59:57 +0100 Subject: [PATCH 06/24] docs: fixes url of link to Vue3 version (#2006) Co-authored-by: Lachlan Miller --- docs/.vuepress/theme/Layout.vue | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/.vuepress/theme/Layout.vue b/docs/.vuepress/theme/Layout.vue index dc1a028a7..5e1811726 100644 --- a/docs/.vuepress/theme/Layout.vue +++ b/docs/.vuepress/theme/Layout.vue @@ -9,7 +9,10 @@

To read docs for Vue Test Utils for Vue 3, - . + .

From 0ee41be6be9ea301082ba0b8bbbb79dbe0dd5257 Mon Sep 17 00:00:00 2001 From: vaebe <52314078+vaebe@users.noreply.github.com> Date: Wed, 18 Jan 2023 08:00:24 +0800 Subject: [PATCH 07/24] =?UTF-8?q?docs(zh):=20api/wrapper/emitted=20Notes?= =?UTF-8?q?=20=E6=96=AD=E8=A8=80=E4=BA=8B=E4=BB=B6=E7=9A=84=E6=95=B0?= =?UTF-8?q?=E9=87=8F=20to=20=E6=96=AD=E8=A8=80=E4=BA=8B=E4=BB=B6=E7=9A=84?= =?UTF-8?q?=E6=9C=89=E6=95=88=E6=95=B0=E6=8D=AE=20(#2014)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/zh/api/wrapper/emitted.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/zh/api/wrapper/emitted.md b/docs/zh/api/wrapper/emitted.md index c1fe56f42..f629ef3e1 100644 --- a/docs/zh/api/wrapper/emitted.md +++ b/docs/zh/api/wrapper/emitted.md @@ -30,7 +30,7 @@ test('emit demo', async () => { // 断言事件的数量 expect(wrapper.emitted().foo.length).toBe(2) - // 断言事件的数量 + // 断言事件的有效数据 expect(wrapper.emitted().foo[1]).toEqual([123]) }) ``` From ac70014a07b16ba9ba223d51d890218b779635f8 Mon Sep 17 00:00:00 2001 From: Lachlan Miller Date: Wed, 18 Jan 2023 10:14:01 +1000 Subject: [PATCH 08/24] chore: update nvmrc --- .nvmrc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.nvmrc b/.nvmrc index e338b8659..6f7f377bf 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -v10 +v16 From b08c1db111205531aba8a8948626b9bf5c26818b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 18 Jan 2023 10:15:11 +1000 Subject: [PATCH 09/24] build(deps): bump express from 4.17.1 to 4.18.2 (#2044) Bumps [express](https://github.com/expressjs/express) from 4.17.1 to 4.18.2. - [Release notes](https://github.com/expressjs/express/releases) - [Changelog](https://github.com/expressjs/express/blob/master/History.md) - [Commits](https://github.com/expressjs/express/compare/4.17.1...4.18.2) --- updated-dependencies: - dependency-name: express dependency-type: indirect ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 354 +++++++++++++++++++++++++++++++----------------------- 1 file changed, 207 insertions(+), 147 deletions(-) diff --git a/yarn.lock b/yarn.lock index 817506336..176108856 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2834,13 +2834,13 @@ abbrev@1: resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== -accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.7: - version "1.3.7" - resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd" - integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA== +accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.8: + version "1.3.8" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" + integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== dependencies: - mime-types "~2.1.24" - negotiator "0.6.2" + mime-types "~2.1.34" + negotiator "0.6.3" acorn-dynamic-import@^4.0.0: version "4.0.0" @@ -3111,7 +3111,7 @@ array-find-index@^1.0.1: array-flatten@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" - integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI= + integrity sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg== array-flatten@^2.1.0: version "2.1.2" @@ -3488,21 +3488,23 @@ bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.11.9: resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== -body-parser@1.19.0, body-parser@^1.19.0: - version "1.19.0" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a" - integrity sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw== +body-parser@1.20.1, body-parser@^1.19.0: + version "1.20.1" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.1.tgz#b1812a8912c195cd371a3ee5e66faa2338a5c668" + integrity sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw== dependencies: - bytes "3.1.0" + bytes "3.1.2" content-type "~1.0.4" debug "2.6.9" - depd "~1.1.2" - http-errors "1.7.2" + depd "2.0.0" + destroy "1.2.0" + http-errors "2.0.0" iconv-lite "0.4.24" - on-finished "~2.3.0" - qs "6.7.0" - raw-body "2.4.0" - type-is "~1.6.17" + on-finished "2.4.1" + qs "6.11.0" + raw-body "2.5.1" + type-is "~1.6.18" + unpipe "1.0.0" bonjour@^3.5.0: version "3.5.0" @@ -3736,10 +3738,10 @@ bytes@3.0.0: resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" integrity sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg= -bytes@3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6" - integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg== +bytes@3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" + integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== cac@^6.5.6: version "6.6.1" @@ -3811,6 +3813,14 @@ cachedir@2.2.0: resolved "https://registry.yarnpkg.com/cachedir/-/cachedir-2.2.0.tgz#19afa4305e05d79e417566882e0c8f960f62ff0e" integrity sha512-VvxA0xhNqIIfg0V9AmJkDg91DaJwryutH5rVEZAhcNi4iJFj9f+QxmAjgK1LT9I8OgToX27fypX6/MeCXVbBjQ== +call-bind@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" + integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== + dependencies: + function-bind "^1.1.1" + get-intrinsic "^1.0.2" + call-me-maybe@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.1.tgz#26d208ea89e37b5cbde60250a15f031c16a4d66b" @@ -4406,16 +4416,17 @@ constants-browserify@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" -content-disposition@0.5.3: - version "0.5.3" - resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd" - integrity sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g== +content-disposition@0.5.4: + version "0.5.4" + resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe" + integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ== dependencies: - safe-buffer "5.1.2" + safe-buffer "5.2.1" content-type@~1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" + integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== conventional-changelog-angular@^1.3.3: version "1.6.6" @@ -4617,12 +4628,12 @@ convert-source-map@^1.4.0, convert-source-map@^1.6.0, convert-source-map@^1.7.0: cookie-signature@1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" - integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw= + integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ== -cookie@0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba" - integrity sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg== +cookie@0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b" + integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw== cookie@~0.4.1: version "0.4.1" @@ -5254,6 +5265,11 @@ delegates@^1.0.0: resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= +depd@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" + integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== + depd@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" @@ -5270,10 +5286,10 @@ des.js@^1.0.0: inherits "^2.0.1" minimalistic-assert "^1.0.0" -destroy@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" - integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= +destroy@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" + integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== detect-file@^1.0.0: version "1.0.0" @@ -5524,6 +5540,7 @@ editorconfig@^0.15.3: ee-first@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" + integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== electron-to-chromium@^1.3.523: version "1.3.533" @@ -5576,7 +5593,7 @@ emojis-list@^3.0.0: encodeurl@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" - integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= + integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== encoding@^0.1.11: version "0.1.12" @@ -5930,7 +5947,7 @@ esutils@^2.0.2: etag@~1.8.1: version "1.8.1" resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" - integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= + integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== eventemitter3@^3.1.0: version "3.1.2" @@ -6050,37 +6067,38 @@ expect@^26.2.0: jest-regex-util "^26.0.0" express@^4.17.1: - version "4.17.1" - resolved "https://registry.yarnpkg.com/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134" - integrity sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g== + version "4.18.2" + resolved "https://registry.yarnpkg.com/express/-/express-4.18.2.tgz#3fabe08296e930c796c19e3c516979386ba9fd59" + integrity sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ== dependencies: - accepts "~1.3.7" + accepts "~1.3.8" array-flatten "1.1.1" - body-parser "1.19.0" - content-disposition "0.5.3" + body-parser "1.20.1" + content-disposition "0.5.4" content-type "~1.0.4" - cookie "0.4.0" + cookie "0.5.0" cookie-signature "1.0.6" debug "2.6.9" - depd "~1.1.2" + depd "2.0.0" encodeurl "~1.0.2" escape-html "~1.0.3" etag "~1.8.1" - finalhandler "~1.1.2" + finalhandler "1.2.0" fresh "0.5.2" + http-errors "2.0.0" merge-descriptors "1.0.1" methods "~1.1.2" - on-finished "~2.3.0" + on-finished "2.4.1" parseurl "~1.3.3" path-to-regexp "0.1.7" - proxy-addr "~2.0.5" - qs "6.7.0" + proxy-addr "~2.0.7" + qs "6.11.0" range-parser "~1.2.1" - safe-buffer "5.1.2" - send "0.17.1" - serve-static "1.14.1" - setprototypeof "1.1.1" - statuses "~1.5.0" + safe-buffer "5.2.1" + send "0.18.0" + serve-static "1.15.0" + setprototypeof "1.2.0" + statuses "2.0.1" type-is "~1.6.18" utils-merge "1.0.1" vary "~1.1.2" @@ -6287,7 +6305,7 @@ fill-range@^7.0.1: dependencies: to-regex-range "^5.0.1" -finalhandler@1.1.2, finalhandler@~1.1.2: +finalhandler@1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d" integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA== @@ -6300,6 +6318,19 @@ finalhandler@1.1.2, finalhandler@~1.1.2: statuses "~1.5.0" unpipe "~1.0.0" +finalhandler@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.2.0.tgz#7d23fe5731b207b4640e4fcd00aec1f9207a7b32" + integrity sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg== + dependencies: + debug "2.6.9" + encodeurl "~1.0.2" + escape-html "~1.0.3" + on-finished "2.4.1" + parseurl "~1.3.3" + statuses "2.0.1" + unpipe "~1.0.0" + find-cache-dir@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.1.0.tgz#8d0f94cd13fe43c6c7c261a0d86115ca918c05f7" @@ -6426,10 +6457,10 @@ form-data@~2.3.2: combined-stream "1.0.6" mime-types "^2.1.12" -forwarded@~0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84" - integrity sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ= +forwarded@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" + integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== fragment-cache@^0.2.1: version "0.2.1" @@ -6440,7 +6471,7 @@ fragment-cache@^0.2.1: fresh@0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" - integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= + integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== from2@^2.1.0: version "2.3.0" @@ -6526,6 +6557,7 @@ fsevents@^2.1.2, fsevents@~2.1.2: function-bind@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== functional-red-black-tree@^1.0.1: version "1.0.1" @@ -6560,6 +6592,15 @@ get-caller-file@^2.0.1: resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== +get-intrinsic@^1.0.2: + version "1.1.3" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.3.tgz#063c84329ad93e83893c7f4f243ef63ffa351385" + integrity sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A== + dependencies: + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.3" + get-own-enumerable-property-symbols@^3.0.0: version "3.0.2" resolved "https://registry.yarnpkg.com/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz#b5fde77f22cbe35f390b4e089922c50bce6ef664" @@ -6947,6 +6988,11 @@ has-symbols@^1.0.0, has-symbols@^1.0.1: resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8" integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg== +has-symbols@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" + integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== + has-unicode@^2.0.0, has-unicode@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" @@ -7151,16 +7197,16 @@ http-deceiver@^1.2.7: resolved "https://registry.yarnpkg.com/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87" integrity sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc= -http-errors@1.7.2: - version "1.7.2" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.2.tgz#4f5029cf13239f31036e5b2e55292bcfbcc85c8f" - integrity sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg== +http-errors@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" + integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== dependencies: - depd "~1.1.2" - inherits "2.0.3" - setprototypeof "1.1.1" - statuses ">= 1.5.0 < 2" - toidentifier "1.0.0" + depd "2.0.0" + inherits "2.0.4" + setprototypeof "1.2.0" + statuses "2.0.1" + toidentifier "1.0.1" http-errors@~1.6.2: version "1.6.3" @@ -7171,17 +7217,6 @@ http-errors@~1.6.2: setprototypeof "1.1.0" statuses ">= 1.4.0 < 2" -http-errors@~1.7.2: - version "1.7.3" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06" - integrity sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw== - dependencies: - depd "~1.1.2" - inherits "2.0.4" - setprototypeof "1.1.1" - statuses ">= 1.5.0 < 2" - toidentifier "1.0.0" - http-parser-js@>=0.5.1: version "0.5.2" resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.2.tgz#da2e31d237b393aae72ace43882dd7e270a8ff77" @@ -9203,6 +9238,7 @@ mdurl@^1.0.1: media-typer@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" + integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== memory-fs@^0.4.1: version "0.4.1" @@ -9265,7 +9301,7 @@ meow@^4.0.0: merge-descriptors@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" - integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E= + integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w== merge-source-map@^1.1.0: version "1.1.0" @@ -9291,7 +9327,7 @@ merge@^1.2.1: methods@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" - integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= + integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== micromatch@4.x, micromatch@^4.0.2: version "4.0.2" @@ -9331,10 +9367,10 @@ mime-db@1.44.0, "mime-db@>= 1.43.0 < 2": resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.44.0.tgz#fa11c5eb0aca1334b4233cb4d52f10c5a6272f92" integrity sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg== -mime-db@1.45.0: - version "1.45.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.45.0.tgz#cceeda21ccd7c3a745eba2decd55d4b73e7879ea" - integrity sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w== +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== mime-types@^2.1.12, mime-types@~2.1.17, mime-types@~2.1.19: version "2.1.27" @@ -9343,12 +9379,12 @@ mime-types@^2.1.12, mime-types@~2.1.17, mime-types@~2.1.19: dependencies: mime-db "1.44.0" -mime-types@~2.1.24: - version "2.1.28" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.28.tgz#1160c4757eab2c5363888e005273ecf79d2a0ecd" - integrity sha512-0TO2yJ5YHYr7M2zzT7gDU1tbwHxEUWBCLt0lscSNpcdAfFyJOVEpRYNS7EXVcTLNj/25QO8gulHC5JtTzSE2UQ== +mime-types@~2.1.24, mime-types@~2.1.34: + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== dependencies: - mime-db "1.45.0" + mime-db "1.52.0" mime@1.6.0: version "1.6.0" @@ -9505,17 +9541,12 @@ ms@2.0.0: resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== -ms@2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" - integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== - ms@2.1.2, ms@^2.0.0: version "2.1.2" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== -ms@^2.1.1: +ms@2.1.3, ms@^2.1.1: version "2.1.3" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== @@ -9586,10 +9617,10 @@ natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" -negotiator@0.6.2: - version "0.6.2" - resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" - integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== +negotiator@0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" + integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== neo-async@^2.5.0, neo-async@^2.6.0, neo-async@^2.6.1: version "2.6.2" @@ -9883,6 +9914,11 @@ object-inspect@^1.7.0: resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.8.0.tgz#df807e5ecf53a609cc6bfe93eac3cc7be5b3a9d0" integrity sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA== +object-inspect@^1.9.0: + version "1.12.3" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.3.tgz#ba62dffd67ee256c8c086dfae69e016cd1f198b9" + integrity sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g== + object-is@^1.0.1: version "1.1.2" resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.2.tgz#c5d2e87ff9e119f78b7a088441519e2eec1573b6" @@ -9949,6 +9985,13 @@ octokit-pagination-methods@^1.1.0: resolved "https://registry.yarnpkg.com/octokit-pagination-methods/-/octokit-pagination-methods-1.1.0.tgz#cf472edc9d551055f9ef73f6e42b4dbb4c80bea4" integrity sha512-fZ4qZdQ2nxJvtcasX7Ghl+WlWS/d9IgnBIwFZXVNNZUmzpno91SX5bc5vuxiuKoCtK78XxGGNuSCrDC7xYB3OQ== +on-finished@2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" + integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== + dependencies: + ee-first "1.1.1" + on-finished@~2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" @@ -10358,7 +10401,7 @@ path-parse@^1.0.6: path-to-regexp@0.1.7: version "0.1.7" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" - integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= + integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ== path-type@^1.0.0: version "1.1.0" @@ -10951,12 +10994,12 @@ protoduck@^5.0.1: dependencies: genfun "^5.0.0" -proxy-addr@~2.0.5: - version "2.0.6" - resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.6.tgz#fdc2336505447d3f2f2c638ed272caf614bbb2bf" - integrity sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw== +proxy-addr@~2.0.7: + version "2.0.7" + resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" + integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== dependencies: - forwarded "~0.1.2" + forwarded "0.2.0" ipaddr.js "1.9.1" proxy-from-env@^1.0.0: @@ -11059,10 +11102,12 @@ qjobs@^1.2.0: resolved "https://registry.yarnpkg.com/qjobs/-/qjobs-1.2.0.tgz#c45e9c61800bd087ef88d7e256423bdd49e5d071" integrity sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg== -qs@6.7.0: - version "6.7.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc" - integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ== +qs@6.11.0: + version "6.11.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" + integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q== + dependencies: + side-channel "^1.0.4" qs@~6.5.2: version "6.5.3" @@ -11114,13 +11159,13 @@ range-parser@^1.2.1, range-parser@~1.2.1: resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== -raw-body@2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.0.tgz#a1ce6fb9c9bc356ca52e89256ab59059e13d0332" - integrity sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q== +raw-body@2.5.1: + version "2.5.1" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.1.tgz#fe1b1628b181b700215e5fd42389f98b71392857" + integrity sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig== dependencies: - bytes "3.1.0" - http-errors "1.7.2" + bytes "3.1.2" + http-errors "2.0.0" iconv-lite "0.4.24" unpipe "1.0.0" @@ -11733,7 +11778,7 @@ safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== -safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@^5.2.1, safe-buffer@~5.2.0: +safe-buffer@5.2.1, safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@^5.2.1, safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== @@ -11747,6 +11792,7 @@ safe-regex@^1.1.0: "safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== sane@^4.0.3: version "4.1.0" @@ -11855,24 +11901,24 @@ semver@^7.2.1, semver@^7.3.2: resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938" integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ== -send@0.17.1: - version "0.17.1" - resolved "https://registry.yarnpkg.com/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8" - integrity sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg== +send@0.18.0: + version "0.18.0" + resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" + integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg== dependencies: debug "2.6.9" - depd "~1.1.2" - destroy "~1.0.4" + depd "2.0.0" + destroy "1.2.0" encodeurl "~1.0.2" escape-html "~1.0.3" etag "~1.8.1" fresh "0.5.2" - http-errors "~1.7.2" + http-errors "2.0.0" mime "1.6.0" - ms "2.1.1" - on-finished "~2.3.0" + ms "2.1.3" + on-finished "2.4.1" range-parser "~1.2.1" - statuses "~1.5.0" + statuses "2.0.1" serialize-javascript@^2.1.2: version "2.1.2" @@ -11899,15 +11945,15 @@ serve-index@^1.9.1: mime-types "~2.1.17" parseurl "~1.3.2" -serve-static@1.14.1: - version "1.14.1" - resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.1.tgz#666e636dc4f010f7ef29970a88a674320898b2f9" - integrity sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg== +serve-static@1.15.0: + version "1.15.0" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540" + integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g== dependencies: encodeurl "~1.0.2" escape-html "~1.0.3" parseurl "~1.3.3" - send "0.17.1" + send "0.18.0" set-blocking@^2.0.0, set-blocking@~2.0.0: version "2.0.0" @@ -11940,10 +11986,10 @@ setprototypeof@1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" -setprototypeof@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683" - integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw== +setprototypeof@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" + integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== sha.js@^2.4.0, sha.js@^2.4.8: version "2.4.10" @@ -11995,6 +12041,15 @@ shellwords@^0.1.1: resolved "https://registry.yarnpkg.com/shellwords/-/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b" integrity sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww== +side-channel@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" + integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== + dependencies: + call-bind "^1.0.0" + get-intrinsic "^1.0.2" + object-inspect "^1.9.0" + sigmund@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/sigmund/-/sigmund-1.0.1.tgz#3ff21f198cad2175f9f3b781853fd94d0d19b590" @@ -12354,7 +12409,12 @@ static-extend@^0.1.1: define-property "^0.2.5" object-copy "^0.1.0" -"statuses@>= 1.4.0 < 2", "statuses@>= 1.5.0 < 2", statuses@~1.5.0: +statuses@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" + integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== + +"statuses@>= 1.4.0 < 2", statuses@~1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" @@ -12937,10 +12997,10 @@ to-regex@^3.0.1, to-regex@^3.0.2: regex-not "^1.0.2" safe-regex "^1.1.0" -toidentifier@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" - integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw== +toidentifier@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" + integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== toml@^3.0.0: version "3.0.0" @@ -13085,7 +13145,7 @@ type-fest@^0.8.1: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== -type-is@~1.6.17, type-is@~1.6.18: +type-is@~1.6.18: version "1.6.18" resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== @@ -13266,7 +13326,7 @@ universalify@^2.0.0: unpipe@1.0.0, unpipe@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" - integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= + integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== unquote@~1.1.1: version "1.1.1" @@ -13407,7 +13467,7 @@ utila@~0.4: utils-merge@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" - integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= + integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== uuid@^3.0.1, uuid@^3.3.2, uuid@^3.4.0: version "3.4.0" @@ -13451,7 +13511,7 @@ validate-npm-package-name@^3.0.0: vary@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" - integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= + integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== vee-validate@^2.1.3: version "2.1.3" From 5013304e492818e050edcd609429a3161227910a Mon Sep 17 00:00:00 2001 From: Simon He <57086651+Simon-He95@users.noreply.github.com> Date: Wed, 18 Jan 2023 08:15:39 +0800 Subject: [PATCH 10/24] refactor: tidy up (#2036) --- packages/shared/validators.js | 8 ++++---- packages/test-utils/src/wrapper.js | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/shared/validators.js b/packages/shared/validators.js index b11b1ae9e..986049d33 100644 --- a/packages/shared/validators.js +++ b/packages/shared/validators.js @@ -33,7 +33,7 @@ export function isVueComponent(c: any): boolean { return true } - if (c === null || typeof c !== 'object') { + if (!isPlainObject(c)) { return false } @@ -63,7 +63,7 @@ export function componentNeedsCompiling(component: Component): boolean { export function isRefSelector(refOptionsObject: any): boolean { if ( - typeof refOptionsObject !== 'object' || + !isPlainObject(refOptionsObject) || Object.keys(refOptionsObject || {}).length !== 1 ) { return false @@ -73,7 +73,7 @@ export function isRefSelector(refOptionsObject: any): boolean { } export function isNameSelector(nameOptionsObject: any): boolean { - if (typeof nameOptionsObject !== 'object' || nameOptionsObject === null) { + if (!isPlainObject(nameOptionsObject)) { return false } @@ -89,7 +89,7 @@ export function isDynamicComponent(c: any) { } export function isComponentOptions(c: any) { - return c !== null && typeof c === 'object' && (c.template || c.render) + return isPlainObject(c) && (c.template || c.render) } export function isFunctionalComponent(c: any) { diff --git a/packages/test-utils/src/wrapper.js b/packages/test-utils/src/wrapper.js index 7d5e2c724..bbaae815a 100644 --- a/packages/test-utils/src/wrapper.js +++ b/packages/test-utils/src/wrapper.js @@ -19,6 +19,7 @@ import { warnDeprecated, isVueWrapper } from 'shared/util' +import { isPlainObject } from 'shared/validators' import { isElementVisible } from 'shared/is-visible' import find from './find' import createWrapper from './create-wrapper' @@ -719,8 +720,7 @@ export default class Wrapper implements BaseWrapper { Object.keys(data).forEach(key => { // Don't let people set entire objects, because reactivity won't work if ( - typeof data[key] === 'object' && - data[key] !== null && + isPlainObject(data[key]) && // $FlowIgnore : Problem with possibly null this.vm data[key] === this.vm[key] ) { From 6b9bea4177ef201d9c16dc78eb55f3cba3015740 Mon Sep 17 00:00:00 2001 From: Lachlan Miller Date: Wed, 18 Jan 2023 11:44:59 +1000 Subject: [PATCH 11/24] chore: update nvm (#2049) * chore: update nvmrc * chore: fix docs --- .nvmrc | 2 +- docs/.vuepress/theme/Layout.vue | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/.nvmrc b/.nvmrc index e338b8659..6f7f377bf 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -v10 +v16 diff --git a/docs/.vuepress/theme/Layout.vue b/docs/.vuepress/theme/Layout.vue index 5e1811726..dc1a028a7 100644 --- a/docs/.vuepress/theme/Layout.vue +++ b/docs/.vuepress/theme/Layout.vue @@ -9,10 +9,7 @@

To read docs for Vue Test Utils for Vue 3, - . + .

From 9bfe35d31466f7a97100f3a4a4c6c7eaa1dd668c Mon Sep 17 00:00:00 2001 From: Kirill Romanov Date: Fri, 27 Jan 2023 05:01:31 +0300 Subject: [PATCH 12/24] fix: stubs components inlined in render function (#2017) * fix: stubs components inlined in render function * chore: fix linting Co-authored-by: Lachlan Miller --- .../create-instance/create-component-stubs.js | 6 +- .../create-instance/patch-create-element.js | 10 ++- test/specs/mounting-options/stubs.spec.js | 86 +++++++++++++++++++ 3 files changed, 98 insertions(+), 4 deletions(-) diff --git a/packages/create-instance/create-component-stubs.js b/packages/create-instance/create-component-stubs.js index 7185ab648..0b8f8d094 100644 --- a/packages/create-instance/create-component-stubs.js +++ b/packages/create-instance/create-component-stubs.js @@ -43,10 +43,10 @@ function resolveComponent(obj: Object, component: string): Object { ) } -function getCoreProperties(componentOptions: Component): Object { +function getCoreProperties(componentOptions: Component, name?: string): Object { return { attrs: componentOptions.attrs, - name: componentOptions.name, + name: componentOptions.name || name, model: componentOptions.model, props: componentOptions.props, on: componentOptions.on, @@ -108,7 +108,7 @@ export function createStubFromComponent( } return { - ...getCoreProperties(componentOptions), + ...getCoreProperties(componentOptions, name), $_vueTestUtils_original: originalComponent, $_doNotStubChildren: true, render(h, context) { diff --git a/packages/create-instance/patch-create-element.js b/packages/create-instance/patch-create-element.js index 02b7d1256..daab487f9 100644 --- a/packages/create-instance/patch-create-element.js +++ b/packages/create-instance/patch-create-element.js @@ -68,8 +68,16 @@ export function patchCreateElement(_Vue, stubs, stubAllComponents) { } if (isConstructor(el) || isComponentOptions(el)) { + const componentOptions = isConstructor(el) ? el.options : el + const elName = componentOptions.name + + const stubbedComponent = resolveComponent(elName, stubs) + if (stubbedComponent) { + return originalCreateElement(stubbedComponent, ...args) + } + if (stubAllComponents) { - const stub = createStubFromComponent(el, el.name || 'anonymous', _Vue) + const stub = createStubFromComponent(el, elName || 'anonymous', _Vue) return originalCreateElement(stub, ...args) } const Constructor = shouldExtend(el, _Vue) ? extend(el, _Vue) : el diff --git a/test/specs/mounting-options/stubs.spec.js b/test/specs/mounting-options/stubs.spec.js index fa926c278..1fa368b9b 100644 --- a/test/specs/mounting-options/stubs.spec.js +++ b/test/specs/mounting-options/stubs.spec.js @@ -704,4 +704,90 @@ describeWithShallowAndMount('options.stub', mountingMethod => { `` ) }) + + it('stubs component inlined in render function with custom stub', () => { + let childComponentCreated = false + let childComponent2Created = false + const ChildComponent = Vue.extend({ + name: 'child-component', + template: '
', + created() { + childComponentCreated = true + } + }) + const ChildComponent2 = { + name: 'child-component-2', + template: '
', + created() { + childComponent2Created = true + } + } + + const ParentComponent = { + name: 'parent-component', + render(h) { + return h('div', [h(ChildComponent), h(ChildComponent2)]) + } + } + + const wrapper = mountingMethod(ParentComponent, { + stubs: { + ChildComponent: { + name: 'child-component', + template: '
' + }, + ChildComponent2: { + name: 'child-component-2', + template: '
' + } + } + }) + + expect(childComponentCreated).toBe(false) + expect(childComponent2Created).toBe(false) + + expect(wrapper.find('.stub').exists()).toBe(true) + expect(wrapper.find('.stub-2').exists()).toBe(true) + expect(wrapper.find(ChildComponent).exists()).toBe(true) + expect(wrapper.find(ChildComponent2).exists()).toBe(true) + }) + + it('stubs component inlined in render function with default stub', () => { + let childComponentCreated = false + let childComponent2Created = false + const ChildComponent = Vue.extend({ + name: 'child-component', + template: '
', + created() { + childComponentCreated = true + } + }) + const ChildComponent2 = { + name: 'child-component-2', + template: '
', + created() { + childComponent2Created = true + } + } + + const ParentComponent = { + name: 'parent-component', + render(h) { + return h('div', [h(ChildComponent), h(ChildComponent2)]) + } + } + + const wrapper = mountingMethod(ParentComponent, { + stubs: { + ChildComponent: true, + ChildComponent2: true + } + }) + + expect(childComponentCreated).toBe(false) + expect(childComponent2Created).toBe(false) + + expect(wrapper.find(ChildComponent).exists()).toBe(true) + expect(wrapper.find(ChildComponent2).exists()).toBe(true) + }) }) From e49099684321552530b7651ef8985f101829a765 Mon Sep 17 00:00:00 2001 From: Lachlan Miller Date: Fri, 27 Jan 2023 12:06:27 +1000 Subject: [PATCH 13/24] chore: publish 1.3.4 --- lerna.json | 2 +- .../dist/vue-server-test-utils.js | 32 ++++++++++++------- .../test-utils/dist/vue-test-utils.esm.js | 32 ++++++++++++------- .../test-utils/dist/vue-test-utils.iife.js | 32 ++++++++++++------- packages/test-utils/dist/vue-test-utils.js | 32 ++++++++++++------- .../test-utils/dist/vue-test-utils.umd.js | 32 ++++++++++++------- 6 files changed, 106 insertions(+), 56 deletions(-) diff --git a/lerna.json b/lerna.json index 77f280927..d65541fe6 100644 --- a/lerna.json +++ b/lerna.json @@ -5,5 +5,5 @@ ], "npmClient": "yarn", "useWorkspaces": true, - "version": "1.3.3" + "version": "1.3.4" } diff --git a/packages/server-test-utils/dist/vue-server-test-utils.js b/packages/server-test-utils/dist/vue-server-test-utils.js index 4190a0872..6e9298823 100644 --- a/packages/server-test-utils/dist/vue-server-test-utils.js +++ b/packages/server-test-utils/dist/vue-server-test-utils.js @@ -1750,7 +1750,7 @@ function isVueComponent(c) { return true } - if (c === null || typeof c !== 'object') { + if (!isPlainObject(c)) { return false } @@ -1780,7 +1780,7 @@ function componentNeedsCompiling(component) { function isRefSelector(refOptionsObject) { if ( - typeof refOptionsObject !== 'object' || + !isPlainObject(refOptionsObject) || Object.keys(refOptionsObject || {}).length !== 1 ) { return false @@ -1790,7 +1790,7 @@ function isRefSelector(refOptionsObject) { } function isNameSelector(nameOptionsObject) { - if (typeof nameOptionsObject !== 'object' || nameOptionsObject === null) { + if (!isPlainObject(nameOptionsObject)) { return false } @@ -1806,7 +1806,7 @@ function isDynamicComponent(c) { } function isComponentOptions(c) { - return c !== null && typeof c === 'object' && (c.template || c.render) + return isPlainObject(c) && (c.template || c.render) } function isFunctionalComponent(c) { @@ -8084,7 +8084,10 @@ ErrorWrapper.prototype.destroy = function destroy () { */ function isStyleVisible(element) { - if (!(element instanceof HTMLElement) && !(element instanceof SVGElement)) { + if ( + !(element instanceof window.HTMLElement) && + !(element instanceof window.SVGElement) + ) { return false } @@ -10187,8 +10190,7 @@ Wrapper.prototype.setProps = function setProps (data) { Object.keys(data).forEach(function (key) { // Don't let people set entire objects, because reactivity won't work if ( - typeof data[key] === 'object' && - data[key] !== null && + isPlainObject(data[key]) && // $FlowIgnore : Problem with possibly null this.vm data[key] === this$1.vm[key] ) { @@ -13478,10 +13480,10 @@ function resolveComponent$1(obj, component) { ) } -function getCoreProperties(componentOptions) { +function getCoreProperties(componentOptions, name) { return { attrs: componentOptions.attrs, - name: componentOptions.name, + name: componentOptions.name || name, model: componentOptions.model, props: componentOptions.props, on: componentOptions.on, @@ -13542,7 +13544,7 @@ function createStubFromComponent( Vue__default['default'].config.ignoredElements.push(tagName); } - return Object.assign({}, getCoreProperties(componentOptions), + return Object.assign({}, getCoreProperties(componentOptions, name), {$_vueTestUtils_original: originalComponent, $_doNotStubChildren: true, render: function render(h, context) { @@ -13723,8 +13725,16 @@ function patchCreateElement(_Vue, stubs, stubAllComponents) { } if (isConstructor(el) || isComponentOptions(el)) { + var componentOptions = isConstructor(el) ? el.options : el; + var elName = componentOptions.name; + + var stubbedComponent = resolveComponent(elName, stubs); + if (stubbedComponent) { + return originalCreateElement.apply(void 0, [ stubbedComponent ].concat( args )) + } + if (stubAllComponents) { - var stub = createStubFromComponent(el, el.name || 'anonymous', _Vue); + var stub = createStubFromComponent(el, elName || 'anonymous', _Vue); return originalCreateElement.apply(void 0, [ stub ].concat( args )) } var Constructor = shouldExtend(el) ? extend(el, _Vue) : el; diff --git a/packages/test-utils/dist/vue-test-utils.esm.js b/packages/test-utils/dist/vue-test-utils.esm.js index ec5ae5f13..1be3a1bb8 100644 --- a/packages/test-utils/dist/vue-test-utils.esm.js +++ b/packages/test-utils/dist/vue-test-utils.esm.js @@ -1897,7 +1897,7 @@ function isVueComponent(c) { return true } - if (c === null || typeof c !== 'object') { + if (!isPlainObject(c)) { return false } @@ -1927,7 +1927,7 @@ function componentNeedsCompiling(component) { function isRefSelector(refOptionsObject) { if ( - typeof refOptionsObject !== 'object' || + !isPlainObject(refOptionsObject) || Object.keys(refOptionsObject || {}).length !== 1 ) { return false @@ -1937,7 +1937,7 @@ function isRefSelector(refOptionsObject) { } function isNameSelector(nameOptionsObject) { - if (typeof nameOptionsObject !== 'object' || nameOptionsObject === null) { + if (!isPlainObject(nameOptionsObject)) { return false } @@ -1953,7 +1953,7 @@ function isDynamicComponent(c) { } function isComponentOptions(c) { - return c !== null && typeof c === 'object' && (c.template || c.render) + return isPlainObject(c) && (c.template || c.render) } function isFunctionalComponent(c) { @@ -2263,10 +2263,10 @@ function resolveComponent$1(obj, component) { ) } -function getCoreProperties(componentOptions) { +function getCoreProperties(componentOptions, name) { return { attrs: componentOptions.attrs, - name: componentOptions.name, + name: componentOptions.name || name, model: componentOptions.model, props: componentOptions.props, on: componentOptions.on, @@ -2327,7 +2327,7 @@ function createStubFromComponent( Vue.config.ignoredElements.push(tagName); } - return Object.assign({}, getCoreProperties(componentOptions), + return Object.assign({}, getCoreProperties(componentOptions, name), {$_vueTestUtils_original: originalComponent, $_doNotStubChildren: true, render: function render(h, context) { @@ -2508,8 +2508,16 @@ function patchCreateElement(_Vue, stubs, stubAllComponents) { } if (isConstructor(el) || isComponentOptions(el)) { + var componentOptions = isConstructor(el) ? el.options : el; + var elName = componentOptions.name; + + var stubbedComponent = resolveComponent(elName, stubs); + if (stubbedComponent) { + return originalCreateElement.apply(void 0, [ stubbedComponent ].concat( args )) + } + if (stubAllComponents) { - var stub = createStubFromComponent(el, el.name || 'anonymous', _Vue); + var stub = createStubFromComponent(el, elName || 'anonymous', _Vue); return originalCreateElement.apply(void 0, [ stub ].concat( args )) } var Constructor = shouldExtend(el) ? extend(el, _Vue) : el; @@ -9011,7 +9019,10 @@ ErrorWrapper.prototype.destroy = function destroy () { */ function isStyleVisible(element) { - if (!(element instanceof HTMLElement) && !(element instanceof SVGElement)) { + if ( + !(element instanceof window.HTMLElement) && + !(element instanceof window.SVGElement) + ) { return false } @@ -11114,8 +11125,7 @@ Wrapper.prototype.setProps = function setProps (data) { Object.keys(data).forEach(function (key) { // Don't let people set entire objects, because reactivity won't work if ( - typeof data[key] === 'object' && - data[key] !== null && + isPlainObject(data[key]) && // $FlowIgnore : Problem with possibly null this.vm data[key] === this$1.vm[key] ) { diff --git a/packages/test-utils/dist/vue-test-utils.iife.js b/packages/test-utils/dist/vue-test-utils.iife.js index d2ad58734..30744f78a 100644 --- a/packages/test-utils/dist/vue-test-utils.iife.js +++ b/packages/test-utils/dist/vue-test-utils.iife.js @@ -1901,7 +1901,7 @@ var VueTestUtils = (function (exports, Vue, vueTemplateCompiler) { return true } - if (c === null || typeof c !== 'object') { + if (!isPlainObject(c)) { return false } @@ -1931,7 +1931,7 @@ var VueTestUtils = (function (exports, Vue, vueTemplateCompiler) { function isRefSelector(refOptionsObject) { if ( - typeof refOptionsObject !== 'object' || + !isPlainObject(refOptionsObject) || Object.keys(refOptionsObject || {}).length !== 1 ) { return false @@ -1941,7 +1941,7 @@ var VueTestUtils = (function (exports, Vue, vueTemplateCompiler) { } function isNameSelector(nameOptionsObject) { - if (typeof nameOptionsObject !== 'object' || nameOptionsObject === null) { + if (!isPlainObject(nameOptionsObject)) { return false } @@ -1957,7 +1957,7 @@ var VueTestUtils = (function (exports, Vue, vueTemplateCompiler) { } function isComponentOptions(c) { - return c !== null && typeof c === 'object' && (c.template || c.render) + return isPlainObject(c) && (c.template || c.render) } function isFunctionalComponent(c) { @@ -2267,10 +2267,10 @@ var VueTestUtils = (function (exports, Vue, vueTemplateCompiler) { ) } - function getCoreProperties(componentOptions) { + function getCoreProperties(componentOptions, name) { return { attrs: componentOptions.attrs, - name: componentOptions.name, + name: componentOptions.name || name, model: componentOptions.model, props: componentOptions.props, on: componentOptions.on, @@ -2331,7 +2331,7 @@ var VueTestUtils = (function (exports, Vue, vueTemplateCompiler) { Vue__default['default'].config.ignoredElements.push(tagName); } - return Object.assign({}, getCoreProperties(componentOptions), + return Object.assign({}, getCoreProperties(componentOptions, name), {$_vueTestUtils_original: originalComponent, $_doNotStubChildren: true, render: function render(h, context) { @@ -2512,8 +2512,16 @@ var VueTestUtils = (function (exports, Vue, vueTemplateCompiler) { } if (isConstructor(el) || isComponentOptions(el)) { + var componentOptions = isConstructor(el) ? el.options : el; + var elName = componentOptions.name; + + var stubbedComponent = resolveComponent(elName, stubs); + if (stubbedComponent) { + return originalCreateElement.apply(void 0, [ stubbedComponent ].concat( args )) + } + if (stubAllComponents) { - var stub = createStubFromComponent(el, el.name || 'anonymous', _Vue); + var stub = createStubFromComponent(el, elName || 'anonymous', _Vue); return originalCreateElement.apply(void 0, [ stub ].concat( args )) } var Constructor = shouldExtend(el) ? extend(el, _Vue) : el; @@ -9015,7 +9023,10 @@ var VueTestUtils = (function (exports, Vue, vueTemplateCompiler) { */ function isStyleVisible(element) { - if (!(element instanceof HTMLElement) && !(element instanceof SVGElement)) { + if ( + !(element instanceof window.HTMLElement) && + !(element instanceof window.SVGElement) + ) { return false } @@ -11118,8 +11129,7 @@ var VueTestUtils = (function (exports, Vue, vueTemplateCompiler) { Object.keys(data).forEach(function (key) { // Don't let people set entire objects, because reactivity won't work if ( - typeof data[key] === 'object' && - data[key] !== null && + isPlainObject(data[key]) && // $FlowIgnore : Problem with possibly null this.vm data[key] === this$1.vm[key] ) { diff --git a/packages/test-utils/dist/vue-test-utils.js b/packages/test-utils/dist/vue-test-utils.js index c577f2e63..80ce8337c 100644 --- a/packages/test-utils/dist/vue-test-utils.js +++ b/packages/test-utils/dist/vue-test-utils.js @@ -1905,7 +1905,7 @@ function isVueComponent(c) { return true } - if (c === null || typeof c !== 'object') { + if (!isPlainObject(c)) { return false } @@ -1935,7 +1935,7 @@ function componentNeedsCompiling(component) { function isRefSelector(refOptionsObject) { if ( - typeof refOptionsObject !== 'object' || + !isPlainObject(refOptionsObject) || Object.keys(refOptionsObject || {}).length !== 1 ) { return false @@ -1945,7 +1945,7 @@ function isRefSelector(refOptionsObject) { } function isNameSelector(nameOptionsObject) { - if (typeof nameOptionsObject !== 'object' || nameOptionsObject === null) { + if (!isPlainObject(nameOptionsObject)) { return false } @@ -1961,7 +1961,7 @@ function isDynamicComponent(c) { } function isComponentOptions(c) { - return c !== null && typeof c === 'object' && (c.template || c.render) + return isPlainObject(c) && (c.template || c.render) } function isFunctionalComponent(c) { @@ -2271,10 +2271,10 @@ function resolveComponent$1(obj, component) { ) } -function getCoreProperties(componentOptions) { +function getCoreProperties(componentOptions, name) { return { attrs: componentOptions.attrs, - name: componentOptions.name, + name: componentOptions.name || name, model: componentOptions.model, props: componentOptions.props, on: componentOptions.on, @@ -2335,7 +2335,7 @@ function createStubFromComponent( Vue__default['default'].config.ignoredElements.push(tagName); } - return Object.assign({}, getCoreProperties(componentOptions), + return Object.assign({}, getCoreProperties(componentOptions, name), {$_vueTestUtils_original: originalComponent, $_doNotStubChildren: true, render: function render(h, context) { @@ -2516,8 +2516,16 @@ function patchCreateElement(_Vue, stubs, stubAllComponents) { } if (isConstructor(el) || isComponentOptions(el)) { + var componentOptions = isConstructor(el) ? el.options : el; + var elName = componentOptions.name; + + var stubbedComponent = resolveComponent(elName, stubs); + if (stubbedComponent) { + return originalCreateElement.apply(void 0, [ stubbedComponent ].concat( args )) + } + if (stubAllComponents) { - var stub = createStubFromComponent(el, el.name || 'anonymous', _Vue); + var stub = createStubFromComponent(el, elName || 'anonymous', _Vue); return originalCreateElement.apply(void 0, [ stub ].concat( args )) } var Constructor = shouldExtend(el) ? extend(el, _Vue) : el; @@ -9019,7 +9027,10 @@ ErrorWrapper.prototype.destroy = function destroy () { */ function isStyleVisible(element) { - if (!(element instanceof HTMLElement) && !(element instanceof SVGElement)) { + if ( + !(element instanceof window.HTMLElement) && + !(element instanceof window.SVGElement) + ) { return false } @@ -11122,8 +11133,7 @@ Wrapper.prototype.setProps = function setProps (data) { Object.keys(data).forEach(function (key) { // Don't let people set entire objects, because reactivity won't work if ( - typeof data[key] === 'object' && - data[key] !== null && + isPlainObject(data[key]) && // $FlowIgnore : Problem with possibly null this.vm data[key] === this$1.vm[key] ) { diff --git a/packages/test-utils/dist/vue-test-utils.umd.js b/packages/test-utils/dist/vue-test-utils.umd.js index 23eae2145..a6df35715 100644 --- a/packages/test-utils/dist/vue-test-utils.umd.js +++ b/packages/test-utils/dist/vue-test-utils.umd.js @@ -1904,7 +1904,7 @@ return true } - if (c === null || typeof c !== 'object') { + if (!isPlainObject(c)) { return false } @@ -1934,7 +1934,7 @@ function isRefSelector(refOptionsObject) { if ( - typeof refOptionsObject !== 'object' || + !isPlainObject(refOptionsObject) || Object.keys(refOptionsObject || {}).length !== 1 ) { return false @@ -1944,7 +1944,7 @@ } function isNameSelector(nameOptionsObject) { - if (typeof nameOptionsObject !== 'object' || nameOptionsObject === null) { + if (!isPlainObject(nameOptionsObject)) { return false } @@ -1960,7 +1960,7 @@ } function isComponentOptions(c) { - return c !== null && typeof c === 'object' && (c.template || c.render) + return isPlainObject(c) && (c.template || c.render) } function isFunctionalComponent(c) { @@ -2270,10 +2270,10 @@ ) } - function getCoreProperties(componentOptions) { + function getCoreProperties(componentOptions, name) { return { attrs: componentOptions.attrs, - name: componentOptions.name, + name: componentOptions.name || name, model: componentOptions.model, props: componentOptions.props, on: componentOptions.on, @@ -2334,7 +2334,7 @@ Vue__default['default'].config.ignoredElements.push(tagName); } - return Object.assign({}, getCoreProperties(componentOptions), + return Object.assign({}, getCoreProperties(componentOptions, name), {$_vueTestUtils_original: originalComponent, $_doNotStubChildren: true, render: function render(h, context) { @@ -2515,8 +2515,16 @@ } if (isConstructor(el) || isComponentOptions(el)) { + var componentOptions = isConstructor(el) ? el.options : el; + var elName = componentOptions.name; + + var stubbedComponent = resolveComponent(elName, stubs); + if (stubbedComponent) { + return originalCreateElement.apply(void 0, [ stubbedComponent ].concat( args )) + } + if (stubAllComponents) { - var stub = createStubFromComponent(el, el.name || 'anonymous', _Vue); + var stub = createStubFromComponent(el, elName || 'anonymous', _Vue); return originalCreateElement.apply(void 0, [ stub ].concat( args )) } var Constructor = shouldExtend(el) ? extend(el, _Vue) : el; @@ -9018,7 +9026,10 @@ */ function isStyleVisible(element) { - if (!(element instanceof HTMLElement) && !(element instanceof SVGElement)) { + if ( + !(element instanceof window.HTMLElement) && + !(element instanceof window.SVGElement) + ) { return false } @@ -11121,8 +11132,7 @@ Object.keys(data).forEach(function (key) { // Don't let people set entire objects, because reactivity won't work if ( - typeof data[key] === 'object' && - data[key] !== null && + isPlainObject(data[key]) && // $FlowIgnore : Problem with possibly null this.vm data[key] === this$1.vm[key] ) { From 19e5e45b3f63929da6ebc877d775f75f29d4d46c Mon Sep 17 00:00:00 2001 From: Lachlan Miller Date: Fri, 27 Jan 2023 12:07:10 +1000 Subject: [PATCH 14/24] v1.3.4 --- packages/server-test-utils/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/server-test-utils/package.json b/packages/server-test-utils/package.json index c7d8da9f7..af5867dfd 100644 --- a/packages/server-test-utils/package.json +++ b/packages/server-test-utils/package.json @@ -1,6 +1,6 @@ { "name": "@vue/server-test-utils", - "version": "1.3.3", + "version": "1.3.4", "description": "Utilities for testing Vue components.", "main": "dist/vue-server-test-utils.js", "types": "types/index.d.ts", From 2734ec4f977b732bdb9d68eff7ad085ea1272829 Mon Sep 17 00:00:00 2001 From: Lachlan Miller Date: Fri, 27 Jan 2023 12:11:19 +1000 Subject: [PATCH 15/24] v1.3.4 --- packages/test-utils/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/test-utils/package.json b/packages/test-utils/package.json index 16903686b..00023f458 100644 --- a/packages/test-utils/package.json +++ b/packages/test-utils/package.json @@ -1,6 +1,6 @@ { "name": "@vue/test-utils", - "version": "1.3.3", + "version": "1.3.4", "description": "Utilities for testing Vue components.", "main": "dist/vue-test-utils.js", "module": "dist/vue-test-utils.esm.js", From be11db69e55b2c781ac6394e80139da54d7a35e9 Mon Sep 17 00:00:00 2001 From: Simon He <57086651+Simon-He95@users.noreply.github.com> Date: Wed, 8 Feb 2023 13:01:08 +0800 Subject: [PATCH 16/24] chore: add lint cache (#2052) * chore: add lint cache * chore: update * chore: revert dist --- .eslintignore | 2 +- .gitignore | 1 + .prettierrc.json | 4 +++- docs/api/options.md | 2 +- docs/fr/api/options.md | 2 +- docs/fr/guides/common-tips.md | 2 +- docs/fr/guides/dom-events.md | 2 +- .../installation/using-other-test-runners.md | 2 +- docs/guides/common-tips.md | 2 +- docs/guides/dom-events.md | 2 +- docs/installation/using-other-test-runners.md | 2 +- docs/ja/api/options.md | 2 +- docs/ja/guides/dom-events.md | 2 +- docs/ja/guides/getting-started.md | 2 +- ...sting-single-file-components-with-karma.md | 4 ++-- docs/ru/api/options.md | 2 +- docs/ru/guides/dom-events.md | 2 +- docs/ru/guides/getting-started.md | 2 +- ...sting-single-file-components-with-karma.md | 4 ++-- docs/zh/api/options.md | 2 +- docs/zh/guides/common-tips.md | 2 +- docs/zh/guides/dom-events.md | 2 +- docs/zh/guides/getting-started.md | 2 +- ...sting-single-file-components-with-karma.md | 4 ++-- package.json | 6 +++--- packages/create-instance/create-instance.js | 6 +++--- .../create-instance/create-scoped-slots.js | 8 ++++---- packages/create-instance/log-events.js | 2 +- packages/shared/validators.js | 4 ++-- packages/test-utils/src/wrapper-array.js | 2 +- packages/test-utils/src/wrapper.js | 10 ++++------ .../components/component-with-computed.vue | 7 ++----- .../components/component-with-transitions.vue | 4 +--- .../component-with-watch-immediate.vue | 2 +- .../components/component-with-watch.vue | 2 +- test/resources/test-mixin.js | 2 +- test/resources/utils.js | 8 ++++---- test/specs/create-local-vue.spec.js | 4 ++-- test/specs/mount.spec.js | 6 +++--- .../mounting-options/scopedSlots.spec.js | 13 ++++++------ test/specs/shallow-mount.spec.js | 4 ++-- test/specs/wrapper-array/at.spec.js | 20 +++++++------------ test/specs/wrapper-array/attributes.spec.js | 4 +--- test/specs/wrapper-array/classes.spec.js | 4 +--- test/specs/wrapper-array/contains.spec.js | 8 ++++---- test/specs/wrapper-array/find.spec.js | 8 +++----- test/specs/wrapper-array/findAll.spec.js | 8 +++----- test/specs/wrapper-array/html.spec.js | 8 +++----- test/specs/wrapper-array/is.spec.js | 5 +---- test/specs/wrapper-array/isEmpty.spec.js | 5 +---- test/specs/wrapper-array/isVisible.spec.js | 5 +---- .../specs/wrapper-array/isVueInstance.spec.js | 5 +---- test/specs/wrapper-array/name.spec.js | 5 +---- test/specs/wrapper-array/props.spec.js | 8 +++----- test/specs/wrapper-array/setData.spec.js | 5 +---- test/specs/wrapper-array/setProps.spec.js | 5 +---- test/specs/wrapper-array/text.spec.js | 5 +---- test/specs/wrapper-array/trigger.spec.js | 5 +---- test/specs/wrapper/emittedByOrder.spec.js | 6 +++--- test/specs/wrapper/find.spec.js | 18 ++++------------- test/specs/wrapper/findAll.spec.js | 7 +------ test/specs/wrapper/overview.spec.js | 8 ++++++-- test/specs/wrapper/props.spec.js | 4 +--- test/specs/wrapper/setData.spec.js | 7 ++----- test/specs/wrapper/setProps.spec.js | 13 +++++------- yarn.lock | 7 ++++++- 66 files changed, 132 insertions(+), 196 deletions(-) diff --git a/.eslintignore b/.eslintignore index 1521c8b76..884a2323e 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1 +1 @@ -dist +**/dist/** diff --git a/.gitignore b/.gitignore index 63161737b..8161b78c2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ .DS_Store node_modules/ +.eslintcache # Editor files /.idea diff --git a/.prettierrc.json b/.prettierrc.json index b2095be81..f79acadcb 100644 --- a/.prettierrc.json +++ b/.prettierrc.json @@ -1,4 +1,6 @@ { "semi": false, - "singleQuote": true + "singleQuote": true, + "trailingComma": "none", + "arrowParens": "avoid" } diff --git a/docs/api/options.md b/docs/api/options.md index 3fa3b0548..68efd2eeb 100644 --- a/docs/api/options.md +++ b/docs/api/options.md @@ -169,7 +169,7 @@ You can also pass a function that takes the props as an argument: ```js shallowMount(Component, { scopedSlots: { - foo: function(props) { + foo: function (props) { return this.$createElement('div', props.index) } } diff --git a/docs/fr/api/options.md b/docs/fr/api/options.md index ed2171e5f..c4a13604d 100644 --- a/docs/fr/api/options.md +++ b/docs/fr/api/options.md @@ -168,7 +168,7 @@ Vous pouvez également passer une fonction qui prend les props comme argument : ```js shallowMount(Component, { scopedSlots: { - foo: function(props) { + foo: function (props) { return this.$createElement('div', props.index) } } diff --git a/docs/fr/guides/common-tips.md b/docs/fr/guides/common-tips.md index f9dad1e0f..da6e8d863 100644 --- a/docs/fr/guides/common-tips.md +++ b/docs/fr/guides/common-tips.md @@ -221,7 +221,7 @@ En pratique, bien que nous appelions et attendions `setData` pour assurer la mis ```js const transitionStub = () => ({ - render: function(h) { + render: function (h) { return this.$options._renderChildren } }) diff --git a/docs/fr/guides/dom-events.md b/docs/fr/guides/dom-events.md index b90f33ea2..0d8bce39e 100644 --- a/docs/fr/guides/dom-events.md +++ b/docs/fr/guides/dom-events.md @@ -144,7 +144,7 @@ Ce composant permet d'incrémenter/décrémenter la quantité à l'aide de diff }, watch: { - quantity: function(newValue) { + quantity: function (newValue) { this.$emit('input', newValue) } } diff --git a/docs/fr/installation/using-other-test-runners.md b/docs/fr/installation/using-other-test-runners.md index d019ec8a9..2ad784d22 100644 --- a/docs/fr/installation/using-other-test-runners.md +++ b/docs/fr/installation/using-other-test-runners.md @@ -12,7 +12,7 @@ Vous trouverez ci-dessous une configuration de base de Karma pour Vue Test Utils // karma.conf.js var webpackConfig = require('./webpack.config.js') -module.exports = function(config) { +module.exports = function (config) { config.set({ frameworks: ['mocha'], files: ['test/**/*.spec.js'], diff --git a/docs/guides/common-tips.md b/docs/guides/common-tips.md index e394786a3..240119ebf 100644 --- a/docs/guides/common-tips.md +++ b/docs/guides/common-tips.md @@ -223,7 +223,7 @@ In practice, although we are calling and awaiting `setData` to ensure the DOM is ```js const transitionStub = () => ({ - render: function(h) { + render: function (h) { return this.$options._renderChildren } }) diff --git a/docs/guides/dom-events.md b/docs/guides/dom-events.md index df0988d45..d203a740c 100644 --- a/docs/guides/dom-events.md +++ b/docs/guides/dom-events.md @@ -142,7 +142,7 @@ This component allows to increment/decrement the quantity using various keys. }, watch: { - quantity: function(newValue) { + quantity: function (newValue) { this.$emit('input', newValue) } } diff --git a/docs/installation/using-other-test-runners.md b/docs/installation/using-other-test-runners.md index 0b49972e0..48349f267 100644 --- a/docs/installation/using-other-test-runners.md +++ b/docs/installation/using-other-test-runners.md @@ -12,7 +12,7 @@ Following is a basic Karma config for Vue Test Utils: // karma.conf.js var webpackConfig = require('./webpack.config.js') -module.exports = function(config) { +module.exports = function (config) { config.set({ frameworks: ['mocha'], files: ['test/**/*.spec.js'], diff --git a/docs/ja/api/options.md b/docs/ja/api/options.md index 7f6a550bd..8d4e8e7cc 100644 --- a/docs/ja/api/options.md +++ b/docs/ja/api/options.md @@ -94,7 +94,7 @@ props を引数に取る関数を渡すことができます。 ```js shallowMount(Component, { scopedSlots: { - foo: function(props) { + foo: function (props) { return this.$createElement('div', props.index) } } diff --git a/docs/ja/guides/dom-events.md b/docs/ja/guides/dom-events.md index 3a3f35aaa..562117299 100644 --- a/docs/ja/guides/dom-events.md +++ b/docs/ja/guides/dom-events.md @@ -134,7 +134,7 @@ it('Click on yes button calls our method with argument "yes"', async () => { } }, watch: { - quantity: function(newValue) { + quantity: function (newValue) { this.$emit('input', newValue) } } diff --git a/docs/ja/guides/getting-started.md b/docs/ja/guides/getting-started.md index d085eb9c7..cdcf63728 100644 --- a/docs/ja/guides/getting-started.md +++ b/docs/ja/guides/getting-started.md @@ -131,7 +131,7 @@ it('will catch the error using done', done => { }) it('will catch the error using a promise', () => { - return Vue.nextTick().then(function() { + return Vue.nextTick().then(function () { expect(true).toBe(false) }) }) diff --git a/docs/ja/installation/testing-single-file-components-with-karma.md b/docs/ja/installation/testing-single-file-components-with-karma.md index 26ef15c6b..9e2c91f2a 100644 --- a/docs/ja/installation/testing-single-file-components-with-karma.md +++ b/docs/ja/installation/testing-single-file-components-with-karma.md @@ -36,7 +36,7 @@ npm install --save-dev @vue/test-utils karma karma-chrome-launcher karma-mocha k var webpackConfig = require('./webpack.config.js') -module.exports = function(config) { +module.exports = function (config) { config.set({ frameworks: ['mocha'], @@ -160,7 +160,7 @@ npm install --save-dev babel-plugin-istanbul ```js // karma.conf.js -module.exports = function(config) { +module.exports = function (config) { config.set({ // ... diff --git a/docs/ru/api/options.md b/docs/ru/api/options.md index 40968a0bc..afeb619f3 100644 --- a/docs/ru/api/options.md +++ b/docs/ru/api/options.md @@ -107,7 +107,7 @@ shallowMount(Component, { ```js shallowMount(Component, { scopedSlots: { - foo: function(props) { + foo: function (props) { return this.$createElement('div', props.index) } } diff --git a/docs/ru/guides/dom-events.md b/docs/ru/guides/dom-events.md index b3ce272cb..5f472fc95 100644 --- a/docs/ru/guides/dom-events.md +++ b/docs/ru/guides/dom-events.md @@ -136,7 +136,7 @@ describe('Click event', () => { }, watch: { - quantity: function(newValue) { + quantity: function (newValue) { this.$emit('input', newValue) } } diff --git a/docs/ru/guides/getting-started.md b/docs/ru/guides/getting-started.md index 77b324fa2..a4cc198d7 100644 --- a/docs/ru/guides/getting-started.md +++ b/docs/ru/guides/getting-started.md @@ -131,7 +131,7 @@ it('должен отлавливать ошибку с использовани }) it('должен отлавливать ошибку с использованием promise', () => { - return Vue.nextTick().then(function() { + return Vue.nextTick().then(function () { expect(true).toBe(false) }) }) diff --git a/docs/ru/installation/testing-single-file-components-with-karma.md b/docs/ru/installation/testing-single-file-components-with-karma.md index 0105006e2..fe2cacf8a 100644 --- a/docs/ru/installation/testing-single-file-components-with-karma.md +++ b/docs/ru/installation/testing-single-file-components-with-karma.md @@ -36,7 +36,7 @@ npm install --save-dev @vue/test-utils karma karma-chrome-launcher karma-mocha k var webpackConfig = require('./webpack.config.js') -module.exports = function(config) { +module.exports = function (config) { config.set({ frameworks: ['mocha'], @@ -160,7 +160,7 @@ npm install --save-dev babel-plugin-istanbul ```js // karma.conf.js -module.exports = function(config) { +module.exports = function (config) { config.set({ // ... diff --git a/docs/zh/api/options.md b/docs/zh/api/options.md index 076090228..40b86c2ad 100644 --- a/docs/zh/api/options.md +++ b/docs/zh/api/options.md @@ -167,7 +167,7 @@ shallowMount(Component, { ```js shallowMount(Component, { scopedSlots: { - foo: function(props) { + foo: function (props) { return this.$createElement('div', props.index) } } diff --git a/docs/zh/guides/common-tips.md b/docs/zh/guides/common-tips.md index 110fc0a96..780c980c9 100644 --- a/docs/zh/guides/common-tips.md +++ b/docs/zh/guides/common-tips.md @@ -222,7 +222,7 @@ test('should render Foo, then hide it', async () => { ```js const transitionStub = () => ({ - render: function(h) { + render: function (h) { return this.$options._renderChildren } }) diff --git a/docs/zh/guides/dom-events.md b/docs/zh/guides/dom-events.md index a3c858807..1af79fc2a 100644 --- a/docs/zh/guides/dom-events.md +++ b/docs/zh/guides/dom-events.md @@ -142,7 +142,7 @@ it('Click on yes button calls our method with argument "yes"', async () => { }, watch: { - quantity: function(newValue) { + quantity: function (newValue) { this.$emit('input', newValue) } } diff --git a/docs/zh/guides/getting-started.md b/docs/zh/guides/getting-started.md index 70f35f93b..7b10a0336 100644 --- a/docs/zh/guides/getting-started.md +++ b/docs/zh/guides/getting-started.md @@ -164,7 +164,7 @@ it('will catch the error using done', done => { }) it('will catch the error using a promise', () => { - return Vue.nextTick().then(function() { + return Vue.nextTick().then(function () { expect(true).toBe(false) }) }) diff --git a/docs/zh/installation/testing-single-file-components-with-karma.md b/docs/zh/installation/testing-single-file-components-with-karma.md index 544ae4521..a1a5dc19c 100644 --- a/docs/zh/installation/testing-single-file-components-with-karma.md +++ b/docs/zh/installation/testing-single-file-components-with-karma.md @@ -36,7 +36,7 @@ npm install --save-dev @vue/test-utils karma karma-chrome-launcher karma-mocha k var webpackConfig = require('./webpack.config.js') -module.exports = function(config) { +module.exports = function (config) { config.set({ frameworks: ['mocha'], @@ -160,7 +160,7 @@ npm install --save-dev babel-plugin-istanbul ```js // karma.conf.js -module.exports = function(config) { +module.exports = function (config) { config.set({ // ... diff --git a/package.json b/package.json index 4ada8c2e2..d75249253 100644 --- a/package.json +++ b/package.json @@ -17,10 +17,10 @@ "docs": "vuepress dev docs", "docs:build": "vuepress build docs", "flow": "flow check", - "lint": "eslint --ext js,vue .", + "lint": "eslint --ext js,vue . --cache", "lint:docs": "eslint --ext js,vue,md docs --ignore-path .gitignore", "lint:fix": "yarn lint -- --fix", - "format": "prettier --write \"**/*.{js,json,vue,md}\"", + "format": "prettier --write \"**/*.{js,json,vue,md}\" --cache", "format:check": "prettier --check \"**/*.{js,json,vue,md}\"", "release": "yarn build && yarn test:unit && lerna publish --conventional-commits -m \"chore(release): publish %s\"", "test": "yarn format:check && yarn lint && yarn lint:docs && yarn flow && yarn test:types && yarn test:unit -w 1 && yarn test:unit:browser", @@ -91,7 +91,7 @@ "karma-spec-reporter": "^0.0.32", "karma-webpack": "^4.0.2", "lint-staged": "^9.5.0", - "prettier": "^1.16.0", + "prettier": "^2.8.1", "puppeteer": "^5.2.1", "rollup-plugin-delete": "^2.0.0", "@rollup/plugin-replace": "^2.3.3", diff --git a/packages/create-instance/create-instance.js b/packages/create-instance/create-instance.js index 3c0ba7d2e..7aaafb962 100644 --- a/packages/create-instance/create-instance.js +++ b/packages/create-instance/create-instance.js @@ -107,7 +107,7 @@ export default function createInstance( const parentComponentOptions = options.parentComponent || {} const originalParentComponentProvide = parentComponentOptions.provide - parentComponentOptions.provide = function() { + parentComponentOptions.provide = function () { return { ...getValuesFromCallableOption.call(this, originalParentComponentProvide), // $FlowIgnore @@ -116,7 +116,7 @@ export default function createInstance( } const originalParentComponentData = parentComponentOptions.data - parentComponentOptions.data = function() { + parentComponentOptions.data = function () { return { ...getValuesFromCallableOption.call(this, originalParentComponentData), vueTestUtils_childProps: { ...options.propsData } @@ -126,7 +126,7 @@ export default function createInstance( parentComponentOptions.$_doNotStubChildren = true parentComponentOptions.$_isWrapperParent = true parentComponentOptions._isFunctionalContainer = componentOptions.functional - parentComponentOptions.render = function(h) { + parentComponentOptions.render = function (h) { return h( Constructor, createContext(options, scopedSlots, this.vueTestUtils_childProps), diff --git a/packages/create-instance/create-scoped-slots.js b/packages/create-instance/create-scoped-slots.js index 50464d9ee..daa4f3cb1 100644 --- a/packages/create-instance/create-scoped-slots.js +++ b/packages/create-instance/create-scoped-slots.js @@ -8,9 +8,9 @@ function isDestructuringSlotScope(slotScope: string): boolean { return /^{.*}$/.test(slotScope) } -function getVueTemplateCompilerHelpers( - _Vue: Component -): { [name: string]: Function } { +function getVueTemplateCompilerHelpers(_Vue: Component): { + [name: string]: Function +} { // $FlowIgnore const vue = new _Vue() const helpers = {} @@ -111,7 +111,7 @@ export default function createScopedSlots( const slotScope = scopedSlotMatches.match && scopedSlotMatches.match[1] - scopedSlots[scopedSlotName] = function(props) { + scopedSlots[scopedSlotName] = function (props) { let res if (isFn) { res = renderFn.call({ ...helpers }, props) diff --git a/packages/create-instance/log-events.js b/packages/create-instance/log-events.js index 9de6abf20..c3fd97f0d 100644 --- a/packages/create-instance/log-events.js +++ b/packages/create-instance/log-events.js @@ -15,7 +15,7 @@ export function logEvents( export function addEventLogger(_Vue: Component): void { _Vue.mixin({ - beforeCreate: function() { + beforeCreate: function () { this.__emitted = Object.create(null) this.__emittedByOrder = [] logEvents(this, this.__emitted, this.__emittedByOrder) diff --git a/packages/shared/validators.js b/packages/shared/validators.js index 986049d33..c72591d22 100644 --- a/packages/shared/validators.js +++ b/packages/shared/validators.js @@ -137,10 +137,10 @@ function makeMap(str: string, expectsLowerCase?: boolean) { map[list[i]] = true } return expectsLowerCase - ? function(val: string) { + ? function (val: string) { return map[val.toLowerCase()] } - : function(val: string) { + : function (val: string) { return map[val] } } diff --git a/packages/test-utils/src/wrapper-array.js b/packages/test-utils/src/wrapper-array.js index f5bd64bf7..e29cb2bed 100644 --- a/packages/test-utils/src/wrapper-array.js +++ b/packages/test-utils/src/wrapper-array.js @@ -5,7 +5,7 @@ import type VueWrapper from './vue-wrapper' import { throwError } from 'shared/util' export default class WrapperArray implements BaseWrapper { - +wrappers: Array + +wrappers: Array; +length: number selector: Selector | void diff --git a/packages/test-utils/src/wrapper.js b/packages/test-utils/src/wrapper.js index bbaae815a..bcf7985ef 100644 --- a/packages/test-utils/src/wrapper.js +++ b/packages/test-utils/src/wrapper.js @@ -29,11 +29,11 @@ import createDOMEvent from './create-dom-event' import { throwIfInstancesThrew } from './error' export default class Wrapper implements BaseWrapper { - +vnode: VNode | null + +vnode: VNode | null; +vm: Component | void _emitted: { [name: string]: Array> } - _emittedByOrder: Array<{ name: string, args: Array }> - +element: Element + _emittedByOrder: Array<{ name: string, args: Array }>; + +element: Element; +options: WrapperOptions isFunctionalComponent: boolean rootNode: VNode | Element @@ -502,9 +502,7 @@ export default class Wrapper implements BaseWrapper { ? value.map((calledWith, index) => { const callParams = calledWith.map(param => typeof param === 'object' - ? JSON.stringify(param) - .replace(/"/g, '') - .replace(/,/g, ', ') + ? JSON.stringify(param).replace(/"/g, '').replace(/,/g, ', ') : param ) diff --git a/test/resources/components/component-with-computed.vue b/test/resources/components/component-with-computed.vue index 02445747a..d608e4885 100644 --- a/test/resources/components/component-with-computed.vue +++ b/test/resources/components/component-with-computed.vue @@ -11,11 +11,8 @@ export default { message: 'egassem' }), computed: { - reversedMessage: function() { - return this.message - .split('') - .reverse() - .join('') + reversedMessage: function () { + return this.message.split('').reverse().join('') } } } diff --git a/test/resources/components/component-with-transitions.vue b/test/resources/components/component-with-transitions.vue index 9af326ce4..e8965da44 100644 --- a/test/resources/components/component-with-transitions.vue +++ b/test/resources/components/component-with-transitions.vue @@ -1,9 +1,7 @@ diff --git a/test/resources/components/component-with-watch-immediate.vue b/test/resources/components/component-with-watch-immediate.vue index f8abce285..736be6939 100644 --- a/test/resources/components/component-with-watch-immediate.vue +++ b/test/resources/components/component-with-watch-immediate.vue @@ -6,7 +6,7 @@ +``` + +**Teste** + +```js +import { mount } from '@vue/test-utils' +import ParentComponent from '@/components/ParentComponent' +import ChildComponent from '@/components/ChildComponent' + +describe('ParentComponent', () => { + it("displays 'Emitted!' when custom event is emitted", () => { + const wrapper = mount(ParentComponent) + wrapper.findComponent(ChildComponent).vm.$emit('custom') + expect(wrapper.html()).toContain('Emitted!') + }) +}) +``` + +### Manipulando o Estado de Componente + +Você pode manipular o estado do componente diretamente usando o método `setData` ou o método `setProps` no envolvedor (wrapper): + +```js +it('manipulates state', async () => { + await wrapper.setData({ count: 10 }) + + await wrapper.setProps({ foo: 'bar' }) +}) +``` + +### Imitando Propriedades + +Você pode passar as propriedades para o componente usando opção `propsData` embutida da Vue: + +```js +import { mount } from '@vue/test-utils' + +mount(Component, { + propsData: { + aProp: 'some value' + } +}) +``` + +Você pode também atualizar as propriedades de um componente já montado com o método `wrapper.setProps({})`. + +_Para uma lista completa das opções, consulte a [seção opções de montagem](../api/options.md) da documentação._ + +### Imitando Transições + +Apesar das chamadas de `await Vue.nextTick()` funcionarem bem para a maioria dos casos de uso, existem algumas situações onde soluções adicionais são necessárias. Estes problemas serão resolvidos antes da biblioteca `vue-test-utils` sair da beta. Um destes exemplos é o teste unitário de componentes com o envolvedor `` fornecido pela Vue. + +```vue + + + +``` + +Você pode querer escrever um teste que verifica que se Foo está exibido, então quando o `show` é definido para `false`, o Foo não é mais renderizado. Tal teste poderia ser escrito como o seguinte: + +```js +test('should render Foo, then hide it', async () => { + const wrapper = mount(Foo) + expect(wrapper.text()).toMatch(/Foo/) + + await wrapper.setData({ + show: false + }) + + expect(wrapper.text()).not.toMatch(/Foo/) +}) +``` + +Na prática, apesar de nós estarmos chamando e chamando o `setData` para garantir que o DOM é atualizado, este teste falha. Isto é um problema em andamento relacionado a como a Vue implementa o componente ``, isto nós gostaríamos de resolver antes da versão 1.0. Por agora, existem algumas soluções: + +#### Usando o auxiliar `transitionStub` + +```js +const transitionStub = () => ({ + render: function(h) { + return this.$options._renderChildren + } +}) + +test('should render Foo, then hide it', async () => { + const wrapper = mount(Foo, { + stubs: { + transition: transitionStub() + } + }) + expect(wrapper.text()).toMatch(/Foo/) + + await wrapper.setData({ + show: false + }) + + expect(wrapper.text()).not.toMatch(/Foo/) +}) +``` + +Isto sobrescreve o comportamento padrão do componente `` e renderiza os filhos assim que condição booleana relevante mudar, visto que é o oposto de aplicar classes de CSS, que é como componente `` da Vue funciona. + +#### Evitar `setData` + +Uma outra alternativa é simplesmente evitar usar o `setData` ao escrever dois testes, com a configuração necessária realizada usando as opções `mount` ou `shallowMount`: + +```js +test('should render Foo', async () => { + const wrapper = mount(Foo, { + data() { + return { + show: true + } + } + }) + + expect(wrapper.text()).toMatch(/Foo/) +}) + +test('should not render Foo', async () => { + const wrapper = mount(Foo, { + data() { + return { + show: false + } + } + }) + + expect(wrapper.text()).not.toMatch(/Foo/) +}) +``` + +### Aplicando Plugins Globais e Mixins + +Alguns componentes podem depender de funcionalidades injetadas por um plugin global ou mixin, por exemplo a `vuex` e a `vue-router`. + +Se você estiver escrevendo testes para componentes em uma aplicação especifica, você pode configurar os mesmos plugins globais e mixins de uma vez na entrada de seus testes. Mas em alguns casos, por exemplo testando um conjunto de componente genérico que podem ser partilhados entre aplicações diferentes, é melhor testar seus componentes em uma configuração mais isolada, sem poluir o construtor global da `Vue`. Nós podemos usar o método [`createLocalVue`](../api/createLocalVue.md) para alcançar isso: + +```js +import { createLocalVue, mount } from '@vue/test-utils' + +// cria construtor de `Vue` estendido +const localVue = createLocalVue() + +// instala os plugins como normais +localVue.use(MyPlugin) + +// passa o `localVue` para as opções do `mount` +mount(Component, { + localVue +}) +``` + +**Repare que alguns plugins, como a Vue Router, adicionam propriedades de somente leitura ao construtor global da Vue. Isto torna impossível reinstalar o plugin em construtor `localVue`, ou adicionar imitações para estas propriedades de somente leitura.** + +### Imitando Injeções + +Uma outra estratégia para propriedades injetadas é simplesmente imitá-las. Você fazer isso com a opção `mocks`: + +```js +import { mount } from '@vue/test-utils' + +const $route = { + path: '/', + hash: '', + params: { id: '123' }, + query: { q: 'hello' } +} + +mount(Component, { + mocks: { + // adiciona objeto `$route` imitado para a instância da Vue + // antes da montagem do componente + $route + } +}) +``` + +### Forjando componentes + +Você pode sobrescrever componentes que são registados globalmente ou localmente usando a opção `stubs`: + +```js +import { mount } from '@vue/test-utils' + +mount(Component, { + // Resolverá o `globally-registered-component` com o + // forjado vazio + stubs: ['globally-registered-component'] +}) +``` + +### Lidando com o Roteamento + +Visto que o roteamento por definição tem haver com toda estrutura da aplicação e envolve vários componentes, ele é melhor testado através de integração ou testes fim-à-fim (end-to-end). Para componentes individuais que dependem de funcionalidades da `vue-router`, você pode imitá-las usando as técnicas mencionadas acima. + +### Detetando estilos + +O seu teste apenas pode detetar estilos em linha quando estiver executando no `jsdom`. diff --git a/docs/pt/guides/dom-events.md b/docs/pt/guides/dom-events.md new file mode 100644 index 000000000..a8daea085 --- /dev/null +++ b/docs/pt/guides/dom-events.md @@ -0,0 +1,215 @@ +## Testando eventos de Teclado, Rato e outros do DOM + + + +### Acionar eventos + +O `Wrapper` expõe um método `trigger` assíncrono. Ele pode ser usado para acionar eventos do DOM. + +```js +test('triggers a click', async () => { + const wrapper = mount(MyComponent) + + await wrapper.trigger('click') +}) +``` + +Você deve estar ciente de que o método `find` retorna também um `Wrapper`. Assumindo que o `MyComponent` contém um botão, o seguinte código clica neste botão. + +```js +test('triggers a click', async () => { + const wrapper = mount(MyComponent) + + await wrapper.find('button').trigger('click') +}) +``` + +### Opções + +O método `trigger` recebe um objeto `options` opcional. As propriedades dentro do objeto `options` são adicionadas ao Event. + +Repare que o alvo não pode ser adicionado dentro do objeto `options`. + +```js +test('triggers a click', async () => { + const wrapper = mount(MyComponent) + + await wrapper.trigger('click', { button: 0 }) +}) +``` + +### Exemplo de Clique do Rato + +**Componente sob teste** + +```html + + + +``` + +**Testar** + +```js +import YesNoComponent from '@/components/YesNoComponent' +import { mount } from '@vue/test-utils' +import sinon from 'sinon' + +it('Click on yes button calls our method with argument "yes"', async () => { + const spy = sinon.spy() + const wrapper = mount(YesNoComponent, { + propsData: { + callMe: spy + } + }) + await wrapper.find('button.yes').trigger('click') + + spy.should.have.been.calledWith('yes') +}) +``` + +### Exemplo de Teclado + +**Componente sob teste** + +Este componente permite incrementar/decrementar a quantidade usando várias teclas. + +```html + + + +``` + +**Testar** + +```js +import QuantityComponent from '@/components/QuantityComponent' +import { mount } from '@vue/test-utils' + +describe('Key event tests', () => { + it('Quantity is zero by default', () => { + const wrapper = mount(QuantityComponent) + expect(wrapper.vm.quantity).toBe(0) + }) + + it('Up arrow key increments quantity by 1', async () => { + const wrapper = mount(QuantityComponent) + await wrapper.trigger('keydown.up') + expect(wrapper.vm.quantity).toBe(1) + }) + + it('Down arrow key decrements quantity by 1', async () => { + const wrapper = mount(QuantityComponent) + wrapper.vm.quantity = 5 + await wrapper.trigger('keydown.down') + expect(wrapper.vm.quantity).toBe(4) + }) + + it('Escape sets quantity to 0', async () => { + const wrapper = mount(QuantityComponent) + wrapper.vm.quantity = 5 + await wrapper.trigger('keydown.esc') + expect(wrapper.vm.quantity).toBe(0) + }) + + it('Magic character "a" sets quantity to 13', async () => { + const wrapper = mount(QuantityComponent) + await wrapper.trigger('keydown', { + key: 'a' + }) + expect(wrapper.vm.quantity).toBe(13) + }) +}) +``` + +**Limitações** + +O nome da tecla depois do ponto `keydown.up` é traduzido para um `KeyCode` (código da tecla). Isto é suportado para os seguintes nomes: + +| nome da tecla | código da tecla | +| ------------- | --------------- | +| enter | 13 | +| esc | 27 | +| tab | 9 | +| space | 32 | +| delete | 46 | +| backspace | 8 | +| insert | 45 | +| up | 38 | +| down | 40 | +| left | 37 | +| right | 39 | +| end | 35 | +| home | 36 | +| pageup | 33 | +| pagedown | 34 | diff --git a/docs/pt/guides/getting-started.md b/docs/pt/guides/getting-started.md new file mode 100644 index 000000000..a80ea34f7 --- /dev/null +++ b/docs/pt/guides/getting-started.md @@ -0,0 +1,76 @@ +## Começar agora + + + +### O que é o Vue Test Utils? + +A Vue Test Utils (VTU) é um conjunto de funções utilitárias com o fim de simplificar os testes de componentes de Vue.js. Ele fornece alguns métodos para **montar** e **interagir** com componentes de Vue.js em um modo isolado. + +Vamos ver um exemplo: + +```js +// Importa o método `mount()` do Vue Test Utils +import { mount } from '@vue/test-utils' + +// O componente para testar +const MessageComponent = { + template: '

{{ msg }}

', + props: ['msg'] +} + +test('displays message', () => { + // mount() retorna um componente de Vue envolvido com qual podemos interagir + const wrapper = mount(MessageComponent, { + propsData: { + msg: 'Hello world' + } + }) + + // Afirma o texto renderizado do componente + expect(wrapper.text()).toContain('Hello world') +}) +``` + +Os componentes montados são retornados dentro de um [Wrapper (envolvedor)](../api/wrapper/), o qual expõe métodos para consulta e interação com o componente sob teste. + +### Simulando a Interação do Usuário + +Vamos imaginar um componente contador que incrementa quando o usuário clica no botão: + +```js +const Counter = { + template: ` +
+ +

Total clicks: {{ count }}

+
+ `, + data() { + return { count: 0 } + } +} +``` + +Para simular o comportamento, nós precisamos primeiro localizar o botão com o `wrapper.find()`, o qual retorna um **envolvedor para o elemento `button`**. Nós podemos então simular o clique ao chamar `.trigger()` no envolvedor do botão: + +```js +test('increments counter value on click', async () => { + const wrapper = mount(Counter) + const button = wrapper.find('button') + const text = wrapper.find('p') + + expect(text.text()).toContain('Total clicks: 0') + + await button.trigger('click') + + expect(text.text()).toContain('Total clicks: 1') +}) +``` + +Repare como o teste deve ser `async` e que o `trigger` precisa ser esperado. Consulte o guia [Testando Comportamento Assíncronos](./README.md#testing-asynchronous-behavior) para entender porquê isto é necessário e outras coisas a considerar quando estiver testando cenários assíncronos. + +### O que se segue + +Consulte as nossas [dicas comuns para quando estiver escrevendo testes](./README.md#knowing-what-to-test). + +Por outro lado, você pode explorar a [API completa](../api/). diff --git a/docs/pt/guides/testing-async-components.md b/docs/pt/guides/testing-async-components.md new file mode 100644 index 000000000..8a55f9af0 --- /dev/null +++ b/docs/pt/guides/testing-async-components.md @@ -0,0 +1,143 @@ +## Testando Comportamento Assíncrono + +Existem dois tipos de comportamentos assíncronos que você encontrará em seus testes: + +1. Atualizações aplicadas pelo Vue +2. Comportamento assíncrono fora do Vue + +### Atualizações aplicadas pela Vue + +O Vue agrupa atualizações pendentes da DOM e aplica elas assincronamente para prevenir re-renderizações desnecessárias causadas por várias mutações de dados. + +_Você pode ler mais sobre atualizações assíncronas na [documentação do Vue](https://vuejs.org/v2/guide/reactivity.html#Async-Update-Queue)_ + +Na prática, isto significa que depois da mutação de uma propriedade reativa, para confirmar aquela mudança o seu teste tem que aguardar enquanto o Vue estiver desempenhando atualizações. +Uma maneira é usar o `await Vue.nextTick()`, mas uma maneira mais fácil e clara é apenas esperar (`await`) o método que com qual você mudou o estado, tipo `trigger`. + +```js +// dentro do conjunto de teste, adicione este caso de teste +it('button click should increment the count text', async () => { + expect(wrapper.text()).toContain('0') + const button = wrapper.find('button') + await button.trigger('click') + expect(wrapper.text()).toContain('1') +}) +``` + +Esperar o acionador acima é o mesmo que fazer: + +```js +it('button click should increment the count text', async () => { + expect(wrapper.text()).toContain('0') + const button = wrapper.find('button') + button.trigger('click') + await Vue.nextTick() + expect(wrapper.text()).toContain('1') +}) +``` + +Os métodos que podem ser esperados são: + +- [setData](../api/wrapper/README.md#o-método-setdata) +- [setValue](../api/wrapper/README.md#o-método-setvalue) +- [setChecked](../api/wrapper/README.md#o-método-setchecked) +- [setSelected](../api/wrapper/README.md#o-método-setselected) +- [setProps](../api/wrapper/README.md#o-método-setprops) +- [trigger](../api/wrapper/README.md#o-método-trigger) + +### Comportamento assíncrono fora do Vue + +Um dos comportamentos assíncrono mais comuns fora de Vue é a chamada de API dentro de ações de Vuex. Os seguintes exemplos mostram como testar um método que faz uma chama de API. Este exemplo usa o `Jest` para executar o teste e imitar a biblioteca de HTTP `axios`. Mais sobre as imitações manuais de `Jest` podem ser encontradas [aqui](https://jestjs.io/docs/en/manual-mocks.html#content). + +A implementação da imitação do `axios` parece com isto: + +```js +export default { + get: () => Promise.resolve({ data: 'value' }) +} +``` + +O componente abaixo faz uma chamada de API quando um botão é clicado, depois atribui a resposta ao `value`. + +```html + + + +``` + +Um teste pode ser escrito da seguinte maneira: + +```js +import { shallowMount } from '@vue/test-utils' +import Foo from './Foo' +jest.mock('axios', () => ({ + get: Promise.resolve('value') +})) + +it('fetches async when a button is clicked', () => { + const wrapper = shallowMount(Foo) + wrapper.find('button').trigger('click') + expect(wrapper.text()).toBe('value') +}) +``` + +Este teste atualmente falha porque a afirmação é chamada antes de resolver a promessa em `fetchResults`. A maioria das bibliotecas de testes unitários fornecem uma _callback (função de resposta)_ para permitir que o executor saiba quando o teste está completo ou terminado. Ambos `Jest` e `Mocha` usam o `done`. Nós podemos usar o `done` em combinação com o `$nextTick` ou `setTimeout` para garantir que quaisquer promessas estão resolvidas antes da afirmação ser feita. + +```js +it('fetches async when a button is clicked', done => { + const wrapper = shallowMount(Foo) + wrapper.find('button').trigger('click') + wrapper.vm.$nextTick(() => { + expect(wrapper.text()).toBe('value') + done() + }) +}) +``` + +A razão pela qual o `setTimeout` permite o teste passar é porque a fila de micro-tarefa onde as funções de resposta de promessa são processadas executam antes da fila de tarefa, onde as funções de respostas de `setTimeout` são processadas. Isto significa que no momento que a função de resposta de `setTimeout` executa, quaisquer funções de resposta de promessa na fila de micro-tarefa terão que ser executadas. O `$nextTick` por outro lado agenda uma micro-tarefa, mas visto que a fila de micro-tarefa é processada no sentido de que o primeiro a entrar é o primeiro a sair isso também garante que a função de resposta de promessa tem sido executada no momento que a afirmação é feita. Para uma explicação mais detalhada consulte a seguinte [ligação](https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/). + +Uma outra solução é usar uma função `async` e um pacote como o [flush-promises](https://www.npmjs.com/package/flush-promises). O `flush-promises` libera todos manipuladores de promessa pendentes resolvidas. Você pode `await` a chamada de `flushPromises` para liberar promessas pendentes e melhorar a legibilidade do seu teste. + +O teste atualizado parece com isto: + +```js +import { shallowMount } from '@vue/test-utils' +import flushPromises from 'flush-promises' +import Foo from './Foo' +jest.mock('axios') + +it('fetches async when a button is clicked', async () => { + const wrapper = shallowMount(Foo) + wrapper.find('button').trigger('click') + await flushPromises() + expect(wrapper.text()).toBe('value') +}) +``` + +Esta mesma técnica pode ser aplicada às ações de Vuex, as quais retornam uma promessa por padrão. + +#### Porquê não apenas `await button.trigger()` ? + +Como explicado acima, existe uma diferença entre o tempo que leva para o Vue atualizar seus componentes, e o tempo que leva para uma promessa, como aquela de `axios` resolver. + +Um ótima regra para seguir é sempre esperar (`await`) em mutações como o `trigger` ou o `setProps`. +Se o seu código depende de algo assíncrono, como a chamada de `axios`, adicione uma espera (`await`) para a chamada `flushPromises` também. diff --git a/docs/pt/guides/useful-libraries-for-testing.md b/docs/pt/guides/useful-libraries-for-testing.md new file mode 100644 index 000000000..a20d29cc2 --- /dev/null +++ b/docs/pt/guides/useful-libraries-for-testing.md @@ -0,0 +1,21 @@ +## Bibliotecas Úteis para Testes + +A Vue Test Utils fornece métodos úteis para testes de componentes de Vue.js. Os membros da comunidade tem também escrito algumas bibliotecas adicionais as quais ou estendem a `vue-test-utils` com métodos extras úteis, ou fornecem ferramentas para testes de outras coisas encontradas dentro de aplicações de Vue.js. + +### A Biblioteca de Testes de Vue + +A [Vue Testing Library ou Biblioteca de Testes de Vue](https://github.com/testing-library/vue-testing-library) é um conjunto de ferramentas focadas em testes de componentes sem depender de detalhes de implementação. Construida com a acessibilidade em mente, sua abordagem também torna a refatoração uma brisa. + +É construida sobre a Vue Test Utils. + +### `vuex-mock-store` + +A [`vuex-mock-store`](https://github.com/posva/vuex-mock-store) fornece uma simples e direta imitação da memória para simplificar os testes de componentes consumindo uma memória de Vuex. + +### `jest-matcher-vue-test-utils` + +A [`jest-matcher-vue-test-utils`](https://github.com/hmsk/jest-matcher-vue-test-utils) adiciona correspondentes adicionais para o executor de teste Jest com o propósito de tornar as afirmações mais expressivas. + +### `jest-mock-axios` + +A [`jest-mock-axios`](https://github.com/knee-cola/jest-mock-axios) permite você imitar facilmente o `axios`, um cliente de HTTP comum, dentro de seus testes. Ele funciona fora da caixa com Jest, e o autor fornece um guia de como suportar outros executores de teste dentro da documentação. diff --git a/docs/pt/guides/using-with-typescript.md b/docs/pt/guides/using-with-typescript.md new file mode 100644 index 000000000..9e0f5b94d --- /dev/null +++ b/docs/pt/guides/using-with-typescript.md @@ -0,0 +1,157 @@ +## Usando com o TypeScript + +> Um exemplo de projeto para este configuração está disponível no [GitHub](https://github.com/vuejs/vue-test-utils-typescript-example). + +O TypeScript é um superconjunto popular de JavaScript que adiciona tipos e classes sobre o JavaScript habitual. A Vue Test Utils inclui tipos dentro do pacote distribuído, assim ela funciona bem com o TypeScript. + +Neste guia, nós iremos caminhar através de como definir uma configuração de estes para um projeto de TypeScript usando Jest e a Vue Test Utils a partir de uma configuração básica de TypeScript da Vue CLI. + +### Adicionado o TypeScript + +Primeiro, você precisa criar um projeto. Se você não tiver a Vue CLI instalada, instale ela globalmente: + +```shell +$ npm install -g @vue/cli +``` + +E crie um projeto ao executar: + +```shell +$ vue create hello-world +``` + +No pronto da CLI, escolha a opção `Manually select features`, selecione TypeScript, e pressione Enter. Isto criará um projeto com o TypeScript já configurado. + +::: tip NOTA +Se você quiser mais um guia mais detalhado sobre a configuração de Vue com o TypeScript, consulte o [guia de iniciação de Vue com TypeScript](https://github.com/Microsoft/TypeScript-Vue-Starter). +::: + +O próximo passo é adicionar o Jest ao projeto. + +### Configurando o Jest + +O Jest é um executor de teste desenvolvido pelo Facebook, com o propósito de entregar uma solução de testes unitários com baterias incluídas. Você pode aprender mais sobre o Jest na sua [documentação oficial](https://jestjs.io/). + +Instale o Jest e a Vue Test Utils: + +```bash +$ npm install --save-dev jest @vue/test-utils +``` + +Depois defina um roteiro `test:unit` dentro de `package.json`. + +```json +// package.json +{ + // .. + "scripts": { + // .. + "test:unit": "jest" + } + // .. +} +``` + +### Processando Componentes de Único Ficheiro dentro do Jest + +Para ensinar o Jest a como processar ficheiros `*.vue`, nós precisamos instalar e configurar o pré-processador `vue-jest`: + +```bash +npm install --save-dev vue-jest +``` + +Depois, criar um bloco de `jest` dentro de `package.json`: + +```json +{ + // ... + "jest": { + "moduleFileExtensions": [ + "js", + "ts", + "json", + // diz ao Jest para manipular ficheiros `*.vue` + "vue" + ], + "transform": { + // processa ficheiros `*.vue` com o `vue-jest` + ".*\\.(vue)$": "vue-jest" + }, + "testURL": "http://localhost/" + } +} +``` + +### Configurando o TypeScript para o Jest + +No sentido de usar ficheiros de TypeScript dentro de testes, nós precisamos configurar o Jest para compilar o TypeScript. Para isso nós precisamos instalar o `ts-jest`: + +```bash +$ npm install --save-dev ts-jest +``` + +Depois, nós precisamos dizer ao Jest para processar os ficheiros de teste em TypeScript com o `ts-jest` ao adicionar um entrada sob `jest.transform` dentro de `package.json`: + +```json +{ + // ... + "jest": { + // ... + "transform": { + // ... + // processar os ficheiros `*.ts` com o `ts-jest` + "^.+\\.tsx?$": "ts-jest" + } + // ... + } +} +``` + +### Colocação de Ficheiros de Teste + +Por padrão, o Jest selecionará recursivamente todos ficheiros que têm uma extensão `.spec.js` ou `.test.js` dentro do projeto inteiro. + +Para executar o teste de ficheiros com uma extensão `.ts`, nós precisamos mudar a `testRegex` na secção de configuração dentro do ficheiro `package.json`. + +Adicione o seguinte ao campo `jest` dentro de `package.json`: + +```json +{ + // ... + "jest": { + // ... + "testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$" + } +} +``` + +O Jest recomenda a criação de um diretório `__tests__` exatamente próximo ao código a ser testado, mas esteja à vontade para estruturar os seus testes como você desejar. Apenas saiba que o Jest criaria um diretório `__snapshots__` próximo aos ficheiros de teste que executam testes instantâneos. + +### Escrevendo um Teste Unitário + +Agora que nós temos o projeto configurado, é hora de escrever um teste unitário. + +Crie um ficheiro `src/components/__tests__/HelloWorld.spec.ts`, e adicione o seguinte código: + +```js +// src/components/__tests__/HelloWorld.spec.ts +import { shallowMount } from '@vue/test-utils' +import HelloWorld from '../HelloWorld.vue' + +describe('HelloWorld.vue', () => { + test('renders props.msg when passed', () => { + const msg = 'new message' + const wrapper = shallowMount(HelloWorld, { + propsData: { msg } + }) + expect(wrapper.text()).toMatch(msg) + }) +}) +``` + +É tudo o que nós precisamos fazer para ter o TypeScript e a Vue Test Utils trabalhando juntos! + +### Recursos + +- [Exemplo de projeto para esta configuração](https://github.com/vuejs/vue-test-utils-typescript-example) +- [Jest](https://jestjs.io/) diff --git a/docs/pt/guides/using-with-vue-router.md b/docs/pt/guides/using-with-vue-router.md new file mode 100644 index 000000000..03d81f26e --- /dev/null +++ b/docs/pt/guides/using-with-vue-router.md @@ -0,0 +1,86 @@ +## Usando com o Vue Router + +### Instalando o Vue Router dentro de testes + +Você nunca deve instalar o Vue Router sobre o construtor base de Vue dentro de testes. A instalação de Vue Router adiciona `$route` e `$router` como propriedades de apenas leitura sobre o protótipo de Vue. + +Para evitar isso, nós podemos criar um `localVue`, e instalar o Vue Router sobre ele. + +```js +import { shallowMount, createLocalVue } from '@vue/test-utils' +import VueRouter from 'vue-router' + +const localVue = createLocalVue() +localVue.use(VueRouter) +const router = new VueRouter() + +shallowMount(Component, { + localVue, + router +}) +``` + +> **Nota:** A instalação de Vue Router sobre um `localVue` também adiciona o `$route` e `$router` como propriedades de apenas leitura ao `localVue`. Isto significa que você não pode usar a opção `mocks` para sobrescrever o `$route` e o `$router` quando estiver montando um componente usando um `localVue` com o Vue Router instalado. + +### Testando componentes que usam o `router-link` ou `router-view` + +Quando você instalar o Vue Router, os componentes `router-link` e `router-view` são registados. Isto significa que nós podemos usar eles em qualquer lugar dentro da aplicação sem a necessidade de importar eles. + +Quando nós executamos os testes, nós precisamos tornar estes componentes de Vue Router disponíveis para o componente que estamos montando. Há dois métodos de fazer isso. + +### Usando os stubs + +```js +import { shallowMount } from '@vue/test-utils' + +shallowMount(Component, { + stubs: ['router-link', 'router-view'] +}) +``` + +### Instalando o Vue Router com o `localVue` + +```js +import { mount, createLocalVue } from '@vue/test-utils' +import VueRouter from 'vue-router' + +const localVue = createLocalVue() +localVue.use(VueRouter) + +mount(Component, { + localVue, + router +}) +``` + +A instância do roteador está disponível para todos componentes filhos, isto é útil para testes de nível de integração. + +### Imitando o `#route` e o `$router` + +Algumas vezes você deseja testar aquele componente que faz alguma coisa com parâmetros dos objetos `$route` e `$router`. Para fazer isso, você pode passar imitações personalizadas para a instância de Vue. + +```js +import { shallowMount } from '@vue/test-utils' + +const $route = { + path: '/some/path' +} + +const wrapper = shallowMount(Component, { + mocks: { + $route + } +}) + +wrapper.vm.$route.path // /some/path +``` + +> **Nota:** os valores imitados de `$route` e `$router` não estão disponíveis aos componentes filhos, ou forje estes componentes ou use o método `localVue`. + +### Conclusão + +A instalação de Vue Router adiciona o `$route` e o `$router` como propriedades de apenas leitura sobre o protótipo de Vue. + +Isso significa que quaisquer testes futuros que tentar imitar o `$route` ou o `$router` falhará. + +Para evitar isso, nunca instale o Vue Router globalmente quando você estiver executando os testes; use um `localVue` como detalhado acima. diff --git a/docs/pt/guides/using-with-vuex.md b/docs/pt/guides/using-with-vuex.md new file mode 100644 index 000000000..311c0cb17 --- /dev/null +++ b/docs/pt/guides/using-with-vuex.md @@ -0,0 +1,393 @@ +# Usando com a Vuex + +Neste guia, iremos ver como testar a Vuex em componentes com a Vue Test Utils, e como testar uma memória da Vuex. + + + +## Testando a Vuex em componentes + +### Imitando Ações + +Vamos ver um pouco de código. + +Isto é o componente que nós queremos testar. Ele chama as ações da Vuex. + +```html + + + +``` + +Para o propósito deste teste, nós não temos interesse no que as ações fazem, ou em como a memória se parece. Nós apenas precisamos saber que estas ações estão sendo disparadas quando elas deveriam, e que elas são disparadas com o valor esperado. + +Para testar isto, nós precisamos passar uma imitação da memória para a Vue quando nós montamos superficialmente (shallowMount) o nosso componente. + +Ao invés de passar a memória para o construtor base da Vue, nós podemos passar ela para um - [localVue](../api/options.md#localvue). Um localVue é um construtor isolado da Vue que nós podemos realizar mudanças sem afetar o construtor global da Vue. + +Veremos que isto se parece: + +```js +import { shallowMount, createLocalVue } from '@vue/test-utils' +import Vuex from 'vuex' +import Actions from '../../../src/components/Actions' + +const localVue = createLocalVue() + +localVue.use(Vuex) + +describe('Actions.vue', () => { + let actions + let store + + beforeEach(() => { + actions = { + actionClick: jest.fn(), + actionInput: jest.fn() + } + store = new Vuex.Store({ + actions + }) + }) + + it('dispatches "actionInput" when input event value is "input"', () => { + const wrapper = shallowMount(Actions, { store, localVue }) + const input = wrapper.find('input') + input.element.value = 'input' + input.trigger('input') + expect(actions.actionInput).toHaveBeenCalled() + }) + + it('does not dispatch "actionInput" when event value is not "input"', () => { + const wrapper = shallowMount(Actions, { store, localVue }) + const input = wrapper.find('input') + input.element.value = 'not input' + input.trigger('input') + expect(actions.actionInput).not.toHaveBeenCalled() + }) + + it('calls store action "actionClick" when button is clicked', () => { + const wrapper = shallowMount(Actions, { store, localVue }) + wrapper.find('button').trigger('click') + expect(actions.actionClick).toHaveBeenCalled() + }) +}) +``` + +O que está acontecendo aqui? Primeiro nós dizemos a Vue para usar a Vuex com o método `localVue`. Isto é apenas um envolvedor em volta da `Vue.use`. + +Nós depois fazemos uma imitação da memória ao chamar `new Vuex.Store` com as nossas imitações de valores. Nós apenas passamos ela para as ações, visto que é tudo com o que nós nos preocupamos. + +As ações são [funções de imitação da jest](https://jestjs.io/docs/en/mock-functions.html). Estas funções de imitação nos dão métodos para afirmar se as ações foram chamadas ou não. + +Nós podemos então afirmar em nossos testes que a ação forjada foi chamada quando esperada. + +Agora a maneira que nós definimos a memória pode parecer um pouco estranha para você. + +Estamos usando `beforeEach` para garantir que nós temos uma memória limpa antes de cada teste. O `beforeEach` é um gatilho da mocha que é chamada antes de cada teste. No nosso teste, nós estamos re-atribuindo os valores das variáveis da memória. Se nós não fizéssemos isto, as funções de imitação precisariam ser automaticamente re-definidas. Ela também nos deixa mudar o estado em nossos testes, sem isto afetar os testes futuros. + +A coisa mais importante a anotar neste teste é que **nós criamos uma imitação da memória da Vuex e depois passamos ela para a Vue Test Utils**. + +Excelente, agora nós podemos imitar as ações, veremos em imitando os getters. + +### Imitando os Getters + +```html + + + +``` + +Este é um componente razoavelmente simples. Ele renderiza o resultado dos getters `clicks` e `inputValue`. Novamente, nós não nos preocupamos com o que os getters retornam – apenas que seus resultados estão sendo renderizado corretamente. + +Vejamos o teste: + +```js +import { shallowMount, createLocalVue } from '@vue/test-utils' +import Vuex from 'vuex' +import Getters from '../../../src/components/Getters' + +const localVue = createLocalVue() + +localVue.use(Vuex) + +describe('Getters.vue', () => { + let getters + let store + + beforeEach(() => { + getters = { + clicks: () => 2, + inputValue: () => 'input' + } + + store = new Vuex.Store({ + getters + }) + }) + + it('Renders "store.getters.inputValue" in first p tag', () => { + const wrapper = shallowMount(Getters, { store, localVue }) + const p = wrapper.find('p') + expect(p.text()).toBe(getters.inputValue()) + }) + + it('Renders "store.getters.clicks" in second p tag', () => { + const wrapper = shallowMount(Getters, { store, localVue }) + const p = wrapper.findAll('p').at(1) + expect(p.text()).toBe(getters.clicks().toString()) + }) +}) +``` + +O teste é similar aos nossas ações de teste. Nós criamos uma imitação de memória antes de cada teste, passamos ele como uma opção quando nós chamamos `shallowMount`, e afirmar que o valor renderizado pela nossa imitação de getters está sendo renderizada. + +Isto é genial, mas se nós quiséssemos verificar se nossos getters estão retornando a parte correta do nosso estado? + +### Imitando com Módulos + +Os [módulos](https://vuex.vuejs.org/guide/modules.html) são úteis para separação da nossa memória em pedaços gerenciáveis. Eles também exportam os getters. Nós podemos usar estes nos nossos testes. + +Vejamos o nosso componente: + +```html + + + +``` + +Componente simples que inclui uma ação e o getter. + +E o teste: + +```js +import { shallowMount, createLocalVue } from '@vue/test-utils' +import Vuex from 'vuex' +import MyComponent from '../../../src/components/MyComponent' +import myModule from '../../../src/store/myModule' + +const localVue = createLocalVue() + +localVue.use(Vuex) + +describe('MyComponent.vue', () => { + let actions + let state + let store + + beforeEach(() => { + state = { + clicks: 2 + } + + actions = { + moduleActionClick: jest.fn() + } + + store = new Vuex.Store({ + modules: { + myModule: { + state, + actions, + getters: myModule.getters, + namespaced: true + } + } + }) + }) + + it('calls store action "moduleActionClick" when button is clicked', () => { + const wrapper = shallowMount(MyComponent, { store, localVue }) + const button = wrapper.find('button') + button.trigger('click') + expect(actions.moduleActionClick).toHaveBeenCalled() + }) + + it('renders "state.clicks" in first p tag', () => { + const wrapper = shallowMount(MyComponent, { store, localVue }) + const p = wrapper.find('p') + expect(p.text()).toBe(state.clicks.toString()) + }) +}) +``` + +### Testando uma Memória da Vuex + +Existem duas abordagens para testes de uma memória da Vuex. A primeira abordagem é fazer testes unitários de getters, mutações, e ações separadamente. A segunda abordagem é criar uma memória e testar ela. Veremos ambas abordagens. + +Para ver como testar uma memória da Vuex, iremos criar um simples memória de contador (counter). A memória terá uma mutação `increment` e um getter `evenOrOdd`. + +```js +// mutations.js +export default { + increment(state) { + state.count++ + } +} +``` + +```js +// getters.js +export default { + evenOrOdd: state => (state.count % 2 === 0 ? 'even' : 'odd') +} +``` + +### Testando getters, mutações, e ações separadamente + +Os getters, mutações, e ações são todas funções de JavaScript, então nós podemos testar elas sem usar Vue Test Utils e Vuex. + +O benefício de testar os getters, mutações, e ações separadamente é que seus testes unitários são detalhados. Quando eles falham, você sabe exatamente o que está errado com o seu código. A desvantagem é que você precisará imitar as funções de Vuex, como `commit` e o `dispatch`. Isto pode levar para uma situação em que seus testes unitários passam, mas seu código de produção falha porque suas imitações estão incorretas. + +Criaremos dois ficheiros de teste, o `mutations.spec.js` e o `getters.spec.js`: + +Primeiro, vamos testar as mutações de `increment`: + +```js +// mutations.spec.js + +import mutations from './mutations' + +test('"increment" increments "state.count" by 1', () => { + const state = { + count: 0 + } + mutations.increment(state) + expect(state.count).toBe(1) +}) +``` + +Agora vamos testar o getter `evenOrOdd`. Nós podemos testar ele ao criar uma imitação `state`, chamando o getter com o `state` e verificar se ele retorna o valor correto. + +```js +// getters.spec.js + +import getters from './getters' + +test('"evenOrOdd" returns even if "state.count" is even', () => { + const state = { + count: 2 + } + expect(getters.evenOrOdd(state)).toBe('even') +}) + +test('"evenOrOdd" returns odd if "state.count" is odd', () => { + const state = { + count: 1 + } + expect(getters.evenOrOdd(state)).toBe('odd') +}) +``` + +### Testando uma execução da memória + +Um outra abordagem para testar uma memória da Vuex é criar uma execução da memória usando a configuração da memória. + +O benefício da criação de uma instância de execução da memória é que nós não temos que imitar nenhuma função da Vuex. + +A desvantagem é que quando um teste quebrar, pode ser difícil encontrar onde o problema está. + +Vamos escrever um teste. Quando nós criamos uma memória, usaremos o `localVue` para evitar a poluição da base do construtor da Vue. O teste cria uma memória usando a exportação de `store-config.js`: + +```js +// store-config.js + +import mutations from './mutations' +import getters from './getters' + +export default { + state: { + count: 0 + }, + mutations, + getters +} +``` + +```js +// store-config.spec.js + +import { createLocalVue } from '@vue/test-utils' +import Vuex from 'vuex' +import storeConfig from './store-config' +import { cloneDeep } from 'lodash' + +test('increments "count" value when "increment" is committed', () => { + const localVue = createLocalVue() + localVue.use(Vuex) + const store = new Vuex.Store(cloneDeep(storeConfig)) + expect(store.state.count).toBe(0) + store.commit('increment') + expect(store.state.count).toBe(1) +}) + +test('updates "evenOrOdd" getter when "increment" is committed', () => { + const localVue = createLocalVue() + localVue.use(Vuex) + const store = new Vuex.Store(cloneDeep(storeConfig)) + expect(store.getters.evenOrOdd).toBe('even') + store.commit('increment') + expect(store.getters.evenOrOdd).toBe('odd') +}) +``` + +Repare que nós usamos o `cloneDeep` para clonar a configuração da memória antes da criação uma memória com ela. Isto porque a Vuex realiza mutações nas opções do objeto usado para criar a memória. Para ter a certeza que nós temos uma memória limpa em cada teste, nós precisamos clonar o objeto `storeConfig`. + +No entanto, o `cloneDeep` não é "profunda (deep)" o suficiente para também clonar os módulos da memória. Se a sua `storeConfig` incluírem os módulos, você precisará passar um objeto para `new Vuex.Store()`, deste jeito: + +```js +import myModule from './myModule' +// ... +const store = new Vuex.Store({ modules: { myModule: cloneDeep(myModule) } }) +``` + +### Recursos + +- [Projeto de exemplo para testes de componentes](https://github.com/eddyerburgh/vue-test-utils-vuex-example) +- [Projeto de exemplo para testes da memória](https://github.com/eddyerburgh/testing-vuex-store-example) +- [`localVue`](../api/options.md#localvue) +- [`createLocalVue`](../api/createLocalVue.md) diff --git a/docs/pt/installation/README.md b/docs/pt/installation/README.md new file mode 100644 index 000000000..6b31dbce9 --- /dev/null +++ b/docs/pt/installation/README.md @@ -0,0 +1,5 @@ +# Instalação + +!!!include(docs/pt/installation/semantic-versioning.md)!!! +!!!include(docs/pt/installation/using-with-jest.md)!!! +!!!include(docs/pt/installation/using-other-test-runners.md)!!! diff --git a/docs/pt/installation/semantic-versioning.md b/docs/pt/installation/semantic-versioning.md new file mode 100644 index 000000000..b05837c2d --- /dev/null +++ b/docs/pt/installation/semantic-versioning.md @@ -0,0 +1,3 @@ +## Versionamento Semântico + +O Vue Test Utils segue o [Versionamento Semântico](https://semver.org/) dentro de todos os seus projetos oficiais para funcionalidades documentadas e comportamento. Para comportamento não documentado ou interior exposto, as mudanças são descritas dentro das [notas de lançamento](https://github.com/vuejs/vue-test-utils/releases). diff --git a/docs/pt/installation/using-other-test-runners.md b/docs/pt/installation/using-other-test-runners.md new file mode 100644 index 000000000..de70fb5f4 --- /dev/null +++ b/docs/pt/installation/using-other-test-runners.md @@ -0,0 +1,60 @@ +## Usando outros executores de Teste + +### Executando o Vue Test Utils com o Karma + +O [Karma](http://karma-runner.github.io/) é um executor de teste que lança o navegador, executa os testes, e reporta eles de volta para nós. + +Adicionalmente ao Karma, você pode desejar usar o framework [Mocha](https://mochajs.org/) para escrever os testes e a biblioteca [Chai](http://chaijs.com/) para afirmação de teste. Também, você talvez também deseja verificar o [Sinon](http://sinonjs.org/) para criação de espiões e forjados. + +A seguir é uma configuração básica do Karma para o Vue Test Utils: + +```js +// karma.conf.js +var webpackConfig = require('./webpack.config.js') + +module.exports = function(config) { + config.set({ + frameworks: ['mocha'], + files: ['test/**/*.spec.js'], + webpack: webpackConfig, + reporters: ['spec'], + browsers: ['Chrome'], + preprocessors: { + '**/*.spec.js': ['webpack', 'sourcemap'] + } + }) +} +``` + +### Executando o Vue Test Utils com o mocha webpack + +Uma outra estratégia para testar Componentes de Ficheiro Único (SFCs em Inglês) é compilar todos os nossos testes via webpack e depois executar ele dentro de um executor de teste. A vantagem desta abordagem é que ela dá para nós suporte completo para todas as funcionalidades do webpack e do `vue-loader`, assim nós não temos que fazer acordos dentro do nosso código-fonte. + +Nós selecionamos o [`mochapack`](https://github.com/sysgears/mochapack) para fornecer uma experiência toda otimizada para esta tarefa em particular. + +A primeira coisa a fazer é a instalação das dependências de teste: + +```bash +npm install --save-dev @vue/test-utils mocha mochapack +``` + +Depois da instalação do Vue Test Utils e o `mochapack`, você precisará definir um roteiro de teste dentro do seu `package.json`: + +```json +// package.json +{ + "scripts": { + "test": "mochapack --webpack-config webpack.config.js --require test/setup.js test/**/*.spec.js" + } +} +``` + +### Executando o Vue Test Utils sem uma etapa de construção + +Enquanto é comum construir aplicações em Vue usando ferramentas taís como o [webpack](https://webpack.js.org/) para empacotar a aplicação, `vue-loader` para entregar Componentes de Ficheiro Único (SFC em Inglês), é possível usar o Vue Test Utils com muito menos. Os requisitos mínimos para a Vue Test Utils, além dela mesma são: + +- Vue +- [vue-template-compiler](https://github.com/vuejs/vue/tree/dev/packages/vue-template-compiler#readme) +- um DOM (seja ele [jsdom](https://github.com/jsdom/jsdom) dentro de um ambiente Node, ou o DOM dentro de um navegador real) + +Repare que o `jsdom` (ou qualquer outra implementação do DOM) deve ser exigido e instalado antes da Vue Test Utils, porque ele espera um DOM (DOM real, ou JSDOM) existir. diff --git a/docs/pt/installation/using-with-jest.md b/docs/pt/installation/using-with-jest.md new file mode 100644 index 000000000..aa3fd3056 --- /dev/null +++ b/docs/pt/installation/using-with-jest.md @@ -0,0 +1,119 @@ +## Usando o Vue Test Utils com o Jest (recomendado) + +O Jest é um executor de teste desenvolvido pelo Facebook (agora Meta), com o objetivo de entregar uma solução de testes unitários com baterias inclusas. Você pode aprender mais sobre o Jest em sua [documentação oficial](https://jestjs.io/). + + + +### Instalação com a Vue CLI (recomendado) + +Se você estiver usando a Vue CLI para construir o seu projeto, você pode usar o plugin [cli-plugin-unit-jest](https://cli.vuejs.org/core-plugins/unit-jest.html) para executar testes do Jest. + +```bash +$ vue add unit-jest +``` + +O plugin empurra todas dependências obrigatórias (incluindo o jest), cria um ficheiro `jest.config.js` com padrões sensíveis, e gera um exemplo de conjunto de teste. + +Depois disso, tudo o que você precisa fazer é instalar a Vue Test Utils. + +```bash +$ npm install --save-dev @vue/test-utils +``` + +### Instalação Manual + +Depois de configurar o Jest, a primeira coisa que você precisa fazer é instalar a Vue Test Utils e a [`vue-jest`](https://github.com/vuejs/vue-jest) para processar os Componentes de Ficheiro Único: + +```bash +$ npm install --save-dev @vue/test-utils vue-jest +``` + +A seguir, você precisa dizer ao Jest para transformar ficheiros `.vue` usando `vue-jest`. Você pode fazer isso ao adicionar a seguinte configuração dentro do `package.json` ou dentro de um [ficheiro dedicado de configuração do Jest](https://jestjs.io/docs/en/configuration): + +```json +{ + "jest": { + "moduleFileExtensions": [ + "js", + "json", + // dizer ao Jest para manipular ficheiros `*.vue` + "vue" + ], + "transform": { + // processar ficheiros `*.vue` com o `vue-jest` + ".*\\.(vue)$": "vue-jest" + } + } +} +``` + +#### Usando com o Babel + +Se você for usar o `babel` e importar componentes de vue de ficheiro único com a extensão `.vue` dentro dos seus testes, você precisará instalar o babel e transformar os ficheiros com o `babel-jest`. + +```bash +npm install --save-dev babel-jest @babel/core @babel/preset-env babel-core@^7.0.0-bridge.0 +``` + +Depois, você precisa dizer ao Jest para transformar ficheiros os `.js` usando o `babel-jest`. Você pode fazer isso adicionando a seguinte configuração dentro do `package.json` ou dentro de um [ficheiro dedicado de configuração do Jest](https://jestjs.io/docs/en/configuration): + +```json +{ + "jest": { + "transform": { + // processa ficheiros `*.js` com o `babel-jest` + ".*\\.(js)$": "babel-jest" + } + } +} +``` + +A seguir você precisa criar a configuração de babel usando os ficheiros de configuração [babel.config.json](https://babeljs.io/docs/en/configuration#babelconfigjson) ou o [.babelrc.json](https://babeljs.io/docs/en/configuration#babelrcjson): + +```json +{ + "presets": ["@babel/preset-env"] +} +``` + +Você pode também adicionar estas opções ao `package.json`: + +```json +{ + "babel": { + "presets": ["@babel/preset-env"] + } +} +``` + +#### Manipulando os apelidos (aliases) do webpack + +Se você usar um resolvedor de apelidos dentro da configuração do webpack, por exemplo apelidando o `@` para o `/src`, você precisa adicionar uma configuração de correspondência para o Jest também, usando a opção `moduleNameMapper`: + +```json +{ + "jest": { + // suportar o mesmo mapeamento de apelido de `@ -> src` dentro do código fonte. + "moduleNameMapper": { + "^@/(.*)$": "/src/$1" + } + } +} +``` + +### Cobertura de Código + +O Jest pode ser usado para gerar relatórios de cobertura em vários formatos. Isto está desativado por padrão (para ambas instalação via vue-cli e para uma manual). A seguir está um exemplo simples para começar com: + +Estenda a sua configuração `jest` com a opção [`collectCoverage`](https://jestjs.io/docs/en/configuration#collectcoverage-boolean), e depois adicione o arranjo [`collectCoverageFrom`](https://jestjs.io/docs/en/configuration#collectcoveragefrom-array) para definir os ficheiros para os quais a informações de cobertura devem ser coletadas. + +```json +{ + "jest": { + "collectCoverage": true, + "collectCoverageFrom": ["**/*.{js,vue}", "!**/node_modules/**"] + } +} +``` + +Isto ativará os relatórios de cobertura com os [relatórios de cobertura padrão](https://jestjs.io/docs/en/configuration#coveragereporters-array-string). A documentação mais avançada pode ser encontrada dentro da [documentação da configuração do Jest](https://jestjs.io/docs/en/configuration#collectcoverage-boolean), onde você pode encontrar opções para os limites de cobertura, alvo de diretórios de saída, etc. diff --git a/docs/pt/upgrading-to-v1/README.md b/docs/pt/upgrading-to-v1/README.md new file mode 100644 index 000000000..90a3cfb5f --- /dev/null +++ b/docs/pt/upgrading-to-v1/README.md @@ -0,0 +1,84 @@ +### Atualizando para V1.0 + +Depois de um longo período em Beta, a Vue Test Utils finalmente lançou a versão 1.0! Nós depreciamos alguns métodos que não eram úteis, então você poderá ver vários avisos de depreciação depois da atualização. Este guia ajudará você a migrar para longe deles. + +Você pode ler as notas de lançamentos para versão 1 [aqui](https://github.com/vuejs/vue-test-utils/releases) ou as discussões sobre as depreciações [aqui](https://github.com/vuejs/rfcs/pull/161). + +### O método `find` + +Na beta, o método `find` poderia ser usado para buscar ambos nós do DOM (usando a sintaxe de `querySelector`) ou um componente (através de uma referência de componente, uma opção `ref` ou uma opção `name`). Este comportamento agora está dividido em dois métodos: `find` e `findComponent`. + +Se você estava usando esta sintaxe: + +- `find(Foo)` +- `find({ name: 'foo' })` +- `find({ ref: 'my-ref' })` + +Mude-os para serem `findComponent`. + +Você pode continuar usando o `find` em nós do DOM usando a sintaxe de `querySelector`. + +### O método `isVueInstance` + +Este método foi depreciado porque ele tende a encorajar detalhes de implementação de testes, o que é uma má prática. As afirmações usando isto podem simplesmente ser removidas; se você realmente precisar de um substituto, você pode usar o `expect((...).vm).toBeTruthy()`, o que é basicamente o que o método `isVueInstance` está fazendo. + +### O método `contains` + +Os testes usando o método `contains` podem ser substituídos por `find` ou `findComponent` ou `get`. Por exemplo, `expect(wrapper.contains('#el')).toBe(true)` pode ser escrito como `wrapper.get('#el')`, o que lançará um erro se o seletor não for correspondido. Um outra maneira de escrever isto usando o `find` é `expect(wrapper.find('#el').element).toBeTruthy()`. + +### O método `is` + +Você pode sobrescrever os testes usando o `is` para usar `element.tagName` no lugar. Por exemplo, `wrapper.find('div').is('div')` pode ser escrito como `wrapper.find('div').element.tagName`. + +### O método `isEmpty` + +Saber se um nó do DOM está vazio não é uma funcionalidade especifica da Vue, e não é algo que é difícil de saber. No lugar de reinventar a roda, nós decidimos que é melhor delegar para uma solução bem testa existente por padrão. Considere o excelente correspondente `toBeEmpty` da [jest-dom](https://github.com/testing-library/jest-dom#tobeempty), por exemplo, se você estiver usando o Jest. + +### O método `name` + +Afirmações contra o método `name` encorajam detalhes de implementação de testes, o que é uma má prática. Se você precisar desta funcionalidade, você pode usar o `vm.$options.name` para componentes de Vue ou `element.tagName` para nós do DOM. Novamente, considere se você realmente precisa deste teste - é provável que você não precisa. + +### As opções `setMethods` e `mountingOptions.methods` + +Ao usar `setMethods`, você está fazendo mutação da instância da Vue - isto não é algo que a Vue suporte, e pode levar para testes escamosos e acoplados. + +Não existe uma substituição direta para isto. Se você tiver um método complexo você gostaria de apagar, considere mover ele para um outro ficheiro e usando a funcionalidade de imitar ou forjar do seu executor de teste. + +Por exemplo, você pode querer evitar uma chamada de API: + +```js +const Foo = { + created() { + this.getData() + }, + methods: { + getData() { + axios.get('...') + } + } +} +``` + +Em lugar de fazer: + +```js +mount(Foo, { + methods: { + getData: () => {} + } +}) +``` + +Imite a dependência `axios`. No Jest, por exemplo, você pode fazer isso com `jest.mock('axios')`. Isto evitará a chamada da API, sem mutação da seu componente de Vue. + +Se você precisar de mais ajuda para a migração, você pode juntar-se ao [servidor VueLand](https://chat.vuejs.org/) no Discord. + +### Avisos de Depreciação + +Os avisos de depreciação podem ser silenciados. + +```js +import { config } from '@vue/test-utils' + +config.showDeprecationWarnings = false +```