From bdc7c01d62fa2f3ed578be149a12cb1c8cdbc066 Mon Sep 17 00:00:00 2001
From: Cesar
Date: Thu, 20 Jan 2022 14:43:09 -0700
Subject: [PATCH] feat: convert cypress.json to cypress.config.js (#19748)
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: ElevateBart
---
.../__snapshots__/config-generator.spec.ts.js | 72 ++++++++
packages/data-context/src/DataActions.ts | 6 +
packages/data-context/src/DataContext.ts | 6 +
.../src/actions/MigrationActions.ts | 19 +++
packages/data-context/src/actions/index.ts | 1 +
.../src/sources/FileDataSource.ts | 10 ++
.../src/sources/MigrationDataSource.ts | 64 ++++++++
packages/data-context/src/sources/index.ts | 1 +
packages/data-context/src/util/index.ts | 1 +
packages/data-context/src/util/migration.ts | 80 +++++++++
.../test/unit/config-generator.spec.ts | 75 +++++++++
.../cypress/e2e/support/e2eProjectDirs.ts | 1 +
.../support/mock-graphql/stubgql-Migration.ts | 2 +
packages/graphql/schemas/schema.graphql | 9 +
.../schemaTypes/objectTypes/gql-Migration.ts | 24 ++-
.../schemaTypes/objectTypes/gql-Mutation.ts | 14 ++
.../launchpad/cypress/e2e/migration.cy.ts | 41 +++++
packages/launchpad/src/Main.vue | 6 +-
.../src/migration/MigrationWizard.cy.tsx | 51 ++++--
.../src/migration/MigrationWizard.vue | 155 ++++++++++--------
system-tests/projects/migration/cypress.json | 18 ++
.../migration/cypress/plugins/index.js | 5 +
22 files changed, 570 insertions(+), 91 deletions(-)
create mode 100644 packages/data-context/__snapshots__/config-generator.spec.ts.js
create mode 100644 packages/data-context/src/actions/MigrationActions.ts
create mode 100644 packages/data-context/src/sources/MigrationDataSource.ts
create mode 100644 packages/data-context/src/util/migration.ts
create mode 100644 packages/data-context/test/unit/config-generator.spec.ts
create mode 100644 packages/launchpad/cypress/e2e/migration.cy.ts
create mode 100644 system-tests/projects/migration/cypress.json
create mode 100644 system-tests/projects/migration/cypress/plugins/index.js
diff --git a/packages/data-context/__snapshots__/config-generator.spec.ts.js b/packages/data-context/__snapshots__/config-generator.spec.ts.js
new file mode 100644
index 0000000000..2b61e80f89
--- /dev/null
+++ b/packages/data-context/__snapshots__/config-generator.spec.ts.js
@@ -0,0 +1,72 @@
+exports['migration utils should create a string when passed only a global option 1'] = `
+const { defineConfig } = require('cypress')
+
+module.export = defineConfig({
+ visualViewport: 300,
+})
+`
+
+exports['migration utils should create a string when passed an empty object 1'] = `
+const { defineConfig } = require('cypress')
+
+module.export = defineConfig({
+
+})
+`
+
+exports['migration utils should create a string when passed only a e2e options 1'] = `
+const { defineConfig } = require('cypress')
+
+module.export = defineConfig({
+
+ e2e: {
+ setupNodeEvents(on, config) {
+ return require('/cypress/plugins/index.js')
+ },
+ baseUrl: 'localhost:3000'
+ },
+})
+`
+
+exports['migration utils should create a string for a config with global, component, and e2e options 1'] = `
+const { defineConfig } = require('cypress')
+
+module.export = defineConfig({
+ visualViewport: 300,
+ e2e: {
+ setupNodeEvents(on, config) {
+ return require('/cypress/plugins/index.js')
+ },
+ baseUrl: 'localhost:300',
+ retries: 2
+ },
+ component: {
+ setupNodeEvents(on, config) {
+ return require('/cypress/plugins/index.js')
+ },
+ retries: 1
+ },
+})
+`
+
+exports['migration utils should create a string when passed only a component options 1'] = `
+const { defineConfig } = require('cypress')
+
+module.export = defineConfig({
+
+ component: {
+ setupNodeEvents(on, config) {
+ return require('/cypress/plugins/index.js')
+ },
+ retries: 2
+ },
+})
+`
+
+exports['migration utils should exclude fields that are no longer valid 1'] = `
+const { defineConfig } = require('cypress')
+
+module.export = defineConfig({
+
+})
+`
diff --git a/packages/data-context/src/DataActions.ts b/packages/data-context/src/DataActions.ts
index fa3e5f588f..31e536cd69 100644
--- a/packages/data-context/src/DataActions.ts
+++ b/packages/data-context/src/DataActions.ts
@@ -6,6 +6,7 @@ import {
FileActions,
ProjectActions,
WizardActions,
+ MigrationActions,
} from './actions'
import { AuthActions } from './actions/AuthActions'
import { DevActions } from './actions/DevActions'
@@ -53,4 +54,9 @@ export class DataActions {
get electron () {
return new ElectronActions(this.ctx)
}
+
+ @cached
+ get migration () {
+ return new MigrationActions(this.ctx)
+ }
}
diff --git a/packages/data-context/src/DataContext.ts b/packages/data-context/src/DataContext.ts
index f5b4c45054..77cb566b77 100644
--- a/packages/data-context/src/DataContext.ts
+++ b/packages/data-context/src/DataContext.ts
@@ -28,6 +28,7 @@ import {
HtmlDataSource,
UtilDataSource,
BrowserApiShape,
+ MigrationDataSource,
} from './sources/'
import { cached } from './util/cached'
import type { GraphQLSchema } from 'graphql'
@@ -225,6 +226,11 @@ export class DataContext {
return new UtilDataSource(this)
}
+ @cached
+ get migration () {
+ return new MigrationDataSource(this)
+ }
+
get projectsList () {
return this.coreData.app.projects
}
diff --git a/packages/data-context/src/actions/MigrationActions.ts b/packages/data-context/src/actions/MigrationActions.ts
new file mode 100644
index 0000000000..7f00fea176
--- /dev/null
+++ b/packages/data-context/src/actions/MigrationActions.ts
@@ -0,0 +1,19 @@
+import type { DataContext } from '..'
+
+export class MigrationActions {
+ constructor (private ctx: DataContext) { }
+
+ async createConfigFile () {
+ const config = await this.ctx.migration.createConfigString()
+
+ await this.ctx.actions.file.writeFileInProject('cypress.config.js', config).catch((error) => {
+ throw error
+ })
+
+ this.ctx.lifecycleManager.refreshMetaState()
+
+ await this.ctx.actions.file.removeFileInProject('cypress.json').catch((error) => {
+ throw error
+ })
+ }
+}
diff --git a/packages/data-context/src/actions/index.ts b/packages/data-context/src/actions/index.ts
index f591e7e451..8ab30cc692 100644
--- a/packages/data-context/src/actions/index.ts
+++ b/packages/data-context/src/actions/index.ts
@@ -8,5 +8,6 @@ export * from './DevActions'
export * from './ElectronActions'
export * from './FileActions'
export * from './LocalSettingsActions'
+export * from './MigrationActions'
export * from './ProjectActions'
export * from './WizardActions'
diff --git a/packages/data-context/src/sources/FileDataSource.ts b/packages/data-context/src/sources/FileDataSource.ts
index 03d99aedd0..1c8b85d008 100644
--- a/packages/data-context/src/sources/FileDataSource.ts
+++ b/packages/data-context/src/sources/FileDataSource.ts
@@ -74,6 +74,16 @@ export class FileDataSource {
}
}
+ isValidJsFile (absolutePath: string) {
+ try {
+ require(absolutePath)
+
+ return true
+ } catch {
+ return false
+ }
+ }
+
private trackFile () {
// this.watchedFilePaths.clear()
// this.fileLoader.clear()
diff --git a/packages/data-context/src/sources/MigrationDataSource.ts b/packages/data-context/src/sources/MigrationDataSource.ts
new file mode 100644
index 0000000000..b376ae1d62
--- /dev/null
+++ b/packages/data-context/src/sources/MigrationDataSource.ts
@@ -0,0 +1,64 @@
+import path from 'path'
+import type { DataContext } from '..'
+import { createConfigString } from '../util/migration'
+
+export class MigrationDataSource {
+ private _config: Cypress.ConfigOptions | null = null
+ constructor (private ctx: DataContext) { }
+
+ async getConfig () {
+ const config = await this.parseCypressConfig()
+
+ return JSON.stringify(config, null, 2)
+ }
+
+ async createConfigString () {
+ const config = await this.parseCypressConfig()
+
+ return createConfigString(config)
+ }
+
+ async getIntegrationFolder () {
+ const config = await this.parseCypressConfig()
+
+ if (config.e2e?.integrationFolder) {
+ return config.e2e.integrationFolder
+ }
+
+ if (config.integrationFolder) {
+ return config.integrationFolder
+ }
+
+ return 'cypress/integration'
+ }
+
+ async getComponentFolder () {
+ const config = await this.parseCypressConfig()
+
+ if (config.component?.componentFolder) {
+ return config.component.componentFolder
+ }
+
+ if (config.componentFolder) {
+ return config.componentFolder
+ }
+
+ return 'cypress/component'
+ }
+
+ private async parseCypressConfig (): Promise {
+ if (this._config) {
+ return this._config
+ }
+
+ if (this.ctx.lifecycleManager.metaState.hasLegacyCypressJson) {
+ const cfgPath = path.join(this.ctx.lifecycleManager?.projectRoot, 'cypress.json')
+
+ this._config = this.ctx.file.readJsonFile(cfgPath) as Cypress.ConfigOptions
+
+ return this._config
+ }
+
+ return {}
+ }
+}
diff --git a/packages/data-context/src/sources/index.ts b/packages/data-context/src/sources/index.ts
index 5b4c1211f3..b5ca9b7a59 100644
--- a/packages/data-context/src/sources/index.ts
+++ b/packages/data-context/src/sources/index.ts
@@ -8,6 +8,7 @@ export * from './FileDataSource'
export * from './GitDataSource'
export * from './GraphQLDataSource'
export * from './HtmlDataSource'
+export * from './MigrationDataSource'
export * from './ProjectDataSource'
export * from './SettingsDataSource'
export * from './StorybookDataSource'
diff --git a/packages/data-context/src/util/index.ts b/packages/data-context/src/util/index.ts
index c6945ae47f..b86833842c 100644
--- a/packages/data-context/src/util/index.ts
+++ b/packages/data-context/src/util/index.ts
@@ -6,4 +6,5 @@ export * from './cached'
export * from './config-file-updater'
export * from './config-options'
export * from './file'
+export * from './migration'
export * from './urqlCacheKeys'
diff --git a/packages/data-context/src/util/migration.ts b/packages/data-context/src/util/migration.ts
new file mode 100644
index 0000000000..b25ba3cb0b
--- /dev/null
+++ b/packages/data-context/src/util/migration.ts
@@ -0,0 +1,80 @@
+import path from 'path'
+
+type ConfigOptions = {
+ global: Record
+ e2e: Record
+ component: Record
+}
+
+export async function createConfigString (cfg: Partial) {
+ return createCypressConfigJs(reduceConfig(cfg), getPluginRelativePath(cfg))
+}
+
+function getPluginRelativePath (cfg: Partial) {
+ const DEFAULT_PLUGIN_PATH = path.normalize('/cypress/plugins/index.js')
+
+ return cfg.pluginsFile ? cfg.pluginsFile : DEFAULT_PLUGIN_PATH
+}
+
+function reduceConfig (cfg: Partial) {
+ const excludedFields = ['pluginsFile', '$schema', 'componentFolder']
+
+ return Object.entries(cfg).reduce((acc, [key, val]) => {
+ if (excludedFields.includes(key)) {
+ return acc
+ }
+
+ if (key === 'e2e' || key === 'component') {
+ const value = val as Record
+
+ return { ...acc, [key]: { ...acc[key], ...value } }
+ }
+
+ if (key === 'testFiles') {
+ return {
+ ...acc,
+ e2e: { ...acc.e2e, specPattern: val },
+ component: { ...acc.component, specPattern: val },
+ }
+ }
+
+ if (key === 'baseUrl') {
+ return {
+ ...acc,
+ e2e: { ...acc.e2e, [key]: val },
+ }
+ }
+
+ return { ...acc, global: { ...acc.global, [key]: val } }
+ }, { global: {}, e2e: {}, component: {} })
+}
+
+function createCypressConfigJs (config: ConfigOptions, pluginPath: string) {
+ const globalString = Object.keys(config.global).length > 0 ? `${formatObjectForConfig(config.global, 2)},` : ''
+ const componentString = Object.keys(config.component).length > 0 ? createTestingTypeTemplate('component', pluginPath, config.component) : ''
+ const e2eString = Object.keys(config.e2e).length > 0 ? createTestingTypeTemplate('e2e', pluginPath, config.e2e) : ''
+
+ return `const { defineConfig } = require('cypress')
+
+module.export = defineConfig({
+ ${globalString}${e2eString}${componentString}
+})`
+}
+
+function formatObjectForConfig (obj: Record, spaces: number) {
+ return JSON.stringify(obj, null, spaces)
+ .replace(/"([^"]+)":/g, '$1:') // remove quotes from fields
+ .replace(/^[{]|[}]$/g, '') // remove opening and closing {}
+ .replace(/"/g, '\'') // single quotes
+ .trim()
+}
+
+function createTestingTypeTemplate (testingType: 'e2e' | 'component', pluginPath: string, options: Record) {
+ return `
+ ${testingType}: {
+ setupNodeEvents(on, config) {
+ return require('${pluginPath}')
+ },
+ ${formatObjectForConfig(options, 4)}
+ },`
+}
diff --git a/packages/data-context/test/unit/config-generator.spec.ts b/packages/data-context/test/unit/config-generator.spec.ts
new file mode 100644
index 0000000000..3fd090eb69
--- /dev/null
+++ b/packages/data-context/test/unit/config-generator.spec.ts
@@ -0,0 +1,75 @@
+import snapshot from 'snap-shot-it'
+import { createConfigString } from '../../src/util/migration'
+
+describe('migration utils', () => {
+ it('should create a string when passed only a global option', async () => {
+ const config = {
+ visualViewport: 300,
+ }
+
+ const generatedConfig = await createConfigString(config)
+
+ snapshot(generatedConfig)
+ })
+
+ it('should create a string when passed only a e2e options', async () => {
+ const config = {
+ e2e: {
+ baseUrl: 'localhost:3000',
+ },
+ }
+
+ const generatedConfig = await createConfigString(config)
+
+ snapshot(generatedConfig)
+ })
+
+ it('should create a string when passed only a component options', async () => {
+ const config = {
+ component: {
+ retries: 2,
+ },
+ }
+
+ const generatedConfig = await createConfigString(config)
+
+ snapshot(generatedConfig)
+ })
+
+ it('should create a string for a config with global, component, and e2e options', async () => {
+ const config = {
+ visualViewport: 300,
+ baseUrl: 'localhost:300',
+ e2e: {
+ retries: 2,
+ },
+ component: {
+ retries: 1,
+ },
+ }
+
+ const generatedConfig = await createConfigString(config)
+
+ snapshot(generatedConfig)
+ })
+
+ it('should create a string when passed an empty object', async () => {
+ const config = {}
+
+ const generatedConfig = await createConfigString(config)
+
+ snapshot(generatedConfig)
+ })
+
+ it('should exclude fields that are no longer valid', async () => {
+ const config = {
+ '$schema': 'http://someschema.com',
+ pluginsFile: 'path/to/plugin/file',
+ componentFolder: 'path/to/component/folder',
+ }
+
+ const generatedConfig = await createConfigString(config)
+
+ snapshot(generatedConfig)
+ })
+})
diff --git a/packages/frontend-shared/cypress/e2e/support/e2eProjectDirs.ts b/packages/frontend-shared/cypress/e2e/support/e2eProjectDirs.ts
index aadfbde3cf..e1e7aab586 100644
--- a/packages/frontend-shared/cypress/e2e/support/e2eProjectDirs.ts
+++ b/packages/frontend-shared/cypress/e2e/support/e2eProjectDirs.ts
@@ -29,6 +29,7 @@ export const e2eProjectDirs = [
'kill-child-process',
'launchpad',
'max-listeners',
+ 'migration',
'multiple-task-registrations',
'multiples-config-files-with-json',
'no-scaffolding',
diff --git a/packages/frontend-shared/cypress/support/mock-graphql/stubgql-Migration.ts b/packages/frontend-shared/cypress/support/mock-graphql/stubgql-Migration.ts
index 91f54ebee4..ccc36a93fe 100644
--- a/packages/frontend-shared/cypress/support/mock-graphql/stubgql-Migration.ts
+++ b/packages/frontend-shared/cypress/support/mock-graphql/stubgql-Migration.ts
@@ -47,4 +47,6 @@ export const stubMigration: MaybeResolver = {
}
},
})`,
+ integrationFolder: 'cypress/integration',
+ componentFolder: 'cypress/component',
}
diff --git a/packages/graphql/schemas/schema.graphql b/packages/graphql/schemas/schema.graphql
index ea8a39341e..11af50dba5 100644
--- a/packages/graphql/schemas/schema.graphql
+++ b/packages/graphql/schemas/schema.graphql
@@ -543,12 +543,18 @@ type LocalSettingsPreferences {
"""Contains all data related to the 9.X to 10.0 migration UI"""
type Migration {
+ """the component folder path used to store components tests"""
+ componentFolder: String!
+
"""contents of the cypress.json file after conversion"""
configAfterCode: String!
"""contents of the cypress.json file before conversion"""
configBeforeCode: String!
+ """the integration folder path used to store e2e tests"""
+ integrationFolder: String!
+
"""List of files needing manual conversion"""
manualFiles: [String!]!
@@ -619,6 +625,9 @@ type Mutation {
"""Check if a give spec file will match the project spec pattern"""
matchesSpecPattern(specFile: String!): Boolean!
+ """Transforms cypress.json file into cypress.config.js file"""
+ migrateConfigFile: Boolean
+
"""Open a path in preferred IDE"""
openDirectoryInIDE(path: String!): Boolean
openExternal(url: String!): Boolean
diff --git a/packages/graphql/src/schemaTypes/objectTypes/gql-Migration.ts b/packages/graphql/src/schemaTypes/objectTypes/gql-Migration.ts
index ba31f24e46..ba67ad1d08 100644
--- a/packages/graphql/src/schemaTypes/objectTypes/gql-Migration.ts
+++ b/packages/graphql/src/schemaTypes/objectTypes/gql-Migration.ts
@@ -14,7 +14,7 @@ export const Migration = objectType({
t.nonNull.field('step', {
type: MigrationStepEnum,
description: 'Step where the migration is right now',
- resolve: () => 'renameManual',
+ resolve: () => 'configFile',
})
t.nonNull.list.nonNull.string('specFilesBefore', {
@@ -40,15 +40,29 @@ export const Migration = objectType({
t.nonNull.string('configBeforeCode', {
description: 'contents of the cypress.json file before conversion',
- resolve: () => {
- return ``
+ resolve: (source, args, ctx) => {
+ return ctx.migration.getConfig()
},
})
t.nonNull.string('configAfterCode', {
description: 'contents of the cypress.json file after conversion',
- resolve: () => {
- return ``
+ resolve: (source, args, ctx) => {
+ return ctx.migration.createConfigString()
+ },
+ })
+
+ t.nonNull.string('integrationFolder', {
+ description: 'the integration folder path used to store e2e tests',
+ resolve: (source, args, ctx) => {
+ return ctx.migration.getIntegrationFolder()
+ },
+ })
+
+ t.nonNull.string('componentFolder', {
+ description: 'the component folder path used to store components tests',
+ resolve: (source, args, ctx) => {
+ return ctx.migration.getComponentFolder()
},
})
},
diff --git a/packages/graphql/src/schemaTypes/objectTypes/gql-Mutation.ts b/packages/graphql/src/schemaTypes/objectTypes/gql-Mutation.ts
index 61b7704709..b97d779b94 100644
--- a/packages/graphql/src/schemaTypes/objectTypes/gql-Mutation.ts
+++ b/packages/graphql/src/schemaTypes/objectTypes/gql-Mutation.ts
@@ -419,6 +419,20 @@ export const mutation = mutationType({
},
})
+ t.field('migrateConfigFile', {
+ description: 'Transforms cypress.json file into cypress.config.js file',
+ type: 'Boolean',
+ resolve: async (_, args, ctx) => {
+ try {
+ await ctx.actions.migration.createConfigFile()
+
+ return true
+ } catch {
+ return false
+ }
+ },
+ })
+
t.field('setProjectIdInConfigFile', {
description: 'Set the projectId field in the config file of the current project',
type: Query,
diff --git a/packages/launchpad/cypress/e2e/migration.cy.ts b/packages/launchpad/cypress/e2e/migration.cy.ts
new file mode 100644
index 0000000000..69a8dbe61a
--- /dev/null
+++ b/packages/launchpad/cypress/e2e/migration.cy.ts
@@ -0,0 +1,41 @@
+describe('Migration', () => {
+ beforeEach(() => {
+ cy.scaffoldProject('migration')
+ cy.openProject('migration')
+ cy.visitLaunchpad()
+ })
+
+ describe('Configuration', () => {
+ it('should create the cypress.config.js file and delete old config', () => {
+ cy.get('[data-cy="convertConfigButton"]').click()
+
+ cy.withCtx(async (ctx) => {
+ const stats = await ctx.actions.file.checkIfFileExists('cypress.config.js')
+
+ expect(stats).to.not.be.null.and.not.be.undefined
+
+ let doesFileExist = true
+
+ try {
+ await ctx.actions.file.checkIfFileExists('cypress.json')
+ } catch (error) {
+ doesFileExist = false
+ }
+
+ expect(doesFileExist).to.be.false
+ })
+ })
+
+ it('should create a valid js file', () => {
+ cy.get('[data-cy="convertConfigButton"]').click()
+
+ cy.withCtx(async (ctx) => {
+ const configPath = ctx.path.join(ctx.lifecycleManager.projectRoot, 'cypress.config.js')
+
+ const isValidJsFile = ctx.file.isValidJsFile(configPath)
+
+ expect(isValidJsFile).to.be.true
+ })
+ })
+ })
+})
diff --git a/packages/launchpad/src/Main.vue b/packages/launchpad/src/Main.vue
index 4e2261def4..0d50676f6e 100644
--- a/packages/launchpad/src/Main.vue
+++ b/packages/launchpad/src/Main.vue
@@ -13,8 +13,7 @@
:gql="query.data.value"
/>
', { viewportWidth: 1280, viewportHeight: 1100 }, () => {
it('renders Automatic rename', () => {
- cy.mountFragment(MigrationWizardFragmentDoc, {
+ cy.mountFragment(MigrationWizardDataFragmentDoc, {
onResult (res) {
- res.step = 'renameAuto'
+ res.migration = {
+ __typename: 'Migration',
+ step: 'renameAuto',
+ specFilesAfter: ['test.cy.tsx'],
+ specFilesBefore: ['test.spec.tsx'],
+ manualFiles: ['test.cy.tsx'],
+ configAfterCode: '{}',
+ configBeforeCode: '{}',
+ }
},
- render (gql) {
+ render () {
return (
-
+
)
},
})
})
it('renders Manual rename', () => {
- cy.mountFragment(MigrationWizardFragmentDoc, {
+ cy.mountFragment(MigrationWizardDataFragmentDoc, {
onResult (res) {
- res.step = 'renameManual'
+ res.migration = {
+ __typename: 'Migration',
+ step: 'renameManual',
+ specFilesAfter: ['test.cy.tsx'],
+ specFilesBefore: ['test.spec.tsx'],
+ manualFiles: ['test.cy.tsx'],
+ configAfterCode: '{}',
+ configBeforeCode: '{}',
+ }
},
- render (gql) {
+ render () {
return (
-
+
)
},
})
})
it('renders Config File migration', () => {
- cy.mountFragment(MigrationWizardFragmentDoc, {
+ cy.mountFragment(MigrationWizardDataFragmentDoc, {
onResult (res) {
- res.step = 'configFile'
+ res.migration = {
+ ...res.migration,
+ __typename: 'Migration',
+ step: 'configFile',
+ specFilesAfter: ['test.cy.tsx'],
+ specFilesBefore: ['test.spec.tsx'],
+ manualFiles: ['test.cy.tsx'],
+ configAfterCode: '{}',
+ configBeforeCode: '{}',
+ }
},
- render (gql) {
+ render () {
return (
-
+
)
},
})
diff --git a/packages/launchpad/src/migration/MigrationWizard.vue b/packages/launchpad/src/migration/MigrationWizard.vue
index 8c6908cd87..03752097a7 100644
--- a/packages/launchpad/src/migration/MigrationWizard.vue
+++ b/packages/launchpad/src/migration/MigrationWizard.vue
@@ -7,69 +7,71 @@
>
{{ t('migration.wizard.description') }}
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+ class="animate-spin icon-dark-white icon-light-gray-400"
+ />
+
+ {{ t('migration.wizard.step2.buttonWait') }}
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
+
+
+
diff --git a/system-tests/projects/migration/cypress.json b/system-tests/projects/migration/cypress.json
new file mode 100644
index 0000000000..279a1128a8
--- /dev/null
+++ b/system-tests/projects/migration/cypress.json
@@ -0,0 +1,18 @@
+{
+ "$schema": "https://on.cypress.io/cypress.schema.json",
+ "baseUrl": "http://localhost:3000",
+ "retries": 2,
+ "defaultCommandTimeout": 5000,
+ "fixturesFolder": false,
+ "componentFolder": "src",
+ "testFiles": "**/*.spec.{tsx,js}",
+ "pluginsFile": "cypress/plugins/index.ts",
+ "e2e": {
+ "defaultCommandTimeout": 10000,
+ "slowTestThreshold": 5000
+ },
+ "component": {
+ "slowTestThreshold": 5000,
+ "retries": 1
+ }
+}
\ No newline at end of file
diff --git a/system-tests/projects/migration/cypress/plugins/index.js b/system-tests/projects/migration/cypress/plugins/index.js
new file mode 100644
index 0000000000..af7dd141fc
--- /dev/null
+++ b/system-tests/projects/migration/cypress/plugins/index.js
@@ -0,0 +1,5 @@
+module.exports = (on, config) => {
+ return {
+ test: 'value',
+ }
+}