diff --git a/packages/core/jest.setup.js b/packages/core/jest.setup.js new file mode 100644 index 0000000000..70c5472408 --- /dev/null +++ b/packages/core/jest.setup.js @@ -0,0 +1 @@ +require('@testing-library/jest-dom') diff --git a/packages/core/package.json b/packages/core/package.json index a23d734f6a..fb77964783 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -33,6 +33,11 @@ "pre-commit": "tsdx lint" } }, + "jest": { + "setupFilesAfterEnv": [ + "/jest.setup.js" + ] + }, "engines": { "yarn": "^1.19.1", "node": ">=12.16.1" @@ -46,6 +51,8 @@ "next": "^9.2.2-canary.21" }, "devDependencies": { + "@testing-library/react": "9.4.1", + "@testing-library/jest-dom": "5.1.1", "@types/react": "16.9.23", "next": "9.2.3-canary.8", "prisma2": "2.0.0-preview022" diff --git a/packages/core/src/components/Form.tsx b/packages/core/src/components/Form.tsx index 00e0e5b6e0..5c9afcf6b7 100644 --- a/packages/core/src/components/Form.tsx +++ b/packages/core/src/components/Form.tsx @@ -1,5 +1,5 @@ -import React from 'react' import Router from 'next/router' +import React from 'react' export default function({children, action, method, ...props}: {[index: string]: any}) { const [i, setI] = React.useState(0) @@ -22,10 +22,9 @@ export default function({children, action, method, ...props}: {[index: string]: const form = event.target as HTMLFormElement const data = new URLSearchParams() - for (const pair of new FormData(form).entries()) { - console.log(pair[0], pair[1]) + for (const [key, value] of new FormData(form).entries()) { // TODO: handle file types - data.append(pair[0], pair[1] as string) + data.append(key, value.toString()) } const res = await fetch(action, { diff --git a/packages/core/src/controller.ts b/packages/core/src/controller.ts index ba03a6cc0a..6de2104849 100644 --- a/packages/core/src/controller.ts +++ b/packages/core/src/controller.ts @@ -1,9 +1,9 @@ -import {NextApiRequest, NextApiResponse} from 'next' import {PrismaClient} from '@prisma/client' -import prettyMs from 'pretty-ms' +import {NextApiRequest, NextApiResponse} from 'next' import permit from 'permit-params' -import {isServer} from './utils' +import prettyMs from 'pretty-ms' import {ControllerInput, ControllerInstance} from '../types/controller' +import {isServer} from './utils' export {default as Form} from './components/Form' diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index e1aaae04d1..87693e5351 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -1,9 +1,2 @@ export * from './components' export * from './controller' - -export const sum = (a: number, b: number) => { - if ('development' === process.env.NODE_ENV) { - console.log('boop') - } - return a + b -} diff --git a/packages/core/test/blah.test.ts b/packages/core/test/blah.test.ts deleted file mode 100644 index 33c7ef5073..0000000000 --- a/packages/core/test/blah.test.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { sum } from '../src'; - -describe('blah', () => { - it('works', () => { - expect(sum(1, 1)).toEqual(2); - }); -}); diff --git a/packages/core/test/components/Form.test.tsx b/packages/core/test/components/Form.test.tsx new file mode 100644 index 0000000000..6b14818446 --- /dev/null +++ b/packages/core/test/components/Form.test.tsx @@ -0,0 +1,60 @@ +import {fireEvent, render, RenderResult, wait} from '@testing-library/react' +import Router from 'next/router' +import React, {FC} from 'react' +import Form from '../../src/components/Form' +jest.mock('next/router') + +/** + * Creates a mock implementation of fetch which will resolve asynchronously with the provided `res` param + * @param res The response that will be sent back + */ +function mockFetch(res: any = {ok: true}) { + Object.assign(global, { + fetch: jest.fn().mockImplementation(async () => res), + }) +} + +describe('Form', () => { + beforeAll(() => { + mockFetch() + }) + + const TestHarness: FC = () => ( +
+ + + > +
+ ) + + const submitForm = async (page: RenderResult) => { + const form = await page.findByRole('form') + const button = await page.findByRole('button') + fireEvent.click(button, {target: form}) + await wait() + } + + it('renders', async () => { + const page = await render() + expect(page.getByLabelText('Title')).toHaveValue('test') + }) + + describe('with redirect', () => { + beforeAll(() => { + const headers = {Location: 'location', 'x-as': 'xas'} as any + mockFetch({ + ok: true, + headers: { + get: jest.fn().mockImplementation(key => headers[key]), + }, + }) + }) + + it('triggers routing', async () => { + const page = await render() + await submitForm(page) + + expect(Router.push).toBeCalledWith('location', 'xas') + }) + }) +}) diff --git a/packages/core/test/controller-fixtures.ts b/packages/core/test/controller-fixtures.ts new file mode 100644 index 0000000000..3c5e70f88c --- /dev/null +++ b/packages/core/test/controller-fixtures.ts @@ -0,0 +1,45 @@ +import {Controller, harnessServerProps} from '../src/controller' + +const SimpleController = Controller(() => ({ + name: 'SimpleController', + + async index() { + return {status: 200, data: {message: 'indexed'}} + }, + + async show() { + return {status: 200, data: {message: 'shown'}} + }, + + async create() { + return { + status: 201, + data: {message: 'created'}, + } + }, + + async update() { + return { + status: 200, + data: {message: 'updated'}, + } + }, + + async delete() { + return { + status: 204, + data: {}, + } + }, +})) + +const RedirectController = Controller(() => ({ + name: 'RedirectController', + + async create() { + return {redirect: {href: 'href', as: 'as'}} + }, +})) + +export const unstable_getSimpleServerProps = harnessServerProps(SimpleController) +export const unstable_getRedirectServerProps = harnessServerProps(RedirectController) diff --git a/packages/core/test/controller.test.ts b/packages/core/test/controller.test.ts new file mode 100644 index 0000000000..98f8dc6f8d --- /dev/null +++ b/packages/core/test/controller.test.ts @@ -0,0 +1,76 @@ +import * as fixtures from './controller-fixtures' + +describe('controller', () => { + const createContext = (opts: any = {}) => ({ + query: {}, + ...opts, + req: {method: 'GET', url: '/', socket: {remoteAddress: 'testAddress'}, ...opts.req}, + res: {status: jest.fn(), ...opts.res}, + }) + + const createSimpleRequest = (ctx: any) => fixtures.unstable_getSimpleServerProps(ctx) + const createRedirectRequest = (ctx: any) => fixtures.unstable_getRedirectServerProps(ctx) + + it('simple index response', async () => { + const ctx = createContext() + const returning = (await createSimpleRequest(ctx)) as {props: any} + expect(returning.props).toMatchObject({message: 'indexed'}) + expect(ctx.res.status).toBeCalledWith(200) + }) + + it('simple show response', async () => { + const ctx = createContext({query: {id: 123}}) + const returning = (await createSimpleRequest(ctx)) as {props: any} + expect(returning.props).toMatchObject({message: 'shown'}) + expect(ctx.res.status).toBeCalledWith(200) + }) + + it('simple create response', async () => { + const ctx = createContext({req: {method: 'POST'}}) + const returning = (await createSimpleRequest(ctx)) as {props: any} + expect(returning.props).toMatchObject({message: 'created'}) + }) + + it('simple update response', async () => { + const ctx = createContext({req: {method: 'PATCH'}}) + const returning = (await createSimpleRequest(ctx)) as {props: any} + expect(returning.props).toMatchObject({message: 'updated'}) + }) + + it('simple delete response', async () => { + const ctx = createContext({req: {method: 'DELETE'}}) + await createSimpleRequest(ctx) + expect(ctx.res.status).toBeCalledWith(204) + }) + + it('simple head response', async () => { + const ctx = createContext({ + req: {method: 'HEAD'}, + res: {status: jest.fn().mockImplementation(() => ctx.res), end: jest.fn()}, + }) + await createSimpleRequest(ctx) + expect(ctx.res.status).toBeCalledWith(204) + expect(ctx.res.end).toBeCalled() + }) + + it('simple unknown response', async () => { + const ctx = createContext({req: {method: 'UNKNOWN'}, res: {status: jest.fn(), end: jest.fn()}}) + await createSimpleRequest(ctx) + expect(ctx.res.status).toBeCalledWith(404) + }) + + it('simple api response', async () => { + const ctx = createContext({req: {url: '/api/simple'}, res: {status: jest.fn(), json: jest.fn()}}) + await createSimpleRequest(ctx) + expect(ctx.res.json).toBeCalledWith({message: 'indexed'}) + expect(ctx.res.status).toBeCalledWith(200) + }) + + it('redirect response', async () => { + const ctx = createContext({req: {method: 'POST'}, res: {setHeader: jest.fn(), end: jest.fn()}}) + await createRedirectRequest(ctx) + + expect(ctx.res.setHeader).toBeCalledWith('Location', 'href') + expect(ctx.res.setHeader).toBeCalledWith('x-as', 'as') + }) +}) diff --git a/yarn.lock b/yarn.lock index 30c659fe06..a714b44738 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1000,7 +1000,7 @@ dependencies: regenerator-runtime "^0.13.2" -"@babel/runtime@^7.4.5", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.2": +"@babel/runtime@^7.4.5", "@babel/runtime@^7.6.2", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.3": version "7.8.4" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.8.4.tgz#d79f5a2040f7caa24d53e563aad49cbc05581308" integrity sha512-neAp3zt80trRVBI1x0azq6c57aNBqYZH8KhMm3TaB7wEI5Q4A2SHfBHE8w9gOhI/lrqxtEbXZgQIrHP+wvSGwQ== @@ -2460,6 +2460,11 @@ dependencies: any-observable "^0.3.0" +"@sheerun/mutationobserver-shim@^0.3.2": + version "0.3.2" + resolved "https://registry.yarnpkg.com/@sheerun/mutationobserver-shim/-/mutationobserver-shim-0.3.2.tgz#8013f2af54a2b7d735f71560ff360d3a8176a87b" + integrity sha512-vTCdPp/T/Q3oSqwHmZ5Kpa9oI7iLtGl3RQaA/NyLHikvcrPxACkkKVr/XzkSPJWXHRhKGzVvb0urJsbMlRxi1Q== + "@sindresorhus/is@^0.14.0": version "0.14.0" resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" @@ -2479,6 +2484,43 @@ dependencies: defer-to-connect "^1.0.1" +"@testing-library/dom@^6.11.0": + version "6.12.2" + resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-6.12.2.tgz#5d549acf43f2e0c23b2abfd4e36d65594c3b2741" + integrity sha512-KCnvHra5fV+wDxg3wJObGvZFxq7v1DJt829GNFLuRDjKxVNc/B5AdsylNF5PMHFbWMXDsHwM26d2NZcZO9KjbQ== + dependencies: + "@babel/runtime" "^7.6.2" + "@sheerun/mutationobserver-shim" "^0.3.2" + "@types/testing-library__dom" "^6.0.0" + aria-query "3.0.0" + pretty-format "^24.9.0" + wait-for-expect "^3.0.0" + +"@testing-library/jest-dom@5.1.1": + version "5.1.1" + resolved "https://registry.yarnpkg.com/@testing-library/jest-dom/-/jest-dom-5.1.1.tgz#e88a5c08f9b9f36b384f948a0532eae2abbc8204" + integrity sha512-7xnmBFcUmmUVAUhFiZ/u3CxFh1e46THAwra4SiiKNCW4By26RedCRwEk0rtleFPZG0wlTSNOKDvJjWYy93dp0w== + dependencies: + "@babel/runtime" "^7.8.3" + "@types/testing-library__jest-dom" "^5.0.0" + chalk "^3.0.0" + css "^2.2.4" + css.escape "^1.5.1" + jest-diff "^25.1.0" + jest-matcher-utils "^25.1.0" + lodash "^4.17.15" + pretty-format "^25.1.0" + redent "^3.0.0" + +"@testing-library/react@9.4.1": + version "9.4.1" + resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-9.4.1.tgz#955771568aa3216107d307bfdf470bf2394308a0" + integrity sha512-sta3ui24HPgW92quHyQj6gpOkNgLNx8BX/QOU4k1bddo43ZdqlGwmzCYwL93bExfhergwiau+IzBGl7TCsSFeA== + dependencies: + "@babel/runtime" "^7.8.3" + "@testing-library/dom" "^6.11.0" + "@types/testing-library__react" "^9.1.2" + "@types/babel__core@^7.1.0": version "7.1.6" resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.6.tgz#16ff42a5ae203c9af1c6e190ed1f30f83207b610" @@ -2589,7 +2631,7 @@ "@types/istanbul-lib-coverage" "*" "@types/istanbul-lib-report" "*" -"@types/jest@^25.1.3": +"@types/jest@*", "@types/jest@^25.1.3": version "25.1.3" resolved "https://registry.yarnpkg.com/@types/jest/-/jest-25.1.3.tgz#9b0b5addebccfb631175870be8ba62182f1bc35a" integrity sha512-jqargqzyJWgWAJCXX96LBGR/Ei7wQcZBvRv0PLEu9ZByMfcs23keUJrKv9FMR6YZf9YCbfqDqgmY+JUBsnqhrg== @@ -2650,7 +2692,14 @@ resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.3.tgz#2ab0d5da2e5815f94b0b9d4b95d1e5f243ab2ca7" integrity sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw== -"@types/react@16.9.23": +"@types/react-dom@*": + version "16.9.5" + resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-16.9.5.tgz#5de610b04a35d07ffd8f44edad93a71032d9aaa7" + integrity sha512-BX6RQ8s9D+2/gDhxrj8OW+YD4R+8hj7FEM/OJHGNR0KipE1h1mSsf39YeyC81qafkq+N3rU3h3RFbLSwE5VqUg== + dependencies: + "@types/react" "*" + +"@types/react@*", "@types/react@16.9.23": version "16.9.23" resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.23.tgz#1a66c6d468ba11a8943ad958a8cb3e737568271c" integrity sha512-SsGVT4E7L2wLN3tPYLiF20hmZTPGuzaayVunfgXzUn1x4uHVsKH6QDJQ/TdpHqwsTLd4CwrmQ2vOgxN7gE24gw== @@ -2691,6 +2740,28 @@ resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-1.0.1.tgz#0a851d3bd96498fa25c33ab7278ed3bd65f06c3e" integrity sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw== +"@types/testing-library__dom@*", "@types/testing-library__dom@^6.0.0": + version "6.12.1" + resolved "https://registry.yarnpkg.com/@types/testing-library__dom/-/testing-library__dom-6.12.1.tgz#37af28fae051f9e3feed5684535b1540c97ae28b" + integrity sha512-cgqnEjxKk31tQt29j4baSWaZPNjQf3bHalj2gcHQTpW5SuHRal76gOpF0vypeEo6o+sS5inOvvNdzLY0B3FB2A== + dependencies: + pretty-format "^24.3.0" + +"@types/testing-library__jest-dom@^5.0.0": + version "5.0.1" + resolved "https://registry.yarnpkg.com/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.0.1.tgz#cc7f384535a3d9597e27f58d38a795f5c137cc53" + integrity sha512-GiPXQBVF9O4DG9cssD2d266vozBJvC5Tnv6aeH5ujgYJgys1DYm9AFCz7YC+STR5ksGxq3zCt+yP8T1wbk2DFg== + dependencies: + "@types/jest" "*" + +"@types/testing-library__react@^9.1.2": + version "9.1.2" + resolved "https://registry.yarnpkg.com/@types/testing-library__react/-/testing-library__react-9.1.2.tgz#e33af9124c60a010fc03a34eff8f8a34a75c4351" + integrity sha512-CYaMqrswQ+cJACy268jsLAw355DZtPZGt3Jwmmotlcu8O/tkoXBI6AeZ84oZBJsIsesozPKzWzmv/0TIU+1E9Q== + dependencies: + "@types/react-dom" "*" + "@types/testing-library__dom" "*" + "@types/through@*": version "0.0.30" resolved "https://registry.yarnpkg.com/@types/through/-/through-0.0.30.tgz#e0e42ce77e897bd6aead6f6ea62aeb135b8a3895" @@ -3025,9 +3096,9 @@ acorn@^6.0.1, acorn@^6.2.1: integrity sha512-gac8OEcQ2Li1dxIEWGZzsp2BitJxwkwcOm0zHAJLcPJaVvm58FRnk6RkuLRpU1EujipU2ZFODv2P9DLMfnV8mw== acorn@^7.0.0, acorn@^7.1.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.1.0.tgz#949d36f2c292535da602283586c2477c57eb2d6c" - integrity sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ== + version "7.1.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.1.1.tgz#e35668de0b402f359de515c5482a1ab9f89a69bf" + integrity sha512-add7dgA5ppRPxCFJoAGfMDi7PIBXq1RtGo7BhbLaxwrXPOmw8gq48Y9ozT01hUKy9byMjlR20EJhu5zlkErEkg== adjust-sourcemap-loader@2.0.0: version "2.0.0" @@ -3131,11 +3202,11 @@ ansi-escapes@^3.0.0, ansi-escapes@^3.1.0, ansi-escapes@^3.2.0: integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ== ansi-escapes@^4.2.1: - version "4.3.0" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.0.tgz#a4ce2b33d6b214b7950d8595c212f12ac9cc569d" - integrity sha512-EiYhwo0v255HUL6eDyuLrXEkTi7WwVCLAw+SeOQ7M7qdun1z1pum4DEm/nuqIVbPvi9RPPc9k9LbyBv6H0DwVg== + version "4.3.1" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.1.tgz#a5c47cc43181f1f38ffd7076837700d395522a61" + integrity sha512-JWF7ocqNrp8u9oqpgV+wH5ftbt+cfvv+PTjOvKLT3AdYly/LmORARfEVT1iyjwN+4MqE5UmVKoAdIBqeoCHgLA== dependencies: - type-fest "^0.8.1" + type-fest "^0.11.0" ansi-html@0.0.7: version "0.0.7" @@ -3243,7 +3314,7 @@ argparse@^1.0.7: dependencies: sprintf-js "~1.0.2" -aria-query@^3.0.0: +aria-query@3.0.0, aria-query@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-3.0.0.tgz#65b3fcc1ca1155a8c9ae64d6eee297f15d5133cc" integrity sha1-ZbP8wcoRVajJrmTW7uKX8V1RM8w= @@ -5130,7 +5201,12 @@ css-unit-converter@^1.1.1: resolved "https://registry.yarnpkg.com/css-unit-converter/-/css-unit-converter-1.1.1.tgz#d9b9281adcfd8ced935bdbaba83786897f64e996" integrity sha1-2bkoGtz9jO2TW9urqDeGiX9k6ZY= -css@2.2.4, css@^2.0.0: +css.escape@^1.5.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/css.escape/-/css.escape-1.5.1.tgz#42e27d4fa04ae32f931a4b4d4191fa9cddee97cb" + integrity sha1-QuJ9T6BK4y+TGktNQZH6nN3ul8s= + +css@2.2.4, css@^2.0.0, css@^2.2.4: version "2.2.4" resolved "https://registry.yarnpkg.com/css/-/css-2.2.4.tgz#c646755c73971f2bba6a601e2cf2fd71b1298929" integrity sha512-oUnjmWpy0niI3x/mPL8dVEI1l7MnG3+HHyRPHf+YFSbK+svOhXpmSOcDURUh2aOCgl2grzrOPt1nHLuCVFULLw== @@ -5281,7 +5357,7 @@ debug@3.1.0: dependencies: ms "2.0.0" -debug@^3.0.0, debug@^3.1.0: +debug@^3.0.0, debug@^3.1.0, debug@^3.2.6: version "3.2.6" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== @@ -5448,6 +5524,11 @@ detect-indent@^6.0.0: resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-6.0.0.tgz#0abd0f549f69fc6659a254fe96786186b6f528fd" integrity sha512-oSyFlqaTHCItVRGK5RmrmjB+CmaMOW7IaNA/kdxqhoa6d17j/5ce9O9eWXmV/KEdRwqpQA+Vqe8a8Bsybu4YnA== +detect-libc@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" + integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= + detect-newline@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-2.1.0.tgz#f41f1c10be4b00e87b5f13da680759f2c5bfd3e2" @@ -7375,9 +7456,9 @@ http-cache-semantics@^3.8.1: integrity sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w== http-cache-semantics@^4.0.0: - version "4.0.4" - resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz#13eeb612424bb113d52172c28a13109c46fa85d7" - integrity sha512-Z2EICWNJou7Tr9Bd2M2UqDJq3A9F2ePG9w3lIpjoyuSyXFP9QbniJVu3XQYytuw5ebmG7dXSXO9PgAjJG8DDKA== + version "4.1.0" + resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390" + integrity sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ== http-call@^5.1.2: version "5.3.0" @@ -7490,7 +7571,7 @@ hyperlinker@^1.0.0: resolved "https://registry.yarnpkg.com/hyperlinker/-/hyperlinker-1.0.0.tgz#23dc9e38a206b208ee49bc2d6c8ef47027df0c0e" integrity sha512-Ty8UblRWFEcfSuIaajM34LdPXIhbs1ajEX/BBPv24J+enSVaEVY63xQ6lTO9VRYS5LAoghIG0IDJ+p+IPzKUQQ== -iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@~0.4.13: +iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@^0.4.4, iconv-lite@~0.4.13: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== @@ -9994,6 +10075,11 @@ mimic-response@^1.0.0, mimic-response@^1.0.1: resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== +min-indent@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.0.tgz#cfc45c37e9ec0d8f0a0ec3dd4ef7f7c3abe39256" + integrity sha1-z8RcN+nsDY8KDsPdTvf3w6vjklY= + mini-css-extract-plugin@0.8.0: version "0.8.0" resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-0.8.0.tgz#81d41ec4fe58c713a96ad7c723cdb2d0bd4d70e1" @@ -10216,6 +10302,15 @@ natural-orderby@^2.0.1: resolved "https://registry.yarnpkg.com/natural-orderby/-/natural-orderby-2.0.3.tgz#8623bc518ba162f8ff1cdb8941d74deb0fdcc016" integrity sha512-p7KTHxU0CUrcOXe62Zfrb5Z13nLvPhSWR/so3kFulUQU0sgUll2Z0LwpsLN351eOOD+hRGu/F1g+6xDfPeD++Q== +needle@^2.2.1: + version "2.3.2" + resolved "https://registry.yarnpkg.com/needle/-/needle-2.3.2.tgz#3342dea100b7160960a450dc8c22160ac712a528" + integrity sha512-DUzITvPVDUy6vczKKYTnWc/pBZ0EnjMJnQ3y+Jo5zfKFimJs7S3HFCxCRZYB9FUZcrzUQr3WsmvZgddMEIZv6w== + dependencies: + debug "^3.2.6" + iconv-lite "^0.4.4" + sax "^1.2.4" + negotiator@0.6.2: version "0.6.2" resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" @@ -10570,6 +10665,22 @@ node-notifier@^6.0.0: shellwords "^0.1.1" which "^1.3.1" +node-pre-gyp@*: + version "0.14.0" + resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.14.0.tgz#9a0596533b877289bcad4e143982ca3d904ddc83" + integrity sha512-+CvDC7ZttU/sSt9rFjix/P05iS43qHCOOGzcr3Ry99bXG7VX953+vFyEuph/tfqoYu8dttBkE86JSKBO2OzcxA== + dependencies: + detect-libc "^1.0.2" + mkdirp "^0.5.1" + needle "^2.2.1" + nopt "^4.0.1" + npm-packlist "^1.1.6" + npmlog "^4.0.2" + rc "^1.2.7" + rimraf "^2.6.1" + semver "^5.3.0" + tar "^4.4.2" + node-releases@^1.1.44, node-releases@^1.1.50: version "1.1.50" resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.50.tgz#803c40d2c45db172d0410e4efec83aa8c6ad0592" @@ -10678,7 +10789,7 @@ npm-normalize-package-bin@^1.0.0, npm-normalize-package-bin@^1.0.1: semver "^5.6.0" validate-npm-package-name "^3.0.0" -npm-packlist@^1.4.4: +npm-packlist@^1.1.6, npm-packlist@^1.4.4: version "1.4.8" resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.8.tgz#56ee6cc135b9f98ad3d51c1c95da22bbb9b2ef3e" integrity sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A== @@ -10741,7 +10852,7 @@ npm-run-path@^4.0.0: dependencies: path-key "^3.0.0" -npmlog@^4.1.2: +npmlog@^4.0.2, npmlog@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== @@ -11915,7 +12026,7 @@ pretty-bytes@^5.2.0: resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.3.0.tgz#f2849e27db79fb4d6cfe24764fc4134f165989f2" integrity sha512-hjGrh+P926p4R4WbaB6OckyRtO0F0/lQBiT+0gnxjV+5kjPBrfVBFCsCLbMqVQeydvIoouYTCmmEURiH3R1Bdg== -pretty-format@^24.9.0: +pretty-format@^24.3.0, pretty-format@^24.9.0: version "24.9.0" resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-24.9.0.tgz#12fac31b37019a4eea3c11aa9a959eb7628aa7c9" integrity sha512-00ZMZUiHaJrNfk33guavqgvfJS30sLYf0f8+Srklv0AMPodGGHcoHgksZ3OThYnIvOd+8yMCn0YiEOogjlgsnA== @@ -12262,7 +12373,7 @@ raw-body@2.4.0: iconv-lite "0.4.24" unpipe "1.0.0" -rc@^1.1.0, rc@^1.2.8: +rc@^1.1.0, rc@^1.2.7, rc@^1.2.8: version "1.2.8" resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== @@ -12536,6 +12647,14 @@ redent@^2.0.0: indent-string "^3.0.0" strip-indent "^2.0.0" +redent@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/redent/-/redent-3.0.0.tgz#e557b7998316bb53c9f1f56fa626352c6963059f" + integrity sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg== + dependencies: + indent-string "^4.0.0" + strip-indent "^3.0.0" + redeyed@~2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/redeyed/-/redeyed-2.1.1.tgz#8984b5815d99cb220469c99eeeffe38913e6cc0b" @@ -12973,7 +13092,7 @@ rimraf@2.6.3: dependencies: glob "^7.1.3" -rimraf@^2.2.8, rimraf@^2.5.4, rimraf@^2.6.2, rimraf@^2.6.3: +rimraf@^2.2.8, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.2, rimraf@^2.6.3: version "2.7.1" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== @@ -13201,7 +13320,7 @@ semver-regex@^2.0.0: resolved "https://registry.yarnpkg.com/semver-regex/-/semver-regex-2.0.0.tgz#a93c2c5844539a770233379107b38c7b4ac9d338" integrity sha512-mUdIBBvdn0PLOeP3TEkMH7HHeUP3GjsXCwKarjv/kGmUFOYg1VqEemKhoQpWMu6X2I8kHeuVdGibLGkVK+/5Qw== -"semver@2 || 3 || 4 || 5", "semver@2.x || 3.x || 4 || 5", semver@^5.0.3, semver@^5.4.1, semver@^5.5, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0, semver@^5.7.0, semver@^5.7.1: +"semver@2 || 3 || 4 || 5", "semver@2.x || 3.x || 4 || 5", semver@^5.0.3, semver@^5.3.0, semver@^5.4.1, semver@^5.5, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0, semver@^5.7.0, semver@^5.7.1: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== @@ -13899,6 +14018,13 @@ strip-indent@^2.0.0: resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-2.0.0.tgz#5ef8db295d01e6ed6cbf7aab96998d7822527b68" integrity sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g= +strip-indent@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-3.0.0.tgz#c32e1cee940b6b3432c771bc2c54bcce73cd3001" + integrity sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ== + dependencies: + min-indent "^1.0.0" + strip-json-comments@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.0.1.tgz#85713975a91fb87bf1b305cca77395e40d2a64a7" @@ -14060,7 +14186,7 @@ tar-stream@^2.0.0: inherits "^2.0.3" readable-stream "^3.1.1" -tar@^4.4.10, tar@^4.4.12, tar@^4.4.8: +tar@^4.4.10, tar@^4.4.12, tar@^4.4.2, tar@^4.4.8: version "4.4.13" resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.13.tgz#43b364bc52888d555298637b10d60790254ab525" integrity sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA== @@ -14584,6 +14710,11 @@ type-detect@4.0.8, type-detect@^4.0.0, type-detect@^4.0.5: resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== +type-fest@^0.11.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.11.0.tgz#97abf0872310fed88a5c466b25681576145e33f1" + integrity sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ== + type-fest@^0.3.0: version "0.3.1" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.3.1.tgz#63d00d204e059474fe5e1b7c011112bbd1dc29e1" @@ -15177,6 +15308,11 @@ w3c-xmlserializer@^1.1.2: webidl-conversions "^4.0.2" xml-name-validator "^3.0.0" +wait-for-expect@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/wait-for-expect/-/wait-for-expect-3.0.2.tgz#d2f14b2f7b778c9b82144109c8fa89ceaadaa463" + integrity sha512-cfS1+DZxuav1aBYbaO/kE06EOS8yRw7qOFoD3XtjTkYvCvh3zUvNST8DXK/nPaeqIzIv3P3kL3lRJn8iwOiSag== + walker@^1.0.7, walker@~1.0.5: version "1.0.7" resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.7.tgz#2f7f9b8fd10d677262b18a884e28d19618e028fb" @@ -15619,14 +15755,6 @@ yargs-parser@^16.1.0: camelcase "^5.0.0" decamelize "^1.2.0" -yargs-parser@^17.1.0: - version "17.1.0" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-17.1.0.tgz#b95ff3201e98b89e86070f92bef636016a0b0766" - integrity sha512-67zLl4/kWtp9eyVuxX+fHZ2Ey4ySWh0awDJlk/EtT0vzspsXbzrFsh76WjYSP3L++zhSwHQRUE3MCBe754RuEg== - dependencies: - camelcase "^5.0.0" - decamelize "^1.2.0" - yargs@13.3.0, yargs@^13.3.0: version "13.3.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.0.tgz#4c657a55e07e5f2cf947f8a366567c04a0dedc83" @@ -15661,9 +15789,9 @@ yargs@^14.2.2: yargs-parser "^15.0.0" yargs@^15.0.0: - version "15.2.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.2.0.tgz#cb9fc7f7ec429f7e9329b623f5c707a62dae506a" - integrity sha512-E+o8C37U+M7N15rBJVxr0MoInp+O7XNhMqveSGWA5uhddqs8qtkZ+uvT9FI32QML0SKidXdDONr40Xe3tDO9FA== + version "15.1.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.1.0.tgz#e111381f5830e863a89550bd4b136bb6a5f37219" + integrity sha512-T39FNN1b6hCW4SOIk1XyTOWxtXdcen0t+XYrysQmChzSipvhBO8Bj0nK1ozAasdk24dNWuMZvr4k24nz+8HHLg== dependencies: cliui "^6.0.0" decamelize "^1.2.0" @@ -15675,7 +15803,7 @@ yargs@^15.0.0: string-width "^4.2.0" which-module "^2.0.0" y18n "^4.0.0" - yargs-parser "^17.1.0" + yargs-parser "^16.1.0" yeoman-environment@^2.3.4, yeoman-environment@^2.8.0: version "2.8.0"