test(launchpad): add e2e tests for Project Setup - Round 3 (#19704)
Co-authored-by: Tyler Biethman <tbiethman@users.noreply.github.com> Co-authored-by: Tyler Biethman <tbiethman@gmail.com>
@@ -41,7 +41,7 @@
|
||||
"combine-properties": "0.1.0",
|
||||
"concurrently": "^6.2.0",
|
||||
"cross-env": "6.0.3",
|
||||
"cypress-real-events": "1.4.0",
|
||||
"cypress-real-events": "1.6.0",
|
||||
"faker": "5.5.3",
|
||||
"fuzzysort": "^1.1.4",
|
||||
"graphql": "^15.5.1",
|
||||
|
||||
@@ -30,10 +30,10 @@ export class WizardActions {
|
||||
this.ctx.coreData.wizard.chosenFramework = framework
|
||||
|
||||
if (framework !== 'react' && framework !== 'vue') {
|
||||
this.setBundler('webpack')
|
||||
return this.setBundler('webpack')
|
||||
}
|
||||
|
||||
return this.data
|
||||
return this.setBundler(null)
|
||||
}
|
||||
|
||||
setBundler (bundler: NexusGenEnums['SupportedBundlers'] | null) {
|
||||
|
||||
@@ -38,14 +38,14 @@ export class WizardDataSource {
|
||||
}
|
||||
|
||||
get chosenFramework () {
|
||||
return FRONTEND_FRAMEWORKS.find((f) => f.type === this.ctx.wizardData.chosenFramework)
|
||||
return FRONTEND_FRAMEWORKS.find((f) => f.type === this.ctx.wizardData.chosenFramework) || null
|
||||
}
|
||||
|
||||
get chosenBundler () {
|
||||
return BUNDLERS.find((f) => f.type === this.ctx.wizardData.chosenBundler)
|
||||
return BUNDLERS.find((f) => f.type === this.ctx.wizardData.chosenBundler) || null
|
||||
}
|
||||
|
||||
get chosenLanguage () {
|
||||
return CODE_LANGUAGES.find((f) => f.type === this.ctx.wizardData.chosenLanguage)
|
||||
return CODE_LANGUAGES.find((f) => f.type === this.ctx.wizardData.chosenLanguage) || null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,6 +66,7 @@ export const e2eProjectDirs = [
|
||||
'pristine',
|
||||
'pristine-with-ct-testing',
|
||||
'pristine-with-e2e-testing',
|
||||
'pristine-with-e2e-testing-and-storybook',
|
||||
'react-code-gen',
|
||||
'read-only-project-root',
|
||||
'record',
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { CodegenTypeMap, Wizard } from '../generated/test-graphql-types.gen'
|
||||
import { BUNDLERS, CODE_LANGUAGES, FRONTEND_FRAMEWORKS } from '@packages/types/src/constants'
|
||||
import { BUNDLERS, CODE_LANGUAGES, FRONTEND_FRAMEWORKS, PACKAGES_DESCRIPTIONS } from '@packages/types/src/constants'
|
||||
import { MaybeResolver, testNodeId } from './clientTestUtils'
|
||||
|
||||
export const allBundlers = BUNDLERS.map((bundler, idx) => {
|
||||
@@ -15,13 +15,13 @@ export const stubWizard: MaybeResolver<Wizard> = {
|
||||
packagesToInstall: [
|
||||
{
|
||||
...testNodeId('WizardNpmPackage'),
|
||||
description: 'Used to interact with React components via Cypress',
|
||||
description: PACKAGES_DESCRIPTIONS['@cypress/react'],
|
||||
name: '@cypress/react',
|
||||
package: '@cypress/react',
|
||||
},
|
||||
{
|
||||
...testNodeId('WizardNpmPackage'),
|
||||
description: 'Used to bundle code',
|
||||
description: PACKAGES_DESCRIPTIONS['@cypress/webpack-dev-server'],
|
||||
name: '@cypress/webpack-dev-server',
|
||||
package: '@cypress/webpack-dev-server',
|
||||
},
|
||||
|
||||
@@ -153,18 +153,20 @@ export const mutation = mutationType({
|
||||
input: nonNull(arg({ type: WizardUpdateInput })),
|
||||
},
|
||||
resolve: async (source, args, ctx) => {
|
||||
if (args.input.bundler !== undefined) {
|
||||
ctx.actions.wizard.setBundler(args.input.bundler)
|
||||
if (args.input.framework) {
|
||||
ctx.actions.wizard.setFramework(args.input.framework)
|
||||
}
|
||||
|
||||
if (args.input.framework !== undefined) {
|
||||
ctx.actions.wizard.setFramework(args.input.framework)
|
||||
if (args.input.bundler) {
|
||||
ctx.actions.wizard.setBundler(args.input.bundler)
|
||||
}
|
||||
|
||||
if (args.input.codeLanguage) {
|
||||
ctx.actions.wizard.setCodeLanguage(args.input.codeLanguage)
|
||||
}
|
||||
|
||||
// TODO: remove when live-mutations are implements
|
||||
// signal to launchpad to reload the data context
|
||||
ctx.emitter.toLaunchpad()
|
||||
|
||||
return ctx.wizardData
|
||||
|
||||
@@ -20,6 +20,8 @@ import '../../../src/main.scss'
|
||||
import '@iconify/iconify'
|
||||
import '@purge-icons/generated'
|
||||
|
||||
import 'cypress-real-events/support'
|
||||
|
||||
import './commands'
|
||||
import './attachFileWithPath'
|
||||
import installCustomPercyCommand from '@packages/ui-components/cypress/support/customPercyCommand'
|
||||
|
||||
@@ -1,145 +0,0 @@
|
||||
describe('Launchpad: Onboarding Flow', () => {
|
||||
beforeEach(() => {
|
||||
cy.scaffoldProject('pristine')
|
||||
cy.openProject('pristine')
|
||||
})
|
||||
|
||||
it('can setup component testing', () => {
|
||||
cy.visitLaunchpad()
|
||||
cy.percySnapshot()
|
||||
cy.get('[data-cy-testingType=component]').click()
|
||||
cy.get('[data-testid=select-framework]').should('be.visible')
|
||||
cy.percySnapshot()
|
||||
cy.get('[data-testid=select-framework]').click()
|
||||
cy.findByText('Vue.js').click()
|
||||
cy.get('[data-testid=select-framework]').should('contain', 'Vue.js')
|
||||
cy.get('[data-testid=select-bundler]')
|
||||
.findByText(cy.i18n.setupPage.projectSetup.bundlerPlaceholder)
|
||||
.click()
|
||||
|
||||
cy.findByText('Webpack').click()
|
||||
cy.get('[data-testid=select-bundler]').should('contain', 'Webpack')
|
||||
|
||||
cy.percySnapshot()
|
||||
|
||||
cy.reload()
|
||||
cy.get('[data-testid=select-framework]').should('contain', 'Vue.js')
|
||||
cy.get('[data-testid=select-bundler]').should('contain', 'Webpack')
|
||||
cy.findByText('Next Step').click()
|
||||
cy.get('h1').should('contain', 'Dependencies')
|
||||
cy.findByText('I\'ve installed them').click()
|
||||
cy.findByText('We added the following files to your project.')
|
||||
cy.percySnapshot()
|
||||
cy.findByText('Continue').click()
|
||||
cy.withCtx((ctx) => {
|
||||
return ctx.file.readFileInProject('cypress.config.js')
|
||||
})
|
||||
|
||||
cy.findByText('Choose a Browser', { timeout: 10000 })
|
||||
cy.findByText('Choose your preferred browser for component testing.')
|
||||
})
|
||||
|
||||
it('can setup component testing with TS', () => {
|
||||
cy.visitLaunchpad()
|
||||
cy.get('[data-cy-testingType=component]').click()
|
||||
cy.get('[data-testid=select-framework]').click()
|
||||
cy.findByText('React.js').click()
|
||||
cy.get('[data-testid=select-framework]').should('contain', 'React.js')
|
||||
cy.get('[data-testid=select-bundler]')
|
||||
.findByText(cy.i18n.setupPage.projectSetup.bundlerPlaceholder)
|
||||
.click()
|
||||
|
||||
cy.findByText('Webpack').click()
|
||||
cy.get('[data-testid=select-bundler]').should('contain', 'Webpack')
|
||||
cy.reload()
|
||||
cy.get('[data-testid=select-framework]').should('contain', 'React.js')
|
||||
cy.get('[data-testid=select-bundler]').should('contain', 'Webpack')
|
||||
cy.findByText('TypeScript').click()
|
||||
cy.findByText('Next Step').click()
|
||||
cy.get('h1').should('contain', 'Dependencies')
|
||||
cy.findByText('I\'ve installed them').click()
|
||||
cy.findByText('We added the following files to your project.')
|
||||
cy.findByText('Continue').click()
|
||||
cy.withCtx((ctx) => {
|
||||
return ctx.file.readFileInProject('cypress.config.ts')
|
||||
})
|
||||
})
|
||||
|
||||
it('can setup e2e testing', () => {
|
||||
cy.visitLaunchpad()
|
||||
cy.get('[data-cy-testingType=e2e]').click()
|
||||
cy.findByText('We added the following files to your project.')
|
||||
cy.percySnapshot()
|
||||
cy.findByText('Continue').click()
|
||||
cy.findByText('Choose a Browser')
|
||||
cy.findByText('Choose your preferred browser for E2E testing.')
|
||||
})
|
||||
|
||||
it('can setup e2e testing after component has been setup', () => {
|
||||
cy.visitLaunchpad()
|
||||
cy.get('[data-cy-testingType=component]').click()
|
||||
cy.get('[data-testid=select-framework]').click()
|
||||
cy.findByText('Vue.js').click()
|
||||
cy.get('[data-testid=select-framework]').should('contain', 'Vue.js')
|
||||
cy.get('[data-testid=select-bundler]')
|
||||
.findByText(cy.i18n.setupPage.projectSetup.bundlerPlaceholder)
|
||||
.click()
|
||||
|
||||
cy.findByText('Webpack').click()
|
||||
cy.get('[data-testid=select-bundler]').should('contain', 'Webpack')
|
||||
cy.reload()
|
||||
cy.get('[data-testid=select-framework]').should('contain', 'Vue.js')
|
||||
cy.get('[data-testid=select-bundler]').should('contain', 'Webpack')
|
||||
cy.findByText('Next Step').click()
|
||||
cy.get('h1').should('contain', 'Dependencies')
|
||||
cy.findByText('I\'ve installed them').click()
|
||||
cy.findByText('We added the following files to your project.')
|
||||
cy.findByText('Continue').click()
|
||||
cy.findByText('Choose a Browser', { timeout: 10000 })
|
||||
|
||||
cy.findByText('Switch testing type').click()
|
||||
|
||||
cy.visitLaunchpad()
|
||||
cy.get('[data-cy-testingType=e2e]').click()
|
||||
cy.findByText('We added the following files to your project.')
|
||||
cy.get('[data-cy="changes"]')
|
||||
cy.findByText('Continue').closest('button').should('be.disabled')
|
||||
|
||||
cy.withCtx((ctx, o) => {
|
||||
const tmpl = `
|
||||
const { defineConfig } = require("cypress")
|
||||
module.exports = defineConfig({
|
||||
component: {
|
||||
supportFile: 'cypress/support/component.js',
|
||||
devServer: require('@cypress/webpack-dev-server'),
|
||||
devServerConfig: {}
|
||||
},
|
||||
e2e: {
|
||||
supportFile: 'cypress/support/e2e.js',
|
||||
specPattern: 'cypress/e2e/**/*.cy.{js,ts}',
|
||||
viewportHeight: 660,
|
||||
viewportWidth: 1000,
|
||||
setupNodeEvents(on, config) {
|
||||
//
|
||||
},
|
||||
}
|
||||
})
|
||||
`
|
||||
|
||||
ctx.actions.file.writeFileInProject('cypress.config.js', tmpl)
|
||||
})
|
||||
|
||||
cy.findByText('Continue').closest('button').should('not.be.disabled').click()
|
||||
cy.findByText('Choose a Browser', { timeout: 10000 })
|
||||
})
|
||||
|
||||
it('can open unconfigured component testing type, go back to the testing chooser', () => {
|
||||
cy.scaffoldProject('pristine-with-e2e-testing')
|
||||
cy.openProject('pristine-with-e2e-testing')
|
||||
cy.visitLaunchpad()
|
||||
cy.get('[data-cy-testingType=component]').click()
|
||||
cy.get('h1').should('not.contain', 'Welcome to Cypress!')
|
||||
cy.contains('Back').click()
|
||||
cy.get('h1').should('contain', 'Welcome to Cypress!')
|
||||
})
|
||||
})
|
||||
@@ -1,8 +1,11 @@
|
||||
import { FRONTEND_FRAMEWORKS, BUNDLERS, CODE_LANGUAGES, PACKAGES_DESCRIPTIONS } from '@packages/types/src/constants'
|
||||
|
||||
describe('Launchpad: Setup Project', () => {
|
||||
beforeEach(() => {
|
||||
cy.scaffoldProject('pristine') // not configured
|
||||
cy.scaffoldProject('pristine-with-ct-testing') // component configured
|
||||
cy.scaffoldProject('pristine-with-e2e-testing') // e2e configured
|
||||
cy.scaffoldProject('pristine-with-e2e-testing-and-storybook') // e2e configured
|
||||
})
|
||||
|
||||
const verifyWelcomePage = ({ e2eIsConfigured, ctIsConfigured }) => {
|
||||
@@ -49,17 +52,27 @@ describe('Launchpad: Setup Project', () => {
|
||||
it('close modal with escape key', () => {
|
||||
cy.contains('Review the differences').click()
|
||||
cy.get('#app').should('have.attr', 'aria-hidden', 'true')
|
||||
cy.findByRole('dialog', { name: 'Key Differences' }).should('be.visible')
|
||||
|
||||
cy.findByRole('dialog', { name: 'Key Differences' })
|
||||
.as('aboutTestingTypes')
|
||||
.should('be.visible')
|
||||
|
||||
cy.get('body').type('{esc}')
|
||||
cy.get('#app').should('not.have.attr', 'aria-hidden')
|
||||
cy.get('@aboutTestingTypes').should('not.exist')
|
||||
})
|
||||
|
||||
it('closes modal by clicking outside of modal', () => {
|
||||
cy.contains('Review the differences').click()
|
||||
cy.get('#app').should('have.attr', 'aria-hidden', 'true')
|
||||
cy.findByRole('dialog', { name: 'Key Differences' }).should('be.visible')
|
||||
|
||||
cy.findByRole('dialog', { name: 'Key Differences' })
|
||||
.as('aboutTestingTypes')
|
||||
.should('be.visible')
|
||||
|
||||
cy.get('body').click(5, 5)
|
||||
cy.get('#app').should('not.have.attr', 'aria-hidden')
|
||||
cy.get('@aboutTestingTypes').should('not.exist')
|
||||
})
|
||||
|
||||
it('closes modal by clicking close button', () => {
|
||||
@@ -67,18 +80,21 @@ describe('Launchpad: Setup Project', () => {
|
||||
cy.get('#app').should('have.attr', 'aria-hidden', 'true')
|
||||
|
||||
cy.findByRole('dialog', { name: 'Key Differences' })
|
||||
.as('aboutTestingTypes')
|
||||
.should('be.visible')
|
||||
.within(() => {
|
||||
cy.get('h2').contains('Key Differences').should('be.visible')
|
||||
})
|
||||
|
||||
cy.findByRole('button', { name: 'Close' }).click()
|
||||
// cy.get('[aria-label=Close]').click()
|
||||
cy.get('#app').should('not.have.attr', 'aria-hidden')
|
||||
cy.get('@aboutTestingTypes').should('not.exist')
|
||||
})
|
||||
|
||||
// FIXME: enter key down isn't trigger close callback. working correctly when manually tested.
|
||||
// could be related to this bug? https://github.com/cypress-io/cypress/issues/14864
|
||||
// Cypress enter key down isn't trigger close callback. Working correctly when manually tested
|
||||
// or when using the cypress-real-evens plugin.
|
||||
// Could be related to this bug? https://github.com/cypress-io/cypress/issues/14864
|
||||
// FIXME: https://github.com/cypress-io/cypress/pull/19726
|
||||
it.skip('closes modal by pressing enter key when close button is focused', () => {
|
||||
cy.contains('Review the differences').click()
|
||||
cy.get('#app').should('have.attr', 'aria-hidden', 'true')
|
||||
@@ -98,7 +114,7 @@ describe('Launchpad: Setup Project', () => {
|
||||
})
|
||||
|
||||
cy.get('#app').should('not.have.attr', 'aria-hidden')
|
||||
cy.get('@aboutTestTypes').should('not.be.visible')
|
||||
cy.get('@aboutTestingTypes').should('not.exist')
|
||||
})
|
||||
|
||||
it('clicking "Need Help?" links to Cypress documentation', () => {
|
||||
@@ -140,7 +156,7 @@ describe('Launchpad: Setup Project', () => {
|
||||
// project has a cypress.configuration file with component testing configured
|
||||
describe('project that has not been configured for e2e', () => {
|
||||
// FIXME: ProjectLifecycleManager is skipping straight to browser pages when it should show setup page.
|
||||
it.skip('shows the first step in configuration when selecting e2e tests', () => {
|
||||
it.skip('shows the configuration setup page when selecting e2e tests', () => {
|
||||
cy.openProject('pristine-with-ct-testing')
|
||||
cy.visitLaunchpad()
|
||||
|
||||
@@ -183,7 +199,7 @@ describe('Launchpad: Setup Project', () => {
|
||||
})
|
||||
})
|
||||
|
||||
it('shows the first step in configuration when opened via cli with --e2e flag', () => {
|
||||
it('shows the configuration setup page when opened via cli with --e2e flag', () => {
|
||||
cy.openProject('pristine-with-ct-testing', ['--e2e'])
|
||||
cy.visitLaunchpad()
|
||||
|
||||
@@ -201,33 +217,58 @@ describe('Launchpad: Setup Project', () => {
|
||||
})
|
||||
})
|
||||
|
||||
it('can setup e2e testing for a project not been configured for cypress', () => {
|
||||
cy.openProject('pristine')
|
||||
cy.visitLaunchpad()
|
||||
describe('project not been configured for cypress', () => {
|
||||
it('can setup e2e testing for a project', () => {
|
||||
cy.openProject('pristine')
|
||||
cy.visitLaunchpad()
|
||||
|
||||
verifyWelcomePage({ e2eIsConfigured: false, ctIsConfigured: false })
|
||||
verifyWelcomePage({ e2eIsConfigured: false, ctIsConfigured: false })
|
||||
|
||||
// @ts-ignore
|
||||
cy.get('body').tab().tab()
|
||||
// @ts-ignore
|
||||
cy.get('body').tab().tab()
|
||||
|
||||
cy.get('[data-cy-testingtype="e2e"]')
|
||||
.should('have.focus')
|
||||
.type('{enter}')
|
||||
cy.get('[data-cy-testingtype="e2e"]')
|
||||
.should('have.focus')
|
||||
.type('{enter}')
|
||||
|
||||
cy.contains('h1', 'Configuration Files')
|
||||
cy.findByText('We added the following files to your project.')
|
||||
cy.contains('h1', 'Configuration Files')
|
||||
cy.findByText('We added the following files to your project.')
|
||||
|
||||
cy.get('[data-cy=valid]').within(() => {
|
||||
cy.contains('cypress.config.js')
|
||||
cy.contains('cypress/support/e2e.js')
|
||||
cy.contains('cypress/fixtures/example.json')
|
||||
cy.get('[data-cy=valid]').within(() => {
|
||||
cy.contains('cypress.config.js')
|
||||
cy.contains('cypress/support/e2e.js')
|
||||
cy.contains('cypress/fixtures/example.json')
|
||||
})
|
||||
|
||||
cy.findByRole('button', { name: 'Continue' })
|
||||
.should('not.have.disabled')
|
||||
.click()
|
||||
|
||||
cy.contains(/(Initializing Config|Choose a Browser)/)
|
||||
})
|
||||
|
||||
it('shows the configuration setup page when opened via cli with --e2e flag', () => {
|
||||
cy.openProject('pristine-with-ct-testing', ['--e2e'])
|
||||
cy.visitLaunchpad()
|
||||
|
||||
cy.contains('h1', 'Configuration Files')
|
||||
cy.contains('We added the following files to your project.')
|
||||
|
||||
cy.get('[data-cy=changes]').within(() => {
|
||||
cy.contains('cypress.config.js')
|
||||
})
|
||||
|
||||
cy.get('[data-cy=valid]').within(() => {
|
||||
cy.contains('cypress/support/e2e.js')
|
||||
cy.contains('cypress/fixtures/example.json')
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('Component setup', () => {
|
||||
describe('project has been configured for component testing', () => {
|
||||
it('it skips the setup page when choosing component tests to run', () => {
|
||||
it('skips the setup steps when choosing component tests to run', () => {
|
||||
cy.openProject('pristine-with-ct-testing')
|
||||
cy.visitLaunchpad()
|
||||
|
||||
@@ -247,7 +288,7 @@ describe('Launchpad: Setup Project', () => {
|
||||
})
|
||||
|
||||
describe('project that has not been configured for component testing', () => {
|
||||
it('shows the "choose framework" page when selecting component tests', () => {
|
||||
it('shows the first setup page for configuration when selecting component tests', () => {
|
||||
cy.openProject('pristine-with-e2e-testing')
|
||||
cy.visitLaunchpad()
|
||||
|
||||
@@ -257,6 +298,154 @@ describe('Launchpad: Setup Project', () => {
|
||||
|
||||
cy.get('h1').should('contain', 'Project Setup')
|
||||
cy.contains('Confirm the front-end framework and bundler used in your project.')
|
||||
|
||||
cy.findByRole('button', {
|
||||
name: 'Front-end Framework Pick a framework',
|
||||
expanded: false,
|
||||
})
|
||||
.should('have.attr', 'aria-haspopup', 'true')
|
||||
|
||||
cy.findByRole('button', { name: 'Next Step' }).should('have.disabled')
|
||||
|
||||
cy.findByRole('button', { name: 'Back' }).click()
|
||||
|
||||
verifyWelcomePage({ e2eIsConfigured: true, ctIsConfigured: false })
|
||||
})
|
||||
|
||||
const hasStorybookPermutations = [false, true]
|
||||
|
||||
FRONTEND_FRAMEWORKS.forEach((framework) => {
|
||||
hasStorybookPermutations.forEach((hasStorybookDep) => {
|
||||
framework.supportedBundlers.forEach((testBundler) => {
|
||||
const bundler = BUNDLERS.find((b) => b.type === testBundler)
|
||||
|
||||
if (!bundler) {
|
||||
throw new Error(`${framework.name} claims to support the bundler, ${testBundler}, however it is not a valid Cypress bundler.`)
|
||||
}
|
||||
|
||||
CODE_LANGUAGES.forEach((lang) => {
|
||||
let testTitle = `can setup ${framework.name} + ${lang.name}`
|
||||
|
||||
if (framework.supportedBundlers.length > 1) {
|
||||
testTitle = `can setup ${framework.name} + ${bundler.name} + ${lang.name}`
|
||||
}
|
||||
|
||||
if (hasStorybookDep) {
|
||||
testTitle += ` for project using Storybook`
|
||||
}
|
||||
|
||||
it(testTitle, () => {
|
||||
cy.openProject(hasStorybookDep ? 'pristine-with-e2e-testing-and-storybook' : 'pristine-with-e2e-testing')
|
||||
cy.visitLaunchpad()
|
||||
|
||||
verifyWelcomePage({ e2eIsConfigured: true, ctIsConfigured: false })
|
||||
|
||||
cy.get('[data-cy-testingtype="component"]').click()
|
||||
|
||||
cy.log('Choose project setup')
|
||||
cy.get('h1').should('contain', 'Project Setup')
|
||||
cy.contains('Confirm the front-end framework and bundler used in your project.')
|
||||
|
||||
cy.findByRole('button', { name: 'Next Step' })
|
||||
.should('have.disabled')
|
||||
.as('nextStepButton')
|
||||
|
||||
cy.findByRole('button', {
|
||||
name: 'Front-end Framework Pick a framework',
|
||||
expanded: false,
|
||||
})
|
||||
.click()
|
||||
|
||||
cy.findByRole('option', { name: framework.name }).click()
|
||||
cy.findByRole('button', { name: `Front-end Framework ${framework.name}` }) // ensure selected option updates
|
||||
|
||||
if (framework.supportedBundlers.length > 1) {
|
||||
cy.findByRole('button', {
|
||||
name: 'Bundler Pick a bundler',
|
||||
expanded: false,
|
||||
})
|
||||
.should('have.attr', 'aria-haspopup', 'true')
|
||||
.click()
|
||||
.should('have.attr', 'aria-expanded', 'true')
|
||||
|
||||
framework.supportedBundlers.forEach((supportedBundler) => {
|
||||
cy.findByRole('option', { name: Cypress._.startCase(supportedBundler) })
|
||||
.find('svg')
|
||||
.should('have.attr', 'data-cy', `${Cypress._.lowerCase(supportedBundler)}-logo`)
|
||||
})
|
||||
|
||||
cy.findByRole('option', { name: bundler.name })
|
||||
.find('svg')
|
||||
.should('have.attr', 'data-cy', `${Cypress._.lowerCase(bundler.name)}-logo`)
|
||||
.click()
|
||||
|
||||
cy.findByRole('button', { name: `Bundler ${bundler.name}` }) // ensure selected option updates
|
||||
}
|
||||
|
||||
cy.findByRole('button', { name: lang.name }).click()
|
||||
|
||||
cy.log('Go to next step')
|
||||
cy.get('@nextStepButton').should('not.have.disabled').click()
|
||||
|
||||
cy.contains('h1', 'Install Dev Dependencies')
|
||||
cy.contains('p', 'Paste the command below into your terminal to install the required packages.')
|
||||
|
||||
cy.log('Return to previous step')
|
||||
cy.findByRole('button', { name: 'Back' })
|
||||
.click()
|
||||
|
||||
cy.findByRole('button', { name: `Front-end Framework ${framework.name}` })
|
||||
if (framework.supportedBundlers.length > 1) {
|
||||
cy.findByRole('button', { name: `Bundler ${bundler.name}` })
|
||||
}
|
||||
|
||||
cy.findByRole('button', { name: lang.name })
|
||||
cy.findByRole('button', { name: 'Next Step' }).click()
|
||||
|
||||
cy.log('Go to next step and verify Install Dev Dependencies page')
|
||||
cy.contains('h1', 'Install Dev Dependencies')
|
||||
|
||||
let installCommand = `yarn add -D ${framework.package} ${bundler.package}`
|
||||
|
||||
if (hasStorybookDep) {
|
||||
installCommand += ` ${framework.storybookDep}`
|
||||
}
|
||||
|
||||
cy.contains('code', installCommand)
|
||||
|
||||
const validatePackage = (packageName) => {
|
||||
cy.validateExternalLink({
|
||||
name: packageName,
|
||||
href: `https://www.npmjs.com/package/${packageName}`,
|
||||
})
|
||||
|
||||
cy.contains(PACKAGES_DESCRIPTIONS[framework.package].split('<span')[0])
|
||||
}
|
||||
|
||||
validatePackage(framework.package)
|
||||
validatePackage(bundler.package)
|
||||
if (hasStorybookDep) {
|
||||
validatePackage(framework.storybookDep)
|
||||
}
|
||||
|
||||
cy.findByRole('button', { name: 'I\'ve installed them' }).click()
|
||||
|
||||
// FIXME: remove if-check once this is fixed. https://cypress-io.atlassian.net/browse/UNIFY-980
|
||||
if (lang.type !== 'ts') {
|
||||
cy.get('[data-cy=changes]').within(() => {
|
||||
cy.contains('cypress.config.js')
|
||||
})
|
||||
}
|
||||
|
||||
cy.get('[data-cy=valid]').within(() => {
|
||||
cy.contains('cypress/component/index.html')
|
||||
cy.contains(`cypress/support/component.${lang.type}`)
|
||||
cy.contains('cypress/fixtures/example.json')
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
it('opens to the "choose framework" page when opened via cli with --component flag', () => {
|
||||
@@ -269,20 +458,88 @@ describe('Launchpad: Setup Project', () => {
|
||||
})
|
||||
|
||||
describe('project not been configured for cypress', () => {
|
||||
it('can setup component testing for a project not been configured for cypress', () => {
|
||||
it('can setup component testing', () => {
|
||||
cy.openProject('pristine')
|
||||
cy.visitLaunchpad()
|
||||
|
||||
verifyWelcomePage({ e2eIsConfigured: false, ctIsConfigured: false })
|
||||
|
||||
// @ts-ignore
|
||||
cy.get('body').tab().tab().tab()
|
||||
|
||||
cy.get('[data-cy-testingtype="component"]')
|
||||
.focus()
|
||||
.should('have.focus')
|
||||
.type('{enter}')
|
||||
|
||||
cy.findByText('Confirm the front-end framework and bundler used in your project.')
|
||||
|
||||
cy.findByRole('button', { name: 'Front-end Framework Pick a framework' }).click()
|
||||
cy.findByRole('option', { name: 'Create React App' }).click()
|
||||
|
||||
cy.get('[data-testid="select-bundler"').should('not.exist')
|
||||
cy.findByRole('button', { name: 'Next Step' }).should('not.have.disabled')
|
||||
|
||||
cy.findByRole('button', { name: 'Back' }).click()
|
||||
cy.get('[data-cy-testingtype="component"]').click()
|
||||
|
||||
cy.findByRole('button', { name: 'Front-end Framework Create React App' }).click()
|
||||
cy.findByRole('option', { name: 'React.js' }).click()
|
||||
|
||||
cy.findByRole('button', { name: 'Next Step' }).should('have.disabled')
|
||||
|
||||
cy.findByRole('button', { name: 'Bundler Pick a bundler' }).click()
|
||||
cy.findByRole('option', { name: 'Webpack' }).click()
|
||||
cy.findByRole('button', { name: 'Next Step' }).should('not.have.disabled')
|
||||
|
||||
cy.findByRole('button', { name: 'Front-end Framework React.js' }).click()
|
||||
cy.findByRole('option', { name: 'Create React App' }).click()
|
||||
cy.findByRole('button', { name: 'Bundler Webpack' }).should('not.exist')
|
||||
cy.findByRole('button', { name: 'Next Step' }).should('not.have.disabled')
|
||||
|
||||
cy.findByRole('button', { name: 'Next Step' }).click()
|
||||
cy.findByRole('button', { name: 'I\'ve installed them' }).click()
|
||||
|
||||
cy.get('[data-cy=valid]').within(() => {
|
||||
cy.contains('cypress.config.js')
|
||||
cy.contains('cypress/component/index.html')
|
||||
cy.contains(`cypress/support/component.js`)
|
||||
cy.contains('cypress/fixtures/example.json')
|
||||
})
|
||||
|
||||
// Fix me: https://cypress-io.atlassian.net/browse/UNIFY-981
|
||||
// cy.findByRole('button', { name: 'Continue' }).click()
|
||||
// cy.contains(/(Initializing Config|Choose a Browser)/)
|
||||
cy.findByRole('button', { name: 'Continue' }).click()
|
||||
cy.contains(/(Initializing Config|Choose a Browser)/)
|
||||
})
|
||||
|
||||
it('opens to the "choose framework" page when opened via cli with --component flag', () => {
|
||||
cy.openProject('pristine')
|
||||
cy.visitLaunchpad()
|
||||
|
||||
verifyWelcomePage({ e2eIsConfigured: false, ctIsConfigured: false })
|
||||
|
||||
cy.get('[data-cy-testingtype="component"]')
|
||||
.focus()
|
||||
.should('have.focus')
|
||||
.type('{enter}')
|
||||
|
||||
cy.findByText('Confirm the front-end framework and bundler used in your project.')
|
||||
|
||||
cy.findByRole('button', { name: 'Front-end Framework Pick a framework' }).click()
|
||||
cy.findByRole('option', { name: 'Create React App' }).click()
|
||||
cy.findByRole('button', { name: 'TypeScript' }).click()
|
||||
cy.findByRole('button', { name: 'Next Step' }).click()
|
||||
cy.findByRole('button', { name: 'I\'ve installed them' }).click()
|
||||
|
||||
cy.get('[data-cy=valid]').within(() => {
|
||||
cy.contains('cypress.config.ts')
|
||||
cy.contains('cypress/component/index.html')
|
||||
cy.contains(`cypress/support/component.ts`)
|
||||
cy.contains('cypress/fixtures/example.json')
|
||||
})
|
||||
|
||||
// Fix me: https://cypress-io.atlassian.net/browse/UNIFY-981
|
||||
// cy.findByRole('button', { name: 'Continue' }).click()
|
||||
// cy.contains(/(Initializing Config|Choose a Browser)/)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -3,3 +3,4 @@ require('../../../../frontend-shared/cypress/e2e/support/e2eSupport')
|
||||
|
||||
require('./dropFileWithPath')
|
||||
require('cypress-plugin-tab')
|
||||
require('cypress-real-events/support')
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
"concurrently": "^6.2.0",
|
||||
"cross-env": "6.0.3",
|
||||
"cypress-plugin-tab": "1.0.5",
|
||||
"cypress-real-events": "1.6.0",
|
||||
"graphql": "^15.5.1",
|
||||
"graphql-tag": "^2.12.5",
|
||||
"gravatar": "1.8.0",
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
|
||||
<svg data-cy="nextjs-logo" version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
|
||||
<path class="icon-dark" d="M386.3985596,35.5079727C217.0600281-64.0607605,1.8845311,57.5499001,0.012267,253.8817902c-1.8282685,191.716507,201.0625916,315.5454712,370.0206604,231.1632233L185.5603943,213.6362915l0.0000305,167.9969177c0,18.6138916-35.6191101,18.6138916-35.6191101,0V156.4207916c0-14.7758484,27.4472504-15.9884033,35.2252045-3.1443481l210.2631683,317.2959595C553.3806763,368.835144,551.2467041,132.4364166,386.3985596,35.5079727z M362.6429443,353.4465332l-35.7316284-54.5765381V149.4583282c0-13.9324646,35.7316284-13.9324646,35.7316284,0V353.4465332z" fill="black"/>
|
||||
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 667 B After Width: | Height: | Size: 688 B |
@@ -1,4 +1,4 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 400">
|
||||
<svg data-cy="nuxtjs-logo" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 400">
|
||||
<g fill-rule="nonzero" transform="translate(0 50)" fill="none">
|
||||
<path d="M227.92099 83.45116l-13.6889 24.10141-46.8148-82.44693L23.7037 278.17052h97.3037c0 13.31084 10.61252 24.10142 23.70371 24.10142H23.70371c-8.46771 0-16.29145-4.59601-20.5246-12.05272-4.23315-7.4567-4.23272-16.64312.00114-24.0994L146.89383 13.05492c4.23415-7.45738 12.0596-12.05138 20.5284-12.05138 8.46878 0 16.29423 4.594 20.52839 12.05138l39.97037 70.39623z" fill="#00C58E"/>
|
||||
<path d="M331.6642 266.11981l-90.05432-158.56724-13.6889-24.10141-13.68888 24.10141-90.04445 158.56724c-4.23385 7.45629-4.23428 16.64271-.00113 24.09941 4.23314 7.4567 12.05689 12.05272 20.5246 12.05272h166.4c8.46946 0 16.29644-4.591 20.532-12.04837 4.23555-7.45736 4.23606-16.64592.00132-24.10376h.01976zM144.7111 278.17052L227.921 131.65399l83.19012 146.51653h-166.4z" fill="#2F495E"/>
|
||||
|
||||
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg viewBox="0 0 500 500" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1">
|
||||
<svg data-cy="react-logo" viewBox="0 0 500 500" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1">
|
||||
<g id="group">
|
||||
<path d="M495.3 248.5 C495.3 216 454.6 185.2 392.2 166.1 406.6 102.5 400.2 51.9 372 35.7 365.5 31.9 357.9 30.1 349.6 30.1 L349.6 52.4 C354.2 52.4 357.9 53.3 361 55 374.6 62.8 380.5 92.5 375.9 130.7 374.8 140.1 373 150 370.8 160.1 351.2 155.3 329.8 151.6 307.3 149.2 293.8 130.7 279.8 113.9 265.7 99.2 298.3 68.9 328.9 52.3 349.7 52.3 L349.7 30 C322.2 30 286.2 49.6 249.8 83.6 213.4 49.8 177.4 30.4 149.9 30.4 L149.9 52.7 C170.6 52.7 201.3 69.2 233.9 99.3 219.9 114 205.9 130.7 192.6 149.2 170 151.6 148.6 155.3 129 160.2 126.7 150.2 125 140.5 123.8 131.2 119.1 93 124.9 63.3 138.4 55.4 141.4 53.6 145.3 52.8 149.9 52.8 L149.9 30.5 C141.5 30.5 133.9 32.3 127.3 36.1 99.2 52.3 92.9 102.8 107.4 166.2 45.2 185.4 4.7 216.1 4.7 248.5 4.7 281 45.4 311.8 107.8 330.9 93.4 394.5 99.8 445.1 128 461.3 134.5 465.1 142.1 466.9 150.5 466.9 178 466.9 214 447.3 250.4 413.3 286.8 447.1 322.8 466.5 350.3 466.5 358.7 466.5 366.3 464.7 372.9 460.9 401 444.7 407.3 394.2 392.8 330.8 454.8 311.7 495.3 280.9 495.3 248.5 Z M365.1 181.8 C361.4 194.7 356.8 208 351.6 221.3 347.5 213.3 343.2 205.3 338.5 197.3 333.9 189.3 329 181.5 324.1 173.9 338.3 176 352 178.6 365.1 181.8 Z M319.3 288.3 C311.5 301.8 303.5 314.6 295.2 326.5 280.3 327.8 265.2 328.5 250 328.5 234.9 328.5 219.8 327.8 205 326.6 196.7 314.7 188.6 302 180.8 288.6 173.2 275.5 166.3 262.2 160 248.8 166.2 235.4 173.2 222 180.7 208.9 188.5 195.4 196.5 182.6 204.8 170.7 219.7 169.4 234.8 168.7 250 168.7 265.1 168.7 280.2 169.4 295 170.6 303.3 182.5 311.4 195.2 319.2 208.6 326.8 221.7 333.7 235 340 248.4 333.7 261.8 326.8 275.2 319.3 288.3 Z M351.6 275.3 C357 288.7 361.6 302.1 365.4 315.1 352.3 318.3 338.5 321 324.2 323.1 329.1 315.4 334 307.5 338.6 299.4 343.2 291.4 347.5 283.3 351.6 275.3 Z M250.2 382 C240.9 372.4 231.6 361.7 222.4 350 231.4 350.4 240.6 350.7 249.9 350.7 259.3 350.7 268.6 350.5 277.7 350 268.7 361.7 259.4 372.4 250.2 382 Z M175.8 323.1 C161.6 321 147.9 318.4 134.8 315.2 138.5 302.3 143.1 289 148.3 275.7 152.4 283.7 156.7 291.7 161.4 299.7 166.1 307.7 170.9 315.5 175.8 323.1 Z M249.7 115 C259 124.6 268.3 135.3 277.5 147 268.5 146.6 259.3 146.3 250 146.3 240.6 146.3 231.3 146.5 222.2 147 231.2 135.3 240.5 124.6 249.7 115 Z M175.7 173.9 C170.8 181.6 165.9 189.5 161.3 197.6 156.7 205.6 152.4 213.6 148.3 221.6 142.9 208.2 138.3 194.8 134.5 181.8 147.6 178.7 161.4 176 175.7 173.9 Z M85.2 299.1 C49.8 284 26.9 264.2 26.9 248.5 26.9 232.8 49.8 212.9 85.2 197.9 93.8 194.2 103.2 190.9 112.9 187.8 118.6 207.4 126.1 227.8 135.4 248.7 126.2 269.5 118.8 289.8 113.2 309.3 103.3 306.2 93.9 302.8 85.2 299.1 Z M139 442 C125.4 434.2 119.5 404.5 124.1 366.3 125.2 356.9 127 347 129.2 336.9 148.8 341.7 170.2 345.4 192.7 347.8 206.2 366.3 220.2 383.1 234.3 397.8 201.7 428.1 171.1 444.7 150.3 444.7 145.8 444.6 142 443.7 139 442 Z M376.2 365.8 C380.9 404 375.1 433.7 361.6 441.6 358.6 443.4 354.7 444.2 350.1 444.2 329.4 444.2 298.7 427.7 266.1 397.6 280.1 382.9 294.1 366.2 307.4 347.7 330 345.3 351.4 341.6 371 336.7 373.3 346.8 375.1 356.5 376.2 365.8 Z M414.7 299.1 C406.1 302.8 396.7 306.1 387 309.2 381.3 289.6 373.8 269.2 364.5 248.3 373.7 227.5 381.1 207.2 386.7 187.7 396.6 190.8 406 194.2 414.8 197.9 450.2 213 473.1 232.8 473.1 248.5 473 264.2 450.1 284.1 414.7 299.1 Z" fill="#3077c6" fill-opacity="1" stroke="none"/>
|
||||
<path d="M295.6 248.5 C295.6 273.739 275.139 294.2 249.9 294.2 224.661 294.2 204.2 273.739 204.2 248.5 204.2 223.261 224.661 202.8 249.9 202.8 275.139 202.8 295.6 223.261 295.6 248.5 Z" fill="#3077c6" fill-opacity="1" stroke="none"/>
|
||||
|
||||
|
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 3.7 KiB |
@@ -1,4 +1,4 @@
|
||||
<svg viewBox="0 0 410 404" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<svg data-cy="vite-logo" viewBox="0 0 410 404" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M399.641 59.5246L215.643 388.545C211.844 395.338 202.084 395.378 198.228 388.618L10.5817 59.5563C6.38087 52.1896 12.6802 43.2665 21.0281 44.7586L205.223 77.6824C206.398 77.8924 207.601 77.8904 208.776 77.6763L389.119 44.8058C397.439 43.2894 403.768 52.1434 399.641 59.5246Z" fill="url(#paint0_linear)"/>
|
||||
<path d="M292.965 1.5744L156.801 28.2552C154.563 28.6937 152.906 30.5903 152.771 32.8664L144.395 174.33C144.198 177.662 147.258 180.248 150.51 179.498L188.42 170.749C191.967 169.931 195.172 173.055 194.443 176.622L183.18 231.775C182.422 235.487 185.907 238.661 189.532 237.56L212.947 230.446C216.577 229.344 220.065 232.527 219.297 236.242L201.398 322.875C200.278 328.294 207.486 331.249 210.492 326.603L212.5 323.5L323.454 102.072C325.312 98.3645 322.108 94.137 318.036 94.9228L279.014 102.454C275.347 103.161 272.227 99.746 273.262 96.1583L298.731 7.86689C299.767 4.27314 296.636 0.855181 292.965 1.5744Z" fill="url(#paint1_linear)"/>
|
||||
<defs>
|
||||
|
||||
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
@@ -1,2 +1,2 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg version="1.1" viewBox="0 0 261.76 226.69" xmlns="http://www.w3.org/2000/svg"><g transform="matrix(1.3333 0 0 -1.3333 -76.311 313.34)"><g transform="translate(178.06 235.01)"><path d="m0 0-22.669-39.264-22.669 39.264h-75.491l98.16-170.02 98.16 170.02z" fill="#41b883"/></g><g transform="translate(178.06 235.01)"><path d="m0 0-22.669-39.264-22.669 39.264h-36.227l58.896-102.01 58.896 102.01z" fill="#34495e"/></g></g></svg>
|
||||
<svg data-cy="vue-logo" version="1.1" viewBox="0 0 261.76 226.69" xmlns="http://www.w3.org/2000/svg"><g transform="matrix(1.3333 0 0 -1.3333 -76.311 313.34)"><g transform="translate(178.06 235.01)"><path d="m0 0-22.669-39.264-22.669 39.264h-75.491l98.16-170.02 98.16 170.02z" fill="#41b883"/></g><g transform="translate(178.06 235.01)"><path d="m0 0-22.669-39.264-22.669 39.264h-36.227l58.896-102.01 58.896 102.01z" fill="#34495e"/></g></g></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 467 B After Width: | Height: | Size: 486 B |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 774 875.7"><title>icon</title><path fill="#FFF" d="M387 0l387 218.9v437.9L387 875.7 0 656.8V218.9z"/><path fill="#8ed6fb" d="M704.9 641.7L399.8 814.3V679.9l190.1-104.6 115 66.4zm20.9-18.9V261.9l-111.6 64.5v232l111.6 64.4zM67.9 641.7L373 814.3V679.9L182.8 575.3 67.9 641.7zM47 622.8V261.9l111.6 64.5v232L47 622.8zm13.1-384.3L373 61.5v129.9L172.5 301.7l-1.6.9-110.8-64.1zm652.6 0l-312.9-177v129.9l200.5 110.2 1.6.9 110.8-64z"/><path fill="#1c78c0" d="M373 649.3L185.4 546.1V341.8L373 450.1v199.2zm26.8 0l187.6-103.1V341.8L399.8 450.1v199.2zm-13.4-207zM198.1 318.2l188.3-103.5 188.3 103.5-188.3 108.7-188.3-108.7z"/></svg>
|
||||
<svg data-cy="webpack-logo" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 774 875.7"><title>icon</title><path fill="#FFF" d="M387 0l387 218.9v437.9L387 875.7 0 656.8V218.9z"/><path fill="#8ed6fb" d="M704.9 641.7L399.8 814.3V679.9l190.1-104.6 115 66.4zm20.9-18.9V261.9l-111.6 64.5v232l111.6 64.4zM67.9 641.7L373 814.3V679.9L182.8 575.3 67.9 641.7zM47 622.8V261.9l111.6 64.5v232L47 622.8zm13.1-384.3L373 61.5v129.9L172.5 301.7l-1.6.9-110.8-64.1zm652.6 0l-312.9-177v129.9l200.5 110.2 1.6.9 110.8-64z"/><path fill="#1c78c0" d="M373 649.3L185.4 546.1V341.8L373 450.1v199.2zm26.8 0l187.6-103.1V341.8L399.8 450.1v199.2zm-13.4-207zM198.1 318.2l188.3-103.5 188.3 103.5-188.3 108.7-188.3-108.7z"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 673 B After Width: | Height: | Size: 696 B |
@@ -1,27 +1,51 @@
|
||||
import { EnvironmentSetupFragmentDoc } from '../generated/graphql-test'
|
||||
import EnvironmentSetup from './EnvironmentSetup.vue'
|
||||
import type { WizardSetupData } from './Wizard.vue'
|
||||
import { FRONTEND_FRAMEWORKS, CODE_LANGUAGES } from '../../../types/src/constants'
|
||||
|
||||
describe('<EnvironmentSetup />', () => {
|
||||
it('playground', { viewportWidth: 800 }, () => {
|
||||
const wizardSetupData: WizardSetupData = {
|
||||
bundler: 'webpack',
|
||||
framework: 'react',
|
||||
codeLanguage: 'ts',
|
||||
}
|
||||
|
||||
it('default component', { viewportWidth: 800 }, () => {
|
||||
cy.mountFragment(EnvironmentSetupFragmentDoc, {
|
||||
render: (gqlVal) => (
|
||||
<div class="m-10">
|
||||
<EnvironmentSetup
|
||||
gql={gqlVal}
|
||||
data={wizardSetupData}
|
||||
nextFn={cy.stub()}
|
||||
/>
|
||||
</div>
|
||||
),
|
||||
})
|
||||
|
||||
cy.get('[data-testid="select-framework"]').click()
|
||||
cy.contains('Nuxt.js').click()
|
||||
cy.findByRole('button', {
|
||||
name: 'Front-end Framework Pick a framework',
|
||||
expanded: false,
|
||||
})
|
||||
.should('have.attr', 'aria-haspopup', 'true')
|
||||
.click()
|
||||
.should('have.attr', 'aria-expanded', 'true')
|
||||
|
||||
const frameworkIconName = (frameworkName) => {
|
||||
if (frameworkName.includes('React')) {
|
||||
return 'react-logo'
|
||||
}
|
||||
|
||||
if (frameworkName.includes('Vue')) {
|
||||
return 'vue-logo'
|
||||
}
|
||||
|
||||
return `${Cypress._.lowerCase(frameworkName).replace(' ', '')}-logo`
|
||||
}
|
||||
|
||||
FRONTEND_FRAMEWORKS.forEach((framework) => {
|
||||
cy.findByRole('option', { name: framework.name })
|
||||
.find('svg')
|
||||
.should('have.attr', 'data-cy', frameworkIconName(framework.name))
|
||||
})
|
||||
|
||||
CODE_LANGUAGES.forEach((lang) => {
|
||||
cy.findByRole('button', { name: lang.name })
|
||||
})
|
||||
|
||||
cy.findByRole('button', { name: 'Next Step' })
|
||||
.should('have.disabled')
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<WizardLayout
|
||||
:back-fn="onBack"
|
||||
:next-fn="onNext"
|
||||
:next-fn="props.nextFn"
|
||||
:can-navigate-forward="canNavigateForward"
|
||||
class="max-w-640px"
|
||||
>
|
||||
@@ -13,10 +13,10 @@
|
||||
:label="t('setupPage.projectSetup.frameworkLabel')"
|
||||
selector-type="framework"
|
||||
data-testid="select-framework"
|
||||
@select-framework="val => emit('wizardSetup', 'framework', val)"
|
||||
@select-framework="val => onWizardSetup('framework', val)"
|
||||
/>
|
||||
<SelectFwOrBundler
|
||||
v-if="props.gql.framework?.type && (!props.gql.bundler || bundlers.length > 1)"
|
||||
v-if="props.gql.framework?.type && bundlers.length > 1"
|
||||
class="pt-3px"
|
||||
:options="bundlers || []"
|
||||
:value="props.gql.bundler?.type ?? undefined"
|
||||
@@ -24,13 +24,13 @@
|
||||
:label="t('setupPage.projectSetup.bundlerLabel')"
|
||||
selector-type="bundler"
|
||||
data-testid="select-bundler"
|
||||
@select-bundler="val => emit('wizardSetup', 'bundler', val)"
|
||||
@select-bundler="val => onWizardSetup('bundler', val)"
|
||||
/>
|
||||
<SelectLanguage
|
||||
:name="t('setupPage.projectSetup.languageLabel')"
|
||||
:options="languages || []"
|
||||
:value="props.gql.language?.id ?? 'js'"
|
||||
@select="val => emit('wizardSetup', 'codeLanguage', val)"
|
||||
:value="props.gql.language?.type ?? 'js'"
|
||||
@select="val => onWizardSetup('codeLanguage', val)"
|
||||
/>
|
||||
</div>
|
||||
</WizardLayout>
|
||||
@@ -42,17 +42,16 @@ import WizardLayout from './WizardLayout.vue'
|
||||
import SelectFwOrBundler from './SelectFwOrBundler.vue'
|
||||
import SelectLanguage from './SelectLanguage.vue'
|
||||
import { gql } from '@urql/core'
|
||||
import { EnvironmentSetupFragment, EnvironmentSetup_ClearTestingTypeDocument } from '../generated/graphql'
|
||||
import {
|
||||
WizardUpdateInput,
|
||||
EnvironmentSetupFragment,
|
||||
EnvironmentSetup_ClearTestingTypeDocument,
|
||||
EnvironmentSetup_WizardUpdateDocument,
|
||||
} from '../generated/graphql'
|
||||
import { useI18n } from '@cy/i18n'
|
||||
import { sortBy } from 'lodash'
|
||||
import type { CurrentStep, WizardSetupData } from './Wizard.vue'
|
||||
import { useMutation } from '@urql/vue'
|
||||
|
||||
const emit = defineEmits<{
|
||||
(event: 'navigate', toPage: CurrentStep): void
|
||||
<K extends keyof WizardSetupData>(event: 'wizardSetup', key: K, val: WizardSetupData[K]): void
|
||||
}>()
|
||||
|
||||
gql`
|
||||
fragment EnvironmentSetup on Wizard {
|
||||
bundler {
|
||||
@@ -101,13 +100,13 @@ fragment EnvironmentSetup on Wizard {
|
||||
|
||||
const props = defineProps<{
|
||||
gql: EnvironmentSetupFragment
|
||||
data: WizardSetupData
|
||||
nextFn: () => void,
|
||||
}>()
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
const bundlers = computed(() => {
|
||||
const _bundlers = props.gql.framework?.supportedBundlers ?? props.gql.allBundlers
|
||||
const _bundlers = props.gql.framework?.supportedBundlers || []
|
||||
|
||||
return _bundlers.map((b) => {
|
||||
return {
|
||||
@@ -120,8 +119,32 @@ const frameworks = computed(() => {
|
||||
return sortBy((props.gql.frameworks ?? []).map((f) => ({ ...f })), 'category')
|
||||
})
|
||||
|
||||
const onNext = () => {
|
||||
emit('navigate', 'installDependencies')
|
||||
gql`
|
||||
mutation EnvironmentSetup_wizardUpdate($input: WizardUpdateInput!) {
|
||||
wizardUpdate(input: $input) {
|
||||
...EnvironmentSetup
|
||||
bundler {
|
||||
id
|
||||
type
|
||||
}
|
||||
framework {
|
||||
id
|
||||
type
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
const wizardUpdateMutation = useMutation(EnvironmentSetup_WizardUpdateDocument)
|
||||
|
||||
const onWizardSetup = <K extends keyof WizardUpdateInput>(key: K, val: WizardUpdateInput[K]) => {
|
||||
const input = {} as unknown as WizardUpdateInput
|
||||
|
||||
input[key] = val
|
||||
|
||||
wizardUpdateMutation.executeMutation({
|
||||
input,
|
||||
})
|
||||
}
|
||||
|
||||
gql`
|
||||
@@ -136,13 +159,18 @@ mutation EnvironmentSetup_ClearTestingType {
|
||||
}
|
||||
`
|
||||
|
||||
const mutation = useMutation(EnvironmentSetup_ClearTestingTypeDocument)
|
||||
const clearTestingTypeMutation = useMutation(EnvironmentSetup_ClearTestingTypeDocument)
|
||||
|
||||
const onBack = () => {
|
||||
mutation.executeMutation({})
|
||||
clearTestingTypeMutation.executeMutation({})
|
||||
}
|
||||
|
||||
const languages = computed(() => props.gql.allLanguages ?? [])
|
||||
|
||||
const canNavigateForward = computed(() => Object.values(props.data).filter((f) => f).length === 3)
|
||||
const canNavigateForward = computed(() => {
|
||||
const { bundler, framework, language } = props.gql
|
||||
|
||||
return bundler !== null && framework !== null && language !== null
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
import { defaultMessages } from '@cy/i18n'
|
||||
import InstallDependencies from './InstallDependencies.vue'
|
||||
import { InstallDependenciesFragmentDoc } from '../generated/graphql-test'
|
||||
import { defaultMessages } from '@cy/i18n'
|
||||
import { PACKAGES_DESCRIPTIONS } from '../../../types/src/constants'
|
||||
|
||||
describe('<InstallDependencies />', () => {
|
||||
beforeEach(() => {
|
||||
beforeEach(function () {
|
||||
this.onBack = cy.stub()
|
||||
|
||||
cy.mountFragment(InstallDependenciesFragmentDoc, {
|
||||
render: (gqlVal) => {
|
||||
return <InstallDependencies gql={gqlVal} />
|
||||
return <InstallDependencies gql={gqlVal} backFn={this.onBack}/>
|
||||
},
|
||||
})
|
||||
})
|
||||
@@ -20,8 +23,8 @@ describe('<InstallDependencies />', () => {
|
||||
.should('be.visible')
|
||||
.and('have.attr', 'href', 'https://www.npmjs.com/package/@cypress/webpack-dev-server')
|
||||
|
||||
cy.contains('Used to interact with React components via Cypress').should('be.visible')
|
||||
cy.contains('Used to bundle code').should('be.visible')
|
||||
cy.contains(PACKAGES_DESCRIPTIONS['@cypress/react'].split('<span')[0])
|
||||
cy.contains(PACKAGES_DESCRIPTIONS['@cypress/webpack-dev-server'].split('<span')[0])
|
||||
|
||||
cy.percySnapshot()
|
||||
})
|
||||
@@ -31,4 +34,15 @@ describe('<InstallDependencies />', () => {
|
||||
cy.contains('button', defaultMessages.setupPage.install.confirmManualInstall).should('be.visible')
|
||||
cy.contains('button', defaultMessages.setupPage.step.back).should('be.visible')
|
||||
})
|
||||
|
||||
it('triggers back button callback', function () {
|
||||
cy.findByRole('button', {
|
||||
name: defaultMessages.setupPage.step.back,
|
||||
})
|
||||
.should('be.visible')
|
||||
.click()
|
||||
.then(() => {
|
||||
expect(this.onBack).to.have.been.calledOnce
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<WizardLayout
|
||||
:next=" t('setupPage.install.confirmManualInstall')"
|
||||
:can-navigate-forward="true"
|
||||
:back-fn="() => emits('navigate', 'selectFramework')"
|
||||
:back-fn="props.backFn"
|
||||
:next-fn="confirmInstalled"
|
||||
class="max-w-640px"
|
||||
>
|
||||
@@ -17,7 +17,6 @@ import WizardLayout from './WizardLayout.vue'
|
||||
import ManualInstall from './ManualInstall.vue'
|
||||
import { gql } from '@urql/core'
|
||||
import { InstallDependenciesFragment, InstallDependencies_ScaffoldFilesDocument } from '../generated/graphql'
|
||||
import type { CurrentStep } from './Wizard.vue'
|
||||
import { useI18n } from '@cy/i18n'
|
||||
import { useMutation } from '@urql/vue'
|
||||
|
||||
@@ -29,10 +28,6 @@ mutation InstallDependencies_scaffoldFiles {
|
||||
}
|
||||
`
|
||||
|
||||
const emits = defineEmits<{
|
||||
(event: 'navigate', currentStep: CurrentStep): void
|
||||
}>()
|
||||
|
||||
gql`
|
||||
fragment InstallDependencies on Query {
|
||||
...ManualInstall
|
||||
@@ -41,6 +36,7 @@ fragment InstallDependencies on Query {
|
||||
|
||||
const props = defineProps<{
|
||||
gql: InstallDependenciesFragment
|
||||
backFn: () => void,
|
||||
}>()
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
import { ManualInstallFragmentDoc } from '../generated/graphql-test'
|
||||
import ManualInstall from './ManualInstall.vue'
|
||||
import { PACKAGES_DESCRIPTIONS } from '../../../types/src/constants'
|
||||
|
||||
describe('<ManualInstall />', () => {
|
||||
it('playground', { viewportWidth: 800, viewportHeight: 600 }, () => {
|
||||
it('lists packages and can copy install command to clipboard', { viewportWidth: 800, viewportHeight: 600 }, () => {
|
||||
const framework = '@cypress/react'
|
||||
const bundler = '@cypress/webpack-dev-server'
|
||||
|
||||
cy.mountFragment(ManualInstallFragmentDoc, {
|
||||
render: (gqlVal) => (
|
||||
<div class="rounded border-1 border-gray-400 m-10">
|
||||
@@ -10,5 +14,40 @@ describe('<ManualInstall />', () => {
|
||||
</div>
|
||||
),
|
||||
})
|
||||
|
||||
const installCommand = `yarn add -D ${framework} ${bundler}`
|
||||
|
||||
// @ts-ignore
|
||||
cy.findByRole('button', { name: 'Copy' }).realClick()
|
||||
|
||||
cy.findByRole('button', { name: 'Copied!' })
|
||||
|
||||
if (Cypress.config('browser').name === 'chrome') {
|
||||
cy.wrap(Cypress.automation('remote:debugger:protocol', {
|
||||
command: 'Browser.grantPermissions',
|
||||
params: {
|
||||
permissions: ['clipboardReadWrite', 'clipboardSanitizedWrite'],
|
||||
origin: window.location.origin,
|
||||
},
|
||||
}))
|
||||
}
|
||||
|
||||
cy.window().its('navigator.permissions')
|
||||
.invoke('query', { name: 'clipboard-read' })
|
||||
.its('state').then(cy.log)
|
||||
|
||||
cy.window().its('navigator.clipboard')
|
||||
.invoke('readText')
|
||||
.should('equal', installCommand)
|
||||
|
||||
const validatePackage = (packageName) => {
|
||||
cy.findByRole('link', { name: packageName })
|
||||
.should('have.attr', 'href', `https://www.npmjs.com/package/${packageName}`)
|
||||
|
||||
cy.contains(PACKAGES_DESCRIPTIONS[framework].split('<span')[0])
|
||||
}
|
||||
|
||||
validatePackage(framework)
|
||||
validatePackage(bundler)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -32,12 +32,10 @@ import { useI18n } from '@cy/i18n'
|
||||
import Button from '@cy/components/Button.vue'
|
||||
import FileRow from '../components/code/FileRow.vue'
|
||||
import LaunchpadHeader from './LaunchpadHeader.vue'
|
||||
import type { CurrentStep } from './Wizard.vue'
|
||||
import { ScaffoldedFilesFragment, ScaffoldedFiles_CompleteSetupDocument } from '../generated/graphql'
|
||||
import { useMutation } from '@urql/vue'
|
||||
|
||||
const emit = defineEmits<{
|
||||
(event: 'navigate', currentStep: CurrentStep): void
|
||||
(event: 'completeSetup')
|
||||
}>()
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
v-for="opt in options"
|
||||
:key="opt.type"
|
||||
class="border-transparent border-1 py-4px px-12px hocus-default hocus:z-10 hover:bg-indigo-50 focus:outline-none first:rounded-l last:rounded-r"
|
||||
:class="opt.id === value ? 'bg-secondary-50 text-secondary-600': 'text-gray-700'"
|
||||
:class="opt.type === value ? 'bg-secondary-50 text-secondary-600': 'text-gray-700'"
|
||||
@click="() => selectOption(opt.type)"
|
||||
>
|
||||
{{ opt.name }}
|
||||
|
||||
@@ -8,14 +8,12 @@
|
||||
<EnvironmentSetup
|
||||
v-if="currentStep === 'selectFramework'"
|
||||
:gql="props.gql.wizard"
|
||||
:data="wizardSetupData"
|
||||
@navigate="setCurrentStep"
|
||||
@wizard-setup="onWizardSetup"
|
||||
:next-fn="() => setCurrentStep('installDependencies')"
|
||||
/>
|
||||
<InstallDependencies
|
||||
v-if="currentStep === 'installDependencies'"
|
||||
:gql="props.gql"
|
||||
@navigate="setCurrentStep"
|
||||
:back-fn="() => setCurrentStep('selectFramework')"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
@@ -24,21 +22,11 @@
|
||||
import EnvironmentSetup from './EnvironmentSetup.vue'
|
||||
import InstallDependencies from './InstallDependencies.vue'
|
||||
import { gql } from '@urql/core'
|
||||
import { CodeLanguageEnum, WizardFragment, Wizard_WizardUpdateDocument } from '../generated/graphql'
|
||||
import type { WizardFragment } from '../generated/graphql'
|
||||
import WarningList from '../warning/WarningList.vue'
|
||||
import { computed, ref } from 'vue'
|
||||
import type { FrontendFramework, Bundler } from '@packages/types/src/constants'
|
||||
import LaunchpadHeader from './LaunchpadHeader.vue'
|
||||
import { useI18n } from '@cy/i18n'
|
||||
import { useMutation } from '@urql/vue'
|
||||
|
||||
export interface WizardSetupData {
|
||||
bundler: Bundler['type'] | null
|
||||
framework: FrontendFramework['type'] | null
|
||||
codeLanguage: CodeLanguageEnum
|
||||
}
|
||||
|
||||
export type CurrentStep = 'selectFramework' | 'installDependencies'
|
||||
|
||||
const props = defineProps<{
|
||||
gql: WizardFragment
|
||||
@@ -46,37 +34,9 @@ const props = defineProps<{
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
gql`
|
||||
mutation Wizard_wizardUpdate($input: WizardUpdateInput!) {
|
||||
wizardUpdate(input: $input) {
|
||||
...EnvironmentSetup
|
||||
bundler {
|
||||
id
|
||||
type
|
||||
}
|
||||
framework {
|
||||
id
|
||||
type
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
export type CurrentStep = 'selectFramework' | 'installDependencies'
|
||||
|
||||
const currentStep = ref<CurrentStep>('selectFramework')
|
||||
const wizardSetupData = ref<WizardSetupData>({
|
||||
bundler: props.gql.wizard.bundler?.type ?? null,
|
||||
framework: props.gql.wizard.framework?.type ?? null,
|
||||
codeLanguage: 'js',
|
||||
})
|
||||
|
||||
const wizardUpdateMutation = useMutation(Wizard_WizardUpdateDocument)
|
||||
|
||||
const onWizardSetup = <K extends keyof WizardSetupData>(key: K, val: WizardSetupData[K]) => {
|
||||
wizardSetupData.value[key] = val
|
||||
wizardUpdateMutation.executeMutation({
|
||||
input: wizardSetupData.value,
|
||||
})
|
||||
}
|
||||
|
||||
const setCurrentStep = (step: CurrentStep) => {
|
||||
currentStep.value = step
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
"../frontend-shared/cypress/**/*.ts"
|
||||
],
|
||||
"compilerOptions": {
|
||||
"types": ["cypress", "cypress-real-events", "@intlify/vite-plugin-vue-i18n/client"],
|
||||
"paths": {
|
||||
"@cy/i18n": ["../frontend-shared/src/locales/i18n"],
|
||||
"@cy/components/*": ["../frontend-shared/src/components/*"],
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
"classnames": "2.3.1",
|
||||
"css-element-queries": "1.2.3",
|
||||
"cypress-multi-reporters": "1.4.0",
|
||||
"cypress-real-events": "1.4.0",
|
||||
"cypress-real-events": "1.6.0",
|
||||
"lodash": "^4.17.21",
|
||||
"markdown-it": "11.0.0",
|
||||
"mobx": "5.15.4",
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
"chai": "^4.2.0",
|
||||
"classnames": "2.3.1",
|
||||
"clean-webpack-plugin": "^3.0.0",
|
||||
"cypress-real-events": "1.4.0",
|
||||
"cypress-real-events": "1.6.0",
|
||||
"eslint-plugin-mocha": "^8.0.0",
|
||||
"eslint-plugin-react": "^7.22.0",
|
||||
"eslint-plugin-react-hooks": "^4.2.0",
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
module.exports = {
|
||||
'stories': [
|
||||
'../src/**/*.stories.@(js|jsx|ts|tsx)',
|
||||
],
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
module.exports = {
|
||||
e2e: {},
|
||||
}
|
||||
@@ -17237,6 +17237,11 @@ cypress-real-events@1.4.0:
|
||||
resolved "https://registry.yarnpkg.com/cypress-real-events/-/cypress-real-events-1.4.0.tgz#39575031a4020581e0bbf105d7a306ee57d94f48"
|
||||
integrity sha512-1s4BQN1D++vFSuaad0qKsWcoApM5tQqPBFyDJEa6JeCZIsAdgMdGLuKi5QNIdl5KTJix0jxglzFJAThyz3borQ==
|
||||
|
||||
cypress-real-events@1.6.0:
|
||||
version "1.6.0"
|
||||
resolved "https://registry.yarnpkg.com/cypress-real-events/-/cypress-real-events-1.6.0.tgz#277024b62a324b6937760a700e831e795c021040"
|
||||
integrity sha512-QxXm0JsQkCrb2uH+fMXNDQ5kNWTzX3OtndBafdsZmNV19j+6JuTK9n52B1YVxrDrr/qzPAojcHJc5PNoQvwp+w==
|
||||
|
||||
d3-array@^1.2.0:
|
||||
version "1.2.4"
|
||||
resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-1.2.4.tgz#635ce4d5eea759f6f605863dbcfc30edc737f71f"
|
||||
|
||||