From 6cbf4c38296d6287fbcbb0ef5ecd21cf63606153 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barth=C3=A9l=C3=A9my=20Ledoux?= Date: Mon, 26 Jul 2021 21:26:45 -0500 Subject: [PATCH 01/14] fix: make vite re-run on supportFile change (#17485) * fix: make vite re-run on supportFile change * chore: vite - add an example of support css * fix lachlan's remarks --- npm/vite-dev-server/cypress/styles.css | 3 +++ npm/vite-dev-server/cypress/support.js | 1 + npm/vite-dev-server/src/index.ts | 6 +++--- npm/vite-dev-server/src/makeCypressPlugin.ts | 13 +++++++++---- npm/vite-dev-server/src/startServer.ts | 6 +++--- 5 files changed, 19 insertions(+), 10 deletions(-) create mode 100644 npm/vite-dev-server/cypress/styles.css diff --git a/npm/vite-dev-server/cypress/styles.css b/npm/vite-dev-server/cypress/styles.css new file mode 100644 index 000000000000..33768f9211ff --- /dev/null +++ b/npm/vite-dev-server/cypress/styles.css @@ -0,0 +1,3 @@ +body { + color: indigo; +} \ No newline at end of file diff --git a/npm/vite-dev-server/cypress/support.js b/npm/vite-dev-server/cypress/support.js index 18915a9458fc..192364e1f2b8 100644 --- a/npm/vite-dev-server/cypress/support.js +++ b/npm/vite-dev-server/cypress/support.js @@ -1,4 +1,5 @@ import '@testing-library/cypress/add-commands' +import './styles.css' before(() => { window.supportFileWasLoaded = true diff --git a/npm/vite-dev-server/src/index.ts b/npm/vite-dev-server/src/index.ts index 2d3a22978028..f5197353b5f7 100644 --- a/npm/vite-dev-server/src/index.ts +++ b/npm/vite-dev-server/src/index.ts @@ -1,8 +1,8 @@ import { debug as debugFn } from 'debug' -import { start as createDevServer, StartDevServer } from './startServer' +import { start as createDevServer, StartDevServerOptions } from './startServer' const debug = debugFn('cypress:vite-dev-server:vite') -export { StartDevServer } +export { StartDevServerOptions } type DoneCallback = () => unknown @@ -11,7 +11,7 @@ export interface ResolvedDevServerConfig { close: (done?: DoneCallback) => void } -export async function startDevServer (startDevServerArgs: StartDevServer): Promise { +export async function startDevServer (startDevServerArgs: StartDevServerOptions): Promise { const viteDevServer = await createDevServer(startDevServerArgs) const app = await viteDevServer.listen() diff --git a/npm/vite-dev-server/src/makeCypressPlugin.ts b/npm/vite-dev-server/src/makeCypressPlugin.ts index 8393d01281be..75c6f8df7ad0 100644 --- a/npm/vite-dev-server/src/makeCypressPlugin.ts +++ b/npm/vite-dev-server/src/makeCypressPlugin.ts @@ -21,8 +21,12 @@ const INIT_FILEPATH = resolve(__dirname, '../client/initCypressTests.js') const HMR_DEPENDENCY_LOOKUP_MAX_ITERATION = 50 -function getSpecsSet (specs: Spec[]) { - return new Set(specs.map((spec) => spec.absolute)) +function getSpecsPathsSet (specs: Spec[], supportFile?: string | null) { + return new Set( + supportFile + ? [...specs.map((spec) => spec.absolute), supportFile] + : specs.map((spec) => spec.absolute), + ) } interface Spec{ @@ -38,10 +42,10 @@ export const makeCypressPlugin = ( ): Plugin => { let base = '/' - let specsPathsSet = getSpecsSet(specs) + let specsPathsSet = getSpecsPathsSet(specs, supportFilePath) devServerEvents.on('dev-server:specs:changed', (specs: Spec[]) => { - specsPathsSet = getSpecsSet(specs) + specsPathsSet = getSpecsPathsSet(specs, supportFilePath) }) const posixSupportFilePath = supportFilePath ? convertPathToPosix(resolve(projectRoot, supportFilePath)) : undefined @@ -101,6 +105,7 @@ export const makeCypressPlugin = ( // as soon as we find one of the specs, we trigger the re-run of tests for (const mod of moduleImporters.values()) { + debug('handleHotUpdate - mod.file', mod.file) if (specsPathsSet.has(mod.file)) { debug('handleHotUpdate - compile success') devServerEvents.emit('dev-server:compile:success') diff --git a/npm/vite-dev-server/src/startServer.ts b/npm/vite-dev-server/src/startServer.ts index b977fd98ec95..ab2468b8e854 100644 --- a/npm/vite-dev-server/src/startServer.ts +++ b/npm/vite-dev-server/src/startServer.ts @@ -13,7 +13,7 @@ interface Options { [key: string]: unknown } -export interface StartDevServer { +export interface StartDevServerOptions { /** * the Cypress options object */ @@ -27,7 +27,7 @@ export interface StartDevServer { viteConfig?: UserConfig } -const resolveServerConfig = async ({ viteConfig, options }: StartDevServer): Promise => { +const resolveServerConfig = async ({ viteConfig, options }: StartDevServerOptions): Promise => { const { projectRoot, supportFile } = options.config const requiredOptions: InlineConfig = { @@ -66,7 +66,7 @@ const resolveServerConfig = async ({ viteConfig, options }: StartDevServer): Pro return finalConfig } -export async function start (devServerOptions: StartDevServer): Promise { +export async function start (devServerOptions: StartDevServerOptions): Promise { if (!devServerOptions.viteConfig) { debug('User did not pass in any Vite dev server configuration') devServerOptions.viteConfig = {} From ae0f8aa8c251f87738cc6e5c3dd8f155ceb9bfa6 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Mon, 26 Jul 2021 22:42:25 -0400 Subject: [PATCH 02/14] chore: release @cypress/vite-dev-server-v2.0.3 [skip ci] --- npm/vite-dev-server/CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/npm/vite-dev-server/CHANGELOG.md b/npm/vite-dev-server/CHANGELOG.md index d8a885c0723e..5990fb6b482f 100644 --- a/npm/vite-dev-server/CHANGELOG.md +++ b/npm/vite-dev-server/CHANGELOG.md @@ -1,3 +1,10 @@ +# [@cypress/vite-dev-server-v2.0.3](https://github.com/cypress-io/cypress/compare/@cypress/vite-dev-server-v2.0.2...@cypress/vite-dev-server-v2.0.3) (2021-07-27) + + +### Bug Fixes + +* make vite re-run on supportFile change ([#17485](https://github.com/cypress-io/cypress/issues/17485)) ([6cbf4c3](https://github.com/cypress-io/cypress/commit/6cbf4c38296d6287fbcbb0ef5ecd21cf63606153)) + # [@cypress/vite-dev-server-v2.0.2](https://github.com/cypress-io/cypress/compare/@cypress/vite-dev-server-v2.0.1...@cypress/vite-dev-server-v2.0.2) (2021-07-15) From 90882a953731f55715f9fd65f954e497f61d23ed Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Mon, 26 Jul 2021 22:42:43 -0400 Subject: [PATCH 03/14] chore: release @cypress/vue-v3.0.0-beta.4 [skip ci] --- npm/vue/CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/npm/vue/CHANGELOG.md b/npm/vue/CHANGELOG.md index 54d3c19ebb5e..fe7df62caa44 100644 --- a/npm/vue/CHANGELOG.md +++ b/npm/vue/CHANGELOG.md @@ -1,3 +1,10 @@ +# [@cypress/vue-v3.0.0-beta.4](https://github.com/cypress-io/cypress/compare/@cypress/vue-v3.0.0-beta.3...@cypress/vue-v3.0.0-beta.4) (2021-07-27) + + +### Bug Fixes + +* do not register CT specific event in e2e mode ([5836203](https://github.com/cypress-io/cypress/commit/58362037fd231c6fdc587e422fc139bf7546ac2d)) + # [@cypress/vue-v3.0.0-beta.3](https://github.com/cypress-io/cypress/compare/@cypress/vue-v3.0.0-beta.2...@cypress/vue-v3.0.0-beta.3) (2021-06-24) From 1e9383db225f0b4bab44a9abcecef0b0193e6a16 Mon Sep 17 00:00:00 2001 From: Tim Griesser Date: Wed, 28 Jul 2021 12:29:35 -0400 Subject: [PATCH 04/14] fix: test runner reporter performance (#17243) Increase performance of test execution by removing lazy initial rendering of runnables, as well as custom styling of the reporter scrollbar --- .../cypress/integration/test_errors_spec.ts | 36 ++++++++++--------- .../integration/unit/runnables_store_spec.ts | 7 ---- packages/reporter/src/lib/base.scss | 13 ------- .../src/runnables/runnable-and-suite.tsx | 2 -- .../reporter/src/runnables/runnable-model.ts | 1 - .../reporter/src/runnables/runnables-store.ts | 20 +---------- packages/reporter/src/test/test.tsx | 6 ++-- .../server/test/e2e/5_screenshots_spec.js | 4 +-- 8 files changed, 25 insertions(+), 64 deletions(-) diff --git a/packages/reporter/cypress/integration/test_errors_spec.ts b/packages/reporter/cypress/integration/test_errors_spec.ts index 2adbeb44ad5f..0c1f6337421b 100644 --- a/packages/reporter/cypress/integration/test_errors_spec.ts +++ b/packages/reporter/cypress/integration/test_errors_spec.ts @@ -247,28 +247,12 @@ describe('test errors', () => { cy.percySnapshot() }) - it('does not show code frame when not included on error', () => { - commandErr.codeFrame = undefined - - cy - .get('.test-err-code-frame') - .should('not.exist') - }) - it('use correct language class', () => { cy .get('.test-err-code-frame pre') .should('have.class', 'language-javascript') }) - it('falls back to text language class', () => { - // @ts-ignore - commandErr.codeFrame.language = null - cy - .get('.test-err-code-frame pre') - .should('have.class', 'language-text') - }) - it('displays tooltip on hover', () => { cy.get('.test-err-code-frame a').first().trigger('mouseover') cy.get('.cy-tooltip').first().should('have.text', 'Open in IDE') @@ -285,6 +269,26 @@ describe('test errors', () => { }) }) + describe('code frames', () => { + it('does not show code frame when not included on error', () => { + commandErr.codeFrame = undefined + setError(commandErr) + + cy + .get('.test-err-code-frame') + .should('not.exist') + }) + + it('falls back to text language class', () => { + // @ts-ignore + commandErr.codeFrame.language = null + setError(commandErr) + cy + .get('.test-err-code-frame pre') + .should('have.class', 'language-text') + }) + }) + describe('studio error', () => { beforeEach(() => { setError(runnablesWithErr) diff --git a/packages/reporter/cypress/integration/unit/runnables_store_spec.ts b/packages/reporter/cypress/integration/unit/runnables_store_spec.ts index 53f2afa7fff9..e66dba0e3f97 100644 --- a/packages/reporter/cypress/integration/unit/runnables_store_spec.ts +++ b/packages/reporter/cypress/integration/unit/runnables_store_spec.ts @@ -158,13 +158,6 @@ describe('runnables store', () => { expect(instance.hasSingleTest).to.be.false }) - it('starts rendering the runnables on requestAnimationFrame', () => { - instance.setRunnables({ tests: [], suites: [createSuite('1', [], []), createSuite('2', [createTest('1')], [])] }) - expect(instance.runnables[0].shouldRender).to.be.true - expect(instance.runnables[1].shouldRender).to.be.true - expect((instance.runnables[1] as SuiteModel).children[0].shouldRender).to.be.true - }) - it('sets scrollTop when app is running and initial scrollTop has been set', () => { instance.setInitialScrollTop(234) instance.setRunnables({}) diff --git a/packages/reporter/src/lib/base.scss b/packages/reporter/src/lib/base.scss index 6f60ed3065e4..1be3a7473ac0 100644 --- a/packages/reporter/src/lib/base.scss +++ b/packages/reporter/src/lib/base.scss @@ -16,19 +16,6 @@ body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input box-sizing: border-box; } - ::-webkit-scrollbar { - width: 10px; - height: 10px; - } - - ::-webkit-scrollbar-thumb { - background: #999; - } - - ::-webkit-scrollbar-track { - background: #DDD; - } - &, input, textarea { diff --git a/packages/reporter/src/runnables/runnable-and-suite.tsx b/packages/reporter/src/runnables/runnable-and-suite.tsx index 66f3939057c9..53c173ada7ca 100644 --- a/packages/reporter/src/runnables/runnable-and-suite.tsx +++ b/packages/reporter/src/runnables/runnable-and-suite.tsx @@ -21,8 +21,6 @@ interface SuiteProps { } const Suite = observer(({ eventManager = events, model }: SuiteProps) => { - if (!model.shouldRender) return null - const _launchStudio = (e: MouseEvent) => { e.preventDefault() e.stopPropagation() diff --git a/packages/reporter/src/runnables/runnable-model.ts b/packages/reporter/src/runnables/runnable-model.ts index 5c6ae09d85ae..89241bef86f6 100644 --- a/packages/reporter/src/runnables/runnable-model.ts +++ b/packages/reporter/src/runnables/runnable-model.ts @@ -9,7 +9,6 @@ export interface RunnableProps { export default class Runnable { @observable id: string - @observable shouldRender: boolean = false @observable title?: string @observable level: number @observable hooks: Array = [] diff --git a/packages/reporter/src/runnables/runnables-store.ts b/packages/reporter/src/runnables/runnables-store.ts index f80065e8594e..449a545347d3 100644 --- a/packages/reporter/src/runnables/runnables-store.ts +++ b/packages/reporter/src/runnables/runnables-store.ts @@ -81,7 +81,7 @@ export class RunnablesStore { this.hasTests = numTests > 0 this.hasSingleTest = numTests === 1 - this._startRendering() + this._finishedInitialRendering() } _createRunnableChildren (runnableProps: RootRunnable, level: number) { @@ -120,24 +120,6 @@ export class RunnablesStore { return test } - // progressively renders the runnables instead of all of them being rendered - // at once. this prevents a noticeable lag in initial rendering when there - // is a large number of tests - _startRendering (index = 0) { - requestAnimationFrame(action('start:rendering', () => { - const runnable = this._runnablesQueue[index] - - if (!runnable) { - this._finishedInitialRendering() - - return - } - - runnable.shouldRender = true - this._startRendering(index + 1) - })) - } - _finishedInitialRendering () { if (this.appState.isRunning) { // have an initial scrollTop set, meaning we reloaded from a domain change diff --git a/packages/reporter/src/test/test.tsx b/packages/reporter/src/test/test.tsx index b0252ca171b9..bc3ec513e306 100644 --- a/packages/reporter/src/test/test.tsx +++ b/packages/reporter/src/test/test.tsx @@ -126,9 +126,9 @@ class Test extends Component { _scrollIntoView () { const { appState, model, scroller } = this.props - const { state, shouldRender } = model + const { state } = model - if (appState.autoScrollingEnabled && (appState.isRunning || appState.studioActive) && shouldRender && state !== 'processing') { + if (appState.autoScrollingEnabled && (appState.isRunning || appState.studioActive) && state !== 'processing') { window.requestAnimationFrame(() => { // since this executes async in a RAF the ref might be null if (this.containerRef.current) { @@ -141,8 +141,6 @@ class Test extends Component { render () { const { model } = this.props - if (!model.shouldRender) return null - return ( { // make sure all of the values are unique expect(sizes).to.deep.eq(_.uniq(sizes)) - // png1 should not be within 3k of png2 - expect(sizes[0]).not.to.be.closeTo(sizes[1], 3000) + // png1 should not be within 1k of png2 + expect(sizes[0]).not.to.be.closeTo(sizes[1], 1000) }).then(() => { return Promise.all([ sizeOf(screenshot1), From f82844e3d30e1cac788092bca90725620f25b8e4 Mon Sep 17 00:00:00 2001 From: Lachlan Miller Date: Fri, 30 Jul 2021 00:10:26 +1000 Subject: [PATCH 05/14] chore(npm/webpack-preprocessor): fix CI pipeline (#17515) * chore: fix test script * update script * revert file * run webpack 4/5 compat tests last * update snapshots for webpack 5 --- circle.yml | 6 +++--- npm/webpack-preprocessor/__snapshots__/compilation.spec.js | 4 ++-- npm/webpack-preprocessor/package.json | 2 +- .../{test-webpack-4-5.js => test-webpack-5.js} | 0 4 files changed, 6 insertions(+), 6 deletions(-) rename npm/webpack-preprocessor/{test-webpack-4-5.js => test-webpack-5.js} (100%) diff --git a/circle.yml b/circle.yml index 497ff70bdb70..0788d724d8dd 100644 --- a/circle.yml +++ b/circle.yml @@ -1270,9 +1270,6 @@ jobs: - run: name: Build command: yarn workspace @cypress/webpack-preprocessor build - - run: - name: Run tests - command: yarn workspace @cypress/webpack-preprocessor test - run: name: Test babelrc command: yarn test @@ -1298,6 +1295,9 @@ jobs: name: Test React app command: yarn test working_directory: npm/webpack-preprocessor/examples/react-app + - run: + name: Run tests + command: yarn workspace @cypress/webpack-preprocessor test - store-npm-logs npm-webpack-dev-server: diff --git a/npm/webpack-preprocessor/__snapshots__/compilation.spec.js b/npm/webpack-preprocessor/__snapshots__/compilation.spec.js index 4a834171bff1..20c347c230c1 100644 --- a/npm/webpack-preprocessor/__snapshots__/compilation.spec.js +++ b/npm/webpack-preprocessor/__snapshots__/compilation.spec.js @@ -1,6 +1,6 @@ exports['webpack preprocessor - e2e correctly preprocesses the file 1'] = ` it("is a test",(function(){expect(1).to.equal(1),expect(2).to.equal(2),expect(Math.min.apply(Math,[3,4])).to.equal(3)})); -//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9AY3lwcmVzcy93ZWJwYWNrLXByZXByb2Nlc3Nvci8uL3Rlc3QvX3Rlc3Qtb3V0cHV0L2V4YW1wbGVfc3BlYy5qcyJdLCJuYW1lcyI6WyJpdCIsImV4cGVjdCIsInRvIiwiZXF1YWwiLCJNYXRoIiwibWluIl0sIm1hcHBpbmdzIjoiQUFBQUEsR0FBRyxhQUFhLFdBR2RDLE9BRmdCLEdBRU5DLEdBQUdDLE1BQU0sR0FDbkJGLE9BSG1CLEdBR1RDLEdBQUdDLE1BQU0sR0FDbkJGLE9BQU9HLEtBQUtDLElBQUwsTUFBQUQsS0FBWSxDQUFDLEVBQUcsS0FBS0YsR0FBR0MsTUFBTSIsImZpbGUiOiJleGFtcGxlX3NwZWNfb3V0cHV0LmpzIiwic291cmNlc0NvbnRlbnQiOlsiaXQoJ2lzIGEgdGVzdCcsICgpID0+IHtcbiAgY29uc3QgW2EsIGJdID0gWzEsIDJdXG5cbiAgZXhwZWN0KGEpLnRvLmVxdWFsKDEpXG4gIGV4cGVjdChiKS50by5lcXVhbCgyKVxuICBleHBlY3QoTWF0aC5taW4oLi4uWzMsIDRdKSkudG8uZXF1YWwoMylcbn0pXG4iXSwic291cmNlUm9vdCI6IiJ9 +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXhhbXBsZV9zcGVjX291dHB1dC5qcyIsIm1hcHBpbmdzIjoiQUFBQUEsR0FBRyxhQUFhLFdBR2RDLE9BRmdCLEdBRU5DLEdBQUdDLE1BQU0sR0FDbkJGLE9BSG1CLEdBR1RDLEdBQUdDLE1BQU0sR0FDbkJGLE9BQU9HLEtBQUtDLElBQUwsTUFBQUQsS0FBWSxDQUFDLEVBQUcsS0FBS0YsR0FBR0MsTUFBTSIsInNvdXJjZXMiOlsid2VicGFjazovL0BjeXByZXNzL3dlYnBhY2stcHJlcHJvY2Vzc29yLy4vdGVzdC9fdGVzdC1vdXRwdXQvZXhhbXBsZV9zcGVjLmpzIl0sInNvdXJjZXNDb250ZW50IjpbIml0KCdpcyBhIHRlc3QnLCAoKSA9PiB7XG4gIGNvbnN0IFthLCBiXSA9IFsxLCAyXVxuXG4gIGV4cGVjdChhKS50by5lcXVhbCgxKVxuICBleHBlY3QoYikudG8uZXF1YWwoMilcbiAgZXhwZWN0KE1hdGgubWluKC4uLlszLCA0XSkpLnRvLmVxdWFsKDMpXG59KVxuIl0sIm5hbWVzIjpbIml0IiwiZXhwZWN0IiwidG8iLCJlcXVhbCIsIk1hdGgiLCJtaW4iXSwic291cmNlUm9vdCI6IiJ9 ` exports['webpack preprocessor - e2e has less verbose syntax error 1'] = ` @@ -16,4 +16,4 @@ SyntaxError: /_test-output/syntax_error_spec.js: Unexpected token (1:18) exports['webpack preprocessor - e2e has less verbose "Module not found" error 1'] = ` Webpack Compilation Error Module not found: Error: Can't resolve './does/not-exist' in '/_test-output' -` \ No newline at end of file +` diff --git a/npm/webpack-preprocessor/package.json b/npm/webpack-preprocessor/package.json index c885ee0acbd2..59e8ea31e898 100644 --- a/npm/webpack-preprocessor/package.json +++ b/npm/webpack-preprocessor/package.json @@ -11,7 +11,7 @@ "secure": "nsp check", "semantic-release": "semantic-release", "size": "npm pack --dry", - "test": "node ./test-webpack-4-5.js", + "test": "node ./test-webpack-5.js", "test-debug": "node --inspect --debug-brk ./node_modules/.bin/_mocha", "test-e2e": "mocha test/e2e/*.spec.*", "test-unit": "mocha test/unit/*.spec.*", diff --git a/npm/webpack-preprocessor/test-webpack-4-5.js b/npm/webpack-preprocessor/test-webpack-5.js similarity index 100% rename from npm/webpack-preprocessor/test-webpack-4-5.js rename to npm/webpack-preprocessor/test-webpack-5.js From a5305de5e4a47b0bc7c47419ef0b19cfa7ff6e18 Mon Sep 17 00:00:00 2001 From: Zach Bloomquist Date: Thu, 29 Jul 2021 10:12:13 -0400 Subject: [PATCH 06/14] fix(types): update cy.shadow docs url (#17506) --- cli/types/cypress.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/types/cypress.d.ts b/cli/types/cypress.d.ts index e4639053aec7..74c9d2450181 100644 --- a/cli/types/cypress.d.ts +++ b/cli/types/cypress.d.ts @@ -1661,7 +1661,7 @@ declare namespace Cypress { * .shadow() * .find('.my-button') * .click() - * @see https://on.cypress.io/experimental + * @see https://on.cypress.io/shadow */ shadow(): Chainable From e49b3a4b9fc99bb392235b7cad36139faff08eec Mon Sep 17 00:00:00 2001 From: Lachlan Miller Date: Fri, 30 Jul 2021 01:23:12 +1000 Subject: [PATCH 07/14] fix(server): correctly include projectRoot when adding a CI project from GUI (#17514) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Barthélémy Ledoux Co-authored-by: semantic-release-bot Co-authored-by: Jennifer Shehane Co-authored-by: Chris Breiding --- npm/vite-dev-server/CHANGELOG.md | 7 ++++++ npm/vite-dev-server/cypress/styles.css | 3 +++ npm/vite-dev-server/cypress/support.js | 1 + npm/vite-dev-server/src/index.ts | 6 ++--- npm/vite-dev-server/src/makeCypressPlugin.ts | 13 ++++++---- npm/vite-dev-server/src/startServer.ts | 6 ++--- npm/vue/CHANGELOG.md | 7 ++++++ .../cypress/integration/setup_project_spec.js | 6 +++-- .../dashboard-projects-api.js | 4 ++-- packages/desktop-gui/src/runs/runs-list.jsx | 4 ++-- .../desktop-gui/src/runs/setup-project.jsx | 3 ++- packages/server/lib/gui/events.js | 4 ++-- packages/server/lib/project_static.ts | 1 + packages/server/test/unit/gui/events_spec.js | 24 +++++++++++++++++-- 14 files changed, 68 insertions(+), 21 deletions(-) create mode 100644 npm/vite-dev-server/cypress/styles.css diff --git a/npm/vite-dev-server/CHANGELOG.md b/npm/vite-dev-server/CHANGELOG.md index d8a885c0723e..5990fb6b482f 100644 --- a/npm/vite-dev-server/CHANGELOG.md +++ b/npm/vite-dev-server/CHANGELOG.md @@ -1,3 +1,10 @@ +# [@cypress/vite-dev-server-v2.0.3](https://github.com/cypress-io/cypress/compare/@cypress/vite-dev-server-v2.0.2...@cypress/vite-dev-server-v2.0.3) (2021-07-27) + + +### Bug Fixes + +* make vite re-run on supportFile change ([#17485](https://github.com/cypress-io/cypress/issues/17485)) ([6cbf4c3](https://github.com/cypress-io/cypress/commit/6cbf4c38296d6287fbcbb0ef5ecd21cf63606153)) + # [@cypress/vite-dev-server-v2.0.2](https://github.com/cypress-io/cypress/compare/@cypress/vite-dev-server-v2.0.1...@cypress/vite-dev-server-v2.0.2) (2021-07-15) diff --git a/npm/vite-dev-server/cypress/styles.css b/npm/vite-dev-server/cypress/styles.css new file mode 100644 index 000000000000..33768f9211ff --- /dev/null +++ b/npm/vite-dev-server/cypress/styles.css @@ -0,0 +1,3 @@ +body { + color: indigo; +} \ No newline at end of file diff --git a/npm/vite-dev-server/cypress/support.js b/npm/vite-dev-server/cypress/support.js index 18915a9458fc..192364e1f2b8 100644 --- a/npm/vite-dev-server/cypress/support.js +++ b/npm/vite-dev-server/cypress/support.js @@ -1,4 +1,5 @@ import '@testing-library/cypress/add-commands' +import './styles.css' before(() => { window.supportFileWasLoaded = true diff --git a/npm/vite-dev-server/src/index.ts b/npm/vite-dev-server/src/index.ts index 2d3a22978028..f5197353b5f7 100644 --- a/npm/vite-dev-server/src/index.ts +++ b/npm/vite-dev-server/src/index.ts @@ -1,8 +1,8 @@ import { debug as debugFn } from 'debug' -import { start as createDevServer, StartDevServer } from './startServer' +import { start as createDevServer, StartDevServerOptions } from './startServer' const debug = debugFn('cypress:vite-dev-server:vite') -export { StartDevServer } +export { StartDevServerOptions } type DoneCallback = () => unknown @@ -11,7 +11,7 @@ export interface ResolvedDevServerConfig { close: (done?: DoneCallback) => void } -export async function startDevServer (startDevServerArgs: StartDevServer): Promise { +export async function startDevServer (startDevServerArgs: StartDevServerOptions): Promise { const viteDevServer = await createDevServer(startDevServerArgs) const app = await viteDevServer.listen() diff --git a/npm/vite-dev-server/src/makeCypressPlugin.ts b/npm/vite-dev-server/src/makeCypressPlugin.ts index ff791dfd5c38..fc177ccbc912 100644 --- a/npm/vite-dev-server/src/makeCypressPlugin.ts +++ b/npm/vite-dev-server/src/makeCypressPlugin.ts @@ -21,8 +21,12 @@ const INIT_FILEPATH = resolve(__dirname, '../client/initCypressTests.js') const HMR_DEPENDENCY_LOOKUP_MAX_ITERATION = 50 -function getSpecsSet (specs: Spec[]) { - return new Set(specs.map((spec) => spec.absolute)) +function getSpecsPathsSet (specs: Spec[], supportFile?: string | null) { + return new Set( + supportFile + ? [...specs.map((spec) => spec.absolute), supportFile] + : specs.map((spec) => spec.absolute), + ) } interface Spec{ @@ -38,10 +42,10 @@ export const makeCypressPlugin = ( ): Plugin => { let base = '/' - let specsPathsSet = getSpecsSet(specs) + let specsPathsSet = getSpecsPathsSet(specs, supportFilePath) devServerEvents.on('dev-server:specs:changed', (specs: Spec[]) => { - specsPathsSet = getSpecsSet(specs) + specsPathsSet = getSpecsPathsSet(specs, supportFilePath) }) const posixSupportFilePath = supportFilePath ? convertPathToPosix(resolve(projectRoot, supportFilePath)) : undefined @@ -101,6 +105,7 @@ export const makeCypressPlugin = ( // as soon as we find one of the specs, we trigger the re-run of tests for (const mod of moduleImporters.values()) { + debug('handleHotUpdate - mod.file', mod.file) if (specsPathsSet.has(mod.file)) { debug('handleHotUpdate - compile success') devServerEvents.emit('dev-server:compile:success', { specFile: mod.file }) diff --git a/npm/vite-dev-server/src/startServer.ts b/npm/vite-dev-server/src/startServer.ts index b977fd98ec95..ab2468b8e854 100644 --- a/npm/vite-dev-server/src/startServer.ts +++ b/npm/vite-dev-server/src/startServer.ts @@ -13,7 +13,7 @@ interface Options { [key: string]: unknown } -export interface StartDevServer { +export interface StartDevServerOptions { /** * the Cypress options object */ @@ -27,7 +27,7 @@ export interface StartDevServer { viteConfig?: UserConfig } -const resolveServerConfig = async ({ viteConfig, options }: StartDevServer): Promise => { +const resolveServerConfig = async ({ viteConfig, options }: StartDevServerOptions): Promise => { const { projectRoot, supportFile } = options.config const requiredOptions: InlineConfig = { @@ -66,7 +66,7 @@ const resolveServerConfig = async ({ viteConfig, options }: StartDevServer): Pro return finalConfig } -export async function start (devServerOptions: StartDevServer): Promise { +export async function start (devServerOptions: StartDevServerOptions): Promise { if (!devServerOptions.viteConfig) { debug('User did not pass in any Vite dev server configuration') devServerOptions.viteConfig = {} diff --git a/npm/vue/CHANGELOG.md b/npm/vue/CHANGELOG.md index 54d3c19ebb5e..fe7df62caa44 100644 --- a/npm/vue/CHANGELOG.md +++ b/npm/vue/CHANGELOG.md @@ -1,3 +1,10 @@ +# [@cypress/vue-v3.0.0-beta.4](https://github.com/cypress-io/cypress/compare/@cypress/vue-v3.0.0-beta.3...@cypress/vue-v3.0.0-beta.4) (2021-07-27) + + +### Bug Fixes + +* do not register CT specific event in e2e mode ([5836203](https://github.com/cypress-io/cypress/commit/58362037fd231c6fdc587e422fc139bf7546ac2d)) + # [@cypress/vue-v3.0.0-beta.3](https://github.com/cypress-io/cypress/compare/@cypress/vue-v3.0.0-beta.2...@cypress/vue-v3.0.0-beta.3) (2021-06-24) diff --git a/packages/desktop-gui/cypress/integration/setup_project_spec.js b/packages/desktop-gui/cypress/integration/setup_project_spec.js index 130513e72abd..bc1b5b534549 100644 --- a/packages/desktop-gui/cypress/integration/setup_project_spec.js +++ b/packages/desktop-gui/cypress/integration/setup_project_spec.js @@ -4,6 +4,7 @@ const onSubmitNewProject = function (orgId) { .contains('.btn', 'Set up project').click() .then(() => { expect(this.ipc.setupDashboardProject).to.be.calledWith({ + projectRoot: '/foo/bar', projectName: this.config.projectName, orgId, public: false, @@ -21,6 +22,7 @@ const onSubmitNewProject = function (orgId) { .then(() => { expect(this.ipc.setupDashboardProject).to.be.calledWith({ projectName: 'New Project', + projectRoot: '/foo/bar', orgId, public: true, }) @@ -114,7 +116,7 @@ describe('Connect to Dashboard', function () { cy.stub(this.ipc, 'getRecordKeys').resolves(this.keys) cy.stub(this.ipc, 'pingApiServer').resolves() cy.stub(this.ipc, 'externalOpen') - cy.stub(this.ipc, 'setProjectId').resolvesArg(0) + cy.stub(this.ipc, 'setProjectId').callsFake((arg) => Promise.resolve(arg.id)) cy.stub(this.ipc, 'beginAuth').resolves() this.getCurrentUser = this.util.deferred() @@ -485,7 +487,7 @@ describe('Connect to Dashboard', function () { cy.get('.setup-project') .contains('.btn', 'Set up project').click() .then(() => { - expect(this.ipc.setProjectId).to.be.calledWith(this.dashboardProjects[1].id) + expect(this.ipc.setProjectId).to.be.calledWith({ id: this.dashboardProjects[1].id, projectRoot: '/foo/bar' }) }) }) diff --git a/packages/desktop-gui/src/dashboard-projects/dashboard-projects-api.js b/packages/desktop-gui/src/dashboard-projects/dashboard-projects-api.js index d437739d819b..42d6534ec190 100644 --- a/packages/desktop-gui/src/dashboard-projects/dashboard-projects-api.js +++ b/packages/desktop-gui/src/dashboard-projects/dashboard-projects-api.js @@ -45,8 +45,8 @@ const setupDashboardProject = (projectDetails) => { .catch(ipc.isUnauthed, ipc.handleUnauthed) } -const setProjectId = (id) => { - return ipc.setProjectId(id) +const setProjectId = (id, projectRoot) => { + return ipc.setProjectId({ id, projectRoot }) } export default { diff --git a/packages/desktop-gui/src/runs/runs-list.jsx b/packages/desktop-gui/src/runs/runs-list.jsx index 13bb56636ae3..f353d24242a9 100644 --- a/packages/desktop-gui/src/runs/runs-list.jsx +++ b/packages/desktop-gui/src/runs/runs-list.jsx @@ -108,8 +108,8 @@ class RunsList extends Component { _getRecordKeys () { if (this._needsKey()) { - projectsApi.getRecordKeys().then((keys = []) => { - if (keys.length) { + projectsApi.getRecordKeys().then((keys) => { + if (keys && keys.length) { this.setState({ recordKey: keys[0].id }) } }) diff --git a/packages/desktop-gui/src/runs/setup-project.jsx b/packages/desktop-gui/src/runs/setup-project.jsx index c5f5f5744529..3f9db844f857 100644 --- a/packages/desktop-gui/src/runs/setup-project.jsx +++ b/packages/desktop-gui/src/runs/setup-project.jsx @@ -375,12 +375,13 @@ class SetupProject extends Component { if (this.state.newProject) { return dashboardProjectsApi.setupDashboardProject({ projectName: this.state.projectName, + projectRoot: this.props.project.path, orgId: this.state.selectedOrgId, public: this.state.public, }) } - return dashboardProjectsApi.setProjectId(this.state.selectedProjectId) + return dashboardProjectsApi.setProjectId(this.state.selectedProjectId, this.props.project.path) .then((id) => { const project = dashboardProjectsStore.getProjectById(id) diff --git a/packages/server/lib/gui/events.js b/packages/server/lib/gui/events.js index f8e2b7eb814f..636f2f0cfc8f 100644 --- a/packages/server/lib/gui/events.js +++ b/packages/server/lib/gui/events.js @@ -332,12 +332,12 @@ const handleEvent = function (options, bus, event, id, type, arg) { .catch(sendErr) case 'setup:dashboard:project': - return ProjectStatic.createCiProject(arg, options.projectRoot) + return ProjectStatic.createCiProject(arg, arg.projectRoot) .then(send) .catch(sendErr) case 'set:project:id': - return ProjectStatic.writeProjectId(arg, options.projectRoot) + return ProjectStatic.writeProjectId(arg.id, arg.projectRoot) .then(send) .catch(sendErr) diff --git a/packages/server/lib/project_static.ts b/packages/server/lib/project_static.ts index 10dde6ce9b18..4768d913a303 100644 --- a/packages/server/lib/project_static.ts +++ b/packages/server/lib/project_static.ts @@ -177,6 +177,7 @@ export async function writeProjectId (id: string, projectRoot: string) { interface ProjectDetails { projectName: string + projectRoot: string orgId: string | null public: boolean } diff --git a/packages/server/test/unit/gui/events_spec.js b/packages/server/test/unit/gui/events_spec.js index 6d8a80e2dece..9c469be9136e 100644 --- a/packages/server/test/unit/gui/events_spec.js +++ b/packages/server/test/unit/gui/events_spec.js @@ -923,9 +923,28 @@ describe('lib/gui/events', () => { }) }) + describe('set:project:id', () => { + it('calls writeProjectId with projectRoot', function () { + const arg = { id: '1', projectRoot: '/project/root/' } + const stub = sinon.stub(ProjectStatic, 'writeProjectId').resolves() + + return this.handleEvent('set:project:id', arg) + .then(() => { + expect(stub).to.be.calledWith(arg.id, arg.projectRoot) + expect(this.send.firstCall.args[0]).to.eq('response') + expect(this.send.firstCall.args[1].id).to.match(/set:project:id-/) + }) + }) + }) + describe('setup:dashboard:project', () => { it('returns result of ProjectStatic.createCiProject', function () { - return this.handleEvent('setup:dashboard:project').then((assert) => { + const arg = { projectRoot: '/project/root/' } + const stub = sinon.stub(ProjectStatic, 'createCiProject').resolves() + + return this.handleEvent('setup:dashboard:project', arg) + .then(() => { + expect(stub).to.be.calledWith(arg, arg.projectRoot) expect(this.send.firstCall.args[0]).to.eq('response') expect(this.send.firstCall.args[1].id).to.match(/setup:dashboard:project-/) }) @@ -936,7 +955,8 @@ describe('lib/gui/events', () => { sinon.stub(ProjectStatic, 'createCiProject').rejects(err) - return this.handleEvent('setup:dashboard:project').then((assert) => { + return this.handleEvent('setup:dashboard:project', { projectRoot: '/foo/bar' }) + .then((assert) => { return assert.sendErrCalledWith(err) }) }) From f4ac2735124f7c6a0d560a964f862635d5958d44 Mon Sep 17 00:00:00 2001 From: Chris Breiding Date: Thu, 29 Jul 2021 13:23:08 -0400 Subject: [PATCH 08/14] release 8.1.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5bc9325f88c2..f987d56a00c6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cypress", - "version": "8.0.0", + "version": "8.1.0", "description": "Cypress.io end to end testing tool", "private": true, "scripts": { From 13f792c70e7e825c40889aca58916b4a94bddada Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barth=C3=A9l=C3=A9my=20Ledoux?= Date: Thu, 29 Jul 2021 14:24:40 -0500 Subject: [PATCH 09/14] build: make vite build strict (#17509) --- npm/vite-dev-server/src/index.ts | 4 ++-- npm/vite-dev-server/src/makeCypressPlugin.ts | 2 +- npm/vite-dev-server/src/startServer.ts | 2 +- npm/vite-dev-server/tsconfig.json | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/npm/vite-dev-server/src/index.ts b/npm/vite-dev-server/src/index.ts index f5197353b5f7..0e063347bdb2 100644 --- a/npm/vite-dev-server/src/index.ts +++ b/npm/vite-dev-server/src/index.ts @@ -15,9 +15,9 @@ export async function startDevServer (startDevServerArgs: StartDevServerOptions) const viteDevServer = await createDevServer(startDevServerArgs) const app = await viteDevServer.listen() - const port = app.config.server.port + const port = app.config.server.port! debug('Component testing vite server started on port', port) - return { port, close: app.httpServer.close } + return { port, close: app.httpServer!.close } } diff --git a/npm/vite-dev-server/src/makeCypressPlugin.ts b/npm/vite-dev-server/src/makeCypressPlugin.ts index fc177ccbc912..5b908253cabd 100644 --- a/npm/vite-dev-server/src/makeCypressPlugin.ts +++ b/npm/vite-dev-server/src/makeCypressPlugin.ts @@ -106,7 +106,7 @@ export const makeCypressPlugin = ( // as soon as we find one of the specs, we trigger the re-run of tests for (const mod of moduleImporters.values()) { debug('handleHotUpdate - mod.file', mod.file) - if (specsPathsSet.has(mod.file)) { + if (mod.file && specsPathsSet.has(mod.file)) { debug('handleHotUpdate - compile success') devServerEvents.emit('dev-server:compile:success', { specFile: mod.file }) diff --git a/npm/vite-dev-server/src/startServer.ts b/npm/vite-dev-server/src/startServer.ts index ab2468b8e854..c2b1758de31e 100644 --- a/npm/vite-dev-server/src/startServer.ts +++ b/npm/vite-dev-server/src/startServer.ts @@ -37,7 +37,7 @@ const resolveServerConfig = async ({ viteConfig, options }: StartDevServerOption const finalConfig: InlineConfig = { ...viteConfig, ...requiredOptions } - finalConfig.plugins = [...(viteConfig.plugins || []), makeCypressPlugin(projectRoot, supportFile, options.devServerEvents, options.specs)] + finalConfig.plugins = [...(finalConfig.plugins || []), makeCypressPlugin(projectRoot, supportFile, options.devServerEvents, options.specs)] // This alias is necessary to avoid a "prefixIdentifiers" issue from slots mounting // only cjs compiler-core accepts using prefixIdentifiers in slots which vue test utils use. diff --git a/npm/vite-dev-server/tsconfig.json b/npm/vite-dev-server/tsconfig.json index f63cf8e16f78..e194d3002e04 100644 --- a/npm/vite-dev-server/tsconfig.json +++ b/npm/vite-dev-server/tsconfig.json @@ -24,7 +24,7 @@ // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ /* Strict Type-Checking Options */ - "strict": false /* Enable all strict type-checking options. */, + "strict": true, /* Enable all strict type-checking options. */ "noImplicitAny": false, /* Module Resolution Options */ From 209efa433d5dfe3efbaf141c231faea3fe44785c Mon Sep 17 00:00:00 2001 From: Zach Bloomquist Date: Fri, 30 Jul 2021 12:05:17 -0400 Subject: [PATCH 10/14] fix: use process.geteuid and catch uid errors in file util (#17488) Co-authored-by: Jennifer Shehane --- .eslintrc.json | 15 ++++++++++++++- cli/test/lib/tasks/verify_spec.js | 1 + packages/electron/lib/electron.js | 1 + packages/server/.eslintrc.json | 2 +- packages/server/lib/util/file.js | 13 ++++++++++++- packages/server/test/e2e/2_cookies_spec.ts | 1 + packages/server/test/integration/cypress_spec.js | 1 + .../cypress/plugins/index.js | 1 + 8 files changed, 32 insertions(+), 3 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index 7e35a14aabd1..91bb4cfa7ee7 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -9,7 +9,20 @@ "rules": { "prefer-spread": "off", "prefer-rest-params": "off", - "no-useless-constructor": "off" + "no-useless-constructor": "off", + "no-restricted-properties": [ + "error", + { + "object": "process", + "property": "geteuid", + "message": "process.geteuid() will throw on Windows. Do not use it unless you catch any potential errors." + }, + { + "object": "os", + "property": "userInfo", + "message": "os.userInfo() will throw when there is not an `/etc/passwd` entry for the current user (like when running with --user 12345 in Docker). Do not use it unless you catch any potential errors." + } + ] }, "settings": { "react": { diff --git a/cli/test/lib/tasks/verify_spec.js b/cli/test/lib/tasks/verify_spec.js index f1f324c85f7f..80ce2daca7c8 100644 --- a/cli/test/lib/tasks/verify_spec.js +++ b/cli/test/lib/tasks/verify_spec.js @@ -1,3 +1,4 @@ +/* eslint-disable no-restricted-properties */ require('../../spec_helper') const path = require('path') diff --git a/packages/electron/lib/electron.js b/packages/electron/lib/electron.js index 686b4a921713..f2b91d68898f 100644 --- a/packages/electron/lib/electron.js +++ b/packages/electron/lib/electron.js @@ -16,6 +16,7 @@ fs = Promise.promisifyAll(fs) * If running as root on Linux, no-sandbox must be passed or Chrome will not start */ const isSandboxNeeded = () => { + // eslint-disable-next-line no-restricted-properties return (os.platform() === 'linux') && (process.geteuid() === 0) } diff --git a/packages/server/.eslintrc.json b/packages/server/.eslintrc.json index a888e77e78dd..930217e0b80b 100644 --- a/packages/server/.eslintrc.json +++ b/packages/server/.eslintrc.json @@ -1,6 +1,6 @@ { "extends": [ - "plugin:@cypress/dev/tests" + "../../.eslintrc.json" ], "parser": "@typescript-eslint/parser", "env": { diff --git a/packages/server/lib/util/file.js b/packages/server/lib/util/file.js index 77bd825da618..753ca4393037 100644 --- a/packages/server/lib/util/file.js +++ b/packages/server/lib/util/file.js @@ -13,6 +13,17 @@ const { default: pQueue } = require('p-queue') const DEBOUNCE_LIMIT = 1000 const LOCK_TIMEOUT = 2000 +function getUid () { + try { + // eslint-disable-next-line no-restricted-properties + return process.geteuid() + } catch (err) { + // process.geteuid() can fail, return a constant + // @see https://github.com/cypress-io/cypress/issues/17415 + return 1 + } +} + class File { constructor (options = {}) { if (!options.path) { @@ -23,7 +34,7 @@ class File { // If multiple users write to a specific directory is os.tmpdir, permission errors can arise. // Instead, we make a user specific directory with os.tmpdir. - this._lockFileDir = path.join(os.tmpdir(), `cypress-${os.userInfo().uid}`) + this._lockFileDir = path.join(os.tmpdir(), `cypress-${getUid()}`) this._lockFilePath = path.join(this._lockFileDir, `${md5(this.path)}.lock`) this._queue = new pQueue({ concurrency: 1 }) diff --git a/packages/server/test/e2e/2_cookies_spec.ts b/packages/server/test/e2e/2_cookies_spec.ts index 8870ce9ec4e9..85ddcf2d8878 100644 --- a/packages/server/test/e2e/2_cookies_spec.ts +++ b/packages/server/test/e2e/2_cookies_spec.ts @@ -1,3 +1,4 @@ +/* eslint-disable no-restricted-properties */ import dayjs from 'dayjs' import parser from 'cookie-parser' import e2e from '../support/helpers/e2e' diff --git a/packages/server/test/integration/cypress_spec.js b/packages/server/test/integration/cypress_spec.js index 334f8a30cf1a..2bc39f0d4150 100644 --- a/packages/server/test/integration/cypress_spec.js +++ b/packages/server/test/integration/cypress_spec.js @@ -1,3 +1,4 @@ +/* eslint-disable no-restricted-properties */ require('../spec_helper') const R = require('ramda') diff --git a/packages/server/test/support/fixtures/projects/read-only-project-root/cypress/plugins/index.js b/packages/server/test/support/fixtures/projects/read-only-project-root/cypress/plugins/index.js index d0a87b4657df..60b3e496ed59 100644 --- a/packages/server/test/support/fixtures/projects/read-only-project-root/cypress/plugins/index.js +++ b/packages/server/test/support/fixtures/projects/read-only-project-root/cypress/plugins/index.js @@ -1,3 +1,4 @@ +/* eslint-disable no-restricted-properties */ const fs = require('fs') const { expect } = require('chai') From d47b1c46e9faa6e0f874ef6683af94cea37c5edb Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 30 Jul 2021 17:15:39 +0000 Subject: [PATCH 11/14] chore: Update Chrome (beta) to 93.0.4577.18 (#17536) Co-authored-by: cypress-bot[bot] <2f0651858c6e38e0+cypress-bot[bot]@users.noreply.github.com> --- browser-versions.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/browser-versions.json b/browser-versions.json index 8e669cf1caed..db0494cb6f7d 100644 --- a/browser-versions.json +++ b/browser-versions.json @@ -1,4 +1,4 @@ { - "chrome:beta": "92.0.4515.107", + "chrome:beta": "93.0.4577.18", "chrome:stable": "92.0.4515.107" } From 67c8a333fb160bdb08b9f08cfd7d274c73d37b3c Mon Sep 17 00:00:00 2001 From: Ben Kucera <14625260+Bkucera@users.noreply.github.com> Date: Fri, 30 Jul 2021 15:08:13 -0400 Subject: [PATCH 12/14] fix: last test skipped with top navigation and already run suite (#17498) Co-authored-by: Chris Breiding --- packages/driver/src/cypress/runner.js | 10 +++ .../3_runnable_execution_spec.ts.js | 73 +++++++++++++++++++ .../test/e2e/3_runnable_execution_spec.ts | 7 ++ .../runnables_already_run_suite.js | 23 ++++++ 4 files changed, 113 insertions(+) create mode 100644 packages/server/test/support/fixtures/projects/e2e/cypress/integration/runnables_already_run_suite.js diff --git a/packages/driver/src/cypress/runner.js b/packages/driver/src/cypress/runner.js index 52144be5f0ed..5b62b6012d6f 100644 --- a/packages/driver/src/cypress/runner.js +++ b/packages/driver/src/cypress/runner.js @@ -383,6 +383,16 @@ const overrideRunnerHook = (Cypress, _runner, getTestById, getTest, setTest, get if (test) { const siblings = getAllSiblingTests(test.parent, getTestById) + const testIsActuallyInSuite = suiteHasTest(this.suite, test.id) + + // we ensure the test actually belongs to this suite. + // the test may not belong to the suite when a suite is skipped + // due to already being run on top navigation + // https://github.com/cypress-io/cypress/issues/9026 + if (!testIsActuallyInSuite) { + return + } + // 1. if we're the very last test in the entire allTests // we wait until the root suite fires // 2. else if we arent the last nested suite we fire if we're diff --git a/packages/server/__snapshots__/3_runnable_execution_spec.ts.js b/packages/server/__snapshots__/3_runnable_execution_spec.ts.js index 3fe12b45bce5..c2a265aa89d3 100644 --- a/packages/server/__snapshots__/3_runnable_execution_spec.ts.js +++ b/packages/server/__snapshots__/3_runnable_execution_spec.ts.js @@ -188,3 +188,76 @@ exports['e2e runnable execution / runnables run correct number of times with nav ` + +exports['e2e runnable execution / runs correctly after top navigation with already ran suite'] = ` + +==================================================================================================== + + (Run Starting) + + ┌────────────────────────────────────────────────────────────────────────────────────────────────┐ + │ Cypress: 1.2.3 │ + │ Browser: FooBrowser 88 │ + │ Specs: 1 found (runnables_already_run_suite.js) │ + │ Searched: cypress/integration/runnables_already_run_suite.js │ + └────────────────────────────────────────────────────────────────────────────────────────────────┘ + + +──────────────────────────────────────────────────────────────────────────────────────────────────── + + Running: runnables_already_run_suite.js (1 of 1) + + + Top level describe + suite 1 + ✓ should pass + suite 2 + 1) should fail + + + 1 passing + 1 failing + + 1) Top level describe + suite 2 + should fail: + AssertionError: expected true to be false + [stack trace lines] + + + + + (Results) + + ┌────────────────────────────────────────────────────────────────────────────────────────────────┐ + │ Tests: 2 │ + │ Passing: 1 │ + │ Failing: 1 │ + │ Pending: 0 │ + │ Skipped: 0 │ + │ Screenshots: 1 │ + │ Video: false │ + │ Duration: X seconds │ + │ Spec Ran: runnables_already_run_suite.js │ + └────────────────────────────────────────────────────────────────────────────────────────────────┘ + + + (Screenshots) + + - /XXX/XXX/XXX/cypress/screenshots/runnables_already_run_suite.js/Top level descri (1280x720) + be -- suite 2 -- should fail (failed).png + + +==================================================================================================== + + (Run Finished) + + + Spec Tests Passing Failing Pending Skipped + ┌────────────────────────────────────────────────────────────────────────────────────────────────┐ + │ ✖ runnables_already_run_suite.js XX:XX 2 1 1 - - │ + └────────────────────────────────────────────────────────────────────────────────────────────────┘ + ✖ 1 of 1 failed (100%) XX:XX 2 1 1 - - + + +` diff --git a/packages/server/test/e2e/3_runnable_execution_spec.ts b/packages/server/test/e2e/3_runnable_execution_spec.ts index 769d05ba9d4b..00e5439f3c23 100644 --- a/packages/server/test/e2e/3_runnable_execution_spec.ts +++ b/packages/server/test/e2e/3_runnable_execution_spec.ts @@ -32,4 +32,11 @@ describe('e2e runnable execution', () => { spec: 'runnable-run-count.spec.js', snapshot: true, }) + + e2e.it('runs correctly after top navigation with already ran suite', { + spec: 'runnables_already_run_suite.js', + snapshot: true, + expectedExitCode: 1, + config: { video: false }, + }) }) diff --git a/packages/server/test/support/fixtures/projects/e2e/cypress/integration/runnables_already_run_suite.js b/packages/server/test/support/fixtures/projects/e2e/cypress/integration/runnables_already_run_suite.js new file mode 100644 index 000000000000..4439b7e54b17 --- /dev/null +++ b/packages/server/test/support/fixtures/projects/e2e/cypress/integration/runnables_already_run_suite.js @@ -0,0 +1,23 @@ +// https://github.com/cypress-io/cypress/issues/9026 +describe('Top level describe ', () => { + before(() => { + // beforeAll hook needed to reproduce issue + }) + + beforeEach(() => {}) + + describe('suite 1', () => { + it('should pass', () => { + cy.visit('http://localhost:3434') + expect(true).to.be.true + }) + }) + + describe('suite 2', () => { + it('should fail', () => { + cy.visit('http://localhost:4545').then(() => { + expect(true).to.be.false + }) + }) + }) +}) From b4733a6179577b0447af9bcdcf417713d5fb38b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barth=C3=A9l=C3=A9my=20Ledoux?= Date: Fri, 30 Jul 2021 16:30:19 -0500 Subject: [PATCH 13/14] fix: vue 3 types, beta suffix & component name (#17508) * fix: update test-utils dependency & remove beta suffix * test: add typescript in the tests * chore: add setup example to cypress vue * build: remove noEmit from tsconfig.json * fix: make bigger types * test: make functinoal and definecompoennt tested * ci: make circle run typechek on vue * test: typescript files * test: remove usage of regenerator-runtime * style: avoid using internal types of vtu + comment --- circle.yml | 4 + npm/vue/.releaserc.js | 2 +- npm/vue/babel.config.json | 22 +- npm/vue/cypress.json | 2 +- .../hello/{Hello-spec.js => Hello-spec.ts} | 1 - ...sage-list-spec.js => message-list-spec.ts} | 6 +- .../component/setup/HelloWorld-spec.ts | 27 + .../cypress/component/setup/HelloWorld.vue | 12 + npm/vue/package.json | 19 +- npm/vue/rollup.config.js | 16 +- npm/vue/src/index.ts | 226 ++++- npm/vue/src/shims-vue.d.ts | 5 + npm/vue/tsconfig.json | 24 +- npm/vue/webpack.config.js | 2 +- yarn.lock | 949 ++++++++++++++---- 15 files changed, 1080 insertions(+), 237 deletions(-) rename npm/vue/cypress/component/basic/hello/{Hello-spec.js => Hello-spec.ts} (92%) rename npm/vue/cypress/component/basic/props/{message-list-spec.js => message-list-spec.ts} (91%) create mode 100644 npm/vue/cypress/component/setup/HelloWorld-spec.ts create mode 100644 npm/vue/cypress/component/setup/HelloWorld.vue create mode 100644 npm/vue/src/shims-vue.d.ts diff --git a/circle.yml b/circle.yml index 0788d724d8dd..9f41937774dd 100644 --- a/circle.yml +++ b/circle.yml @@ -1338,6 +1338,10 @@ jobs: - run: name: Build command: yarn workspace @cypress/vue build + - run: + name: Type Check + command: yarn typecheck + working_directory: npm/vue - run: name: Run component tests command: yarn test:ci:ct diff --git a/npm/vue/.releaserc.js b/npm/vue/.releaserc.js index 1d21d713cfb9..9bbeb518cade 100644 --- a/npm/vue/.releaserc.js +++ b/npm/vue/.releaserc.js @@ -7,6 +7,6 @@ module.exports = { // this line forces releasing 2.X releases on the latest channel { name: 'npm/vue/v2', range: '2.X.X' }, // this one releases v3 on master as beta on the next channel - { name: 'master', channel: 'next', prerelease: 'beta' }, + { name: 'master', channel: 'next' }, ], } diff --git a/npm/vue/babel.config.json b/npm/vue/babel.config.json index 589f7ada6cbd..be7694bf938b 100644 --- a/npm/vue/babel.config.json +++ b/npm/vue/babel.config.json @@ -1,12 +1,32 @@ { + "presets": [ + [ + "@babel/preset-env", + { + "targets": { + "browsers": [ + "last 1 Chrome version", + "last 1 Electron version", + "last 1 Firefox version" + ] + }, + "modules": "cjs" + } + ], + "babel-preset-typescript-vue3", + "@babel/preset-typescript" + ], "plugins": [ - "@babel/plugin-transform-modules-commonjs", [ "babel-plugin-istanbul", { "extension": [ ".js", ".vue" + ], + "exclude": [ + "**/*.spec.{js,ts}", + "**/setup/*.vue" ] } ] diff --git a/npm/vue/cypress.json b/npm/vue/cypress.json index 9aa5956f423b..a25995a3f06c 100644 --- a/npm/vue/cypress.json +++ b/npm/vue/cypress.json @@ -4,6 +4,6 @@ "video": false, "responseTimeout": 2500, "projectId": "134ej7", - "testFiles": "**/*spec.js", + "testFiles": "**/*spec.{js,ts,tsx}", "experimentalFetchPolyfill": true } \ No newline at end of file diff --git a/npm/vue/cypress/component/basic/hello/Hello-spec.js b/npm/vue/cypress/component/basic/hello/Hello-spec.ts similarity index 92% rename from npm/vue/cypress/component/basic/hello/Hello-spec.js rename to npm/vue/cypress/component/basic/hello/Hello-spec.ts index 5c5424bb945e..a1944036620e 100644 --- a/npm/vue/cypress/component/basic/hello/Hello-spec.js +++ b/npm/vue/cypress/component/basic/hello/Hello-spec.ts @@ -1,4 +1,3 @@ -/// import Hello from './Hello.vue' import { mount } from '@cypress/vue' diff --git a/npm/vue/cypress/component/basic/props/message-list-spec.js b/npm/vue/cypress/component/basic/props/message-list-spec.ts similarity index 91% rename from npm/vue/cypress/component/basic/props/message-list-spec.js rename to npm/vue/cypress/component/basic/props/message-list-spec.ts index 15878b5884bb..2f308abcfa4e 100644 --- a/npm/vue/cypress/component/basic/props/message-list-spec.js +++ b/npm/vue/cypress/component/basic/props/message-list-spec.ts @@ -10,12 +10,12 @@ describe('Props', () => { it('has props', () => { const messages = ['one 🍎', 'two 🍌'] - mount(MessageList, { propsData: { messages } }) + mount(MessageList, { props: { messages } }) getItems() .should('have.length', 2) .then((list) => { - expect(list[0].textContent.trim()).to.equal(messages[0]) - expect(list[1].textContent.trim()).to.equal(messages[1]) + expect(list[0].textContent).to.contain(messages[0]) + expect(list[1].textContent).to.contain(messages[1]) }) }) }) diff --git a/npm/vue/cypress/component/setup/HelloWorld-spec.ts b/npm/vue/cypress/component/setup/HelloWorld-spec.ts new file mode 100644 index 000000000000..a5e4a97b9385 --- /dev/null +++ b/npm/vue/cypress/component/setup/HelloWorld-spec.ts @@ -0,0 +1,27 @@ +import { h } from 'vue' +import { mount } from '@cypress/vue' +import HelloWorld from './HelloWorld.vue' + +describe('HelloWorld', () => { + it('normal mount', () => { + mount(HelloWorld, { props: { msg: 'Hello Cypress' } }) + }) + + it('functional mount', () => { + mount(() => h(HelloWorld, { msg: 'Hello Cypress' })) + }) + + it('renders properly', () => { + mount(HelloWorld, { props: { msg: 'Hello Cypress' } }) + cy.get('h1').should('contain', 'Hello Cypress') + }) + + it('adds 1 when clicking the plus button', () => { + mount(HelloWorld, { props: { msg: 'Hello Cypress' } }) + + cy.get('button') + .should('contain', '0') + .click() + .should('contain', '1') + }) +}) diff --git a/npm/vue/cypress/component/setup/HelloWorld.vue b/npm/vue/cypress/component/setup/HelloWorld.vue new file mode 100644 index 000000000000..a2ea84c8b283 --- /dev/null +++ b/npm/vue/cypress/component/setup/HelloWorld.vue @@ -0,0 +1,12 @@ + + + \ No newline at end of file diff --git a/npm/vue/package.json b/npm/vue/package.json index ff32fb50308f..6b2bcca67a3b 100644 --- a/npm/vue/package.json +++ b/npm/vue/package.json @@ -8,19 +8,21 @@ "build-prod": "yarn build", "cy:open": "node ../../scripts/cypress.js open-ct --project ${PWD}", "cy:run": "node ../../scripts/cypress.js run-ct --project ${PWD}", - "test:ci:e2e": "node ../../scripts/cypress.js run --project ${PWD}", + "typecheck": "vue-tsc --noEmit", "test": "yarn cy:run", "watch": "yarn build --watch --watch.exclude ./dist/**/*", + "test:ci:e2e": "node ../../scripts/cypress.js run --project ${PWD}", "test:ci:ct": "node ../../scripts/run-ct-examples.js --examplesList=./examples.env" }, "dependencies": { "@cypress/mount-utils": "0.0.0-development", - "@vue/test-utils": "^2.0.0-rc.9" + "@vue/test-utils": "^2.0.0-rc.10" }, "devDependencies": { "@babel/core": "7.9.0", - "@babel/plugin-transform-modules-commonjs": "7.10.4", + "@babel/plugin-transform-modules-commonjs": "7.9.6", "@babel/preset-env": "7.9.5", + "@babel/preset-typescript": "7.10.1", "@cypress/code-coverage": "3.8.1", "@cypress/webpack-dev-server": "0.0.0-development", "@intlify/vue-i18n-loader": "2.0.0-rc.1", @@ -28,10 +30,11 @@ "@rollup/plugin-node-resolve": "^11.1.1", "@vue/cli-plugin-babel": "~4.4.0", "@vue/cli-service": "~4.4.0", - "@vue/compiler-sfc": "^3.0.5", + "@vue/compiler-sfc": "3.1.5", "axios": "0.19.2", "babel-loader": "8.1.0", - "babel-plugin-istanbul": "6.0.0", + "babel-plugin-istanbul": "^6.0.0", + "babel-preset-typescript-vue3": "^2.0.14", "css-loader": "3.4.2", "cypress": "0.0.0-development", "debug": "4.3.2", @@ -44,12 +47,13 @@ "rollup-plugin-istanbul": "2.0.1", "rollup-plugin-typescript2": "^0.29.0", "tailwindcss": "1.1.4", - "typescript": "3.9.6", - "vue": "3.0.11", + "typescript": "^4.2.3", + "vue": "3.1.5", "vue-i18n": "9.0.0-rc.6", "vue-loader": "16.1.2", "vue-router": "^4.0.0", "vue-style-loader": "4.1.2", + "vue-tsc": "0.2.2", "vuex": "^4.0.0", "webpack": "4.42.0" }, @@ -77,7 +81,6 @@ "cypress", "vue" ], - "unpkg": "dist/cypress-vue.browser.js", "module": "dist/cypress-vue.esm-bundler.js", "peerDependenciesMeta": { "@cypress/webpack-dev-server": { diff --git a/npm/vue/rollup.config.js b/npm/vue/rollup.config.js index 6df7429e5d10..1ea32749f4f1 100644 --- a/npm/vue/rollup.config.js +++ b/npm/vue/rollup.config.js @@ -16,7 +16,6 @@ function createEntry (options) { const { format, input, - isBrowser, } = options const config = { @@ -46,9 +45,6 @@ function createEntry (options) { if (input === 'src/index.ts') { if (format === 'es') { config.output.file = pkg.module - if (isBrowser) { - config.output.file = pkg.unpkg - } } if (format === 'cjs') { @@ -62,14 +58,14 @@ function createEntry (options) { config.plugins.push( ts({ - check: format === 'es' && isBrowser, + check: false, tsconfigOverride: { compilerOptions: { declaration: format === 'es', - target: 'es5', // not sure what this should be? + noEmit: false, module: format === 'cjs' ? 'es2015' : 'esnext', }, - exclude: ['tests'], + exclude: ['cypress/component'], }, }), ) @@ -78,8 +74,6 @@ function createEntry (options) { } export default [ - createEntry({ format: 'es', input: 'src/index.ts', isBrowser: false }), - createEntry({ format: 'es', input: 'src/index.ts', isBrowser: true }), - createEntry({ format: 'iife', input: 'src/index.ts', isBrowser: true }), - createEntry({ format: 'cjs', input: 'src/index.ts', isBrowser: false }), + createEntry({ format: 'es', input: 'src/index.ts' }), + createEntry({ format: 'cjs', input: 'src/index.ts' }), ] diff --git a/npm/vue/src/index.ts b/npm/vue/src/index.ts index 94474a25a32c..2476ba70c29e 100644 --- a/npm/vue/src/index.ts +++ b/npm/vue/src/index.ts @@ -1,5 +1,9 @@ +/* eslint-disable no-redeclare */ /// -import { Component, ComponentPublicInstance } from 'vue' +import { ComponentPublicInstance, VNodeProps, AllowedComponentProps, + ComponentCustomProps, ExtractPropTypes, ExtractDefaultPropTypes, + Component, DefineComponent, FunctionalComponent, ComputedOptions, + MethodOptions, ComponentOptionsMixin, EmitsOptions, ComponentOptionsWithObjectProps, ComponentPropsOptions, ComponentOptionsWithArrayProps, ComponentOptionsWithoutProps } from 'vue' import { MountingOptions, VueWrapper, mount as VTUmount } from '@vue/test-utils' import { injectStylesBeforeElement, @@ -10,6 +14,8 @@ import { const DEFAULT_COMP_NAME = 'unknown' +type GlobalMountOptions = Required>['global'] + // when we mount a Vue component, we add it to the global Cypress object // so here we extend the global Cypress namespace and its Cypress interface declare global { @@ -22,14 +28,14 @@ declare global { } } -type CyMountOptions = Omit, 'attachTo'> & { +type CyMountOptions = Omit, 'attachTo'> & { log?: boolean /** * @deprecated use vue-test-utils `global` instead */ - extensions?: MountingOptions['global'] & { - use?: MountingOptions['global']['plugins'] - mixin?: MountingOptions['global']['mixins'] + extensions?: GlobalMountOptions & { + use?: GlobalMountOptions['plugins'] + mixin?: GlobalMountOptions['mixins'] } } & Partial @@ -53,17 +59,169 @@ Cypress.on('run:start', () => { const document: Document = cy.state('document') let el = document.getElementById(ROOT_ID) + if (!el) { + throw Error(`no element found at query #${ROOT_ID}. Please use the mount utils to mount it properly`) + } + el.innerHTML = '' document.head.innerHTML = initialInnerHtml }) }) -export function mount ( - comp: Component, - options: CyMountOptions = {}, +/** + * the types for mount have been copied directly from the VTU mount + * https://github.com/vuejs/vue-test-utils-next/blob/master/src/mount.ts + * + * If they are updated please copy and pase them again here. + */ + +type PublicProps = VNodeProps & AllowedComponentProps & ComponentCustomProps; + +// Class component - no props +export function mount( + originalComponent: { + new (...args: any[]): V + registerHooks(keys: string[]): void + }, + options?: MountingOptions +): Cypress.Chainable + +// Class component - props +export function mount( + originalComponent: { + new (...args: any[]): V + props(Props: P): any + registerHooks(keys: string[]): void + }, + options?: CyMountOptions

+): Cypress.Chainable + +// Functional component with emits +export function mount( + originalComponent: FunctionalComponent, + options?: CyMountOptions +): Cypress.Chainable + +// Component declared with defineComponent +export function mount< + PropsOrPropOptions = {}, + RawBindings = {}, + D = {}, + C extends ComputedOptions = ComputedOptions, + M extends MethodOptions = MethodOptions, + Mixin extends ComponentOptionsMixin = ComponentOptionsMixin, + Extends extends ComponentOptionsMixin = ComponentOptionsMixin, + E extends EmitsOptions = Record, + EE extends string = string, + PP = PublicProps, + Props = Readonly>, + Defaults = ExtractDefaultPropTypes +>( + component: DefineComponent< + PropsOrPropOptions, + RawBindings, + D, + C, + M, + Mixin, + Extends, + E, + EE, + PP, + Props, + Defaults + >, + options?: CyMountOptions< + Partial & Omit, + D + > +): Cypress.Chainable + +// Component declared with no props +export function mount< + Props = {}, + RawBindings = {}, + D = {}, + C extends ComputedOptions = {}, + M extends Record = {}, + E extends EmitsOptions = Record, + Mixin extends ComponentOptionsMixin = ComponentOptionsMixin, + Extends extends ComponentOptionsMixin = ComponentOptionsMixin, + EE extends string = string +>( + componentOptions: ComponentOptionsWithoutProps< + Props, + RawBindings, + D + >, + options?: CyMountOptions +): Cypress.Chainable + +// Component declared with { props: [] } +export function mount< + PropNames extends string, + RawBindings, + D, + C extends ComputedOptions = {}, + M extends Record = {}, + E extends EmitsOptions = Record, + Mixin extends ComponentOptionsMixin = ComponentOptionsMixin, + Extends extends ComponentOptionsMixin = ComponentOptionsMixin, + EE extends string = string, + Props extends Readonly<{ [key in PropNames]?: any }> = Readonly< + { [key in PropNames]?: any } + > +>( + componentOptions: ComponentOptionsWithArrayProps< + PropNames, + RawBindings, + D, + C, + M, + E, + Mixin, + Extends, + EE, + Props + >, + options?: CyMountOptions +): Cypress.Chainable + +// Component declared with { props: { ... } } +export function mount< + // the Readonly constraint allows TS to treat the type of { required: true } + // as constant instead of boolean. + PropsOptions extends Readonly, + RawBindings, + D, + C extends ComputedOptions = {}, + M extends Record = {}, + E extends EmitsOptions = Record, + Mixin extends ComponentOptionsMixin = ComponentOptionsMixin, + Extends extends ComponentOptionsMixin = ComponentOptionsMixin, + EE extends string = string +>( + componentOptions: ComponentOptionsWithObjectProps< + PropsOptions, + RawBindings, + D, + C, + M, + E, + Mixin, + Extends, + EE + >, + options?: CyMountOptions & PublicProps, D> +): Cypress.Chainable + +// implementation +export function mount ( + componentOptions: any, + options: CyMountOptions = {}, ) { // TODO: get the real displayName and props from VTU shallowMount - const componentName = DEFAULT_COMP_NAME + const componentName = getComponentDisplayName(componentOptions) const message = `<${componentName} ... />` let logInstance: Cypress.Log @@ -82,12 +240,16 @@ export function mount ( let el = document.getElementById(ROOT_ID) + if (!el) { + throw Error(`no element found at query #${ROOT_ID}. Please use the mount utils to mount it properly`) + } + injectStylesBeforeElement(options, document, el) // merge the extensions with global if (options.extensions) { - options.extensions.plugins = [].concat(options.extensions.plugins || [], options.extensions.use || []) - options.extensions.mixins = [].concat(options.extensions.mixins || [], options.extensions.mixin || []) + options.extensions.plugins = ([] as GlobalMountOptions['plugins'])?.concat(options.extensions.plugins || [], options.extensions.use || []) + options.extensions.mixins = ([] as GlobalMountOptions['mixins'])?.concat(options.extensions.mixins || [], options.extensions.mixin || []) options.global = { ...options.extensions, ...options.global } } @@ -98,10 +260,10 @@ export function mount ( el.append(componentNode) // mount the component using VTU and return the wrapper in Cypress.VueWrapper - const wrapper = VTUmount(comp as any, { attachTo: componentNode, ...options }) + const wrapper = VTUmount(componentOptions, { attachTo: componentNode, ...options }) - Cypress.vueWrapper = wrapper - Cypress.vue = wrapper.vm + Cypress.vueWrapper = wrapper as VueWrapper + Cypress.vue = wrapper.vm as ComponentPublicInstance return cy .wrap(wrapper, { log: false }) @@ -119,17 +281,43 @@ export function mount ( }) } +/** + * Extract the compoennt name from the object passed to mount + * @param componentOptions the compoennt passed to mount + * @returns name of the component + */ +function getComponentDisplayName (componentOptions: any): string { + if (componentOptions.name) { + return componentOptions.name + } + + if (componentOptions.__file) { + const filepathSplit = componentOptions.__file.split('/') + const fileName = filepathSplit[filepathSplit.length - 1] + + // remove the extension .js, .ts or .vue from the filename to get the name of the component + const baseFileName = fileName.replace(/\.(js|ts|vue)?$/, '') + + // if the filename is index, then we can use the direct parent foldername, else use the name itself + return (baseFileName === 'index' ? filepathSplit[filepathSplit.length - 2] : baseFileName) + } + + return DEFAULT_COMP_NAME +} + /** * Helper function for mounting a component quickly in test hooks. * @example * import {mountCallback} from '@cypress/vue' * beforeEach(mountVue(component, options)) */ -export function mountCallback ( - component: Component, - options: CyMountOptions = {}, -): () => void { - return () => mount(component, options) +export function mountCallback ( + component: any, + options: any = {}, +): () => Cypress.Chainable { + return () => { + return mount(component, options) + } } setupHooks() diff --git a/npm/vue/src/shims-vue.d.ts b/npm/vue/src/shims-vue.d.ts new file mode 100644 index 000000000000..a1dbcdb9adfe --- /dev/null +++ b/npm/vue/src/shims-vue.d.ts @@ -0,0 +1,5 @@ +declare module '*.vue' { + import { DefineComponent } from 'vue' + const component: DefineComponent<{}, {}, any> + export default component + } \ No newline at end of file diff --git a/npm/vue/tsconfig.json b/npm/vue/tsconfig.json index ea20f06c3e05..2336e1d59bc3 100644 --- a/npm/vue/tsconfig.json +++ b/npm/vue/tsconfig.json @@ -7,15 +7,15 @@ "lib": [ "es2015", "dom" - ] /* Specify library files to be included in the compilation: */, - "allowJs": true /* Allow javascript files to be compiled. */, + ] /* Specify library files to be included in the compilation: */, + "allowJs": true /* Allow javascript files to be compiled. */, // "checkJs": true, /* Report errors in .js files. */ - // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ - "declaration": true /* Generates corresponding '.d.ts' file. */, + "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ + // "declaration": true /* Generates corresponding '.d.ts' file. */, // "sourceMap": true, /* Generates corresponding '.map' file. */ // "outFile": "./", /* Concatenate and emit output to single file. */ - "outDir": "dist" /* Redirect output structure to the directory. */, - // "rootDir": "src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ + "outDir": "dist" /* Redirect output structure to the directory. */, + // "rootDir": "src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ // "removeComments": true, /* Do not emit comments to output. */ // "noEmit": true, /* Do not emit outputs. */ // "importHelpers": true, /* Import emit helpers from 'tslib'. */ @@ -23,8 +23,8 @@ // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ /* Strict Type-Checking Options */ - "strict": false /* Enable all strict type-checking options. */, - "noImplicitAny": false, + "strict": true, /* Enable all strict type-checking options. */ + // "noImplicitAny": true, /* Module Resolution Options */ // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ @@ -33,8 +33,8 @@ // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ // "typeRoots": [], /* List of folders to include type definitions from. */ "types": [ - "cypress" - ] /* Type declaration files to be included in compilation. */, + "cypress", "vue" + ] /* Type declaration files to be included in compilation. */, "allowSyntheticDefaultImports": true /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */, // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ @@ -49,6 +49,6 @@ // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ "esModuleInterop": true }, - "include": ["src/**/*.*"], - "exclude": ["src/**/*-spec.*"] + "include": ["src", "cypress/component/**/*.{ts,tsx}", "cypress/component/**/*.vue"], + "exclude": ["**/Translated*.vue"] } diff --git a/npm/vue/webpack.config.js b/npm/vue/webpack.config.js index bd54d1a7e9bc..4e3fe73893e5 100644 --- a/npm/vue/webpack.config.js +++ b/npm/vue/webpack.config.js @@ -28,7 +28,7 @@ module.exports = { loader: 'vue-loader', }, { - test: /\.js$/, + test: /\.[j,t]s$/, loader: 'babel-loader', }, // this will apply to both plain `.css` files diff --git a/yarn.lock b/yarn.lock index c69eafbd1ec7..47b9e2a5ed8b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -396,12 +396,12 @@ dependencies: "@babel/highlight" "^7.8.3" -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.5.5", "@babel/code-frame@^7.8.3": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.13.tgz#dcfc826beef65e75c50e21d3837d7d95798dd658" - integrity sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g== +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.14.5", "@babel/code-frame@^7.5.5", "@babel/code-frame@^7.8.3": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.14.5.tgz#23b08d740e83f49c5e59945fbf1b43e80bbf4edb" + integrity sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw== dependencies: - "@babel/highlight" "^7.12.13" + "@babel/highlight" "^7.14.5" "@babel/compat-data@^7.12.7", "@babel/compat-data@^7.13.0", "@babel/compat-data@^7.13.15", "@babel/compat-data@^7.13.5", "@babel/compat-data@^7.13.8", "@babel/compat-data@^7.9.0": version "7.14.0" @@ -564,21 +564,21 @@ jsesc "^2.5.1" source-map "^0.5.0" -"@babel/generator@^7.12.10", "@babel/generator@^7.12.11", "@babel/generator@^7.12.5", "@babel/generator@^7.14.0", "@babel/generator@^7.4.0", "@babel/generator@^7.4.4", "@babel/generator@^7.6.0", "@babel/generator@^7.8.3", "@babel/generator@^7.9.0": - version "7.14.1" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.14.1.tgz#1f99331babd65700183628da186f36f63d615c93" - integrity sha512-TMGhsXMXCP/O1WtQmZjpEYDhCYC9vFhayWZPJSZCGkPJgUqX0rF0wwtrYvnzVxIjcF80tkUertXVk5cwqi5cAQ== +"@babel/generator@^7.12.10", "@babel/generator@^7.12.11", "@babel/generator@^7.12.5", "@babel/generator@^7.14.0", "@babel/generator@^7.14.8", "@babel/generator@^7.4.0", "@babel/generator@^7.4.4", "@babel/generator@^7.6.0", "@babel/generator@^7.8.3", "@babel/generator@^7.9.0": + version "7.14.8" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.14.8.tgz#bf86fd6af96cf3b74395a8ca409515f89423e070" + integrity sha512-cYDUpvIzhBVnMzRoY1fkSEhK/HmwEVwlyULYgn/tMQYd6Obag3ylCjONle3gdErfXBW61SVTlR9QR7uWlgeIkg== dependencies: - "@babel/types" "^7.14.1" + "@babel/types" "^7.14.8" jsesc "^2.5.1" source-map "^0.5.0" -"@babel/helper-annotate-as-pure@^7.0.0", "@babel/helper-annotate-as-pure@^7.10.4", "@babel/helper-annotate-as-pure@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.12.13.tgz#0f58e86dfc4bb3b1fcd7db806570e177d439b6ab" - integrity sha512-7YXfX5wQ5aYM/BOlbSccHDbuXXFPxeoUmfWtz8le2yTkTZc+BxsiEnENFoi2SlmA8ewDkG2LgIMIVzzn2h8kfw== +"@babel/helper-annotate-as-pure@^7.0.0", "@babel/helper-annotate-as-pure@^7.10.4", "@babel/helper-annotate-as-pure@^7.12.13", "@babel/helper-annotate-as-pure@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.14.5.tgz#7bf478ec3b71726d56a8ca5775b046fc29879e61" + integrity sha512-EivH9EgBIb+G8ij1B2jAwSH36WnGvkQSEC6CkX/6v6ZFlw5fVOHvsgGF4uiEHO2GzMvunZb6tDLQEQSdrdocrA== dependencies: - "@babel/types" "^7.12.13" + "@babel/types" "^7.14.5" "@babel/helper-builder-binary-assignment-operator-visitor@^7.12.13": version "7.12.13" @@ -598,16 +598,17 @@ browserslist "^4.14.5" semver "^6.3.0" -"@babel/helper-create-class-features-plugin@^7.13.0", "@babel/helper-create-class-features-plugin@^7.13.11", "@babel/helper-create-class-features-plugin@^7.3.0", "@babel/helper-create-class-features-plugin@^7.4.4", "@babel/helper-create-class-features-plugin@^7.8.3": - version "7.13.11" - resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.13.11.tgz#30d30a005bca2c953f5653fc25091a492177f4f6" - integrity sha512-ays0I7XYq9xbjCSvT+EvysLgfc3tOkwCULHjrnscGT3A9qD4sk3wXnJ3of0MAWsWGjdinFvajHU2smYuqXKMrw== +"@babel/helper-create-class-features-plugin@^7.13.0", "@babel/helper-create-class-features-plugin@^7.13.11", "@babel/helper-create-class-features-plugin@^7.14.6", "@babel/helper-create-class-features-plugin@^7.3.0", "@babel/helper-create-class-features-plugin@^7.4.4", "@babel/helper-create-class-features-plugin@^7.8.3": + version "7.14.8" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.14.8.tgz#a6f8c3de208b1e5629424a9a63567f56501955fc" + integrity sha512-bpYvH8zJBWzeqi1o+co8qOrw+EXzQ/0c74gVmY205AWXy9nifHrOg77y+1zwxX5lXE7Icq4sPlSQ4O2kWBrteQ== dependencies: - "@babel/helper-function-name" "^7.12.13" - "@babel/helper-member-expression-to-functions" "^7.13.0" - "@babel/helper-optimise-call-expression" "^7.12.13" - "@babel/helper-replace-supers" "^7.13.0" - "@babel/helper-split-export-declaration" "^7.12.13" + "@babel/helper-annotate-as-pure" "^7.14.5" + "@babel/helper-function-name" "^7.14.5" + "@babel/helper-member-expression-to-functions" "^7.14.7" + "@babel/helper-optimise-call-expression" "^7.14.5" + "@babel/helper-replace-supers" "^7.14.5" + "@babel/helper-split-export-declaration" "^7.14.5" "@babel/helper-create-regexp-features-plugin@^7.12.13": version "7.12.17" @@ -647,36 +648,35 @@ dependencies: "@babel/types" "^7.13.0" -"@babel/helper-function-name@^7.12.13", "@babel/helper-function-name@^7.8.3": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.12.13.tgz#93ad656db3c3c2232559fd7b2c3dbdcbe0eb377a" - integrity sha512-TZvmPn0UOqmvi5G4vvw0qZTpVptGkB1GL61R6lKvrSdIxGm5Pky7Q3fpKiIkQCAtRCBUwB0PaThlx9vebCDSwA== +"@babel/helper-function-name@^7.12.13", "@babel/helper-function-name@^7.14.5", "@babel/helper-function-name@^7.8.3": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.14.5.tgz#89e2c474972f15d8e233b52ee8c480e2cfcd50c4" + integrity sha512-Gjna0AsXWfFvrAuX+VKcN/aNNWonizBj39yGwUzVDVTlMYJMK2Wp6xdpy72mfArFq5uK+NOuexfzZlzI1z9+AQ== dependencies: - "@babel/helper-get-function-arity" "^7.12.13" - "@babel/template" "^7.12.13" - "@babel/types" "^7.12.13" + "@babel/helper-get-function-arity" "^7.14.5" + "@babel/template" "^7.14.5" + "@babel/types" "^7.14.5" -"@babel/helper-get-function-arity@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.12.13.tgz#bc63451d403a3b3082b97e1d8b3fe5bd4091e583" - integrity sha512-DjEVzQNz5LICkzN0REdpD5prGoidvbdYk1BVgRUOINaWJP2t6avB27X1guXK1kXNrX0WMfsrm1A/ZBthYuIMQg== +"@babel/helper-get-function-arity@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.14.5.tgz#25fbfa579b0937eee1f3b805ece4ce398c431815" + integrity sha512-I1Db4Shst5lewOM4V+ZKJzQ0JGGaZ6VY1jYvMghRjqs6DWgxLCIyFt30GlnKkfUeFLpJt2vzbMVEXVSXlIFYUg== dependencies: - "@babel/types" "^7.12.13" + "@babel/types" "^7.14.5" -"@babel/helper-hoist-variables@^7.13.0": - version "7.13.0" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.13.0.tgz#5d5882e855b5c5eda91e0cadc26c6e7a2c8593d8" - integrity sha512-0kBzvXiIKfsCA0y6cFEIJf4OdzfpRuNk4+YTeHZpGGc666SATFKTz6sRncwFnQk7/ugJ4dSrCj6iJuvW4Qwr2g== +"@babel/helper-hoist-variables@^7.13.0", "@babel/helper-hoist-variables@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.14.5.tgz#e0dd27c33a78e577d7c8884916a3e7ef1f7c7f8d" + integrity sha512-R1PXiz31Uc0Vxy4OEOm07x0oSjKAdPPCh3tPivn/Eo8cvz6gveAeuyUUPB21Hoiif0uoPQSSdhIPS3352nvdyQ== dependencies: - "@babel/traverse" "^7.13.0" - "@babel/types" "^7.13.0" + "@babel/types" "^7.14.5" -"@babel/helper-member-expression-to-functions@^7.13.0", "@babel/helper-member-expression-to-functions@^7.13.12": - version "7.13.12" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.13.12.tgz#dfe368f26d426a07299d8d6513821768216e6d72" - integrity sha512-48ql1CLL59aKbU94Y88Xgb2VFy7a95ykGRbJJaaVv+LX5U8wFpLfiGXJJGUozsmA1oEh/o5Bp60Voq7ACyA/Sw== +"@babel/helper-member-expression-to-functions@^7.14.5", "@babel/helper-member-expression-to-functions@^7.14.7": + version "7.14.7" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.14.7.tgz#97e56244beb94211fe277bd818e3a329c66f7970" + integrity sha512-TMUt4xKxJn6ccjcOW7c4hlwyJArizskAhoSTOCkA0uZ+KghIaci0Qg9R043kUMWI9mtQfgny+NQ5QATnZ+paaA== dependencies: - "@babel/types" "^7.13.12" + "@babel/types" "^7.14.5" "@babel/helper-module-imports@^7.0.0", "@babel/helper-module-imports@^7.12.1", "@babel/helper-module-imports@^7.12.13", "@babel/helper-module-imports@^7.12.5", "@babel/helper-module-imports@^7.13.12", "@babel/helper-module-imports@^7.8.3": version "7.13.12" @@ -685,7 +685,7 @@ dependencies: "@babel/types" "^7.13.12" -"@babel/helper-module-transforms@^7.10.4", "@babel/helper-module-transforms@^7.12.1", "@babel/helper-module-transforms@^7.13.0", "@babel/helper-module-transforms@^7.14.0", "@babel/helper-module-transforms@^7.9.0": +"@babel/helper-module-transforms@^7.12.1", "@babel/helper-module-transforms@^7.13.0", "@babel/helper-module-transforms@^7.14.0", "@babel/helper-module-transforms@^7.9.0": version "7.14.0" resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.14.0.tgz#8fcf78be220156f22633ee204ea81f73f826a8ad" integrity sha512-L40t9bxIuGOfpIGA3HNkJhU9qYrf4y5A5LUSw7rGMSn+pcG8dfJ0g6Zval6YJGd2nEjI7oP00fRdnhLKndx6bw== @@ -699,22 +699,22 @@ "@babel/traverse" "^7.14.0" "@babel/types" "^7.14.0" -"@babel/helper-optimise-call-expression@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.12.13.tgz#5c02d171b4c8615b1e7163f888c1c81c30a2aaea" - integrity sha512-BdWQhoVJkp6nVjB7nkFWcn43dkprYauqtk++Py2eaf/GRDFm5BxRqEIZCiHlZUGAVmtwKcsVL1dC68WmzeFmiA== +"@babel/helper-optimise-call-expression@^7.12.13", "@babel/helper-optimise-call-expression@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.14.5.tgz#f27395a8619e0665b3f0364cddb41c25d71b499c" + integrity sha512-IqiLIrODUOdnPU9/F8ib1Fx2ohlgDhxnIDU7OEVi+kAbEZcyiF7BLU8W6PfvPi9LzztjS7kcbzbmL7oG8kD6VA== dependencies: - "@babel/types" "^7.12.13" + "@babel/types" "^7.14.5" "@babel/helper-plugin-utils@7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz#2f75a831269d4f677de49986dff59927533cf375" integrity sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg== -"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.13.0", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": - version "7.13.0" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.13.0.tgz#806526ce125aed03373bc416a828321e3a6a33af" - integrity sha512-ZPafIPSwzUlAoWT8DKs1W2VyF2gOWthGd5NGFMsBcMMol+ZhK+EQY/e6V96poa6PA/Bh+C9plWN0hXO1uB8AfQ== +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.1", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.13.0", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.14.5.tgz#5ac822ce97eec46741ab70a517971e443a70c5a9" + integrity sha512-/37qQCE3K0vvZKwoK4XU/irIJQdIfCJuhU5eKnNxpFDsOkgFaUAwbv+RYw6eYgsC0E4hS7r5KqGULUogqui0fQ== "@babel/helper-remap-async-to-generator@^7.12.1", "@babel/helper-remap-async-to-generator@^7.13.0": version "7.13.0" @@ -725,22 +725,22 @@ "@babel/helper-wrap-function" "^7.13.0" "@babel/types" "^7.13.0" -"@babel/helper-replace-supers@^7.12.13", "@babel/helper-replace-supers@^7.13.0", "@babel/helper-replace-supers@^7.13.12": - version "7.13.12" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.13.12.tgz#6442f4c1ad912502481a564a7386de0c77ff3804" - integrity sha512-Gz1eiX+4yDO8mT+heB94aLVNCL+rbuT2xy4YfyNqu8F+OI6vMvJK891qGBTqL9Uc8wxEvRW92Id6G7sDen3fFw== +"@babel/helper-replace-supers@^7.12.13", "@babel/helper-replace-supers@^7.13.0", "@babel/helper-replace-supers@^7.13.12", "@babel/helper-replace-supers@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.14.5.tgz#0ecc0b03c41cd567b4024ea016134c28414abb94" + integrity sha512-3i1Qe9/8x/hCHINujn+iuHy+mMRLoc77b2nI9TB0zjH1hvn9qGlXjWlggdwUcju36PkPCy/lpM7LLUdcTyH4Ow== dependencies: - "@babel/helper-member-expression-to-functions" "^7.13.12" - "@babel/helper-optimise-call-expression" "^7.12.13" - "@babel/traverse" "^7.13.0" - "@babel/types" "^7.13.12" + "@babel/helper-member-expression-to-functions" "^7.14.5" + "@babel/helper-optimise-call-expression" "^7.14.5" + "@babel/traverse" "^7.14.5" + "@babel/types" "^7.14.5" -"@babel/helper-simple-access@^7.10.4", "@babel/helper-simple-access@^7.12.1", "@babel/helper-simple-access@^7.13.12": - version "7.13.12" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.13.12.tgz#dd6c538afb61819d205a012c31792a39c7a5eaf6" - integrity sha512-7FEjbrx5SL9cWvXioDbnlYTppcZGuCY6ow3/D5vMggb2Ywgu4dMrpTJX0JdQAIcRRUElOIxF3yEooa9gUb9ZbA== +"@babel/helper-simple-access@^7.12.1", "@babel/helper-simple-access@^7.13.12", "@babel/helper-simple-access@^7.8.3": + version "7.14.8" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.14.8.tgz#82e1fec0644a7e775c74d305f212c39f8fe73924" + integrity sha512-TrFN4RHh9gnWEU+s7JloIho2T76GPwRHhdzOWLqTrMnlas8T9O7ec+oEDNsRXndOmru9ymH9DFrEOxpzPoSbdg== dependencies: - "@babel/types" "^7.13.12" + "@babel/types" "^7.14.8" "@babel/helper-skip-transparent-expression-wrappers@^7.12.1": version "7.12.1" @@ -749,17 +749,17 @@ dependencies: "@babel/types" "^7.12.1" -"@babel/helper-split-export-declaration@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.12.13.tgz#e9430be00baf3e88b0e13e6f9d4eaf2136372b05" - integrity sha512-tCJDltF83htUtXx5NLcaDqRmknv652ZWCHyoTETf1CXYJdPC7nohZohjUgieXhv0hTJdRf2FjDueFehdNucpzg== +"@babel/helper-split-export-declaration@^7.12.13", "@babel/helper-split-export-declaration@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.14.5.tgz#22b23a54ef51c2b7605d851930c1976dd0bc693a" + integrity sha512-hprxVPu6e5Kdp2puZUmvOGjaLv9TCe58E/Fl6hRq4YiVQxIcNvuq6uTM2r1mT/oPskuS9CgR+I94sqAYv0NGKA== dependencies: - "@babel/types" "^7.12.13" + "@babel/types" "^7.14.5" -"@babel/helper-validator-identifier@^7.12.11", "@babel/helper-validator-identifier@^7.14.0": - version "7.14.0" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz#d26cad8a47c65286b15df1547319a5d0bcf27288" - integrity sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A== +"@babel/helper-validator-identifier@^7.12.11", "@babel/helper-validator-identifier@^7.14.0", "@babel/helper-validator-identifier@^7.14.5", "@babel/helper-validator-identifier@^7.14.8": + version "7.14.8" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.8.tgz#32be33a756f29e278a0d644fa08a2c9e0f88a34c" + integrity sha512-ZGy6/XQjllhYQrNw/3zfWRwZCTVSiBLZ9DHVZxn9n2gip/7ab8mv2TWlKPIBk26RwedCBoWdjLmn+t9na2Gcow== "@babel/helper-validator-option@^7.12.11", "@babel/helper-validator-option@^7.12.17": version "7.12.17" @@ -785,12 +785,12 @@ "@babel/traverse" "^7.14.0" "@babel/types" "^7.14.0" -"@babel/highlight@^7.0.0", "@babel/highlight@^7.10.4", "@babel/highlight@^7.12.13", "@babel/highlight@^7.8.3": - version "7.13.10" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.13.10.tgz#a8b2a66148f5b27d666b15d81774347a731d52d1" - integrity sha512-5aPpe5XQPzflQrFwL1/QoeHkP2MsA4JCntcXHRhEsdsfPVkvPi2w7Qix4iV7t5S/oC9OodGrggd8aco1g3SZFg== +"@babel/highlight@^7.0.0", "@babel/highlight@^7.10.4", "@babel/highlight@^7.14.5", "@babel/highlight@^7.8.3": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.14.5.tgz#6861a52f03966405001f6aa534a01a24d99e8cd9" + integrity sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg== dependencies: - "@babel/helper-validator-identifier" "^7.12.11" + "@babel/helper-validator-identifier" "^7.14.5" chalk "^2.0.0" js-tokens "^4.0.0" @@ -799,10 +799,10 @@ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.13.0.tgz#49b9b6ee213e5634fa80361dae139effef893f78" integrity sha512-w80kxEMFhE3wjMOQkfdTvv0CSdRSJZptIlLhU4eU/coNJeWjduspUFz+IRnBbAq6m5XYBFMoT1TNkk9K9yf10g== -"@babel/parser@^7.0.0", "@babel/parser@^7.1.0", "@babel/parser@^7.1.6", "@babel/parser@^7.12.0", "@babel/parser@^7.12.10", "@babel/parser@^7.12.11", "@babel/parser@^7.12.13", "@babel/parser@^7.12.7", "@babel/parser@^7.13.9", "@babel/parser@^7.14.0", "@babel/parser@^7.4.3", "@babel/parser@^7.4.5", "@babel/parser@^7.6.0", "@babel/parser@^7.7.0", "@babel/parser@^7.8.3", "@babel/parser@^7.9.0": - version "7.14.1" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.14.1.tgz#1bd644b5db3f5797c4479d89ec1817fe02b84c47" - integrity sha512-muUGEKu8E/ftMTPlNp+mc6zL3E9zKWmF5sDHZ5MSsoTP9Wyz64AhEf9kD08xYJ7w6Hdcu8H550ircnPyWSIF0Q== +"@babel/parser@^7.0.0", "@babel/parser@^7.1.0", "@babel/parser@^7.1.6", "@babel/parser@^7.12.0", "@babel/parser@^7.12.10", "@babel/parser@^7.12.11", "@babel/parser@^7.12.7", "@babel/parser@^7.13.9", "@babel/parser@^7.14.0", "@babel/parser@^7.14.5", "@babel/parser@^7.14.8", "@babel/parser@^7.4.3", "@babel/parser@^7.4.5", "@babel/parser@^7.6.0", "@babel/parser@^7.7.0", "@babel/parser@^7.8.3", "@babel/parser@^7.9.0", "@babel/parser@^7.9.6": + version "7.14.8" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.14.8.tgz#66fd41666b2d7b840bd5ace7f7416d5ac60208d4" + integrity sha512-syoCQFOoo/fzkWDeM0dLEZi5xqurb5vuyzwIMNZRNun+N/9A4cUZeQaE7dTrB8jGaKuJRBtEOajtnmw0I5hvvA== "@babel/plugin-proposal-async-generator-functions@^7.12.1", "@babel/plugin-proposal-async-generator-functions@^7.13.5", "@babel/plugin-proposal-async-generator-functions@^7.2.0", "@babel/plugin-proposal-async-generator-functions@^7.8.3": version "7.13.15" @@ -1131,12 +1131,12 @@ dependencies: "@babel/helper-plugin-utils" "^7.12.13" -"@babel/plugin-syntax-typescript@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.12.13.tgz#9dff111ca64154cef0f4dc52cf843d9f12ce4474" - integrity sha512-cHP3u1JiUiG2LFDKbXnwVad81GvfyIOmCD6HIEId6ojrY0Drfy2q1jw7BwN7dE84+kTnBjLkXoL3IEy/3JPu2w== +"@babel/plugin-syntax-typescript@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.14.5.tgz#b82c6ce471b165b5ce420cf92914d6fb46225716" + integrity sha512-u6OXzDaIXjEstBRRoBCQ/uKQKlbuaeE5in0RvWdA4pN6AhqxTIwUsnHPU1CFZA/amYObMsuWhYfRl3Ch90HD0Q== dependencies: - "@babel/helper-plugin-utils" "^7.12.13" + "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-transform-arrow-functions@^7.12.1", "@babel/plugin-transform-arrow-functions@^7.13.0", "@babel/plugin-transform-arrow-functions@^7.2.0", "@babel/plugin-transform-arrow-functions@^7.8.3": version "7.13.0" @@ -1281,16 +1281,6 @@ "@babel/helper-plugin-utils" "^7.13.0" babel-plugin-dynamic-import-node "^2.3.3" -"@babel/plugin-transform-modules-commonjs@7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.10.4.tgz#66667c3eeda1ebf7896d41f1f16b17105a2fbca0" - integrity sha512-Xj7Uq5o80HDLlW64rVfDBhao6OX89HKUmb+9vWYaLXBZOma4gA6tw4Ni1O5qVDoZWUV0fxMYA0aYzOawz0l+1w== - dependencies: - "@babel/helper-module-transforms" "^7.10.4" - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/helper-simple-access" "^7.10.4" - babel-plugin-dynamic-import-node "^2.3.3" - "@babel/plugin-transform-modules-commonjs@7.12.1": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.12.1.tgz#fa403124542636c786cf9b460a0ffbb48a86e648" @@ -1301,6 +1291,16 @@ "@babel/helper-simple-access" "^7.12.1" babel-plugin-dynamic-import-node "^2.3.3" +"@babel/plugin-transform-modules-commonjs@7.9.6": + version "7.9.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.9.6.tgz#64b7474a4279ee588cacd1906695ca721687c277" + integrity sha512-7H25fSlLcn+iYimmsNe3uK1at79IE6SKW9q0/QeEHTMC9MdOZ+4bA+T1VFB5fgOqBWoqlifXRzYD0JPdmIrgSQ== + dependencies: + "@babel/helper-module-transforms" "^7.9.0" + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-simple-access" "^7.8.3" + babel-plugin-dynamic-import-node "^2.3.3" + "@babel/plugin-transform-modules-commonjs@^7.12.1", "@babel/plugin-transform-modules-commonjs@^7.13.0", "@babel/plugin-transform-modules-commonjs@^7.4.4", "@babel/plugin-transform-modules-commonjs@^7.9.0": version "7.14.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.14.0.tgz#52bc199cb581e0992edba0f0f80356467587f161" @@ -1518,14 +1518,14 @@ dependencies: "@babel/helper-plugin-utils" "^7.12.13" -"@babel/plugin-transform-typescript@^7.10.4", "@babel/plugin-transform-typescript@^7.13.0", "@babel/plugin-transform-typescript@^7.2.0", "@babel/plugin-transform-typescript@^7.3.2", "@babel/plugin-transform-typescript@^7.9.0": - version "7.13.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.13.0.tgz#4a498e1f3600342d2a9e61f60131018f55774853" - integrity sha512-elQEwluzaU8R8dbVuW2Q2Y8Nznf7hnjM7+DSCd14Lo5fF63C9qNLbwZYbmZrtV9/ySpSUpkRpQXvJb6xyu4hCQ== +"@babel/plugin-transform-typescript@^7.10.1", "@babel/plugin-transform-typescript@^7.10.4", "@babel/plugin-transform-typescript@^7.13.0", "@babel/plugin-transform-typescript@^7.2.0", "@babel/plugin-transform-typescript@^7.3.2", "@babel/plugin-transform-typescript@^7.9.0": + version "7.14.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.14.6.tgz#6e9c2d98da2507ebe0a883b100cde3c7279df36c" + integrity sha512-XlTdBq7Awr4FYIzqhmYY80WN0V0azF74DMPyFqVHBvf81ZUgc4X7ZOpx6O8eLDK6iM5cCQzeyJw0ynTaefixRA== dependencies: - "@babel/helper-create-class-features-plugin" "^7.13.0" - "@babel/helper-plugin-utils" "^7.13.0" - "@babel/plugin-syntax-typescript" "^7.12.13" + "@babel/helper-create-class-features-plugin" "^7.14.6" + "@babel/helper-plugin-utils" "^7.14.5" + "@babel/plugin-syntax-typescript" "^7.14.5" "@babel/plugin-transform-unicode-escapes@^7.12.1", "@babel/plugin-transform-unicode-escapes@^7.12.13": version "7.12.13" @@ -1941,6 +1941,14 @@ "@babel/plugin-transform-react-jsx-development" "^7.12.17" "@babel/plugin-transform-react-pure-annotations" "^7.12.1" +"@babel/preset-typescript@7.10.1": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.10.1.tgz#a8d8d9035f55b7d99a2461a0bdc506582914d07e" + integrity sha512-m6GV3y1ShiqxnyQj10600ZVOFrSSAa8HQ3qIUk2r+gcGtHTIRw0dJnFLt1WNXpKjtVw7yw1DAPU/6ma2ZvgJuA== + dependencies: + "@babel/helper-plugin-utils" "^7.10.1" + "@babel/plugin-transform-typescript" "^7.10.1" + "@babel/preset-typescript@7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.10.4.tgz#7d5d052e52a682480d6e2cc5aa31be61c8c25e36" @@ -2033,26 +2041,27 @@ "@babel/parser" "^7.12.7" "@babel/types" "^7.12.7" -"@babel/template@^7.0.0", "@babel/template@^7.12.13", "@babel/template@^7.12.7", "@babel/template@^7.4.0", "@babel/template@^7.4.4", "@babel/template@^7.5.4", "@babel/template@^7.6.0", "@babel/template@^7.8.3", "@babel/template@^7.8.6": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.12.13.tgz#530265be8a2589dbb37523844c5bcb55947fb327" - integrity sha512-/7xxiGA57xMo/P2GVvdEumr8ONhFOhfgq2ihK3h1e6THqzTAkHbkXgB0xI9yeTfIUoH3+oAeHhqm/I43OTbbjA== - dependencies: - "@babel/code-frame" "^7.12.13" - "@babel/parser" "^7.12.13" - "@babel/types" "^7.12.13" - -"@babel/traverse@^7.0.0", "@babel/traverse@^7.1.0", "@babel/traverse@^7.12.10", "@babel/traverse@^7.12.9", "@babel/traverse@^7.13.0", "@babel/traverse@^7.14.0", "@babel/traverse@^7.4.3", "@babel/traverse@^7.4.5", "@babel/traverse@^7.6.0", "@babel/traverse@^7.7.0", "@babel/traverse@^7.8.3", "@babel/traverse@^7.9.0": - version "7.14.0" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.14.0.tgz#cea0dc8ae7e2b1dec65f512f39f3483e8cc95aef" - integrity sha512-dZ/a371EE5XNhTHomvtuLTUyx6UEoJmYX+DT5zBCQN3McHemsuIaKKYqsc/fs26BEkHs/lBZy0J571LP5z9kQA== - dependencies: - "@babel/code-frame" "^7.12.13" - "@babel/generator" "^7.14.0" - "@babel/helper-function-name" "^7.12.13" - "@babel/helper-split-export-declaration" "^7.12.13" - "@babel/parser" "^7.14.0" - "@babel/types" "^7.14.0" +"@babel/template@^7.0.0", "@babel/template@^7.12.13", "@babel/template@^7.12.7", "@babel/template@^7.14.5", "@babel/template@^7.4.0", "@babel/template@^7.4.4", "@babel/template@^7.5.4", "@babel/template@^7.6.0", "@babel/template@^7.8.3", "@babel/template@^7.8.6": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.14.5.tgz#a9bc9d8b33354ff6e55a9c60d1109200a68974f4" + integrity sha512-6Z3Po85sfxRGachLULUhOmvAaOo7xCvqGQtxINai2mEGPFm6pQ4z5QInFnUrRpfoSV60BnjyF5F3c+15fxFV1g== + dependencies: + "@babel/code-frame" "^7.14.5" + "@babel/parser" "^7.14.5" + "@babel/types" "^7.14.5" + +"@babel/traverse@^7.0.0", "@babel/traverse@^7.1.0", "@babel/traverse@^7.12.10", "@babel/traverse@^7.12.9", "@babel/traverse@^7.13.0", "@babel/traverse@^7.14.0", "@babel/traverse@^7.14.5", "@babel/traverse@^7.4.3", "@babel/traverse@^7.4.5", "@babel/traverse@^7.6.0", "@babel/traverse@^7.7.0", "@babel/traverse@^7.8.3", "@babel/traverse@^7.9.0": + version "7.14.8" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.14.8.tgz#c0253f02677c5de1a8ff9df6b0aacbec7da1a8ce" + integrity sha512-kexHhzCljJcFNn1KYAQ6A5wxMRzq9ebYpEDV4+WdNyr3i7O44tanbDOR/xjiG2F3sllan+LgwK+7OMk0EmydHg== + dependencies: + "@babel/code-frame" "^7.14.5" + "@babel/generator" "^7.14.8" + "@babel/helper-function-name" "^7.14.5" + "@babel/helper-hoist-variables" "^7.14.5" + "@babel/helper-split-export-declaration" "^7.14.5" + "@babel/parser" "^7.14.8" + "@babel/types" "^7.14.8" debug "^4.1.0" globals "^11.1.0" @@ -2065,12 +2074,12 @@ lodash "^4.17.13" to-fast-properties "^2.0.0" -"@babel/types@^7.0.0", "@babel/types@^7.12.0", "@babel/types@^7.12.1", "@babel/types@^7.12.10", "@babel/types@^7.12.11", "@babel/types@^7.12.13", "@babel/types@^7.12.7", "@babel/types@^7.13.0", "@babel/types@^7.13.12", "@babel/types@^7.14.0", "@babel/types@^7.14.1", "@babel/types@^7.3.0", "@babel/types@^7.4.0", "@babel/types@^7.4.4", "@babel/types@^7.5.0", "@babel/types@^7.6.0", "@babel/types@^7.7.0", "@babel/types@^7.8.3", "@babel/types@^7.8.6", "@babel/types@^7.9.0", "@babel/types@^7.9.5": - version "7.14.1" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.14.1.tgz#095bd12f1c08ab63eff6e8f7745fa7c9cc15a9db" - integrity sha512-S13Qe85fzLs3gYRUnrpyeIrBJIMYv33qSTg1qoBwiG6nPKwUWAD9odSzWhEedpwOIzSEI6gbdQIWEMiCI42iBA== +"@babel/types@^7.0.0", "@babel/types@^7.12.0", "@babel/types@^7.12.1", "@babel/types@^7.12.10", "@babel/types@^7.12.11", "@babel/types@^7.12.13", "@babel/types@^7.12.7", "@babel/types@^7.13.0", "@babel/types@^7.13.12", "@babel/types@^7.14.0", "@babel/types@^7.14.5", "@babel/types@^7.14.8", "@babel/types@^7.3.0", "@babel/types@^7.4.0", "@babel/types@^7.4.4", "@babel/types@^7.5.0", "@babel/types@^7.6.0", "@babel/types@^7.6.1", "@babel/types@^7.7.0", "@babel/types@^7.8.3", "@babel/types@^7.8.6", "@babel/types@^7.9.0", "@babel/types@^7.9.5", "@babel/types@^7.9.6": + version "7.14.8" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.14.8.tgz#38109de8fcadc06415fbd9b74df0065d4d41c728" + integrity sha512-iob4soQa7dZw8nodR/KlOQkPh9S4I8RwCxwRIFuiMRYjOzH/KJzdUfDgz6cGi5dDaclXF4P2PAhCdrBJNIg68Q== dependencies: - "@babel/helper-validator-identifier" "^7.14.0" + "@babel/helper-validator-identifier" "^7.14.8" to-fast-properties "^2.0.0" "@bahmutov/all-paths@1.0.2": @@ -2588,6 +2597,25 @@ global-agent "^2.0.2" global-tunnel-ng "^2.7.1" +"@emmetio/abbreviation@^2.2.2": + version "2.2.2" + resolved "https://registry.yarnpkg.com/@emmetio/abbreviation/-/abbreviation-2.2.2.tgz#746762fd9e7a8c2ea604f580c62e3cfe250e6989" + integrity sha512-TtE/dBnkTCct8+LntkqVrwqQao6EnPAs1YN3cUgxOxTaBlesBCY37ROUAVZrRlG64GNnVShdl/b70RfAI3w5lw== + dependencies: + "@emmetio/scanner" "^1.0.0" + +"@emmetio/css-abbreviation@^2.1.4": + version "2.1.4" + resolved "https://registry.yarnpkg.com/@emmetio/css-abbreviation/-/css-abbreviation-2.1.4.tgz#90362e8a1122ce3b76f6c3157907d30182f53f54" + integrity sha512-qk9L60Y+uRtM5CPbB0y+QNl/1XKE09mSO+AhhSauIfr2YOx/ta3NJw2d8RtCFxgzHeRqFRr8jgyzThbu+MZ4Uw== + dependencies: + "@emmetio/scanner" "^1.0.0" + +"@emmetio/scanner@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@emmetio/scanner/-/scanner-1.0.0.tgz#065b2af6233fe7474d44823e3deb89724af42b5f" + integrity sha512-8HqW8EVqjnCmWXVpqAOZf+EGESdkR27odcMMMGefgKXtar00SoYNSryGv//TELI4T3QFsECo78p+0lmalk/CFA== + "@emotion/babel-plugin-jsx-pragmatic@^0.1.5": version "0.1.5" resolved "https://registry.yarnpkg.com/@emotion/babel-plugin-jsx-pragmatic/-/babel-plugin-jsx-pragmatic-0.1.5.tgz#27debfe9c27c4d83574d509787ae553bf8a34d7e" @@ -7736,16 +7764,21 @@ "@types/estree" "*" "@types/json-schema" "*" -"@types/estree@*", "@types/estree@^0.0.47": - version "0.0.47" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.47.tgz#d7a51db20f0650efec24cd04994f523d93172ed4" - integrity sha512-c5ciR06jK8u9BstrmJyO97m+klJrrhCf9u3rLu3DEAJBirxRqSCvDQoYKmxuYwQI5SZChAWu+tq9oVlGRuzPAg== +"@types/estree@*", "@types/estree@^0.0.48": + version "0.0.48" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.48.tgz#18dc8091b285df90db2f25aa7d906cfc394b7f74" + integrity sha512-LfZwXoGUDo0C3me81HXgkBg5CTQYb6xzEl+fNmbO4JdRiSKQ8A0GD1OBBvKAIsbCUgoyAty7m99GqqMQe784ew== "@types/estree@0.0.39": version "0.0.39" resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f" integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw== +"@types/estree@^0.0.47": + version "0.0.47" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.47.tgz#d7a51db20f0650efec24cd04994f523d93172ed4" + integrity sha512-c5ciR06jK8u9BstrmJyO97m+klJrrhCf9u3rLu3DEAJBirxRqSCvDQoYKmxuYwQI5SZChAWu+tq9oVlGRuzPAg== + "@types/events@*": version "3.0.0" resolved "https://registry.yarnpkg.com/@types/events/-/events-3.0.0.tgz#2862f3f58a9a7f7c3e78d79f130dd4d71c25c2a7" @@ -8650,6 +8683,46 @@ resolved "https://registry.yarnpkg.com/@vitejs/plugin-vue/-/plugin-vue-1.2.0.tgz#f0a92470b74761f90afc8cda204fa3bec9df09f4" integrity sha512-IhSJfJH6IDNEAnhr91+2vhLLe/1SqkA/2BP19jwtn54DGI+cNbZIxiPhHIdKUpdRo0QwErOh6Jy1Maxk2uVo7A== +"@volar/code-gen@^0.26.9": + version "0.26.9" + resolved "https://registry.yarnpkg.com/@volar/code-gen/-/code-gen-0.26.9.tgz#0d08a8a946c2a2775b9908fa56f2ba29cd3c2415" + integrity sha512-1twij6GkLU/OMspsUFrG1w1QoTwc0qy2hCPM8HkOREJOU+3/GFXXvgOWF1STbMmKI1nO6xOOrTAy0QoJUoUaZg== + dependencies: + "@volar/shared" "^0.26.9" + "@volar/source-map" "^0.26.9" + +"@volar/html2pug@^0.26.9": + version "0.26.9" + resolved "https://registry.yarnpkg.com/@volar/html2pug/-/html2pug-0.26.9.tgz#2ae54efad499e9b23c3cf165d4d8a39c32ca3e01" + integrity sha512-O280jqr5zoeUc3ZwgA2ObHZdycjSxz6l0s1ubML/o4b5kSqI15mHXD+NfVppkjx20fI4jKro9u1cbz9gZ6wFag== + dependencies: + domelementtype "^2.2.0" + domhandler "^4.2.0" + htmlparser2 "^6.1.0" + pug "^3.0.2" + +"@volar/shared@^0.26.9": + version "0.26.9" + resolved "https://registry.yarnpkg.com/@volar/shared/-/shared-0.26.9.tgz#cfa10c49d3e4552c0c2077ad9d6a7f51634d0ec3" + integrity sha512-R0ll82ZeDRda8FlMTnltP4eomI258ynla3QLPZ/XDVhP9Ub4+WNEMHx6AWoy+JhdNaY5bHSWTWa43hbnDG45XQ== + dependencies: + upath "^2.0.1" + vscode-jsonrpc "^8.0.0-next.1" + +"@volar/source-map@^0.26.9": + version "0.26.9" + resolved "https://registry.yarnpkg.com/@volar/source-map/-/source-map-0.26.9.tgz#29f02b8ad7e501a0f5c5a3cd9ac855a0a95bf3a8" + integrity sha512-moZ6MXSgALMJMMrFi62Hu0W7F4qtakLjRLnnfmk52FZSuHgV9mTlEEAJ78EmK2Ds647u6VBXYuft7qt358kRuQ== + dependencies: + "@volar/shared" "^0.26.9" + +"@volar/transforms@^0.26.9": + version "0.26.9" + resolved "https://registry.yarnpkg.com/@volar/transforms/-/transforms-0.26.9.tgz#b8d440832f560f618f6f2a666632361163b34c3f" + integrity sha512-aCs5e5O/vuwD5yDv2ARZ/vCPeA2gvE1wq4u2nQeU8sziANWycRumhSWLqKrsDaFUV9PntQVNecYqzdHsTlcV3Q== + dependencies: + "@volar/shared" "^0.26.9" + "@vue/babel-helper-vue-jsx-merge-props@^1.2.1": version "1.2.1" resolved "https://registry.yarnpkg.com/@vue/babel-helper-vue-jsx-merge-props/-/babel-helper-vue-jsx-merge-props-1.2.1.tgz#31624a7a505fb14da1d58023725a4c5f270e6a81" @@ -8661,9 +8734,9 @@ integrity sha512-hz4R8tS5jMn8lDq6iD+yWL6XNB699pGIVLk7WSJnn1dbpjaazsjZQkieJoRX6gW5zpYSCFqQ7jUquPNY65tQYA== "@vue/babel-plugin-jsx@^1.0.0-0": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@vue/babel-plugin-jsx/-/babel-plugin-jsx-1.0.3.tgz#ad5ee86ebc9fc40900add9914534e223c719eace" - integrity sha512-+52ZQFmrM0yh61dQlgwQlfHZXmYbswbQEL25SOSt9QkjegAdfIGu87oELw0l8H6cuJYazZCiNjPR9eU++ZIbxg== + version "1.0.6" + resolved "https://registry.yarnpkg.com/@vue/babel-plugin-jsx/-/babel-plugin-jsx-1.0.6.tgz#184bf3541ab6efdbe5079ab8b20c19e2af100bfb" + integrity sha512-RzYsvBhzKUmY2YG6LoV+W5PnlnkInq0thh1AzCmewwctAgGN6e9UFon6ZrQQV1CO5G5PeME7MqpB+/vvGg0h4g== dependencies: "@babel/helper-module-imports" "^7.0.0" "@babel/plugin-syntax-jsx" "^7.0.0" @@ -8900,6 +8973,28 @@ estree-walker "^2.0.1" source-map "^0.6.1" +"@vue/compiler-core@3.1.5": + version "3.1.5" + resolved "https://registry.yarnpkg.com/@vue/compiler-core/-/compiler-core-3.1.5.tgz#298f905b6065d6d81ff63756f98c60876b393c87" + integrity sha512-TXBhFinoBaXKDykJzY26UEuQU1K07FOp/0Ie+OXySqqk0bS0ZO7Xvl7UmiTUPYcLrWbxWBR7Bs/y55AI0MNc2Q== + dependencies: + "@babel/parser" "^7.12.0" + "@babel/types" "^7.12.0" + "@vue/shared" "3.1.5" + estree-walker "^2.0.1" + source-map "^0.6.1" + +"@vue/compiler-core@3.2.0-beta.6": + version "3.2.0-beta.6" + resolved "https://registry.yarnpkg.com/@vue/compiler-core/-/compiler-core-3.2.0-beta.6.tgz#d518e106839f27b38b0f9e0e2b0ce795d68e8eb7" + integrity sha512-oiICBlip8ry3ihWq98bcCgsK50YDq+lHJlJ0OAtI+14lyhhgqx3HQQytQi3luakr+8OFcsTzs5k1ejcbRkunbQ== + dependencies: + "@babel/parser" "^7.12.0" + "@babel/types" "^7.12.0" + "@vue/shared" "3.2.0-beta.6" + estree-walker "^2.0.1" + source-map "^0.6.1" + "@vue/compiler-dom@3.0.11": version "3.0.11" resolved "https://registry.yarnpkg.com/@vue/compiler-dom/-/compiler-dom-3.0.11.tgz#b15fc1c909371fd671746020ba55b5dab4a730ee" @@ -8916,7 +9011,23 @@ "@vue/compiler-core" "3.0.9" "@vue/shared" "3.0.9" -"@vue/compiler-sfc@3.0.9", "@vue/compiler-sfc@^3.0.5": +"@vue/compiler-dom@3.1.5": + version "3.1.5" + resolved "https://registry.yarnpkg.com/@vue/compiler-dom/-/compiler-dom-3.1.5.tgz#cbb97020c62a5faa3fbc2a97916bd98041ac9856" + integrity sha512-ZsL3jqJ52OjGU/YiT/9XiuZAmWClKInZM2aFJh9gnsAPqOrj2JIELMbkIFpVKR/CrVO/f2VxfPiiQdQTr65jcQ== + dependencies: + "@vue/compiler-core" "3.1.5" + "@vue/shared" "3.1.5" + +"@vue/compiler-dom@3.2.0-beta.6", "@vue/compiler-dom@^3.2.0-beta.5": + version "3.2.0-beta.6" + resolved "https://registry.yarnpkg.com/@vue/compiler-dom/-/compiler-dom-3.2.0-beta.6.tgz#4d3c1221be1fa8177600d9e4e71fd84af82c18c4" + integrity sha512-ThSXPhFzanH/XW1SGZ3I2r5x2z+DcXP0KO7TvTvgcTvxQ/sZod7WTj55uFjfErINcjvflaqLLoHVMtGBWnF/MA== + dependencies: + "@vue/compiler-core" "3.2.0-beta.6" + "@vue/shared" "3.2.0-beta.6" + +"@vue/compiler-sfc@3.0.9": version "3.0.9" resolved "https://registry.yarnpkg.com/@vue/compiler-sfc/-/compiler-sfc-3.0.9.tgz#0f993a6e159ca6ad351d8ee0c4734771d2590115" integrity sha512-meneFRb9xIDgv/gYWCr9xKryvPi0tVffQzLjCkyN4RF1EndqLS71xugUX9wQsS4F1SAP+zlZbcgMFmTSC4OpHw== @@ -8938,6 +9049,52 @@ postcss-selector-parser "^6.0.4" source-map "^0.6.1" +"@vue/compiler-sfc@3.1.5", "@vue/compiler-sfc@^3.0.5": + version "3.1.5" + resolved "https://registry.yarnpkg.com/@vue/compiler-sfc/-/compiler-sfc-3.1.5.tgz#e61e54f3a963b0f4a8e523fbb8632390dc52b0d6" + integrity sha512-mtMY6xMvZeSRx9MTa1+NgJWndrkzVTdJ1pQAmAKQuxyb5LsHVvrgP7kcQFvxPHVpLVTORbTJWHaiqoKrJvi1iA== + dependencies: + "@babel/parser" "^7.13.9" + "@babel/types" "^7.13.0" + "@types/estree" "^0.0.48" + "@vue/compiler-core" "3.1.5" + "@vue/compiler-dom" "3.1.5" + "@vue/compiler-ssr" "3.1.5" + "@vue/shared" "3.1.5" + consolidate "^0.16.0" + estree-walker "^2.0.1" + hash-sum "^2.0.0" + lru-cache "^5.1.1" + magic-string "^0.25.7" + merge-source-map "^1.1.0" + postcss "^8.1.10" + postcss-modules "^4.0.0" + postcss-selector-parser "^6.0.4" + source-map "^0.6.1" + +"@vue/compiler-sfc@^3.2.0-beta.5": + version "3.2.0-beta.6" + resolved "https://registry.yarnpkg.com/@vue/compiler-sfc/-/compiler-sfc-3.2.0-beta.6.tgz#e49996ecce31a0b68ce5b3f67cad433fabe47720" + integrity sha512-v6docclqRg8yqU6lW8qwQNGF3/HvuP2kQXRJgn/mwGPnHAdPbZAbO/CDM8CGg9MYkzqOdr0ix8Ft//gmLpXQjg== + dependencies: + "@babel/parser" "^7.13.9" + "@babel/types" "^7.13.0" + "@types/estree" "^0.0.48" + "@vue/compiler-core" "3.2.0-beta.6" + "@vue/compiler-dom" "3.2.0-beta.6" + "@vue/compiler-ssr" "3.2.0-beta.6" + "@vue/shared" "3.2.0-beta.6" + consolidate "^0.16.0" + estree-walker "^2.0.1" + hash-sum "^2.0.0" + lru-cache "^5.1.1" + magic-string "^0.25.7" + merge-source-map "^1.1.0" + postcss "^8.1.10" + postcss-modules "^4.0.0" + postcss-selector-parser "^6.0.4" + source-map "^0.6.1" + "@vue/compiler-ssr@3.0.9": version "3.0.9" resolved "https://registry.yarnpkg.com/@vue/compiler-ssr/-/compiler-ssr-3.0.9.tgz#aebce25e573b9db34964b682bb1631a7240ba43d" @@ -8946,6 +9103,22 @@ "@vue/compiler-dom" "3.0.9" "@vue/shared" "3.0.9" +"@vue/compiler-ssr@3.1.5": + version "3.1.5" + resolved "https://registry.yarnpkg.com/@vue/compiler-ssr/-/compiler-ssr-3.1.5.tgz#f068652774293256a1e53084bed48a67682df9d2" + integrity sha512-CU5N7Di/a4lyJ18LGJxJYZS2a8PlLdWpWHX9p/XcsjT2TngMpj3QvHVRkuik2u8QrIDZ8OpYmTyj1WDNsOV+Dg== + dependencies: + "@vue/compiler-dom" "3.1.5" + "@vue/shared" "3.1.5" + +"@vue/compiler-ssr@3.2.0-beta.6": + version "3.2.0-beta.6" + resolved "https://registry.yarnpkg.com/@vue/compiler-ssr/-/compiler-ssr-3.2.0-beta.6.tgz#46a10981e4d74e06a2bafe068c39dd99d5bb6a1a" + integrity sha512-imF1MQaYVBJVPOs9QiJ59JCdbMUNNT0K3DTQj5YX/Zs9qkV8yQTEdXgWnsBFSlVdXYktCmEsG2tJb4HrFrKZMA== + dependencies: + "@vue/compiler-dom" "3.2.0-beta.6" + "@vue/shared" "3.2.0-beta.6" + "@vue/component-compiler-utils@^3.1.0", "@vue/component-compiler-utils@^3.1.2": version "3.2.0" resolved "https://registry.yarnpkg.com/@vue/component-compiler-utils/-/component-compiler-utils-3.2.0.tgz#8f85182ceed28e9b3c75313de669f83166d11e5d" @@ -8979,6 +9152,20 @@ dependencies: "@vue/shared" "3.0.11" +"@vue/reactivity@3.1.5": + version "3.1.5" + resolved "https://registry.yarnpkg.com/@vue/reactivity/-/reactivity-3.1.5.tgz#dbec4d9557f7c8f25c2635db1e23a78a729eb991" + integrity sha512-1tdfLmNjWG6t/CsPldh+foumYFo3cpyCHgBYQ34ylaMsJ+SNHQ1kApMIa8jN+i593zQuaw3AdWH0nJTARzCFhg== + dependencies: + "@vue/shared" "3.1.5" + +"@vue/reactivity@^3.2.0-beta.5": + version "3.2.0-beta.5" + resolved "https://registry.yarnpkg.com/@vue/reactivity/-/reactivity-3.2.0-beta.5.tgz#feb93dff247700213fec4c52569b901186850e16" + integrity sha512-MI+C+96B+GML1vWprH8N02blLpVWtkmcyg7ptP5dB6TDFooRA2MRfR4SMTi4rY6kKVR7qc5nc0CxpQ1XoPqFpA== + dependencies: + "@vue/shared" "3.2.0-beta.5" + "@vue/runtime-core@3.0.11": version "3.0.11" resolved "https://registry.yarnpkg.com/@vue/runtime-core/-/runtime-core-3.0.11.tgz#c52dfc6acf3215493623552c1c2919080c562e44" @@ -8987,6 +9174,14 @@ "@vue/reactivity" "3.0.11" "@vue/shared" "3.0.11" +"@vue/runtime-core@3.1.5": + version "3.1.5" + resolved "https://registry.yarnpkg.com/@vue/runtime-core/-/runtime-core-3.1.5.tgz#a545b7f146092929cb5e833e85439150f17ac87b" + integrity sha512-YQbG5cBktN1RowQDKA22itmvQ+b40f0WgQ6CXK4VYoYICAiAfu6Cc14777ve8zp1rJRGtk5oIeS149TOculrTg== + dependencies: + "@vue/reactivity" "3.1.5" + "@vue/shared" "3.1.5" + "@vue/runtime-dom@3.0.11": version "3.0.11" resolved "https://registry.yarnpkg.com/@vue/runtime-dom/-/runtime-dom-3.0.11.tgz#7a552df21907942721feb6961c418e222a699337" @@ -8996,6 +9191,15 @@ "@vue/shared" "3.0.11" csstype "^2.6.8" +"@vue/runtime-dom@3.1.5": + version "3.1.5" + resolved "https://registry.yarnpkg.com/@vue/runtime-dom/-/runtime-dom-3.1.5.tgz#4fa28947d408aa368fa17ea0edc1beb9af1472a1" + integrity sha512-tNcf3JhVR0RfW0kw1p8xZgv30nvX8Y9rsz7eiQ0dHe273sfoCngAG0y4GvMaY4Xd8FsjUwFedd4suQ8Lu8meXg== + dependencies: + "@vue/runtime-core" "3.1.5" + "@vue/shared" "3.1.5" + csstype "^2.6.8" + "@vue/shared@3.0.11": version "3.0.11" resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.0.11.tgz#20d22dd0da7d358bb21c17f9bde8628152642c77" @@ -9006,10 +9210,25 @@ resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.0.9.tgz#09882d745ded52b07e4481d036659d733edd2a9a" integrity sha512-lv20q1O5dybwro+V+vnxHCmSIxi9mvTORSgAbGrANGYK8zF4K1S9TOankIvdkcvfZ88IR95O2pTI2Pb3c3BaNg== -"@vue/test-utils@^2.0.0-rc.9": - version "2.0.0-rc.9" - resolved "https://registry.yarnpkg.com/@vue/test-utils/-/test-utils-2.0.0-rc.9.tgz#b3f817d710a1d0ae2084143520c9d8d3c552bfa6" - integrity sha512-iJNAAfXTTSd2/5vUZpFbUwUwC8w3hbFu8s9ptKkZGsiw6pO6mFsaLs2rzI3Ea/8hwqcF3K7Wp2diKOdzqmb6qg== +"@vue/shared@3.1.5": + version "3.1.5" + resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.1.5.tgz#74ee3aad995d0a3996a6bb9533d4d280514ede03" + integrity sha512-oJ4F3TnvpXaQwZJNF3ZK+kLPHKarDmJjJ6jyzVNDKH9md1dptjC7lWR//jrGuLdek/U6iltWxqAnYOu8gCiOvA== + +"@vue/shared@3.2.0-beta.5": + version "3.2.0-beta.5" + resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.2.0-beta.5.tgz#c2752bac51476bfd9c6050f4a5e97c28eb66f27a" + integrity sha512-DprP8v3vg/nnfl4b93hJ+ujojiFAMwXbng8N9NpNDSuFMZG0zFO3Tqh3X1JQgaE7jUgYoQzR2TTGCKNb/4+QGA== + +"@vue/shared@3.2.0-beta.6", "@vue/shared@^3.2.0-beta.5": + version "3.2.0-beta.6" + resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.2.0-beta.6.tgz#2499399faba055c8f7b8743d5bd47a09fb1b8cc0" + integrity sha512-P00v895ONlx4P6D8p9OyJv+iL0+QghaDm1BDlhP8ibsu9MqHznoyZ/r1rHuLQEAR//4SMMo/9dC3SW8edUPvBw== + +"@vue/test-utils@^2.0.0-rc.10": + version "2.0.0-rc.10" + resolved "https://registry.yarnpkg.com/@vue/test-utils/-/test-utils-2.0.0-rc.10.tgz#9ed689cd7d5a1c9ef6693806010e464d2ecc13b2" + integrity sha512-Z8jY+askU08svsI37NcJSLmWrfkZ/1ATA1DENWezRUX2uv3QyEj7idwx+rfeNSOrlNNBh4NTzypBKOUOklxBRA== "@vue/web-component-wrapper@^1.2.0": version "1.3.0" @@ -10456,6 +10675,11 @@ asn1@~0.2.3: dependencies: safer-buffer "~2.1.0" +assert-never@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/assert-never/-/assert-never-1.2.1.tgz#11f0e363bf146205fb08193b5c7b90f4d1cf44fe" + integrity sha512-TaTivMB6pYI1kXwrFlEhLeGfOqoDNdTxjCdwRfFFkEA30Eu+k48W34nlok2EYWJfFFzqaEmichdNM7th6M5HNw== + assert-plus@1.0.0, assert-plus@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" @@ -11798,6 +12022,16 @@ babel-preset-stage-3@^6.24.1: babel-plugin-transform-exponentiation-operator "^6.24.1" babel-plugin-transform-object-rest-spread "^6.22.0" +babel-preset-typescript-vue3@^2.0.14: + version "2.0.14" + resolved "https://registry.yarnpkg.com/babel-preset-typescript-vue3/-/babel-preset-typescript-vue3-2.0.14.tgz#d60dd7a53d8e1fb60ff755aaaaa5f05c2f871f0f" + integrity sha512-aChegBF7AUMkIyR7aDeAa/boeeLPxfx2lObr4/H7VXXB3PR6KHtsriRFs/vzELCm1rvButQJAFpBRexJqUYTSA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-transform-typescript" "^7.3.2" + "@babel/preset-typescript" "^7.3.3" + "@vue/compiler-sfc" "^3.0.5" + babel-preset-typescript-vue@^1.0.3: version "1.1.1" resolved "https://registry.yarnpkg.com/babel-preset-typescript-vue/-/babel-preset-typescript-vue-1.1.1.tgz#6a617dcb0ee26f911735d5f2bbe530286b2c7c02" @@ -11872,6 +12106,13 @@ babel-types@^6.18.0, babel-types@^6.19.0, babel-types@^6.23.0, babel-types@^6.24 lodash "^4.17.4" to-fast-properties "^1.0.3" +babel-walk@3.0.0-canary-5: + version "3.0.0-canary-5" + resolved "https://registry.yarnpkg.com/babel-walk/-/babel-walk-3.0.0-canary-5.tgz#f66ecd7298357aee44955f235a6ef54219104b11" + integrity sha512-GAwkz0AihzY5bkwIY5QDR+LvsRQgB/B+1foMPvi0FZPMl5fjD7ICiznUiBdLYMH1QYe6vqu4gWYytZOccLouFw== + dependencies: + "@babel/types" "^7.9.6" + babelify@10.0.0: version "10.0.0" resolved "https://registry.yarnpkg.com/babelify/-/babelify-10.0.0.tgz#fe73b1a22583f06680d8d072e25a1e0d1d1d7fb5" @@ -13266,6 +13507,13 @@ character-entities@^1.0.0: resolved "https://registry.yarnpkg.com/character-entities/-/character-entities-1.2.4.tgz#e12c3939b7eaf4e5b15e7ad4c5e28e1d48c5b16b" integrity sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw== +character-parser@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/character-parser/-/character-parser-2.2.0.tgz#c7ce28f36d4bcd9744e5ffc2c5fcde1c73261fc0" + integrity sha1-x84o821LzZdE5f/CxfzeHHMmH8A= + dependencies: + is-regex "^1.0.3" + character-reference-invalid@^1.0.0: version "1.1.4" resolved "https://registry.yarnpkg.com/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz#083329cda0eae272ab3dbbf37e9a382c13af1560" @@ -14321,6 +14569,14 @@ constant-case@^2.0.0: snake-case "^2.1.0" upper-case "^1.1.1" +constantinople@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/constantinople/-/constantinople-4.0.1.tgz#0def113fa0e4dc8de83331a5cf79c8b325213151" + integrity sha512-vCrqcSIq4//Gx74TXXCGnHpulY1dskqLTFGDmhrGxzeXL8lF8kvXv6mpNWlJj1uD4DW23D4ljAqbY4RRaaUZIw== + dependencies: + "@babel/parser" "^7.6.0" + "@babel/types" "^7.6.1" + constants-browserify@1.0.0, constants-browserify@^1.0.0, constants-browserify@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" @@ -16502,6 +16758,11 @@ doctrine@^3.0.0: dependencies: esutils "^2.0.2" +doctypes@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/doctypes/-/doctypes-1.1.0.tgz#ea80b106a87538774e8a3a4a5afe293de489e0a9" + integrity sha1-6oCxBqh1OHdOijpKWv4pPeSJ4Kk= + dom-accessibility-api@^0.5.4: version "0.5.4" resolved "https://registry.yarnpkg.com/dom-accessibility-api/-/dom-accessibility-api-0.5.4.tgz#b06d059cdd4a4ad9a79275f9d414a5c126241166" @@ -16566,10 +16827,10 @@ domelementtype@1, domelementtype@^1.3.1: resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.1.tgz#d048c44b37b0d10a7f2a3d5fee3f4333d790481f" integrity sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w== -domelementtype@^2.0.1, domelementtype@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.1.0.tgz#a851c080a6d1c3d94344aed151d99f669edf585e" - integrity sha512-LsTgx/L5VpD+Q8lmsXSHW2WpA+eBlZ9HPf3erD1IoPF00/3JKHZ3BknUVA2QGDNu69ZNmyFmCWBSO45XjYKC5w== +domelementtype@^2.0.1, domelementtype@^2.1.0, domelementtype@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.2.0.tgz#9a0b6c2782ed6a1c7323d42267183df9bd8b1d57" + integrity sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A== domexception@^1.0.1: version "1.0.1" @@ -16585,12 +16846,12 @@ domhandler@^2.3.0: dependencies: domelementtype "1" -domhandler@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.0.0.tgz#01ea7821de996d85f69029e81fa873c21833098e" - integrity sha512-KPTbnGQ1JeEMQyO1iYXoagsI6so/C96HZiFyByU3T6iAzpXn8EGEvct6unm1ZGoed8ByO2oirxgwxBmqKF9haA== +domhandler@^4.0.0, domhandler@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.2.0.tgz#f9768a5f034be60a89a27c2e4d0f74eba0d8b059" + integrity sha512-zk7sgt970kzPks2Bf+dwT/PLzghLnsivb9CcxkvR8Mzr66Olr0Ofd8neSbglHJHaHa2MadfoSdNlKYAaafmWfA== dependencies: - domelementtype "^2.1.0" + domelementtype "^2.2.0" domutils@^1.5.1, domutils@^1.7.0: version "1.7.0" @@ -16600,14 +16861,14 @@ domutils@^1.5.1, domutils@^1.7.0: dom-serializer "0" domelementtype "1" -domutils@^2.4.3, domutils@^2.4.4: - version "2.4.4" - resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.4.4.tgz#282739c4b150d022d34699797369aad8d19bbbd3" - integrity sha512-jBC0vOsECI4OMdD0GC9mGn7NXPLb+Qt6KW1YDQzeQYRUFKmNG8lh7mO5HiELfr+lLQE7loDVI4QcAxV80HS+RA== +domutils@^2.4.3, domutils@^2.4.4, domutils@^2.5.2: + version "2.7.0" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.7.0.tgz#8ebaf0c41ebafcf55b0b72ec31c56323712c5442" + integrity sha512-8eaHa17IwJUPAiB+SoTYBo5mCdeMgdcAoXJ59m6DT1vw+5iLS3gNoqYaRowaBKtGVrOF1Jz4yDTgYKLK2kvfJg== dependencies: dom-serializer "^1.0.1" - domelementtype "^2.0.1" - domhandler "^4.0.0" + domelementtype "^2.2.0" + domhandler "^4.2.0" dot-case@^2.1.0: version "2.1.1" @@ -16972,6 +17233,14 @@ email-validator@^2.0.3: resolved "https://registry.yarnpkg.com/email-validator/-/email-validator-2.0.4.tgz#b8dfaa5d0dae28f1b03c95881d904d4e40bfe7ed" integrity sha512-gYCwo7kh5S3IDyZPLZf6hSS0MnZT8QmJFqYvbqlDZSbwdZlY6QZWxJ4i/6UhITOJ4XzyI647Bm2MXKCLqnJ4nQ== +emmet@^2.3.0: + version "2.3.4" + resolved "https://registry.yarnpkg.com/emmet/-/emmet-2.3.4.tgz#5ba0d7a5569a68c7697dfa890c772e4f3179d123" + integrity sha512-3IqSwmO+N2ZGeuhDyhV/TIOJFUbkChi53bcasSNRE7Yd+4eorbbYz4e53TpMECt38NtYkZNupQCZRlwdAYA42A== + dependencies: + "@emmetio/abbreviation" "^2.2.2" + "@emmetio/css-abbreviation" "^2.1.4" + "emoji-regex@>=6.0.0 <=6.1.1": version "6.1.1" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-6.1.1.tgz#c6cd0ec1b0642e2a3c67a1137efc5e796da4f88e" @@ -21371,14 +21640,14 @@ htmlparser2@^3.10.1: inherits "^2.0.1" readable-stream "^3.1.1" -htmlparser2@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-6.0.0.tgz#c2da005030390908ca4c91e5629e418e0665ac01" - integrity sha512-numTQtDZMoh78zJpaNdJ9MXb2cv5G3jwUoe3dMQODubZvLoGvTE/Ofp6sHvH8OGKcN/8A47pGLi/k58xHP/Tfw== +htmlparser2@^6.0.0, htmlparser2@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-6.1.0.tgz#c4d762b6c3371a05dbe65e94ae43a9f845fb8fb7" + integrity sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A== dependencies: domelementtype "^2.0.1" domhandler "^4.0.0" - domutils "^2.4.4" + domutils "^2.5.2" entities "^2.0.0" http-assert@^1.3.0: @@ -22395,6 +22664,14 @@ is-equal-shallow@^0.1.3: dependencies: is-primitive "^2.0.0" +is-expression@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/is-expression/-/is-expression-4.0.0.tgz#c33155962abf21d0afd2552514d67d2ec16fd2ab" + integrity sha512-zMIXX63sxzG3XrkHkrAPvm/OVZVSCPNkwMHU8oTX7/U3AL78I0QXCEICXUM13BIa8TYGZ68PiTKfQz3yaTNr4A== + dependencies: + acorn "^7.1.1" + object-assign "^4.1.1" + is-extendable@^0.1.0, is-extendable@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" @@ -22712,6 +22989,11 @@ is-primitive@^2.0.0: resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575" integrity sha1-IHurkWOEmcB7Kt8kCkGochADRXU= +is-promise@^2.0.0: + version "2.2.2" + resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.2.2.tgz#39ab959ccbf9a774cf079f7b40c7a26f763135f1" + integrity sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ== + is-property@^1.0.0, is-property@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84" @@ -22729,13 +23011,13 @@ is-reference@^1.2.1: dependencies: "@types/estree" "*" -is-regex@^1.0.5, is-regex@^1.1.0, is-regex@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.2.tgz#81c8ebde4db142f2cf1c53fc86d6a45788266251" - integrity sha512-axvdhb5pdhEVThqJzYXwMlVuZwC+FF2DpcOhTS+y/8jVq4trxyPgfcwIxIKiyeuLlSQYKkmUaPQJ8ZE4yNKXDg== +is-regex@^1.0.3, is-regex@^1.0.5, is-regex@^1.1.0, is-regex@^1.1.2: + version "1.1.3" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.3.tgz#d029f9aff6448b93ebbe3f33dac71511fdcbef9f" + integrity sha512-qSVXFz28HM7y+IWX6vLCsexdlvzT1PJNFSBuaQLQ5o0IEw8UDYW6/2+eCMVyIsbM8CNLX2a/QWmSpyxYEHY7CQ== dependencies: call-bind "^1.0.2" - has-symbols "^1.0.1" + has-symbols "^1.0.2" is-regexp@^1.0.0: version "1.0.0" @@ -23910,6 +24192,11 @@ js-string-escape@^1.0.1: resolved "https://registry.yarnpkg.com/js-string-escape/-/js-string-escape-1.0.1.tgz#e2625badbc0d67c7533e9edc1068c587ae4137ef" integrity sha1-4mJbrbwNZ8dTPp7cEGjFh65BN+8= +js-stringify@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/js-stringify/-/js-stringify-1.0.2.tgz#1736fddfd9724f28a3682adc6230ae7e4e9679db" + integrity sha1-Fzb939lyTyijaCrcYjCufk6Weds= + js-tokens@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-1.0.1.tgz#cc435a5c8b94ad15acb7983140fc80182c89aeae" @@ -24279,6 +24566,11 @@ jsonc-parser@3.0.0, jsonc-parser@^3.0.0: resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-3.0.0.tgz#abdd785701c7e7eaca8a9ec8cf070ca51a745a22" integrity sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA== +jsonc-parser@^2.3.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-2.3.1.tgz#59549150b133f2efacca48fe9ce1ec0659af2342" + integrity sha512-H8jvkz1O50L3dMZCsLqiuB2tA7muqbSg1AtGEkN0leAqGjsUzDJir3Zwr02BhqdcITPg3ei3mZ+HjMocAknhhg== + jsonfile@^2.1.0: version "2.4.0" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-2.4.0.tgz#3736a2b428b87bbda0cc83b53fa3d633a35c2ae8" @@ -24429,6 +24721,14 @@ jss@10.5.1, jss@^10.5.1: is-in-browser "^1.1.3" tiny-warning "^1.0.2" +jstransformer@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/jstransformer/-/jstransformer-1.0.0.tgz#ed8bf0921e2f3f1ed4d5c1a44f68709ed24722c3" + integrity sha1-7Yvwkh4vPx7U1cGkT2hwntJHIsM= + dependencies: + is-promise "^2.0.0" + promise "^7.0.1" + jsx-ast-utils@^2.1.0, jsx-ast-utils@^2.2.1, jsx-ast-utils@^2.2.3, "jsx-ast-utils@^2.4.1 || ^3.0.0": version "2.4.1" resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-2.4.1.tgz#1114a4c1209481db06c690c2b4f488cc665f657e" @@ -31190,7 +31490,7 @@ promise@7.0.4: dependencies: asap "~2.0.3" -promise@^7.1.1: +promise@^7.0.1, promise@^7.1.1: version "7.3.1" resolved "https://registry.yarnpkg.com/promise/-/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf" integrity sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg== @@ -31330,6 +31630,109 @@ public-encrypt@^4.0.0: randombytes "^2.0.1" safe-buffer "^5.1.2" +pug-attrs@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pug-attrs/-/pug-attrs-3.0.0.tgz#b10451e0348165e31fad1cc23ebddd9dc7347c41" + integrity sha512-azINV9dUtzPMFQktvTXciNAfAuVh/L/JCl0vtPCwvOA21uZrC08K/UnmrL+SXGEVc1FwzjW62+xw5S/uaLj6cA== + dependencies: + constantinople "^4.0.1" + js-stringify "^1.0.2" + pug-runtime "^3.0.0" + +pug-code-gen@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/pug-code-gen/-/pug-code-gen-3.0.2.tgz#ad190f4943133bf186b60b80de483100e132e2ce" + integrity sha512-nJMhW16MbiGRiyR4miDTQMRWDgKplnHyeLvioEJYbk1RsPI3FuA3saEP8uwnTb2nTJEKBU90NFVWJBk4OU5qyg== + dependencies: + constantinople "^4.0.1" + doctypes "^1.1.0" + js-stringify "^1.0.2" + pug-attrs "^3.0.0" + pug-error "^2.0.0" + pug-runtime "^3.0.0" + void-elements "^3.1.0" + with "^7.0.0" + +pug-error@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/pug-error/-/pug-error-2.0.0.tgz#5c62173cb09c34de2a2ce04f17b8adfec74d8ca5" + integrity sha512-sjiUsi9M4RAGHktC1drQfCr5C5eriu24Lfbt4s+7SykztEOwVZtbFk1RRq0tzLxcMxMYTBR+zMQaG07J/btayQ== + +pug-filters@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/pug-filters/-/pug-filters-4.0.0.tgz#d3e49af5ba8472e9b7a66d980e707ce9d2cc9b5e" + integrity sha512-yeNFtq5Yxmfz0f9z2rMXGw/8/4i1cCFecw/Q7+D0V2DdtII5UvqE12VaZ2AY7ri6o5RNXiweGH79OCq+2RQU4A== + dependencies: + constantinople "^4.0.1" + jstransformer "1.0.0" + pug-error "^2.0.0" + pug-walk "^2.0.0" + resolve "^1.15.1" + +pug-lexer@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/pug-lexer/-/pug-lexer-5.0.1.tgz#ae44628c5bef9b190b665683b288ca9024b8b0d5" + integrity sha512-0I6C62+keXlZPZkOJeVam9aBLVP2EnbeDw3An+k0/QlqdwH6rv8284nko14Na7c0TtqtogfWXcRoFE4O4Ff20w== + dependencies: + character-parser "^2.2.0" + is-expression "^4.0.0" + pug-error "^2.0.0" + +pug-linker@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/pug-linker/-/pug-linker-4.0.0.tgz#12cbc0594fc5a3e06b9fc59e6f93c146962a7708" + integrity sha512-gjD1yzp0yxbQqnzBAdlhbgoJL5qIFJw78juN1NpTLt/mfPJ5VgC4BvkoD3G23qKzJtIIXBbcCt6FioLSFLOHdw== + dependencies: + pug-error "^2.0.0" + pug-walk "^2.0.0" + +pug-load@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pug-load/-/pug-load-3.0.0.tgz#9fd9cda52202b08adb11d25681fb9f34bd41b662" + integrity sha512-OCjTEnhLWZBvS4zni/WUMjH2YSUosnsmjGBB1An7CsKQarYSWQ0GCVyd4eQPMFJqZ8w9xgs01QdiZXKVjk92EQ== + dependencies: + object-assign "^4.1.1" + pug-walk "^2.0.0" + +pug-parser@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/pug-parser/-/pug-parser-6.0.0.tgz#a8fdc035863a95b2c1dc5ebf4ecf80b4e76a1260" + integrity sha512-ukiYM/9cH6Cml+AOl5kETtM9NR3WulyVP2y4HOU45DyMim1IeP/OOiyEWRr6qk5I5klpsBnbuHpwKmTx6WURnw== + dependencies: + pug-error "^2.0.0" + token-stream "1.0.0" + +pug-runtime@^3.0.0, pug-runtime@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/pug-runtime/-/pug-runtime-3.0.1.tgz#f636976204723f35a8c5f6fad6acda2a191b83d7" + integrity sha512-L50zbvrQ35TkpHwv0G6aLSuueDRwc/97XdY8kL3tOT0FmhgG7UypU3VztfV/LATAvmUfYi4wNxSajhSAeNN+Kg== + +pug-strip-comments@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/pug-strip-comments/-/pug-strip-comments-2.0.0.tgz#f94b07fd6b495523330f490a7f554b4ff876303e" + integrity sha512-zo8DsDpH7eTkPHCXFeAk1xZXJbyoTfdPlNR0bK7rpOMuhBYb0f5qUVCO1xlsitYd3w5FQTK7zpNVKb3rZoUrrQ== + dependencies: + pug-error "^2.0.0" + +pug-walk@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/pug-walk/-/pug-walk-2.0.0.tgz#417aabc29232bb4499b5b5069a2b2d2a24d5f5fe" + integrity sha512-yYELe9Q5q9IQhuvqsZNwA5hfPkMJ8u92bQLIMcsMxf/VADjNtEYptU+inlufAFYcWdHlwNfZOEnOOQrZrcyJCQ== + +pug@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/pug/-/pug-3.0.2.tgz#f35c7107343454e43bc27ae0ff76c731b78ea535" + integrity sha512-bp0I/hiK1D1vChHh6EfDxtndHji55XP/ZJKwsRqrz6lRia6ZC2OZbdAymlxdVFwd1L70ebrVJw4/eZ79skrIaw== + dependencies: + pug-code-gen "^3.0.2" + pug-filters "^4.0.0" + pug-lexer "^5.0.1" + pug-linker "^4.0.0" + pug-load "^3.0.0" + pug-parser "^6.0.0" + pug-runtime "^3.0.1" + pug-strip-comments "^2.0.0" + pump@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/pump/-/pump-2.0.1.tgz#12399add6e4cf7526d973cbc8b5ce2e2908b3909" @@ -32897,7 +33300,7 @@ regenerate@^1.2.1, regenerate@^1.4.0: resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a" integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A== -regenerator-runtime@0.13.7, regenerator-runtime@^0.13.3, regenerator-runtime@^0.13.4, regenerator-runtime@^0.13.7: +regenerator-runtime@0.13.7: version "0.13.7" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz#cac2dacc8a1ea675feaabaeb8ae833898ae46f55" integrity sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew== @@ -32912,6 +33315,11 @@ regenerator-runtime@^0.12.0: resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz#fa1a71544764c036f8c49b13a08b2594c9f8a0de" integrity sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg== +regenerator-runtime@^0.13.3, regenerator-runtime@^0.13.4, regenerator-runtime@^0.13.7: + version "0.13.9" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz#8925742a98ffd90814988d7566ad30ca3b263b52" + integrity sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA== + regenerator-transform@^0.10.0: version "0.10.1" resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.10.1.tgz#1e4996837231da8b7f3cf4114d71b5691a0680dd" @@ -33245,6 +33653,11 @@ replace-homedir@^1.0.0: is-absolute "^1.0.0" remove-trailing-separator "^1.1.0" +request-light@^0.5.4: + version "0.5.4" + resolved "https://registry.yarnpkg.com/request-light/-/request-light-0.5.4.tgz#497a98c6d8ae49536417a5e2d7f383b934f3e38c" + integrity sha512-t3566CMweOFlUk7Y1DJMu5OrtpoZEb6aSTsLQVT3wtrIEJ5NhcY9G/Oqxvjllzl4a15zXfFlcr9q40LbLVQJqw== + request-progress@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/request-progress/-/request-progress-3.0.0.tgz#4ca754081c7fec63f505e4faa825aa06cd669dbe" @@ -37167,6 +37580,11 @@ toidentifier@1.0.0: resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw== +token-stream@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/token-stream/-/token-stream-1.0.0.tgz#cc200eab2613f4166d27ff9afc7ca56d49df6eb4" + integrity sha1-zCAOqyYT9BZtJ/+a/HylbUnfbrQ= + toposort@^1.0.0: version "1.0.7" resolved "https://registry.yarnpkg.com/toposort/-/toposort-1.0.7.tgz#2e68442d9f64ec720b8cc89e6443ac6caa950029" @@ -37666,11 +38084,6 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= -typescript@3.9.6: - version "3.9.6" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.6.tgz#8f3e0198a34c3ae17091b35571d3afd31999365a" - integrity sha512-Pspx3oKAPJtjNwE92YS05HQoY7z2SFyOpHo9MqJor3BXAGNaPUs83CuVp9VISFkSjyRfiTpmKuAYGJB7S7hOxw== - typescript@4.1.5: version "4.1.5" resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.1.5.tgz#123a3b214aaff3be32926f0d8f1f6e704eb89a72" @@ -38098,6 +38511,11 @@ upath@^1.1.1, upath@^1.2.0: resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894" integrity sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg== +upath@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/upath/-/upath-2.0.1.tgz#50c73dea68d6f6b990f51d279ce6081665d61a8b" + integrity sha512-1uEe95xksV1O0CYKXo8vQvN1JEbtJp7lb7C5U9HMsIp6IVwntkH/oNUzyVNQSd4S1sYk2FpSSW44FqMc8qee5w== + update-check@1.5.2: version "1.5.2" resolved "https://registry.yarnpkg.com/update-check/-/update-check-1.5.2.tgz#2fe09f725c543440b3d7dabe8971f2d5caaedc28" @@ -38898,6 +39316,153 @@ void-elements@^2.0.1: resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec" integrity sha1-wGavtYK7HLQSjWDqkjkulNXp2+w= +void-elements@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-3.1.0.tgz#614f7fbf8d801f0bb5f0661f5b2f5785750e4f09" + integrity sha1-YU9/v42AHwu18GYfWy9XhXUOTwk= + +vscode-css-languageservice@^5.1.4: + version "5.1.4" + resolved "https://registry.yarnpkg.com/vscode-css-languageservice/-/vscode-css-languageservice-5.1.4.tgz#07e4c63f1c3bb06e6f3f329c32b490d20a601bab" + integrity sha512-fIJZJMXbaBsK0ifBb2RmSiLtzwn6NrZnKn7O+0ziIjwAY+rPvSK9St2qqQXFU3reZVRAt/I4GBp40dC/THcUDA== + dependencies: + vscode-languageserver-textdocument "^1.0.1" + vscode-languageserver-types "^3.16.0" + vscode-nls "^5.0.0" + vscode-uri "^3.0.2" + +vscode-emmet-helper@^2.6.4: + version "2.6.4" + resolved "https://registry.yarnpkg.com/vscode-emmet-helper/-/vscode-emmet-helper-2.6.4.tgz#bea47f17649bba26b412f3d1fac18aaee43eba25" + integrity sha512-fP0nunW1RUWEKGf4gqiYLOVNFFGXSRHjCl0pikxtwCFlty8WwimM+RBJ5o0aIiwerrYD30HqeaVyvDW027Sseg== + dependencies: + emmet "^2.3.0" + jsonc-parser "^2.3.0" + vscode-languageserver-textdocument "^1.0.1" + vscode-languageserver-types "^3.15.1" + vscode-nls "^5.0.0" + vscode-uri "^2.1.2" + +vscode-html-languageservice@^4.0.7: + version "4.0.7" + resolved "https://registry.yarnpkg.com/vscode-html-languageservice/-/vscode-html-languageservice-4.0.7.tgz#94f2ed22c821965f828222d13b5aa541b358d992" + integrity sha512-P5TQMYpgxAdLs+PwpC7Lm+0lXCyQAC6kZ41YuPYNHVooC4XO7Y2+ncHBcQJVK4C9LU2cTOAl0lzq4WAxuwRHYw== + dependencies: + vscode-languageserver-textdocument "^1.0.1" + vscode-languageserver-types "^3.16.0" + vscode-nls "^5.0.0" + vscode-uri "^3.0.2" + +vscode-json-languageservice@^4.1.5: + version "4.1.6" + resolved "https://registry.yarnpkg.com/vscode-json-languageservice/-/vscode-json-languageservice-4.1.6.tgz#4275e8daf1cba80273c318f33fbf7a2ede307053" + integrity sha512-DIKb3tcfRtb3tIE6g9SLOl5E9tNSt6kljH08Wa5RwFlVshtXGrDDzttchze4CYy9pJpE9mBtCbRHmLvY1Z1ZXA== + dependencies: + jsonc-parser "^3.0.0" + vscode-languageserver-textdocument "^1.0.1" + vscode-languageserver-types "^3.16.0" + vscode-nls "^5.0.0" + vscode-uri "^3.0.2" + +vscode-jsonrpc@8.0.0-next.1, vscode-jsonrpc@^8.0.0-next.1: + version "8.0.0-next.1" + resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-8.0.0-next.1.tgz#1964688a9851f86900c55e298939a157b2e224ad" + integrity sha512-NoSPIqVWpztdC91oUaiN9PmjAupRAEF8vdXRDLWw2lX2k760dn0gO4CCXkT6GdLSBcF/xKq0zWVTsfd3lpje7g== + +vscode-languageserver-protocol@3.17.0-next.7: + version "3.17.0-next.7" + resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.0-next.7.tgz#2150edb86b6a51c325003b437a522f0dcfc604b4" + integrity sha512-naG6LWmcF+cneRx6ia16rg+ukSWaZNESFRv+rKE5sIp69IFbuehXcRwkyeS1jZa2SRCF/TnN/H+y9gBbvFqsaQ== + dependencies: + vscode-jsonrpc "8.0.0-next.1" + vscode-languageserver-types "3.17.0-next.3" + +vscode-languageserver-textdocument@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.1.tgz#178168e87efad6171b372add1dea34f53e5d330f" + integrity sha512-UIcJDjX7IFkck7cSkNNyzIz5FyvpQfY7sdzVy+wkKN/BLaD4DQ0ppXQrKePomCxTS7RrolK1I0pey0bG9eh8dA== + +vscode-languageserver-types@3.17.0-next.3: + version "3.17.0-next.3" + resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.17.0-next.3.tgz#e1f4311e08ea3193e81126154b6a342fc1c3dba3" + integrity sha512-VQcXnhKYxUW6OiRMhG++SzmZYMJwusXknJGd+FfdOnS1yHAo734OHyR0e2eEHDlv0/oWc8RZPgx/VKSKyondVg== + +vscode-languageserver-types@^3.15.1, vscode-languageserver-types@^3.16.0: + version "3.16.0" + resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.16.0.tgz#ecf393fc121ec6974b2da3efb3155644c514e247" + integrity sha512-k8luDIWJWyenLc5ToFQQMaSrqCHiLwyKPHKPQZ5zz21vM+vIVUSvsRpcbiECH4WR88K2XZqc4ScRcZ7nk/jbeA== + +vscode-languageserver@^8.0.0-next.1: + version "8.0.0-next.1" + resolved "https://registry.yarnpkg.com/vscode-languageserver/-/vscode-languageserver-8.0.0-next.1.tgz#b5844585acf862a7bdaab22d28c9da0f1527d790" + integrity sha512-Sjmjcl5OMvE64eblJMqj8p7JDtJKf3CVkZXOqWwLINoSRCH9tkZdBss37bVOmpTy89sKX9fKwuBbEE8jNb8Isw== + dependencies: + vscode-languageserver-protocol "3.17.0-next.7" + +vscode-nls@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-5.0.0.tgz#99f0da0bd9ea7cda44e565a74c54b1f2bc257840" + integrity sha512-u0Lw+IYlgbEJFF6/qAqG2d1jQmJl0eyAGJHoAJqr2HT4M2BNuQYSEiSE75f52pXHSJm8AlTjnLLbBFPrdz2hpA== + +vscode-pug-languageservice@^0.26.9: + version "0.26.9" + resolved "https://registry.yarnpkg.com/vscode-pug-languageservice/-/vscode-pug-languageservice-0.26.9.tgz#3ae9745e3fb4bb7bd1cbe5f28e4c18f1dafbe5c2" + integrity sha512-WKgam/RsF2N71b5MpBDUnyka4Y2DaFc3Z7bvOrccHWd7fs4p2mAaiAOrOxTuy3Vb+mzhxK437QHbgp7FiNwxuA== + dependencies: + "@volar/code-gen" "^0.26.9" + "@volar/shared" "^0.26.9" + "@volar/source-map" "^0.26.9" + "@volar/transforms" "^0.26.9" + pug-lexer "^5.0.1" + pug-parser "^6.0.0" + vscode-languageserver "^8.0.0-next.1" + +vscode-typescript-languageservice@^0.26.9: + version "0.26.9" + resolved "https://registry.yarnpkg.com/vscode-typescript-languageservice/-/vscode-typescript-languageservice-0.26.9.tgz#fe641e0cf58b7d927d8cc11e3cd18cdd4c012701" + integrity sha512-TwHu99LdIPi276cgIO0cjanATDEhhykUCytuid4MJDNtViUMDio4GqZcyySusO24xoIe5IIPoNxYWXPcwBlt5Q== + dependencies: + "@volar/shared" "^0.26.9" + upath "^2.0.1" + vscode-languageserver "^8.0.0-next.1" + vscode-languageserver-textdocument "^1.0.1" + +vscode-uri@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-2.1.2.tgz#c8d40de93eb57af31f3c715dd650e2ca2c096f1c" + integrity sha512-8TEXQxlldWAuIODdukIb+TR5s+9Ds40eSJrw+1iDDA9IFORPjMELarNQE3myz5XIkWWpdprmJjm1/SxMlWOC8A== + +vscode-uri@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-3.0.2.tgz#ecfd1d066cb8ef4c3a208decdbab9a8c23d055d0" + integrity sha512-jkjy6pjU1fxUvI51P+gCsxg1u2n8LSt0W6KrCNQceaziKzff74GoWmjVG46KieVzybO1sttPQmYfrwSHey7GUA== + +vscode-vue-languageservice@^0.26.6: + version "0.26.9" + resolved "https://registry.yarnpkg.com/vscode-vue-languageservice/-/vscode-vue-languageservice-0.26.9.tgz#300b7c5821587454a976872608208e5ae85b3381" + integrity sha512-ybVaF10QFZZyzHBD/LbOdeS660YC2VL3+F12SzfbKj3xhzDQTFXxsy7FrDrcPUxtYobcZaBrPciBauQH2TVfxQ== + dependencies: + "@volar/code-gen" "^0.26.9" + "@volar/html2pug" "^0.26.9" + "@volar/shared" "^0.26.9" + "@volar/source-map" "^0.26.9" + "@volar/transforms" "^0.26.9" + "@vue/compiler-dom" "^3.2.0-beta.5" + "@vue/compiler-sfc" "^3.2.0-beta.5" + "@vue/reactivity" "^3.2.0-beta.5" + "@vue/shared" "^3.2.0-beta.5" + jsonc-parser "^3.0.0" + request-light "^0.5.4" + upath "^2.0.1" + vscode-css-languageservice "^5.1.4" + vscode-emmet-helper "^2.6.4" + vscode-html-languageservice "^4.0.7" + vscode-json-languageservice "^4.1.5" + vscode-languageserver "^8.0.0-next.1" + vscode-languageserver-textdocument "^1.0.1" + vscode-pug-languageservice "^0.26.9" + vscode-typescript-languageservice "^0.26.9" + vue-eslint-parser@^7.0.0: version "7.6.0" resolved "https://registry.yarnpkg.com/vue-eslint-parser/-/vue-eslint-parser-7.6.0.tgz#01ea1a2932f581ff244336565d712801f8f72561" @@ -38978,6 +39543,13 @@ vue-template-es2015-compiler@^1.9.0: resolved "https://registry.yarnpkg.com/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.9.1.tgz#1ee3bc9a16ecbf5118be334bb15f9c46f82f5825" integrity sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw== +vue-tsc@0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/vue-tsc/-/vue-tsc-0.2.2.tgz#e7fd5e5c789beb31840ad26082cfc8bb6356e733" + integrity sha512-91mzfGneWCuF83WTGRI9HA67IBUh5lrhujnFaHKWHQlpQFcBadkmz0BVoGAuJLQILetC5/CrY3is6FGiWFuY4w== + dependencies: + vscode-vue-languageservice "^0.26.6" + vue@3.0.11: version "3.0.11" resolved "https://registry.yarnpkg.com/vue/-/vue-3.0.11.tgz#c82f9594cbf4dcc869241d4c8dd3e08d9a8f4b5f" @@ -38987,6 +39559,15 @@ vue@3.0.11: "@vue/runtime-dom" "3.0.11" "@vue/shared" "3.0.11" +vue@3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/vue/-/vue-3.1.5.tgz#12879b11d0685ee4478c8869551799630a52f9fe" + integrity sha512-Ho7HNb1nfDoO+HVb6qYZgeaobt1XbY6KXFe4HGs1b9X6RhkWG/113n4/SrtM1LUclM6OrP/Se5aPHHvAPG1iVQ== + dependencies: + "@vue/compiler-dom" "3.1.5" + "@vue/runtime-dom" "3.1.5" + "@vue/shared" "3.1.5" + vuex@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/vuex/-/vuex-4.0.0.tgz#ac877aa76a9c45368c979471e461b520d38e6cf5" @@ -39906,6 +40487,16 @@ winston@2.4.4: isstream "0.1.x" stack-trace "0.0.x" +with@^7.0.0: + version "7.0.2" + resolved "https://registry.yarnpkg.com/with/-/with-7.0.2.tgz#ccee3ad542d25538a7a7a80aad212b9828495bac" + integrity sha512-RNGKj82nUPg3g5ygxkQl0R937xLyho1J24ItRCBTr/m1YnZkzJy1hUiHUJrc/VlsDQzsCnInEGSg3bci0Lmd4w== + dependencies: + "@babel/parser" "^7.9.6" + "@babel/types" "^7.9.6" + assert-never "^1.2.1" + babel-walk "3.0.0-canary-5" + word-wrap@^1.2.3, word-wrap@~1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" From e2f395e330f384993ed1116469102a5315a21270 Mon Sep 17 00:00:00 2001 From: Tim Griesser Date: Mon, 2 Aug 2021 08:54:33 -0400 Subject: [PATCH 14/14] feat: Structuring context & schema so it can be used on the client (#17489) * wip: Structuring context & schema so it can be used on the client * chore: fix dev mode * Continuing to restructure graphql patterns * Cleaning up the server * Don't hash for now, for vite * fix for CI * WIP on integrating with vue * yarn lock * no need to return props from setup * use useResult for more concise and better type safety * fix regression * wip: migrate to apollo * Wip: mostly working with pollInterval * apollo -> urql * cleanup * continuing to cleanup * fix: updates to tests, strict type checking * Tests passing * wip: attempting rename * adding @packages/graphql * simplified fragment testing * fixing build scripts * remove --inspect-brk * fix ci scripts * fix build again * Fix tests * Add express as dep to @packages/graphql * fix packages * chore(launchpad): minor updates (#17551) * apply general improvemets from PR comments * remove unused file * comment out test for now * stub out missing story module Co-authored-by: Lachlan Miller --- npm/design-system/package.json | 2 +- .../src/core/button/Button.stories.tsx | 7 +- .../src/core/input/IconInput.tsx | 2 +- .../src/core/input/Input.spec.tsx | 25 +- .../src/core/input/Input.stories.tsx | 40 +-- npm/vite-dev-server/package.json | 4 +- npm/vue/examples/code-coverage/package.json | 2 +- npm/vue/package.json | 2 +- npm/vue/src/index.ts | 2 +- packages/graphql/.eslintrc.json | 24 ++ packages/graphql/.gitignore | 2 + packages/graphql/index.js | 5 + packages/graphql/package.json | 32 +++ packages/graphql/schema.graphql | 210 +++++++++++++++ packages/graphql/script/build-schema.js | 8 + packages/graphql/src/GraphQL-FAQ.md | 17 ++ packages/graphql/src/actions/BaseActions.ts | 41 +++ packages/graphql/src/constants/index.ts | 3 + .../graphql/src/constants/projectConstants.ts | 10 + .../graphql/src/constants/wizardConstants.ts | 199 ++++++++++++++ packages/graphql/src/context/BaseContext.ts | 24 ++ .../src/contracts/ProjectBaseContract.ts | 4 + packages/graphql/src/contracts/index.ts | 1 + packages/graphql/src/entities/App.ts | 31 +++ packages/graphql/src/entities/Mutation.ts | 101 ++++++++ packages/graphql/src/entities/Project.ts | 85 ++++++ packages/graphql/src/entities/Query.ts | 21 ++ .../graphql/src/entities/TestingTypeInfo.ts | 22 ++ packages/graphql/src/entities/Wizard.ts | 195 ++++++++++++++ .../graphql/src/entities/WizardBundler.ts | 32 +++ .../src/entities/WizardFrontendFramework.ts | 43 ++++ .../graphql/src/entities/WizardNpmPackage.ts | 21 ++ packages/graphql/src/entities/index.ts | 17 ++ .../graphql => graphql/src}/gen/nxs.gen.ts | 170 +++++++++--- packages/graphql/src/index.ts | 13 + packages/graphql/src/schema.ts | 41 +++ .../lib/graphql => graphql/src}/server.ts | 26 +- .../graphql/src/testing/ProjectBaseTest.ts | 1 + packages/graphql/src/testing/testUnionType.ts | 57 +++++ .../graphql/src/util/wizardGetConfigCode.ts | 60 +++++ packages/graphql/tsconfig.json | 8 + .../launchpad/cypress/support/commands.ts | 123 +++++++-- .../cypress/support/testApolloClient.ts | 29 +++ packages/launchpad/graphql-codegen.yml | 16 +- packages/launchpad/package.json | 24 +- packages/launchpad/script/build-schema.js | 3 - packages/launchpad/script/codegen-mount-ts.ts | 67 +++++ packages/launchpad/script/codegen-mount.js | 2 + packages/launchpad/src/App.vue | 7 - .../src/components/ButtonBar.spec.tsx | 57 ++--- .../launchpad/src/components/ButtonBar.vue | 34 ++- .../src/components/ConfigFile.spec.tsx | 39 +-- .../launchpad/src/components/ConfigFile.vue | 65 ++--- .../src/components/EnvironmentSetup.spec.tsx | 115 +++++---- .../src/components/EnvironmentSetup.vue | 159 +++++------- .../components/InstallDependencies.spec.tsx | 16 +- .../src/components/InstallDependencies.vue | 79 +++--- packages/launchpad/src/components/Layout.vue | 40 ++- .../src/components/ManualInstall.spec.tsx | 24 +- .../src/components/ManualInstall.vue | 30 ++- .../launchpad/src/components/OpenBrowser.vue | 10 +- .../src/components/PackagesList.spec.tsx | 11 +- .../launchpad/src/components/PackagesList.vue | 39 +-- .../launchpad/src/components/Select.spec.tsx | 36 ++- packages/launchpad/src/components/Select.vue | 13 +- .../launchpad/src/components/TestingType.vue | 62 +++-- .../launchpad/src/components/Wizard.spec.tsx | 2 +- packages/launchpad/src/components/Wizard.vue | 69 ++--- .../launchpad/src/components/WizardLayout.vue | 50 +++- .../launchpad/src/directives/ClickOutside.ts | 2 +- .../src/graphql/ClientTestContext.ts | 29 +++ .../launchpad/src/graphql/apolloClient.ts | 25 -- packages/launchpad/src/graphql/graphqlIpc.ts | 6 +- packages/launchpad/src/graphql/urqlClient.ts | 30 +++ packages/launchpad/src/main.ts | 9 +- packages/launchpad/src/samples/next/js.js | 7 - packages/launchpad/src/samples/next/ts.ts | 8 - packages/launchpad/src/samples/nuxt/js.js | 15 -- packages/launchpad/src/samples/nuxt/ts.ts | 16 -- packages/launchpad/src/store/app.ts | 109 -------- packages/launchpad/src/store/config.ts | 72 ------ packages/launchpad/src/utils/bundler.ts | 30 --- packages/launchpad/src/utils/configFile.ts | 21 +- packages/launchpad/src/utils/frameworks.ts | 86 ------- packages/launchpad/src/utils/icons.ts | 27 ++ packages/launchpad/src/utils/libraries.ts | 17 -- packages/launchpad/src/utils/packages.ts | 41 --- packages/launchpad/src/utils/testingTypes.ts | 26 -- packages/launchpad/tsconfig.json | 7 +- packages/launchpad/vite.config.ts | 7 +- packages/network/package.json | 2 +- packages/resolve-dist/package.json | 2 +- packages/server/lib/graphql/ExecContext.ts | 3 - packages/server/lib/graphql/ServerActions.ts | 25 ++ packages/server/lib/graphql/ServerContext.ts | 8 + packages/server/lib/graphql/entities/App.ts | 27 -- .../server/lib/graphql/entities/Projects.ts | 57 ----- .../server/lib/graphql/entities/Wizard.ts | 6 - packages/server/lib/graphql/entities/index.ts | 5 - packages/server/lib/graphql/entities/types.ts | 28 -- packages/server/lib/graphql/schema.ts | 25 -- packages/server/lib/graphql/utils/index.ts | 12 - .../server/lib/gui/{events.js => events.ts} | 23 +- packages/server/lib/open_project.js | 2 +- packages/server/lib/project-base.ts | 17 +- packages/server/lib/projects.ts | 91 ------- packages/server/package.json | 8 +- packages/server/schema.graphql | 60 ----- scripts/start.js | 1 + scripts/watch.js | 4 +- yarn.lock | 242 +++++++++--------- 111 files changed, 2582 insertions(+), 1487 deletions(-) create mode 100644 packages/graphql/.eslintrc.json create mode 100644 packages/graphql/.gitignore create mode 100644 packages/graphql/index.js create mode 100644 packages/graphql/package.json create mode 100644 packages/graphql/schema.graphql create mode 100644 packages/graphql/script/build-schema.js create mode 100644 packages/graphql/src/GraphQL-FAQ.md create mode 100644 packages/graphql/src/actions/BaseActions.ts create mode 100644 packages/graphql/src/constants/index.ts create mode 100644 packages/graphql/src/constants/projectConstants.ts create mode 100644 packages/graphql/src/constants/wizardConstants.ts create mode 100644 packages/graphql/src/context/BaseContext.ts create mode 100644 packages/graphql/src/contracts/ProjectBaseContract.ts create mode 100644 packages/graphql/src/contracts/index.ts create mode 100644 packages/graphql/src/entities/App.ts create mode 100644 packages/graphql/src/entities/Mutation.ts create mode 100644 packages/graphql/src/entities/Project.ts create mode 100644 packages/graphql/src/entities/Query.ts create mode 100644 packages/graphql/src/entities/TestingTypeInfo.ts create mode 100644 packages/graphql/src/entities/Wizard.ts create mode 100644 packages/graphql/src/entities/WizardBundler.ts create mode 100644 packages/graphql/src/entities/WizardFrontendFramework.ts create mode 100644 packages/graphql/src/entities/WizardNpmPackage.ts create mode 100644 packages/graphql/src/entities/index.ts rename packages/{server/lib/graphql => graphql/src}/gen/nxs.gen.ts (51%) create mode 100644 packages/graphql/src/index.ts create mode 100644 packages/graphql/src/schema.ts rename packages/{server/lib/graphql => graphql/src}/server.ts (58%) create mode 100644 packages/graphql/src/testing/ProjectBaseTest.ts create mode 100644 packages/graphql/src/testing/testUnionType.ts create mode 100644 packages/graphql/src/util/wizardGetConfigCode.ts create mode 100644 packages/graphql/tsconfig.json create mode 100644 packages/launchpad/cypress/support/testApolloClient.ts delete mode 100644 packages/launchpad/script/build-schema.js create mode 100644 packages/launchpad/script/codegen-mount-ts.ts create mode 100644 packages/launchpad/script/codegen-mount.js create mode 100644 packages/launchpad/src/graphql/ClientTestContext.ts delete mode 100644 packages/launchpad/src/graphql/apolloClient.ts create mode 100644 packages/launchpad/src/graphql/urqlClient.ts delete mode 100644 packages/launchpad/src/samples/next/js.js delete mode 100644 packages/launchpad/src/samples/next/ts.ts delete mode 100644 packages/launchpad/src/samples/nuxt/js.js delete mode 100644 packages/launchpad/src/samples/nuxt/ts.ts delete mode 100644 packages/launchpad/src/store/app.ts delete mode 100644 packages/launchpad/src/store/config.ts delete mode 100644 packages/launchpad/src/utils/bundler.ts delete mode 100644 packages/launchpad/src/utils/frameworks.ts create mode 100644 packages/launchpad/src/utils/icons.ts delete mode 100644 packages/launchpad/src/utils/libraries.ts delete mode 100644 packages/launchpad/src/utils/packages.ts delete mode 100644 packages/launchpad/src/utils/testingTypes.ts delete mode 100644 packages/server/lib/graphql/ExecContext.ts create mode 100644 packages/server/lib/graphql/ServerActions.ts create mode 100644 packages/server/lib/graphql/ServerContext.ts delete mode 100644 packages/server/lib/graphql/entities/App.ts delete mode 100644 packages/server/lib/graphql/entities/Projects.ts delete mode 100644 packages/server/lib/graphql/entities/Wizard.ts delete mode 100644 packages/server/lib/graphql/entities/index.ts delete mode 100644 packages/server/lib/graphql/entities/types.ts delete mode 100644 packages/server/lib/graphql/schema.ts delete mode 100644 packages/server/lib/graphql/utils/index.ts rename packages/server/lib/gui/{events.js => events.ts} (96%) delete mode 100644 packages/server/lib/projects.ts delete mode 100644 packages/server/schema.graphql diff --git a/npm/design-system/package.json b/npm/design-system/package.json index 89ec221d51a0..e781ff2ffaa3 100644 --- a/npm/design-system/package.json +++ b/npm/design-system/package.json @@ -84,7 +84,7 @@ "tsconfig-paths-webpack-plugin": "^3.5.1", "typed-scss-modules": "^4.1.1", "typescript": "^4.2.3", - "vite": "2.2.3", + "vite": "^2.4.4", "webpack": "4.44.1" }, "peerDependencies": { diff --git a/npm/design-system/src/core/button/Button.stories.tsx b/npm/design-system/src/core/button/Button.stories.tsx index ddf523bc9301..1a484a53f1ff 100644 --- a/npm/design-system/src/core/button/Button.stories.tsx +++ b/npm/design-system/src/core/button/Button.stories.tsx @@ -1,5 +1,7 @@ import * as React from 'react' -import { action } from '@storybook/addon-actions' +// TODO: This is causing a "module not defined error" +// Find out why and fix it +// import { action } from '@storybook/addon-actions' import { createStory, createStorybookConfig } from 'stories/util' @@ -11,6 +13,9 @@ import { TextSize } from 'css' import { PaddedBox } from '../surface/paddedBox/PaddedBox' import { Icon } from '../icon/Icon' +// stub it for now +const action = (action: string) => undefined + export default createStorybookConfig({ title: 'Core/Button', }) diff --git a/npm/design-system/src/core/input/IconInput.tsx b/npm/design-system/src/core/input/IconInput.tsx index f5db23d8c0eb..b126889d6099 100644 --- a/npm/design-system/src/core/input/IconInput.tsx +++ b/npm/design-system/src/core/input/IconInput.tsx @@ -23,7 +23,7 @@ export type IconSettings = { ['aria-label']: string } | { onPress?: undefined - ['aria-label']?: undefined + ['aria-label']?: string | undefined }) export type IconInputProps = InputProps<{ diff --git a/npm/design-system/src/core/input/Input.spec.tsx b/npm/design-system/src/core/input/Input.spec.tsx index 2fe6ae783ab6..60cc344a861f 100644 --- a/npm/design-system/src/core/input/Input.spec.tsx +++ b/npm/design-system/src/core/input/Input.spec.tsx @@ -2,9 +2,12 @@ import * as React from 'react' import { composeStories } from '@storybook/testing-react' import * as stories from './Input.stories' import { mountAndSnapshot } from 'util/testing' -import { iconSizesWithSizes } from './Input.stories' +// import { iconSizesWithSizes } from './Input.stories' -const { Input, Icon } = composeStories(stories) +const { + Input, + // Icon +} = composeStories(stories) // TODO: Autogenerate from stories describe('', () => { @@ -13,16 +16,16 @@ describe('', () => { }) it('IconInput', () => { - mountAndSnapshot() + // mountAndSnapshot() }) - it('IconInput sizes', () => { - const IconInput = () => ( - <> - {iconSizesWithSizes(['xs', 's', 'ms', 'm', 'ml', 'l', 'xl', '2xl'])} - - ) + // it('IconInput sizes', () => { + // const IconInput = () => ( + // <> + // {iconSizesWithSizes(['xs', 's', 'ms', 'm', 'ml', 'l', 'xl', '2xl'])} + // + // ) - mountAndSnapshot() - }) + // mountAndSnapshot() + // }) }) diff --git a/npm/design-system/src/core/input/Input.stories.tsx b/npm/design-system/src/core/input/Input.stories.tsx index a4b1aac173cb..ec5d47397f03 100644 --- a/npm/design-system/src/core/input/Input.stories.tsx +++ b/npm/design-system/src/core/input/Input.stories.tsx @@ -1,14 +1,18 @@ import * as React from 'react' -import { action } from '@storybook/addon-actions' +// TODO: This is causing a "module not defined error" +// Find out why and fix it +// import { action } from '@storybook/addon-actions' -import { createStory, createStorybookConfig } from 'stories/util' +import { createStory, createStorybookConfig } from '../../stories/util' import { Input as InputComponent } from './Input' import { IconInput as IconInputComponent } from './IconInput' -import typography from 'css/derived/jsTypography.scss' import { TextSize } from 'css' +// stub it for now +const action = (action: string) => undefined + export default createStorybookConfig({ title: 'Core/Input', excludeStories: ['iconSizesWithSizes'], @@ -38,12 +42,12 @@ export const Icon = createStory(() => ( label={{ type: 'aria', contents: 'full width input' }} prefixIcon={{ icon: 'home', - onPress: action('onPrefixClick'), + // onPress: action('onPrefixClick'), 'aria-label': 'onPrefixClick', }} suffixIcon={{ icon: 'times', - onPress: action('onSuffixClick'), + // onPress: action('onSuffixClick'), 'aria-label': 'onSuffixClick', }} /> @@ -53,7 +57,7 @@ export const Icon = createStory(() => ( label={{ type: 'aria', contents: '500px width input' }} suffixIcon={{ icon: 'times', - onPress: action('onSuffixClick'), + // onPress: action('onSuffixClick'), 'aria-label': 'onSuffixClick', }} value="This is a very long string in an IconInput. This displays the padding on the input section" @@ -62,7 +66,7 @@ export const Icon = createStory(() => ( label={{ type: 'aria', contents: '500px width input' }} prefixIcon={{ icon: 'home', - onPress: action('onPrefixClick'), + // onPress: action('onPrefixClick'), 'aria-label': 'onPrefixClick', }} value="This is a very long string in an IconInput. This displays the padding on the input section" @@ -74,12 +78,12 @@ export const Icon = createStory(() => ( }} prefixIcon={{ icon: 'home', - onPress: action('onPrefixClick'), + // onPress: action('onPrefixClick'), 'aria-label': 'onPrefixClick', }} suffixIcon={{ icon: 'times', - onPress: action('onSuffixClick'), + // onPress: action('onSuffixClick'), 'aria-label': 'onSuffixClick', }} /> @@ -90,7 +94,7 @@ export const Icon = createStory(() => ( }} suffixIcon={{ icon: 'times', - onPress: action('onSuffixClick'), + // onPress: action('onSuffixClick'), 'aria-label': 'onSuffixClick', }} placeholder="The leading icon isn't a button" @@ -99,7 +103,7 @@ export const Icon = createStory(() => ( label={{ type: 'aria', contents: 'leading button only' }} prefixIcon={{ icon: 'home', - onPress: action('onPrefixClick'), + // onPress: action('onPrefixClick'), 'aria-label': 'onPrefixClick', }} suffixIcon={{ @@ -133,10 +137,10 @@ export const iconSizesWithSizes = (sizes: string[]) => sizes.map((key) => { ) }) -export const IconSizes = createStory(() => ( -

-
- {iconSizesWithSizes(Object.keys(typography).filter((key) => key !== 'type' && !key.startsWith('line-height') && !key.startsWith('text-mono') && key !== 'text-3xl' && key !== 'text-4xl'))} -
-
-)) +// export const IconSizes = createStory(() => ( +//
+//
+// {iconSizesWithSizes(Object.keys(typography).filter((key) => key !== 'type' && !key.startsWith('line-height') && !key.startsWith('text-mono') && key !== 'text-3xl' && key !== 'text-4xl'))} +//
+//
+// )) diff --git a/npm/vite-dev-server/package.json b/npm/vite-dev-server/package.json index 50a2f7523192..f90b435141df 100644 --- a/npm/vite-dev-server/package.json +++ b/npm/vite-dev-server/package.json @@ -25,8 +25,8 @@ "mocha-junit-reporter": "^2.0.0", "mocha-multi-reporters": "^1.5.1", "react": "17.0.2", - "vite": "2.2.3", - "vue": "3.1.1" + "vite": "^2.4.4", + "vue": "3.2.0-beta.7" }, "peerDependencies": { "vite": ">= 2.1.3" diff --git a/npm/vue/examples/code-coverage/package.json b/npm/vue/examples/code-coverage/package.json index 1f464721af54..530dadf8dac6 100644 --- a/npm/vue/examples/code-coverage/package.json +++ b/npm/vue/examples/code-coverage/package.json @@ -24,7 +24,7 @@ "nyc": "14.1.1", "sass": "1.32.11", "sass-loader": "7.3.1", - "vue": "3.1.1", + "vue": "3.2.0-beta.7", "vue-loader": "16.2.0", "webpack": "4.46.0" }, diff --git a/npm/vue/package.json b/npm/vue/package.json index 6b2bcca67a3b..7c58898d21eb 100644 --- a/npm/vue/package.json +++ b/npm/vue/package.json @@ -48,7 +48,7 @@ "rollup-plugin-typescript2": "^0.29.0", "tailwindcss": "1.1.4", "typescript": "^4.2.3", - "vue": "3.1.5", + "vue": "3.2.0-beta.7", "vue-i18n": "9.0.0-rc.6", "vue-loader": "16.1.2", "vue-router": "^4.0.0", diff --git a/npm/vue/src/index.ts b/npm/vue/src/index.ts index 2476ba70c29e..04230fbdb2c3 100644 --- a/npm/vue/src/index.ts +++ b/npm/vue/src/index.ts @@ -28,7 +28,7 @@ declare global { } } -type CyMountOptions = Omit, 'attachTo'> & { +export type CyMountOptions = Omit, 'attachTo'> & { log?: boolean /** * @deprecated use vue-test-utils `global` instead diff --git a/packages/graphql/.eslintrc.json b/packages/graphql/.eslintrc.json new file mode 100644 index 000000000000..46ed04aa840b --- /dev/null +++ b/packages/graphql/.eslintrc.json @@ -0,0 +1,24 @@ +{ + "extends": [ + "plugin:@cypress/dev/tests" + ], + "parser": "@typescript-eslint/parser", + "env": { + "cypress/globals": true + }, + "plugins": [ + "cypress" + ], + "overrides": [ + { + "files": [ + "./src/entities/**/*.ts" + ], + "rules": { + "@typescript-eslint/explicit-function-return-type": [ + "error" + ] + } + } + ] +} diff --git a/packages/graphql/.gitignore b/packages/graphql/.gitignore new file mode 100644 index 000000000000..d1ad36227669 --- /dev/null +++ b/packages/graphql/.gitignore @@ -0,0 +1,2 @@ +src/*.js +src/**/*.js \ No newline at end of file diff --git a/packages/graphql/index.js b/packages/graphql/index.js new file mode 100644 index 000000000000..643cb42256ee --- /dev/null +++ b/packages/graphql/index.js @@ -0,0 +1,5 @@ +if (process.env.CYPRESS_INTERNAL_ENV !== 'production') { + require('@packages/ts/register') +} + +module.exports = require('./src') diff --git a/packages/graphql/package.json b/packages/graphql/package.json new file mode 100644 index 000000000000..aa83b2f31f23 --- /dev/null +++ b/packages/graphql/package.json @@ -0,0 +1,32 @@ +{ + "name": "@packages/graphql", + "version": "0.0.0-development", + "private": true, + "main": "index.js", + "browser": "src/index.ts", + "scripts": { + "build": "node script/build-schema.js", + "types": "tsc --noEmit", + "build-prod": "yarn build && tsc", + "clean-deps": "rm -rf node_modules", + "clean": "rm src/**/*.js && rm src/*.js || echo 'cleaned'", + "postinstall": "echo '@packages/graphql needs: yarn build'" + }, + "dependencies": { + "dedent": "^0.7.0", + "express": "4.17.1", + "express-graphql": "^0.12.0", + "graphql": "^15.5.1", + "graphql-scalars": "^1.10.0", + "nexus": "^1.1.0", + "nexus-decorators": "^0.2.0" + }, + "devDependencies": { + "@types/dedent": "^0.7.0" + }, + "files": [ + "src", + "schema.graphql" + ], + "types": "src/index.ts" +} diff --git a/packages/graphql/schema.graphql b/packages/graphql/schema.graphql new file mode 100644 index 000000000000..c0d50a122c7d --- /dev/null +++ b/packages/graphql/schema.graphql @@ -0,0 +1,210 @@ +### This file was generated by Nexus Schema +### Do not make changes to this file directly + + +input AddProjectInput { + isCurrent: Boolean! + projectRoot: String! + testingType: String! +} + +"""Namespace for information related to the app""" +type App { + """The active project in the app""" + activeProject: Project + + """Whether this is the first open of the application or not""" + isFirstOpen: Boolean! + + """All known projects for the app""" + projects: [Project!]! +} + +""" +A date-time string at UTC, such as 2007-12-03T10:15:30Z, compliant with the `date-time` format outlined in section 5.6 of the RFC 3339 profile of the ISO 8601 standard for representation of dates and times using the Gregorian calendar. +""" +scalar DateTime + +enum FrontendFramework { + cra + nextjs + nuxtjs + react + vue + vuecli +} + +""" +The `JSON` scalar type represents JSON values as specified by [ECMA-404](http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf). +""" +scalar JSON @specifiedBy(url: "http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf") + +type Mutation { + """Adds a new project to the app""" + addProject(input: AddProjectInput!): Project! + + """Initializes the plugins for the current active project""" + initializePlugins: Project + + """Installs the dependencies for the component testing step""" + wizardInstallDependencies: Wizard + + """Navigates backward in the wizard""" + wizardNavigate(direction: WizardNavigateDirection!): Wizard + + """Navigates forward in the wizard""" + wizardNavigateForward: Wizard + + """Sets the frontend bundler we want to use for the project""" + wizardSetBundler(bundler: SupportedBundlers!): Wizard + + """Sets the frontend framework we want to use for the project""" + wizardSetFramework(framework: FrontendFramework!): Wizard + + """Sets the frontend bundler we want to use for the project""" + wizardSetManualInstall(isManual: Boolean!): Wizard + + """Sets the current testing type we want to use""" + wizardSetTestingType(type: TestingTypeEnum!): Wizard + + """Validates that the manual install has occurred properly""" + wizardValidateManualInstall: Wizard +} + +enum PluginsState { + error + initialized + initializing + uninitialized +} + +"""A Cypress project is a container""" +type Project { + id: ID! + isCurrent: Boolean! + isOpen: Boolean! + + """If the plugin has errored, contains the associated error message""" + pluginsErrorMessage: String + + """Plugin state for a project""" + pluginsState: PluginsState + projectRoot: String! + + """The title of the project""" + title: String! +} + +"""The root "Query" type containing all entry fields for our querying""" +type Query { + app: App! + + """Metadata about the wizard, null if we arent showing the wizard""" + wizard: Wizard +} + +"""The bundlers that we can use with Cypress""" +enum SupportedBundlers { + vite + webpack +} + +enum TestingTypeEnum { + component + e2e +} + +type TestingTypeInfo { + description: String + id: TestingTypeEnum! + title: String +} + +""" +The Wizard is a container for any state associated with initial onboarding to Cypress +""" +type Wizard { + """All of the bundlers to choose from""" + allBundlers: [WizardBundler!]! + bundler: WizardBundler + canNavigateForward: Boolean! + + """The title of the page, given the current step of the wizard""" + description: String + framework: WizardFrontendFramework + + """All of the component testing frameworks to choose from""" + frameworks: [WizardFrontendFramework!]! + + """Whether we have chosen manual install or not""" + isManualInstall: Boolean! + + """ + A list of packages to install, null if we have not chosen both a framework and bundler + """ + packagesToInstall: [WizardNpmPackage!] + + """Configuration file based on bundler and framework of choice""" + sampleCode(lang: WizardCodeLanguage! = js): String + step: WizardStep! + + """ + The testing type we are setting in the wizard, null if this has not been chosen + """ + testingType: TestingTypeEnum + testingTypes: [TestingTypeInfo!] + + """The title of the page, given the current step of the wizard""" + title: String +} + +"""Wizard bundler""" +type WizardBundler { + id: SupportedBundlers! + + """Whether this is the selected framework bundler""" + isSelected: Boolean + name: String! + package: String! +} + +enum WizardCodeLanguage { + js + ts +} + +"""A frontend framework that we can setup within the app""" +type WizardFrontendFramework { + """The name of the framework""" + id: FrontendFramework! + + """Whether this is the selected framework in the wizard""" + isSelected: Boolean! + + """The name of the framework""" + name: String! + + """All of the supported bundlers for this framework""" + supportedBundlers: [WizardBundler!]! +} + +enum WizardNavigateDirection { + back + forward +} + +"""Details about an NPM Package listed during the wizard install""" +type WizardNpmPackage { + description: String! + + """The package name that you would npm install""" + name: String! +} + +enum WizardStep { + createConfig + installDependencies + selectFramework + setupComplete + welcome +} diff --git a/packages/graphql/script/build-schema.js b/packages/graphql/script/build-schema.js new file mode 100644 index 000000000000..b7bd935d4ffe --- /dev/null +++ b/packages/graphql/script/build-schema.js @@ -0,0 +1,8 @@ +process.env.CYPRESS_INTERNAL_ENV = 'development' +process.env.GRAPHQL_CODEGEN = 'true' +process.env.GRAPHQL_CODEGEN_EXIT = 'true' +// TODO: we should be upgrading ts-node or moving to Thorsten's work soon +// and then this can be removed +process.env.TS_NODE_CACHE = 'false' +require('@packages/ts/register') +require('../src/schema') diff --git a/packages/graphql/src/GraphQL-FAQ.md b/packages/graphql/src/GraphQL-FAQ.md new file mode 100644 index 000000000000..b871f277f10a --- /dev/null +++ b/packages/graphql/src/GraphQL-FAQ.md @@ -0,0 +1,17 @@ +## Development Process + +1. From the monorepo root, run `LAUNCHPAD=1 yarn dev:watch` +2. In launchpad directory, run `yarn watch` + + + +## Why are my types not showing up in the schema + +Ensure that the types are exported so that they are imported into the root `makeSchema`. + +There are often "barrel" files that re-export the types, such as in [`./entities/index.ts`](./entities/index.ts) or [`./constants/index.ts`](./constants/index.ts) + +## Why is my query / mutation not being added + +Queries & mutations must be `static` properties if using nexus-decorators + diff --git a/packages/graphql/src/actions/BaseActions.ts b/packages/graphql/src/actions/BaseActions.ts new file mode 100644 index 000000000000..311b568a26cb --- /dev/null +++ b/packages/graphql/src/actions/BaseActions.ts @@ -0,0 +1,41 @@ +import type { NxsMutationArgs } from 'nexus-decorators' +import type { BaseContext } from '../context/BaseContext' +import type { ProjectBaseContract } from '../contracts/ProjectBaseContract' +import { Project } from '../entities/Project' + +/** + * Acts as the contract for all actions, inherited by: + * - ServerActions + * - ClientTestActions + * + * By having a "base actions" class, we can reuse this code on the client + * and make the client-only test doubles work as realistically as possible + */ +export abstract class BaseActions { + constructor (protected ctx: BaseContext) {} + + abstract installDependencies (): void + + /** + * Adds a new project if it doesn't already exist + */ + async addProject (input: NxsMutationArgs<'addProject'>['input']): Promise { + // Prevent adding the existing project again + const existing = this.ctx.projects.find((p) => p.projectRoot === input.projectRoot) + + if (existing) { + return existing + } + + const newProject = new Project({ + projectRoot: input.projectRoot, + projectBase: await this.createProjectBase(input), + }) + + this.ctx.projects.push(newProject) + + return newProject + } + + abstract createProjectBase(input: NxsMutationArgs<'addProject'>['input']): ProjectBaseContract | Promise +} diff --git a/packages/graphql/src/constants/index.ts b/packages/graphql/src/constants/index.ts new file mode 100644 index 000000000000..589a57e33883 --- /dev/null +++ b/packages/graphql/src/constants/index.ts @@ -0,0 +1,3 @@ +export * from './wizardConstants' + +export * from './projectConstants' diff --git a/packages/graphql/src/constants/projectConstants.ts b/packages/graphql/src/constants/projectConstants.ts new file mode 100644 index 000000000000..3ef2d33c3ba6 --- /dev/null +++ b/packages/graphql/src/constants/projectConstants.ts @@ -0,0 +1,10 @@ +import { enumType } from 'nexus' + +export const PLUGINS_STATE = ['uninitialized', 'initializing', 'initialized', 'error'] as const + +export type PluginsState = typeof PLUGINS_STATE[number] + +export const PluginsStateEnum = enumType({ + name: 'PluginsState', + members: PLUGINS_STATE, +}) diff --git a/packages/graphql/src/constants/wizardConstants.ts b/packages/graphql/src/constants/wizardConstants.ts new file mode 100644 index 000000000000..71f6c388da55 --- /dev/null +++ b/packages/graphql/src/constants/wizardConstants.ts @@ -0,0 +1,199 @@ +import { enumType } from 'nexus' +import dedent from 'dedent' + +import type { NexusGenEnums } from '../gen/nxs.gen' + +export const BUNDLER = ['webpack', 'vite'] as const + +export type Bundler = typeof BUNDLER[number] + +export const BundlerEnum = enumType({ + name: 'SupportedBundlers', + description: 'The bundlers that we can use with Cypress', + members: BUNDLER, +}) + +export const BundlerDisplayNames: Record = { + vite: 'Vite', + webpack: 'Webpack', +} + +export const BundlerPackageNames: Record = { + vite: '@cypress/vite-dev-server', + webpack: '@cypress/webpack-dev-server', +} + +export const WIZARD_NAVIGATE_DIRECTION = ['forward', 'back'] as const + +export type WizardNavigateDirection = typeof WIZARD_NAVIGATE_DIRECTION[number] + +export const WizardNavigateDirectionEnum = enumType({ + name: 'WizardNavigateDirection', + members: WIZARD_NAVIGATE_DIRECTION, +}) + +export const FRONTEND_FRAMEWORK = ['nuxtjs', 'nextjs', 'cra', 'vuecli', 'react', 'vue'] as const + +export type FrontendFramework = typeof FRONTEND_FRAMEWORK[number] + +export const FrontendFrameworkEnum = enumType({ + name: 'FrontendFramework', + members: FRONTEND_FRAMEWORK, +}) + +export const FrameworkDisplayNames: Record = { + cra: 'Create React App', + vuecli: 'Vue CLI', + react: 'React.js', + vue: 'Vue.js', + nextjs: 'Next.js', + nuxtjs: 'Nuxt.js', +} + +export const TESTING_TYPES = ['component', 'e2e'] as const + +export type TestingType = typeof TESTING_TYPES[number] + +export const TestingTypeEnum = enumType({ + name: 'TestingTypeEnum', + members: TESTING_TYPES, +}) + +export const TestingTypeNames: Record = { + component: 'Component Testing', + e2e: 'E2E Testing', +} + +export const TestingTypeDescriptions: Record = { + component: 'Aenean lacinia bibendum nulla sed consectetur. Morbi leo risus, porta ac consectetur ac, vestibulum at eros. Integer posuere erat a ante venenatis dapibus posuere velit aliquet. Aenean lacinia bibendum nulla sed consectetur.', + e2e: 'Aenean lacinia bibendum nulla sed consectetur. Morbi leo risus, porta ac consectetur ac, vestibulum at eros. Integer posuere erat a ante venenatis dapibus posuere velit aliquet. Aenean lacinia bibendum nulla sed consectetur.', +} + +export const WIZARD_STEP = [ + 'welcome', + 'selectFramework', + 'installDependencies', + 'createConfig', + 'setupComplete', +] as const + +export type WizardStep = typeof WIZARD_STEP[number] + +export const WizardStepEnum = enumType({ + name: 'WizardStep', + members: WIZARD_STEP, +}) + +export const WIZARD_TITLES: Record = { + welcome: 'Welcome to Cypress', + selectFramework: 'Project Setup', + installDependencies: 'Install Dev Dependencies', + createConfig: 'Cypress.config', + setupComplete: 'Setup Finished', +} + +export const WIZARD_DESCRIPTIONS: Record = { + welcome: 'Choose which method of testing you would like to set up first.', + selectFramework: 'Confirm the front-end framework and bundler fused in your project.', + installDependencies: 'We need to install the following packages in order for component testing to work.', + createConfig: 'Cypress will now create the following config file in the local directory for this project.', + setupComplete: 'cypress.config.js file was successfully added to your project. Let’s open your browser and start testing some components!', +} + +export const WIZARD_ALT_DESCRIPTIONS = { + +} as const + +export const WIZARD_CODE_LANGUAGE = ['js', 'ts'] as const + +export type WizardCodeLanguage = typeof WIZARD_CODE_LANGUAGE[number] + +export const WizardCodeLanguageEnum = enumType({ + name: 'WizardCodeLanguage', + members: WIZARD_CODE_LANGUAGE, +}) + +export const FRAMEWORK_CONFIG_FILE: Partial | null>> = { + nextjs: { + js: dedent` + const injectNextDevServer = require('@cypress/react/plugins/next') + + module.exports = { + component (on, config) { + injectNextDevServer(on, config) + }, + } + `, + ts: dedent` + import { defineConfig } from 'cypress' + import injectNextDevServer from '@cypress/react/plugins/next' + + export default defineConfig({ + component (on, config) { + injectNextDevServer(on, config) + }, + }) + `, + }, + nuxtjs: { + js: dedent` + const { startDevServer } = require('@cypress/webpack-dev-server') + const { getWebpackConfig } = require('nuxt') + + module.exports = { + component (on, config) { + on('dev-server:start', async (options) => { + let webpackConfig = await getWebpackConfig('modern', 'dev') + + return startDevServer({ + options, + webpackConfig, + }) + }) + }, + } + `, + ts: dedent` + import { defineConfig } from 'cypress' + import { startDevServer } from '@cypress/webpack-dev-server' + import { getWebpackConfig } from 'nuxt' + + export default defineConfig({ + component (on, config) { + on('dev-server:start', async (options) => { + let webpackConfig = await getWebpackConfig('modern', 'dev') + + return startDevServer({ + options, + webpackConfig, + }) + }) + }, + }) + `, + }, +} + +export const PACKAGES_DESCRIPTIONS = { + '@cypress/vue': 'Allows Cypress to mount each Vue component using cy.mount()', + '@cypress/react': 'Allows Cypress to mount each React component using cy.mount()', + '@cypress/webpack-dev-server': 'Allows Cypress to use your existing build configuration in order to bundle and run your tests', + '@cypress/vite-dev-server': 'Allows Cypress to use your existing build configuration in order to bundle and run your tests', + '@cypress/storybook': 'Allows Cypress to automatically read and test each of your stories', +} as const + +export type NpmPackages = keyof typeof PACKAGES_DESCRIPTIONS + +export const PackageMapping: Record = { + nextjs: '@cypress/react', + cra: '@cypress/react', + react: '@cypress/react', + nuxtjs: '@cypress/vue', + vuecli: '@cypress/vue', + vue: '@cypress/vue', +} + +export const BundleMapping: Record = { + vite: '@cypress/vite-dev-server', + webpack: '@cypress/webpack-dev-server', +} diff --git a/packages/graphql/src/context/BaseContext.ts b/packages/graphql/src/context/BaseContext.ts new file mode 100644 index 000000000000..0bb5443c0f5e --- /dev/null +++ b/packages/graphql/src/context/BaseContext.ts @@ -0,0 +1,24 @@ +import type { BaseActions } from '../actions/BaseActions' +import { App, Wizard } from '../entities' +import type { Project } from '../entities/Project' + +/** + * The "Base Context" is the class type that we will use to encapsulate the server state. + * It will be implemented by ServerContext (real state) and TestContext (client state). + * + * This allows us to re-use the entire GraphQL server definition client side for testing, + * without the need to endlessly mock things. + */ +export abstract class BaseContext { + abstract readonly actions: BaseActions + abstract projects: Project[] + + wizard = new Wizard() + app = new App(this) + + isFirstOpen = false + + get activeProject () { + return this.app.activeProject + } +} diff --git a/packages/graphql/src/contracts/ProjectBaseContract.ts b/packages/graphql/src/contracts/ProjectBaseContract.ts new file mode 100644 index 000000000000..5c71649fe53e --- /dev/null +++ b/packages/graphql/src/contracts/ProjectBaseContract.ts @@ -0,0 +1,4 @@ +export interface ProjectBaseContract { + isOpen: boolean + initializePlugins(): Promise +} diff --git a/packages/graphql/src/contracts/index.ts b/packages/graphql/src/contracts/index.ts new file mode 100644 index 000000000000..425a45ab22fd --- /dev/null +++ b/packages/graphql/src/contracts/index.ts @@ -0,0 +1 @@ +export * from './ProjectBaseContract' diff --git a/packages/graphql/src/entities/App.ts b/packages/graphql/src/entities/App.ts new file mode 100644 index 000000000000..7bb8199d85d1 --- /dev/null +++ b/packages/graphql/src/entities/App.ts @@ -0,0 +1,31 @@ +import { nxs, NxsResult } from 'nexus-decorators' +import type { BaseContext } from '../context/BaseContext' +import { Project } from './Project' + +@nxs.objectType({ + description: 'Namespace for information related to the app', +}) +export class App { + constructor (private ctx: BaseContext) {} + + @nxs.field.nonNull.boolean({ + description: 'Whether this is the first open of the application or not', + }) + static get isFirstOpen (): NxsResult<'App', 'isFirstOpen'> { + return true + } + + @nxs.field.nonNull.list.nonNull.type(() => Project, { + description: 'All known projects for the app', + }) + get projects (): NxsResult<'App', 'projects'> { + return this.ctx.projects + } + + @nxs.field.type(() => Project, { + description: 'The active project in the app', + }) + get activeProject (): NxsResult<'App', 'activeProject'> { + return this.projects.find((p) => p.isOpen) ?? null + } +} diff --git a/packages/graphql/src/entities/Mutation.ts b/packages/graphql/src/entities/Mutation.ts new file mode 100644 index 000000000000..b567c8ac54bc --- /dev/null +++ b/packages/graphql/src/entities/Mutation.ts @@ -0,0 +1,101 @@ +import { inputObjectType, mutationType, nonNull } from 'nexus' +import { BundlerEnum, FrontendFrameworkEnum, TestingTypeEnum, WizardNavigateDirectionEnum } from '../constants' + +export const mutation = mutationType({ + definition (t) { + // TODO(tim): in nexus, support for t.wizard(...) + + t.field('wizardSetTestingType', { + type: 'Wizard', + description: 'Sets the current testing type we want to use', + args: { type: nonNull(TestingTypeEnum) }, + resolve: (root, args, ctx) => ctx.wizard.setTestingType(args.type), + }) + + t.field('wizardSetFramework', { + type: 'Wizard', + description: 'Sets the frontend framework we want to use for the project', + args: { framework: nonNull(FrontendFrameworkEnum) }, + resolve: (_, args, ctx) => ctx.wizard.setFramework(args.framework), + }) + + // TODO: Move these 3 to a single wizardUpdate(input: WizardUpdateInput!) + t.field('wizardSetBundler', { + type: 'Wizard', + description: 'Sets the frontend bundler we want to use for the project', + args: { + bundler: nonNull(BundlerEnum), + }, + resolve: (root, args, ctx) => ctx.wizard.setBundler(args.bundler), + }) + + t.field('wizardSetManualInstall', { + type: 'Wizard', + description: 'Sets the frontend bundler we want to use for the project', + args: { + isManual: nonNull('Boolean'), + }, + resolve: (root, args, ctx) => ctx.wizard.setManualInstall(args.isManual), + }) + + t.field('wizardNavigateForward', { + type: 'Wizard', + description: 'Navigates forward in the wizard', + resolve: (_, __, ctx) => ctx.wizard.navigate('forward'), + }) + + t.field('wizardNavigate', { + type: 'Wizard', + args: { + direction: nonNull(WizardNavigateDirectionEnum), + }, + description: 'Navigates backward in the wizard', + resolve: (_, args, ctx) => ctx.wizard.navigate(args.direction), + }) + + t.field('wizardInstallDependencies', { + type: 'Wizard', + description: 'Installs the dependencies for the component testing step', + resolve: (root, args, ctx) => ctx.wizard, + }) + + t.field('wizardValidateManualInstall', { + type: 'Wizard', + description: 'Validates that the manual install has occurred properly', + resolve: (root, args, ctx) => { + return ctx.wizard.validateManualInstall() + }, + }) + + t.nonNull.field('addProject', { + type: 'Project', + description: 'Adds a new project to the app', + args: { + input: nonNull( + inputObjectType({ + name: 'AddProjectInput', + definition (t) { + t.nonNull.string('projectRoot') + t.nonNull.string('testingType') + t.nonNull.boolean('isCurrent') + }, + }), + ), + }, + async resolve (_root, args, ctx) { + const addedProject = await ctx.actions.addProject(args.input) + + return addedProject + }, + }) + + t.field('initializePlugins', { + type: 'Project', + description: 'Initializes the plugins for the current active project', + async resolve (_root, args, ctx) { + // TODO: should we await here, or return a pending state to the client? + return await ctx.activeProject?.initializePlugins() ?? null + }, + }) + }, +}) diff --git a/packages/graphql/src/entities/Project.ts b/packages/graphql/src/entities/Project.ts new file mode 100644 index 000000000000..30f4a1f41623 --- /dev/null +++ b/packages/graphql/src/entities/Project.ts @@ -0,0 +1,85 @@ +// import { createHash } from 'crypto' +import { nxs, NxsResult } from 'nexus-decorators' +import { PluginsState, PluginsStateEnum } from '../constants/projectConstants' +import type { ProjectBaseContract } from '../contracts/ProjectBaseContract' + +export interface ProjectConfig { + projectRoot: string + projectBase: ProjectBaseContract +} + +@nxs.objectType({ + description: 'A Cypress project is a container', +}) +export class Project { + readonly projectBase: ProjectBaseContract + private _pluginsState: PluginsState = 'uninitialized' + private _pluginsErrorMessage?: string + + constructor (private config: ProjectConfig) { + this.projectBase = config.projectBase + } + + @nxs.field.nonNull.id() + id (): NxsResult<'Project', 'id'> { + return this.projectRoot + // return createHash('sha1').update(this.projectRoot).digest('hex') + } + + @nxs.field.nonNull.string({ + description: 'The title of the project', + }) + get title (): NxsResult<'Project', 'title'> { + return 'design-system' // TODO: make this real + } + + @nxs.field.nonNull.string() + get projectRoot (): NxsResult<'Project', 'projectRoot'> { + return this.config.projectRoot + } + + @nxs.field.nonNull.boolean() + get isOpen (): NxsResult<'Project', 'isOpen'> { + return this.config.projectBase.isOpen + } + + @nxs.field.nonNull.boolean() + isCurrent (): NxsResult<'Project', 'isCurrent'> { + return false + } + + @nxs.field.type(() => PluginsStateEnum, { + description: 'Plugin state for a project', + }) + get pluginsState (): NxsResult<'Project', 'pluginsState'> { + return this._pluginsState + } + + @nxs.field.string({ + description: 'If the plugin has errored, contains the associated error message', + }) + get pluginsErrorMessage (): NxsResult<'Project', 'pluginsErrorMessage'> { + if (this.pluginsState === 'error') { + return this._pluginsErrorMessage ?? null + } + + return null + } + + async initializePlugins (): Promise { + if (this.pluginsState !== 'uninitialized' && this.pluginsState !== 'error') { + return this + } + + try { + this._pluginsState = 'initializing' + await this.projectBase.initializePlugins() + this._pluginsState = 'initialized' + } catch (e) { + this._pluginsState = 'error' + this._pluginsErrorMessage = e.message + } + + return this + } +} diff --git a/packages/graphql/src/entities/Query.ts b/packages/graphql/src/entities/Query.ts new file mode 100644 index 000000000000..c21a9346edb6 --- /dev/null +++ b/packages/graphql/src/entities/Query.ts @@ -0,0 +1,21 @@ +import { nxs, NxsQueryResult, NxsResult } from 'nexus-decorators' +import type { NexusGenTypes } from '../gen/nxs.gen' +import { App } from './App' +import { Wizard } from './Wizard' + +@nxs.objectType({ + description: 'The root "Query" type containing all entry fields for our querying', +}) +export class Query { + @nxs.field.nonNull.type(() => App) + app (_: unknown, ctx: NexusGen['context']): NxsQueryResult<'app'> { + return ctx.app + } + + @nxs.field.type(() => Wizard, { + description: 'Metadata about the wizard, null if we arent showing the wizard', + }) + wizard (args: unknown, ctx: NexusGenTypes['context']): NxsResult<'App', 'wizard'> { + return ctx.wizard + } +} diff --git a/packages/graphql/src/entities/TestingTypeInfo.ts b/packages/graphql/src/entities/TestingTypeInfo.ts new file mode 100644 index 000000000000..2132d88c7523 --- /dev/null +++ b/packages/graphql/src/entities/TestingTypeInfo.ts @@ -0,0 +1,22 @@ +import { nxs, NxsResult } from 'nexus-decorators' +import { TestingTypeEnum, TestingType as _TestingType, TestingTypeNames, TestingTypeDescriptions } from '../constants' + +@nxs.objectType() +export class TestingTypeInfo { + constructor (private _id: _TestingType) {} + + @nxs.field.nonNull.type(() => TestingTypeEnum) + get id (): NxsResult<'TestingTypeInfo', 'id'> { + return this._id + } + + @nxs.field.string() + get title (): NxsResult<'TestingTypeInfo', 'title'> { + return TestingTypeNames[this.id] + } + + @nxs.field.string() + get description (): NxsResult<'TestingTypeInfo', 'description'> { + return TestingTypeDescriptions[this.id] + } +} diff --git a/packages/graphql/src/entities/Wizard.ts b/packages/graphql/src/entities/Wizard.ts new file mode 100644 index 000000000000..c17f942dc6b7 --- /dev/null +++ b/packages/graphql/src/entities/Wizard.ts @@ -0,0 +1,195 @@ +import { nxs, NxsArgs, NxsResult } from 'nexus-decorators' +import { BUNDLER, FrontendFramework, Bundler, FRONTEND_FRAMEWORK, TestingTypeEnum, WizardStepEnum, WIZARD_STEP, WizardStep, WIZARD_TITLES, WIZARD_DESCRIPTIONS, TESTING_TYPES, TestingType, PackageMapping, BundleMapping, WizardCodeLanguageEnum, WizardNavigateDirection } from '../constants/wizardConstants' +import { wizardGetConfigCode } from '../util/wizardGetConfigCode' +import { TestingTypeInfo } from './TestingTypeInfo' +import { WizardBundler } from './WizardBundler' +import { WizardFrontendFramework } from './WizardFrontendFramework' +import { WizardNpmPackage } from './WizardNpmPackage' + +@nxs.objectType({ + description: 'The Wizard is a container for any state associated with initial onboarding to Cypress', +}) +export class Wizard { + private currentStep: WizardStep = 'welcome' + private chosenTestingType: TestingType | null + private chosenBundler: Bundler | null + private chosenFramework: FrontendFramework | null + private chosenManualInstall: boolean + + constructor () { + this.chosenTestingType = null + this.chosenBundler = null + this.chosenFramework = null + this.chosenManualInstall = false + } + + @nxs.field.type(() => WizardFrontendFramework) + get framework (): NxsResult<'Wizard', 'framework'> | null { + return this.chosenFramework ? new WizardFrontendFramework(this, this.chosenFramework) : null + } + + @nxs.field.type(() => WizardBundler) + get bundler (): NxsResult<'Wizard', 'bundler'> | null { + return this.chosenBundler ? new WizardBundler(this, this.chosenBundler) : null + } + + @nxs.field.list.nonNull.type(() => WizardNpmPackage, { + description: 'A list of packages to install, null if we have not chosen both a framework and bundler', + }) + get packagesToInstall (): NxsResult<'WizardFrontendFramework', 'packagesToInstall'> { + if (!this.chosenFramework || !this.chosenBundler) { + return null + } + + return [ + new WizardNpmPackage(PackageMapping[this.chosenFramework]), + new WizardNpmPackage(BundleMapping[this.chosenBundler]), + ] + } + + @nxs.field.string({ + description: 'The title of the page, given the current step of the wizard', + }) + get title (): NxsResult<'Wizard', 'title'> { + return WIZARD_TITLES[this.currentStep] + } + + @nxs.field.string({ + description: 'The title of the page, given the current step of the wizard', + }) + get description (): NxsResult<'Wizard', 'title'> { + return WIZARD_DESCRIPTIONS[this.currentStep] + } + + @nxs.field.nonNull.boolean({ + description: 'Whether we have chosen manual install or not', + }) + get isManualInstall (): NxsResult<'Wizard', 'isManualInstall'> { + return this.chosenManualInstall + } + + // GraphQL Fields: + + @nxs.field.nonNull.type(() => WizardStepEnum) + get step (): NxsResult<'Wizard', 'step'> { + return this.currentStep + } + + @nxs.field.type(() => TestingTypeEnum, { + description: 'The testing type we are setting in the wizard, null if this has not been chosen', + }) + testingType (): NxsResult<'Wizard', 'testingType'> { + return this.chosenTestingType + } + + @nxs.field.list.nonNull.type(() => TestingTypeInfo) + testingTypes (): NxsResult<'Wizard', 'testingTypes'> { + return TESTING_TYPES.map((t) => new TestingTypeInfo(t)) + } + + @nxs.field.nonNull.list.nonNull.type(() => WizardFrontendFramework, { + description: 'All of the component testing frameworks to choose from', + }) + frameworks (): NxsResult<'Wizard', 'frameworks'> { + return FRONTEND_FRAMEWORK.map((f) => new WizardFrontendFramework(this, f)) + } + + @nxs.field.nonNull.list.nonNull.type(() => WizardBundler, { + description: 'All of the bundlers to choose from', + }) + allBundlers (): NxsResult<'Wizard', 'allBundlers'> { + return BUNDLER.map((bundler) => new WizardBundler(this, bundler)) + } + + @nxs.field.string({ + description: 'Configuration file based on bundler and framework of choice', + args (t) { + t.nonNull.arg('lang', { + type: WizardCodeLanguageEnum, + default: 'js', + }) + }, + }) + sampleCode (args: NxsArgs<'Wizard', 'sampleCode'>): NxsResult<'Wizard', 'configFile'> { + if (!this.framework || !this.bundler) { + return null + } + + return wizardGetConfigCode({ + framework: this.framework, + bundler: this.bundler, + lang: args.lang, + }) + } + + // Internal Setters: + + setTestingType (testingType: TestingType | null): Wizard { + this.chosenTestingType = testingType + this.currentStep = 'selectFramework' + + return this + } + + setFramework (framework: FrontendFramework): Wizard { + this.chosenFramework = framework + if (framework !== 'react' && framework !== 'vue') { + this.chosenBundler = 'webpack' + } + + return this + } + + setBundler (bundler?: Bundler | null): Wizard { + this.chosenBundler = bundler ?? null + + return this + } + + setManualInstall (isManual: boolean): Wizard { + this.chosenManualInstall = isManual + + return this + } + + @nxs.field.nonNull.boolean() + canNavigateForward (): NxsResult<'Wizard', 'canNavigateForward'> { + // TODO: add constraints here to determine if we can move forward + return true + } + + navigate (direction: WizardNavigateDirection): Wizard { + if (direction === 'back') { + this.navigateBack() + } + + this.navigateForward() + + return this + } + + private navigateBack (): Wizard { + const idx = WIZARD_STEP.indexOf(this.currentStep) + + if (idx !== 0) { + this.currentStep = WIZARD_STEP[idx - 1] + } + + return this + } + + private navigateForward (): Wizard { + const idx = WIZARD_STEP.indexOf(this.currentStep) + + if (idx !== WIZARD_STEP.length - 1) { + this.currentStep = WIZARD_STEP[idx + 1] + } + + return this + } + + validateManualInstall (): Wizard { + // + return this + } +} diff --git a/packages/graphql/src/entities/WizardBundler.ts b/packages/graphql/src/entities/WizardBundler.ts new file mode 100644 index 000000000000..6894f675c1d6 --- /dev/null +++ b/packages/graphql/src/entities/WizardBundler.ts @@ -0,0 +1,32 @@ +import { nxs, NxsResult } from 'nexus-decorators' +import { Bundler, BundlerDisplayNames, BundlerEnum, BundlerPackageNames } from '../constants' +import type { Wizard } from './Wizard' + +@nxs.objectType({ + description: 'Wizard bundler', +}) +export class WizardBundler { + constructor (private wizard: Wizard, private bundler: Bundler) {} + + @nxs.field.nonNull.type(() => BundlerEnum) + get id (): NxsResult<'WizardBundler', 'id'> { + return this.bundler + } + + @nxs.field.nonNull.string() + get name (): NxsResult<'WizardBundler', 'name'> { + return BundlerDisplayNames[this.bundler] + } + + @nxs.field.nonNull.string() + get package (): NxsResult<'WizardBundler', 'package'> { + return BundlerPackageNames[this.bundler] + } + + @nxs.field.boolean({ + description: 'Whether this is the selected framework bundler', + }) + isSelected (): NxsResult<'WizardBundler', 'isSelected'> { + return this.wizard.bundler?.id === this.bundler + } +} diff --git a/packages/graphql/src/entities/WizardFrontendFramework.ts b/packages/graphql/src/entities/WizardFrontendFramework.ts new file mode 100644 index 000000000000..ea3cfa890f05 --- /dev/null +++ b/packages/graphql/src/entities/WizardFrontendFramework.ts @@ -0,0 +1,43 @@ +import { nxs, NxsResult } from 'nexus-decorators' +import { BUNDLER, FrameworkDisplayNames, FrontendFramework, FrontendFrameworkEnum } from '../constants' +import { WizardBundler } from './WizardBundler' +import type { Wizard } from './Wizard' + +@nxs.objectType({ + description: 'A frontend framework that we can setup within the app', +}) +export class WizardFrontendFramework { + constructor (private wizard: Wizard, private framework: FrontendFramework) {} + + @nxs.field.nonNull.type(() => FrontendFrameworkEnum, { + description: 'The name of the framework', + }) + get id (): NxsResult<'WizardFrontendFramework', 'id'> { + return this.framework + } + + @nxs.field.nonNull.string({ + description: 'The name of the framework', + }) + get name (): NxsResult<'WizardFrontendFramework', 'name'> { + return FrameworkDisplayNames[this.framework] + } + + @nxs.field.nonNull.list.nonNull.type(() => WizardBundler, { + description: 'All of the supported bundlers for this framework', + }) + get supportedBundlers (): NxsResult<'WizardFrontendFramework', 'supportedBundlers'> { + if (!this.wizard.framework || this.wizard.framework.id === 'react' || this.wizard.framework.id === 'vue') { + return BUNDLER.map((bundler) => new WizardBundler(this.wizard, bundler)) + } + + return [new WizardBundler(this.wizard, 'webpack')] + } + + @nxs.field.nonNull.boolean({ + description: 'Whether this is the selected framework in the wizard', + }) + get isSelected (): NxsResult<'WizardFrontendFramework', 'isSelected'> { + return this.wizard.framework?.id === this.framework + } +} diff --git a/packages/graphql/src/entities/WizardNpmPackage.ts b/packages/graphql/src/entities/WizardNpmPackage.ts new file mode 100644 index 000000000000..9c5eb32498b7 --- /dev/null +++ b/packages/graphql/src/entities/WizardNpmPackage.ts @@ -0,0 +1,21 @@ +import { nxs, NxsResult } from 'nexus-decorators' +import { NpmPackages, PACKAGES_DESCRIPTIONS } from '../constants' + +@nxs.objectType({ + description: 'Details about an NPM Package listed during the wizard install', +}) +export class WizardNpmPackage { + constructor (private pkg: NpmPackages) {} + + @nxs.field.nonNull.string({ + description: 'The package name that you would npm install', + }) + name (): NxsResult<'WizardNpmPackage', 'name'> { + return this.pkg + } + + @nxs.field.nonNull.string() + description (): NxsResult<'WizardNpmPackage', 'description'> { + return PACKAGES_DESCRIPTIONS[this.pkg] + } +} diff --git a/packages/graphql/src/entities/index.ts b/packages/graphql/src/entities/index.ts new file mode 100644 index 000000000000..dbc8ff63afa9 --- /dev/null +++ b/packages/graphql/src/entities/index.ts @@ -0,0 +1,17 @@ +export * from './App' + +export * from './Mutation' + +export * from './Project' + +export * from './Query' + +export * from './TestingTypeInfo' + +export * from './Wizard' + +export * from './WizardBundler' + +export * from './WizardFrontendFramework' + +export * from './WizardNpmPackage' diff --git a/packages/server/lib/graphql/gen/nxs.gen.ts b/packages/graphql/src/gen/nxs.gen.ts similarity index 51% rename from packages/server/lib/graphql/gen/nxs.gen.ts rename to packages/graphql/src/gen/nxs.gen.ts index 8395febfe876..72c14503fe53 100644 --- a/packages/server/lib/graphql/gen/nxs.gen.ts +++ b/packages/graphql/src/gen/nxs.gen.ts @@ -5,8 +5,15 @@ */ +import type { BaseContext } from "./../context/BaseContext" import type { App } from "./../entities/App" +import type { Project } from "./../entities/Project" +import type { Query } from "./../entities/Query" +import type { TestingTypeInfo } from "./../entities/TestingTypeInfo" import type { Wizard } from "./../entities/Wizard" +import type { WizardBundler } from "./../entities/WizardBundler" +import type { WizardFrontendFramework } from "./../entities/WizardFrontendFramework" +import type { WizardNpmPackage } from "./../entities/WizardNpmPackage" import type { core } from "nexus" declare global { interface NexusGenCustomInputMethods { @@ -47,7 +54,13 @@ export interface NexusGenInputs { } export interface NexusGenEnums { + FrontendFramework: "cra" | "nextjs" | "nuxtjs" | "react" | "vue" | "vuecli" PluginsState: "error" | "initialized" | "initializing" | "uninitialized" + SupportedBundlers: "vite" | "webpack" + TestingTypeEnum: "component" | "e2e" + WizardCodeLanguage: "js" | "ts" + WizardNavigateDirection: "back" | "forward" + WizardStep: "createConfig" | "installDependencies" | "selectFramework" | "setupComplete" | "welcome" } export interface NexusGenScalars { @@ -62,19 +75,14 @@ export interface NexusGenScalars { export interface NexusGenObjects { App: App; - InitPluginsStatus: { // root type - message?: string | null; // String - state: NexusGenEnums['PluginsState']; // PluginsState! - } Mutation: {}; - Project: { // root type - isCurrent: boolean; // Boolean! - isOpen: boolean; // Boolean! - plugins?: NexusGenRootTypes['InitPluginsStatus'] | null; // InitPluginsStatus - projectRoot: string; // String! - } - Query: {}; + Project: Project; + Query: Query; + TestingTypeInfo: TestingTypeInfo; Wizard: Wizard; + WizardBundler: WizardBundler; + WizardFrontendFramework: WizardFrontendFramework; + WizardNpmPackage: WizardNpmPackage; } export interface NexusGenInterfaces { @@ -89,57 +97,139 @@ export type NexusGenAllTypes = NexusGenRootTypes & NexusGenScalars & NexusGenEnu export interface NexusGenFieldTypes { App: { // field return type + activeProject: NexusGenRootTypes['Project'] | null; // Project isFirstOpen: boolean; // Boolean! - } - InitPluginsStatus: { // field return type - message: string | null; // String - state: NexusGenEnums['PluginsState']; // PluginsState! + projects: NexusGenRootTypes['Project'][]; // [Project!]! } Mutation: { // field return type addProject: NexusGenRootTypes['Project']; // Project! - initializePlugins: NexusGenRootTypes['Project']; // Project! + initializePlugins: NexusGenRootTypes['Project'] | null; // Project + wizardInstallDependencies: NexusGenRootTypes['Wizard'] | null; // Wizard + wizardNavigate: NexusGenRootTypes['Wizard'] | null; // Wizard + wizardNavigateForward: NexusGenRootTypes['Wizard'] | null; // Wizard + wizardSetBundler: NexusGenRootTypes['Wizard'] | null; // Wizard + wizardSetFramework: NexusGenRootTypes['Wizard'] | null; // Wizard + wizardSetManualInstall: NexusGenRootTypes['Wizard'] | null; // Wizard + wizardSetTestingType: NexusGenRootTypes['Wizard'] | null; // Wizard + wizardValidateManualInstall: NexusGenRootTypes['Wizard'] | null; // Wizard } Project: { // field return type + id: string; // ID! isCurrent: boolean; // Boolean! isOpen: boolean; // Boolean! - plugins: NexusGenRootTypes['InitPluginsStatus'] | null; // InitPluginsStatus + pluginsErrorMessage: string | null; // String + pluginsState: NexusGenEnums['PluginsState'] | null; // PluginsState projectRoot: string; // String! + title: string; // String! } Query: { // field return type - app: NexusGenRootTypes['App'] | null; // App - openProject: NexusGenRootTypes['Project'] | null; // Project - projects: Array; // [Project]! + app: NexusGenRootTypes['App']; // App! + wizard: NexusGenRootTypes['Wizard'] | null; // Wizard + } + TestingTypeInfo: { // field return type + description: string | null; // String + id: NexusGenEnums['TestingTypeEnum']; // TestingTypeEnum! + title: string | null; // String } Wizard: { // field return type - todo: boolean | null; // Boolean + allBundlers: NexusGenRootTypes['WizardBundler'][]; // [WizardBundler!]! + bundler: NexusGenRootTypes['WizardBundler'] | null; // WizardBundler + canNavigateForward: boolean; // Boolean! + description: string | null; // String + framework: NexusGenRootTypes['WizardFrontendFramework'] | null; // WizardFrontendFramework + frameworks: NexusGenRootTypes['WizardFrontendFramework'][]; // [WizardFrontendFramework!]! + isManualInstall: boolean; // Boolean! + packagesToInstall: NexusGenRootTypes['WizardNpmPackage'][] | null; // [WizardNpmPackage!] + sampleCode: string | null; // String + step: NexusGenEnums['WizardStep']; // WizardStep! + testingType: NexusGenEnums['TestingTypeEnum'] | null; // TestingTypeEnum + testingTypes: NexusGenRootTypes['TestingTypeInfo'][] | null; // [TestingTypeInfo!] + title: string | null; // String + } + WizardBundler: { // field return type + id: NexusGenEnums['SupportedBundlers']; // SupportedBundlers! + isSelected: boolean | null; // Boolean + name: string; // String! + package: string; // String! + } + WizardFrontendFramework: { // field return type + id: NexusGenEnums['FrontendFramework']; // FrontendFramework! + isSelected: boolean; // Boolean! + name: string; // String! + supportedBundlers: NexusGenRootTypes['WizardBundler'][]; // [WizardBundler!]! + } + WizardNpmPackage: { // field return type + description: string; // String! + name: string; // String! } } export interface NexusGenFieldTypeNames { App: { // field return type name + activeProject: 'Project' isFirstOpen: 'Boolean' - } - InitPluginsStatus: { // field return type name - message: 'String' - state: 'PluginsState' + projects: 'Project' } Mutation: { // field return type name addProject: 'Project' initializePlugins: 'Project' + wizardInstallDependencies: 'Wizard' + wizardNavigate: 'Wizard' + wizardNavigateForward: 'Wizard' + wizardSetBundler: 'Wizard' + wizardSetFramework: 'Wizard' + wizardSetManualInstall: 'Wizard' + wizardSetTestingType: 'Wizard' + wizardValidateManualInstall: 'Wizard' } Project: { // field return type name + id: 'ID' isCurrent: 'Boolean' isOpen: 'Boolean' - plugins: 'InitPluginsStatus' + pluginsErrorMessage: 'String' + pluginsState: 'PluginsState' projectRoot: 'String' + title: 'String' } Query: { // field return type name app: 'App' - openProject: 'Project' - projects: 'Project' + wizard: 'Wizard' + } + TestingTypeInfo: { // field return type name + description: 'String' + id: 'TestingTypeEnum' + title: 'String' } Wizard: { // field return type name - todo: 'Boolean' + allBundlers: 'WizardBundler' + bundler: 'WizardBundler' + canNavigateForward: 'Boolean' + description: 'String' + framework: 'WizardFrontendFramework' + frameworks: 'WizardFrontendFramework' + isManualInstall: 'Boolean' + packagesToInstall: 'WizardNpmPackage' + sampleCode: 'String' + step: 'WizardStep' + testingType: 'TestingTypeEnum' + testingTypes: 'TestingTypeInfo' + title: 'String' + } + WizardBundler: { // field return type name + id: 'SupportedBundlers' + isSelected: 'Boolean' + name: 'String' + package: 'String' + } + WizardFrontendFramework: { // field return type name + id: 'FrontendFramework' + isSelected: 'Boolean' + name: 'String' + supportedBundlers: 'WizardBundler' + } + WizardNpmPackage: { // field return type name + description: 'String' + name: 'String' } } @@ -148,6 +238,26 @@ export interface NexusGenArgTypes { addProject: { // args input: NexusGenInputs['AddProjectInput']; // AddProjectInput! } + wizardNavigate: { // args + direction: NexusGenEnums['WizardNavigateDirection']; // WizardNavigateDirection! + } + wizardSetBundler: { // args + bundler: NexusGenEnums['SupportedBundlers']; // SupportedBundlers! + } + wizardSetFramework: { // args + framework: NexusGenEnums['FrontendFramework']; // FrontendFramework! + } + wizardSetManualInstall: { // args + isManual: boolean; // Boolean! + } + wizardSetTestingType: { // args + type: NexusGenEnums['TestingTypeEnum']; // TestingTypeEnum! + } + } + Wizard: { + sampleCode: { // args + lang: NexusGenEnums['WizardCodeLanguage']; // WizardCodeLanguage! + } } } @@ -182,7 +292,7 @@ export type NexusGenFeaturesConfig = { } export interface NexusGenTypes { - context: any; + context: BaseContext; inputTypes: NexusGenInputs; rootTypes: NexusGenRootTypes; inputTypeShapes: NexusGenInputs & NexusGenEnums & NexusGenScalars; diff --git a/packages/graphql/src/index.ts b/packages/graphql/src/index.ts new file mode 100644 index 000000000000..6b6f30865798 --- /dev/null +++ b/packages/graphql/src/index.ts @@ -0,0 +1,13 @@ +export * from './entities' + +export * from './context/BaseContext' + +export * from './actions/BaseActions' + +export * from './constants' + +export { graphqlSchema } from './schema' + +export * from './contracts' + +export { execute, parse } from 'graphql' diff --git a/packages/graphql/src/schema.ts b/packages/graphql/src/schema.ts new file mode 100644 index 000000000000..62e8efd042ab --- /dev/null +++ b/packages/graphql/src/schema.ts @@ -0,0 +1,41 @@ +import { makeSchema, asNexusMethod } from 'nexus' +import path from 'path' +import { JSONResolver, DateTimeResolver } from 'graphql-scalars' +import * as entities from './entities' +import * as constants from './constants' +import * as testingTypes from './testing/testUnionType' + +const customScalars = [ + asNexusMethod(JSONResolver, 'json'), + asNexusMethod(DateTimeResolver, 'dateTime'), +] + +// for vite +const dirname = typeof __dirname !== 'undefined' ? __dirname : '' + +// for vite +process.cwd ??= () => '' + +const isCodegen = Boolean(process.env.GRAPHQL_CODEGEN) + +export const graphqlSchema = makeSchema({ + types: [entities, constants, customScalars, dirname ? null : testingTypes], + shouldGenerateArtifacts: isCodegen, + shouldExitAfterGenerateArtifacts: Boolean(process.env.GRAPHQL_CODEGEN_EXIT), + // for vite + outputs: isCodegen ? { + typegen: path.join(dirname, 'gen/nxs.gen.ts'), + schema: path.join(dirname, '..', 'schema.graphql'), + } : false, + contextType: { + module: path.join(dirname, './context/BaseContext.ts'), + export: 'BaseContext', + }, + formatTypegen (content, type) { + if (type === 'schema') { + return content + } + + return `/* eslint-disable */\n${content}` + }, +}) diff --git a/packages/server/lib/graphql/server.ts b/packages/graphql/src/server.ts similarity index 58% rename from packages/server/lib/graphql/server.ts rename to packages/graphql/src/server.ts index 80447c73106f..c2db56d562cc 100644 --- a/packages/server/lib/graphql/server.ts +++ b/packages/graphql/src/server.ts @@ -1,18 +1,18 @@ import { graphqlHTTP } from 'express-graphql' import express from 'express' import Debug from 'debug' -import { Server } from 'http' +import type { Server } from 'http' import type { AddressInfo } from 'net' import { graphqlSchema } from './schema' -import { ExecContext } from './ExecContext' +import type { BaseContext } from './context/BaseContext' const debug = Debug('cypress:server:graphql') let app: ReturnType let server: Server -export function closeGraphQLServer () { +export function closeGraphQLServer (): Promise { if (!server || !server.listening) { return Promise.resolve(null) } @@ -28,14 +28,30 @@ export function closeGraphQLServer () { }) } -export function startGraphQLServer () { +// singleton during the lifetime of the application +let serverContext: BaseContext | undefined + +// Injected this way, since we want to set this up where the IPC layer +// is established in the server package, which should be an independent +// layer from GraphQL +export function setServerContext (ctx: BaseContext) { + serverContext = ctx + + return ctx +} + +export function startGraphQLServer (): {server: Server, app: Express.Application} { app = express() app.use('/graphql', graphqlHTTP(() => { + if (!serverContext) { + throw new Error(`setServerContext has not been called`) + } + return { schema: graphqlSchema, graphiql: true, - context: new ExecContext({}), + context: serverContext, } })) diff --git a/packages/graphql/src/testing/ProjectBaseTest.ts b/packages/graphql/src/testing/ProjectBaseTest.ts new file mode 100644 index 000000000000..999504d1745f --- /dev/null +++ b/packages/graphql/src/testing/ProjectBaseTest.ts @@ -0,0 +1 @@ +export class ProjectBaseTest {} diff --git a/packages/graphql/src/testing/testUnionType.ts b/packages/graphql/src/testing/testUnionType.ts new file mode 100644 index 000000000000..4edb3cff5c2a --- /dev/null +++ b/packages/graphql/src/testing/testUnionType.ts @@ -0,0 +1,57 @@ +/* eslint-disable */ +// Generated by codegen-mount-ts.ts, do not edit directly +import type { NexusGenObjects } from '@packages/graphql/src/gen/nxs.gen' +export interface TestSourceTypeLookup { + App: NexusGenObjects['App'], + Mutation: NexusGenObjects['Mutation'], + Project: NexusGenObjects['Project'], + Query: NexusGenObjects['Query'], + TestingTypeInfo: NexusGenObjects['TestingTypeInfo'], + Wizard: NexusGenObjects['Wizard'], + WizardBundler: NexusGenObjects['WizardBundler'], + WizardFrontendFramework: NexusGenObjects['WizardFrontendFramework'], + WizardNpmPackage: NexusGenObjects['WizardNpmPackage'], +} + +import { list, nonNull, queryField, unionType } from 'nexus' + +export const testUnionType = unionType({ + name: 'TestUnion', + definition (t) { + // !!! Generated by codegen-mount-ts.ts, do not edit directly !!! + t.members( + 'App', + 'Mutation', + 'Project', + 'Query', + 'TestingTypeInfo', + 'Wizard', + 'WizardBundler', + 'WizardFrontendFramework', + 'WizardNpmPackage' + ) + // !!! Generated by codegen-mount-ts.ts, do not edit directly !!! + }, + resolveType (c) { + // @ts-ignore + return c.__typename ?? c.constructor.name + }, +}) + +// !!! Generated by codegen-mount-ts.ts, do not edit directly !!! +export const testFragmentMember = queryField('testFragmentMember', { + description: 'Provides a fragment target for testing', + type: nonNull(testUnionType), + resolve: (source) => { + return source + } +}) + +// !!! Generated by codegen-mount-ts.ts, do not edit directly !!! +export const testFragmentMemberList = queryField('testFragmentMemberList', { + description: 'Provides a fragment target list for testing', + type: list(nonNull(testUnionType)), + resolve: (source) => { + return source + } +}) diff --git a/packages/graphql/src/util/wizardGetConfigCode.ts b/packages/graphql/src/util/wizardGetConfigCode.ts new file mode 100644 index 000000000000..76029488ac2b --- /dev/null +++ b/packages/graphql/src/util/wizardGetConfigCode.ts @@ -0,0 +1,60 @@ +import { FRAMEWORK_CONFIG_FILE, WizardCodeLanguage } from '../constants/wizardConstants' +import type { WizardBundler } from '../entities/WizardBundler' +import type { WizardFrontendFramework } from '../entities/WizardFrontendFramework' + +interface GetCodeOpts { + framework: WizardFrontendFramework + bundler: WizardBundler + lang: WizardCodeLanguage +} + +const LanguageNames: Record = { + js: 'JavaScript', + ts: 'TypeScript', +} + +export const wizardGetConfigCode = (opts: GetCodeOpts): string | null => { + const { framework, bundler, lang } = opts + + const comments = `Component testing, ${LanguageNames[opts.lang]}, ${framework.name}, ${bundler.name}` + const frameworkConfig = FRAMEWORK_CONFIG_FILE[framework.id] + + if (frameworkConfig) { + return `// ${comments} + +${frameworkConfig[lang]}` + } + + const exportStatement = + lang === 'js' ? 'module.exports = {' : 'export default {' + + const importStatements = + lang === 'js' + ? '' + : [ + `import { startdevServer } from \'${bundler.package}\'`, + `import webpackConfig from './webpack.config'`, + '', + ].join('\n') + + const requireStatements = + lang === 'ts' + ? '' + : [ + `const { startDevServer } = require('${bundler.package}')`, + `const webpackConfig = require('./webpack.config')`, + '', + ].join('\n ') + + const startServerReturn = `return startDevServer({ options, webpackConfig })` + + return `// ${comments} +${importStatements} +${exportStatement} + ${requireStatements}component(on, config) { + on('dev-server:start', (options) => { + ${startServerReturn} + }) + } +}` +} diff --git a/packages/graphql/tsconfig.json b/packages/graphql/tsconfig.json new file mode 100644 index 000000000000..35c3d8446957 --- /dev/null +++ b/packages/graphql/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../ts/tsconfig.json", + "compilerOptions": { + "experimentalDecorators": true, + "noImplicitAny": true, + "importsNotUsedAsValues": "error" + } +} \ No newline at end of file diff --git a/packages/launchpad/cypress/support/commands.ts b/packages/launchpad/cypress/support/commands.ts index d104ae934dd5..76f8f29cf849 100644 --- a/packages/launchpad/cypress/support/commands.ts +++ b/packages/launchpad/cypress/support/commands.ts @@ -1,9 +1,12 @@ -import { mount } from '@cypress/vue' -import { provideApolloClient } from '@vue/apollo-composable' -import { createStoreApp, StoreApp } from '../../src/store/app' -import { initGraphQLipc } from '../../src/graphql/graphqlIpc' -import { apolloClient } from '../../src/graphql/apolloClient' -import { createStoreConfig, StoreConfig } from '../../src/store/config' +import { mount, CyMountOptions } from '@cypress/vue' +import urql, { TypedDocumentNode, useQuery } from '@urql/vue' +import { print, FragmentDefinitionNode } from 'graphql' + +import { testApolloClient } from './testApolloClient' +import { Component, computed, defineComponent, h } from 'vue' + +import { ClientTestContext } from '../../src/graphql/ClientTestContext' +import type { TestSourceTypeLookup } from '@packages/graphql/src/testing/testUnionType' /** * This variable is mimicing ipc provided by electron. @@ -15,48 +18,112 @@ import { createStoreConfig, StoreConfig } from '../../src/store/config' send: () => {}, } -initGraphQLipc() - Cypress.Commands.add( 'mount', - (comp: Parameters[0], options: Parameters[1]) => { - const storeApp = createStoreApp() - const storeConfig = createStoreConfig(storeApp) - - Cypress.storeApp = storeApp - Cypress.storeConfig = storeConfig - - options = options || {} + (comp: C, options: CyMountOptions = {}) => { options.global = options.global || {} options.global.plugins = options.global.plugins || [] - options.global.plugins.push(storeApp) - options.global.plugins.push(storeConfig) - options.global.plugins.push({ install (app) { - provideApolloClient(apolloClient) - } }) + options.global.plugins.push({ + install (app) { + app.use(urql, testApolloClient({ + context: new ClientTestContext(), + })) + }, + }) return mount(comp, options) }, ) +function mountFragment> (source: T, options: MountFragmentConfig, list: boolean = false): Cypress.Chainable { + const ctx = new ClientTestContext() + + return mount(defineComponent({ + name: `mountFragment`, + setup () { + const fieldName = list ? 'testFragmentMemberList' : 'testFragmentMember' + const result = useQuery({ + query: ` + query MountFragmentTest { + ${fieldName} { + ...${(source.definitions[0] as FragmentDefinitionNode).name.value} + } + } + ${print(source)} + `, + }) + + return { + gql: computed(() => result.data.value?.[fieldName]), + } + }, + render: (props) => { + return props.gql ? options.render(props.gql) : h('div') + }, + }), { + global: { + plugins: [ + { + install (app) { + app.use(urql, testApolloClient({ + context: ctx, + rootValue: options.type(ctx), + })) + }, + }, + ], + }, + }).then(() => ctx) +} + +Cypress.Commands.add('mountFragment', mountFragment) + +Cypress.Commands.add('mountFragmentList', (source, options) => { + return mountFragment(source, options, true) +}) + +type GetRootType = T extends TypedDocumentNode + ? U extends { __typename?: infer V } + ? V extends keyof TestSourceTypeLookup + ? TestSourceTypeLookup[V] + : never + : never + : never + +type MountFragmentConfig = { + variables?: T['__variablesType'] + render: (frag: Exclude) => JSX.Element + type: (ctx: ClientTestContext) => GetRootType +} & CyMountOptions + +type MountFragmentListConfig = { + variables?: T['__variablesType'] + render: (frag: Exclude[]) => JSX.Element + type: (ctx: ClientTestContext) => GetRootType[] +} & CyMountOptions + declare global { namespace Cypress { interface Chainable { /** * Install all vue plugins and globals then mount */ - mount: typeof mount - } - interface Cypress { + mount(comp: Component, options?: CyMountOptions): Cypress.Chainable /** - * The sroreApp used in the mount command + * Mount helper for a component with a GraphQL fragment */ - storeApp: StoreApp + mountFragment>( + fragment: T, + config: MountFragmentConfig + ): Cypress.Chainable /** - * The sroreConfig used in the mount command + * Mount helper for a component with a GraphQL fragment, as a list */ - storeConfig: StoreConfig + mountFragmentList>( + fragment: T, + config: MountFragmentListConfig + ): Cypress.Chainable } } } diff --git a/packages/launchpad/cypress/support/testApolloClient.ts b/packages/launchpad/cypress/support/testApolloClient.ts new file mode 100644 index 000000000000..902151410eeb --- /dev/null +++ b/packages/launchpad/cypress/support/testApolloClient.ts @@ -0,0 +1,29 @@ +import { cacheExchange, Client, createClient, dedupExchange, errorExchange } from '@urql/core' +import { executeExchange } from '@urql/exchange-execute' +import { graphqlSchema } from '@packages/graphql' +import type { ClientTestContext } from '../../src/graphql/ClientTestContext' + +interface TestApolloClientConfig { + context: ClientTestContext + rootValue?: any +} + +export function testApolloClient (config: TestApolloClientConfig): Client { + return createClient({ + url: '/graphql', + exchanges: [ + dedupExchange, + cacheExchange, + errorExchange({ + onError (error) { + // eslint-disable-next-line + console.error(error) + }, + }), + executeExchange({ + schema: graphqlSchema, + ...config, + }), + ], + }) +} diff --git a/packages/launchpad/graphql-codegen.yml b/packages/launchpad/graphql-codegen.yml index 13fe6337ce6e..fe5c703503b8 100644 --- a/packages/launchpad/graphql-codegen.yml +++ b/packages/launchpad/graphql-codegen.yml @@ -1,8 +1,8 @@ overwrite: true -schema: '../server/schema.graphql' -documents: 'src/**/*.vue' +schema: '../graphql/schema.graphql' generates: - src/generated/graphql.tsx: + src/generated/graphql.ts: + documents: 'src/**/*.vue' config: immutableTypes: true useTypeImports: true @@ -11,9 +11,13 @@ generates: avoidOptionals: true enumsAsTypes: true plugins: + - add: + content: '/* eslint-disable */' - 'typescript' - 'typescript-operations' - 'typed-document-node' -hooks: - afterOneFileWrite: - - eslint --fix \ No newline at end of file + ../graphql/src/testing/testUnionType.ts: + plugins: + - add: + content: '/* eslint-disable */' + - 'script/codegen-mount.js' diff --git a/packages/launchpad/package.json b/packages/launchpad/package.json index 04841cff0b0e..766bbd7aa476 100644 --- a/packages/launchpad/package.json +++ b/packages/launchpad/package.json @@ -5,25 +5,27 @@ "scripts": { "prebuild": "yarn codegen", "build": "vite build", + "types": "vue-tsc --noEmit", "build-prod": "cross-env NODE_ENV=production yarn build", "clean-deps": "rm -rf node_modules", - "test": "yarn cypress:run:ct", + "test": "yarn cypress:run && yarn types", + "cypress:launch": "cross-env TZ=America/New_York node ../../scripts/cypress open --project ${PWD}", "cypress:open": "cross-env TZ=America/New_York node ../../scripts/cypress open-ct --project ${PWD}", "cypress:run": "cross-env TZ=America/New_York node ../../scripts/cypress run-ct --project ${PWD}", "dev": "NODE_ENV=development LAUNCHPAD=1 node ../../scripts/cypress open", "postinstall": "yarn codegen && echo '@packages/launchpad needs: yarn build'", "start": "http-server -p 5050 dist", - "watch": "yarn build --watch", + "watch": "concurrently \"vite build --watch\" \"yarn codegen --watch\"", "codegen": "graphql-codegen --config ${PWD}/graphql-codegen.yml" }, "dependencies": { "bluebird": "3.5.3", "classnames": "2.3.1", - "vue": "3.1.1" + "vue": "3.2.0-beta.7" }, "devDependencies": { - "@apollo/client": "^3.3.21", "@cypress/vue": "0.0.0-development", + "@graphql-codegen/add": "^2.0.2", "@graphql-codegen/cli": "^1.21.6", "@graphql-codegen/typed-document-node": "^1.18.9", "@graphql-codegen/typescript": "^1.22.4", @@ -31,27 +33,33 @@ "@graphql-typed-document-node/core": "^3.1.0", "@iconify/json": "1.1.368", "@iconify/vue": "3.0.0-beta.1", + "@urql/core": "2.1.5", + "@urql/exchange-execute": "^1.0.4", + "@urql/vue": "0.4.3", "@vitejs/plugin-vue": "1.2.4", "@vitejs/plugin-vue-jsx": "1.1.6", - "@vue/apollo-composable": "4.0.0-alpha.12", "bluebird": "3.5.3", "classnames": "2.3.1", + "concurrently": "^6.2.0", "cross-env": "6.0.3", "graphql": "^15.5.1", "graphql-tag": "^2.12.5", "prismjs": "1.24.0", - "vite": "2.4.1", + "rollup-plugin-polyfill-node": "^0.7.0", + "vite": "^2.4.4", "vite-plugin-components": "0.11.3", "vite-plugin-icons": "0.6.3", "vite-plugin-windicss": "1.2.4", - "vue": "3.1.1", + "vue": "3.2.0-beta.7", "vue-prism-component": "2.0.0", "vue-tsc": "0.0.24", - "windicss": "3.1.4" + "windicss": "3.1.4", + "wonka": "^4.0.15" }, "files": [ "dist", "lib", + "script", "graphql-codegen.yml", "src" ] diff --git a/packages/launchpad/script/build-schema.js b/packages/launchpad/script/build-schema.js deleted file mode 100644 index 172573ae8590..000000000000 --- a/packages/launchpad/script/build-schema.js +++ /dev/null @@ -1,3 +0,0 @@ -process.env.GRAPHQL_CODEGEN = 'true' -require('@packages/ts/register') -require('../../server/lib/graphql/schema') diff --git a/packages/launchpad/script/codegen-mount-ts.ts b/packages/launchpad/script/codegen-mount-ts.ts new file mode 100644 index 000000000000..334e073f6586 --- /dev/null +++ b/packages/launchpad/script/codegen-mount-ts.ts @@ -0,0 +1,67 @@ +import type { CodegenPlugin } from '@graphql-codegen/plugin-helpers' +import { isInterfaceType, isObjectType } from 'graphql' +import path from 'path' + +const plugin: CodegenPlugin = { + plugin: (schema, documents, config, info) => { + const typesMap = schema.getTypeMap() + + let typeMap: string[] = [] + let objects: string[] = [] + + for (const [typeName, type] of Object.entries(typesMap)) { + if (!typeName.startsWith('__') && isObjectType(type) || isInterfaceType(type)) { + typeMap.push(` ${typeName}: NexusGenObjects['${typeName}'],`) + if (isObjectType(type)) { + objects.push(typeName) + } + } + } + + return [ + `// Generated by ${path.basename(__filename)}, do not edit directly`, + `import type { NexusGenObjects } from '@packages/graphql/src/gen/nxs.gen'`, + `export interface TestSourceTypeLookup {`, + typeMap.join('\n'), + `}`, + ` +import { list, nonNull, queryField, unionType } from 'nexus' + +export const testUnionType = unionType({ + name: 'TestUnion', + definition (t) { + // !!! Generated by ${path.basename(__filename)}, do not edit directly !!! + t.members( + ${objects.map((o) => `'${o}'`).join(',\n ')} + ) + // !!! Generated by ${path.basename(__filename)}, do not edit directly !!! + }, + resolveType (c) { + // @ts-ignore + return c.__typename ?? c.constructor.name + }, +}) + +// !!! Generated by ${path.basename(__filename)}, do not edit directly !!! +export const testFragmentMember = queryField('testFragmentMember', { + description: 'Provides a fragment target for testing', + type: nonNull(testUnionType), + resolve: (source) => { + return source + } +}) + +// !!! Generated by ${path.basename(__filename)}, do not edit directly !!! +export const testFragmentMemberList = queryField('testFragmentMemberList', { + description: 'Provides a fragment target list for testing', + type: list(nonNull(testUnionType)), + resolve: (source) => { + return source + } +}) +`, + ].join('\n') + }, +} + +export default plugin diff --git a/packages/launchpad/script/codegen-mount.js b/packages/launchpad/script/codegen-mount.js new file mode 100644 index 000000000000..c4c885dbd4ed --- /dev/null +++ b/packages/launchpad/script/codegen-mount.js @@ -0,0 +1,2 @@ +require('@packages/ts/register') +module.exports = require('./codegen-mount-ts').default diff --git a/packages/launchpad/src/App.vue b/packages/launchpad/src/App.vue index 00ca48281d8a..4ffdfe163a27 100644 --- a/packages/launchpad/src/App.vue +++ b/packages/launchpad/src/App.vue @@ -5,9 +5,6 @@ diff --git a/packages/launchpad/src/components/ButtonBar.spec.tsx b/packages/launchpad/src/components/ButtonBar.spec.tsx index 1d6175f5a787..17581b552783 100644 --- a/packages/launchpad/src/components/ButtonBar.spec.tsx +++ b/packages/launchpad/src/components/ButtonBar.spec.tsx @@ -1,48 +1,47 @@ import ButtonBar from './ButtonBar.vue' describe('', () => { + let nextFn: ReturnType + let backFn: ReturnType + + beforeEach(() => { + nextFn = cy.stub() + backFn = cy.stub() + }) + it('playground', () => { - cy.mount(() => ) + cy.mount(() => ) }) it('should trigger the next function', () => { - cy.mount(() => ).then(() => { - const nextFunction = cy.spy() - - Cypress.storeApp.onNext(nextFunction) - cy.contains('Next Step') - .click() - .then(() => { - expect(nextFunction).to.have.been.calledOnce - }) + cy.mount(() => ) + cy.contains('Next Step') + .click() + .then(() => { + expect(nextFn).to.have.been.calledOnce }) }) it('should trigger the back function', () => { - cy.mount(() => ).then(() => { - const backFunction = cy.spy() - - Cypress.storeApp.onBack(backFunction) - cy.contains('Back') - .click() - .then(() => { - expect(backFunction).to.have.been.calledOnce - }) + cy.mount(() => ) + cy.contains('Back') + .click() + .then(() => { + expect(backFn).to.have.been.calledOnce }) }) it('should show a switch on the right when alt is mentionned and onAlt is set', () => { + const altFunction = cy.spy() + cy.mount(() => ( - - )).then(() => { - const altFunction = cy.spy() - - Cypress.storeApp.onAlt(altFunction) - cy.contains('Install manually') - .click() - .then(() => { - expect(altFunction).to.have.been.calledOnce - }) + + )) + + cy.contains('Install manually') + .click() + .then(() => { + expect(altFunction).to.have.been.calledOnce }) }) }) diff --git a/packages/launchpad/src/components/ButtonBar.vue b/packages/launchpad/src/components/ButtonBar.vue index ed06b21f2067..01a7372133d5 100644 --- a/packages/launchpad/src/components/ButtonBar.vue +++ b/packages/launchpad/src/components/ButtonBar.vue @@ -10,10 +10,10 @@ rounded-b " > - - + +
-
+
@@ -21,8 +21,7 @@ diff --git a/packages/launchpad/src/components/ConfigFile.spec.tsx b/packages/launchpad/src/components/ConfigFile.spec.tsx index 05522d0fe34b..43a70a9b42c6 100644 --- a/packages/launchpad/src/components/ConfigFile.spec.tsx +++ b/packages/launchpad/src/components/ConfigFile.spec.tsx @@ -1,31 +1,32 @@ import { ref } from 'vue' -import { SupportedBundlerWebpack } from '../utils/bundler' -import { SupportedFrameworkNext } from '../utils/frameworks' +import { ConfigFileFragmentDoc } from '../generated/graphql' import ConfigFile from './ConfigFile.vue' describe('', () => { beforeEach(() => { const display = ref(false) - cy.mount(() => ( -
- - {display.value ? : undefined} -
- )).then(() => { - Cypress.storeConfig.setComponentSetup({ - bundler: SupportedBundlerWebpack, - framework: SupportedFrameworkNext, - }) + cy.mountFragment(ConfigFileFragmentDoc, { + type: (ctx) => { + ctx.wizard.setFramework('nuxtjs') - cy.get('[data-cy="show"]').click({ force: true }) + return ctx.wizard + }, + render: (gqlVal) => ( +
+ + {display.value ? : undefined} +
+ ), }) + + cy.get('[data-cy="show"]').click({ force: true }) }) it('playground', { viewportWidth: 1280, viewportHeight: 1024 }, () => { diff --git a/packages/launchpad/src/components/ConfigFile.vue b/packages/launchpad/src/components/ConfigFile.vue index c277df74c4fa..81dc5d5cfc1d 100644 --- a/packages/launchpad/src/components/ConfigFile.vue +++ b/packages/launchpad/src/components/ConfigFile.vue @@ -1,5 +1,5 @@ diff --git a/packages/launchpad/src/components/Layout.vue b/packages/launchpad/src/components/Layout.vue index fcbf92f025a7..7dfb94d23c82 100644 --- a/packages/launchpad/src/components/Layout.vue +++ b/packages/launchpad/src/components/Layout.vue @@ -37,6 +37,7 @@
diff --git a/packages/launchpad/src/components/Select.spec.tsx b/packages/launchpad/src/components/Select.spec.tsx index 8434b216524e..188045c222b3 100644 --- a/packages/launchpad/src/components/Select.spec.tsx +++ b/packages/launchpad/src/components/Select.spec.tsx @@ -1,22 +1,17 @@ import { ref } from 'vue' -import { Framework } from '../utils/frameworks' import Select from './Select.vue' -import LogoVue from '../images/logos/vue.svg' -import LogoReact from '../images/logos/react.svg' const manyOptions = [ { - name: 'VueJs', - logo: LogoVue, + name: 'Vue.js', id: 'vue', }, { - name: 'ReactJs', + name: 'React.js', description: '(detected)', - logo: LogoReact, id: 'react', }, -] +] as const describe('', () => { it('playground', () => { @@ -30,7 +25,7 @@ describe('', () => {
)) - cy.contains('button', 'ReactJs').click() + cy.contains('button', 'React.js').click() }) it('renders the name', () => { @@ -47,7 +42,6 @@ describe('', () => { options={[ { name: 'VueJs', - logo: 'vue', id: 'vue', }, ]} @@ -62,7 +56,7 @@ describe('', () => {