diff --git a/cli/types/cypress.d.ts b/cli/types/cypress.d.ts index 4002b1f5734..b91a34f4b95 100644 --- a/cli/types/cypress.d.ts +++ b/cli/types/cypress.d.ts @@ -3398,6 +3398,12 @@ declare namespace Cypress { * @internal */ specPattern?: '**/*.cy.ts' + + /** + * Raw SVG icon that will be displayed in the Project Setup Wizard. Used for third parties that + * want to render a custom icon. + */ + icon?: string } type ComponentFrameworkDefinition = Omit & { diff --git a/packages/data-context/src/actions/WizardActions.ts b/packages/data-context/src/actions/WizardActions.ts index ed2322c6edf..e8f8ab2cd96 100644 --- a/packages/data-context/src/actions/WizardActions.ts +++ b/packages/data-context/src/actions/WizardActions.ts @@ -1,5 +1,5 @@ import type { NexusGenObjects } from '@packages/graphql/src/gen/nxs.gen' -import { detectFramework, commandsFileBody, supportFileComponent, supportFileE2E, getBundler } from '@packages/scaffold-config' +import { detectFramework, commandsFileBody, supportFileComponent, supportFileE2E, getBundler, CT_FRAMEWORKS, resolveComponentFrameworkDefinition, detectThirdPartyCTFrameworks } from '@packages/scaffold-config' import assert from 'assert' import path from 'path' import Debug from 'debug' @@ -161,6 +161,20 @@ export class WizardActions { } } + async detectFrameworks () { + if (!this.ctx.currentProject) { + return + } + + const officialFrameworks = CT_FRAMEWORKS.map((framework) => resolveComponentFrameworkDefinition(framework)) + const thirdParty = await detectThirdPartyCTFrameworks(this.ctx.currentProject) + const resolvedThirdPartyFrameworks = thirdParty.map(resolveComponentFrameworkDefinition) + + this.ctx.update((d) => { + d.wizard.frameworks = officialFrameworks.concat(resolvedThirdPartyFrameworks) + }) + } + private async scaffoldE2E () { // Order of the scaffoldedFiles is intentional, confirm before changing const scaffoldedFiles = await Promise.all([ diff --git a/packages/graphql/schemas/schema.graphql b/packages/graphql/schemas/schema.graphql index 44e0d1f0b25..b95129d56b7 100644 --- a/packages/graphql/schemas/schema.graphql +++ b/packages/graphql/schemas/schema.graphql @@ -2338,6 +2338,9 @@ type WizardFrontendFramework implements Node { """The category (framework, like react-scripts, or library, like react""" category: String! + """Raw SVG icon of framework""" + icon: String + """Relay style Node ID field for the WizardFrontendFramework field""" id: ID! diff --git a/packages/graphql/src/schemaTypes/objectTypes/gql-Mutation.ts b/packages/graphql/src/schemaTypes/objectTypes/gql-Mutation.ts index 11d4f690921..1a1ed01de9b 100644 --- a/packages/graphql/src/schemaTypes/objectTypes/gql-Mutation.ts +++ b/packages/graphql/src/schemaTypes/objectTypes/gql-Mutation.ts @@ -182,6 +182,7 @@ export const mutation = mutationType({ if (ctx.coreData.currentTestingType && !ctx.lifecycleManager.isTestingTypeConfigured(ctx.coreData.currentTestingType)) { // Component Testing has a wizard to help users configure their project if (ctx.coreData.currentTestingType === 'component') { + await ctx.actions.wizard.detectFrameworks() await ctx.actions.wizard.initialize() } else { // E2E doesn't have such a wizard, we just create/update their cypress.config.js. diff --git a/packages/graphql/src/schemaTypes/objectTypes/gql-WizardFrontendFramework.ts b/packages/graphql/src/schemaTypes/objectTypes/gql-WizardFrontendFramework.ts index 98df48562b3..d61c186f5dd 100644 --- a/packages/graphql/src/schemaTypes/objectTypes/gql-WizardFrontendFramework.ts +++ b/packages/graphql/src/schemaTypes/objectTypes/gql-WizardFrontendFramework.ts @@ -52,5 +52,9 @@ export const WizardFrontendFramework = objectType({ return ctx.wizardData.chosenFramework?.supportedBundlers.map(findBundler) ?? [] }, }) + + t.string('icon', { + description: 'Raw SVG icon of framework', + }) }, }) diff --git a/packages/launchpad/cypress/e2e/scaffold-component-testing.cy.ts b/packages/launchpad/cypress/e2e/scaffold-component-testing.cy.ts index 86299809853..2d6ebe7a587 100644 --- a/packages/launchpad/cypress/e2e/scaffold-component-testing.cy.ts +++ b/packages/launchpad/cypress/e2e/scaffold-component-testing.cy.ts @@ -149,4 +149,34 @@ describe('scaffolding component testing', { verifyConfigFile(`cypress.config.js`) }) }) + + context('3rd party ct plugin', () => { + it('Scaffolds component testing for Qwik using Vite', () => { + cy.scaffoldProject('qwik-app') + cy.openProject('qwik-app') + cy.visitLaunchpad() + cy.skipWelcome() + + cy.withCtx(async (ctx) => { + await ctx.actions.file.removeFileInProject('./node_modules/cypress-ct-qwik') + await ctx.actions.file.moveFileInProject('./cypress-ct-qwik', './node_modules/cypress-ct-qwik') + }) + + cy.contains('Component Testing').click() + cy.contains('button', 'Qwik') + cy.contains('button', 'Next step').click() + + cy.contains('li', '@builder.io/qwik').within(() => { + cy.findByLabelText('installed') + }) + + cy.contains('li', 'vite').within(() => { + cy.findByLabelText('installed') + }) + + cy.contains('button', 'Continue').click() + + verifyConfigFile('cypress.config.js') + }) + }) }) diff --git a/packages/launchpad/src/setup/EnvironmentSetup.vue b/packages/launchpad/src/setup/EnvironmentSetup.vue index dbd58ef62b8..8241ad9344f 100644 --- a/packages/launchpad/src/setup/EnvironmentSetup.vue +++ b/packages/launchpad/src/setup/EnvironmentSetup.vue @@ -65,6 +65,7 @@ fragment EnvironmentSetup on Wizard { isDetected } category + icon } frameworks { id @@ -73,6 +74,7 @@ fragment EnvironmentSetup on Wizard { isDetected type category + icon } allBundlers { id @@ -104,6 +106,7 @@ const frameworks = computed(() => { name: x.name, id: x.id, isDetected: x.isDetected, + icon: x.icon || undefined, } }) diff --git a/packages/launchpad/src/setup/SelectFwOrBundler.vue b/packages/launchpad/src/setup/SelectFwOrBundler.vue index 4d22dbfba70..43c0e93f8e7 100644 --- a/packages/launchpad/src/setup/SelectFwOrBundler.vue +++ b/packages/launchpad/src/setup/SelectFwOrBundler.vue @@ -25,8 +25,14 @@ > +