mirror of
https://github.com/cypress-io/cypress.git
synced 2026-04-24 07:59:12 -05:00
refactor: move currentProject to root data (#18834)
This commit is contained in:
@@ -34,9 +34,8 @@ exports['@packages/data-context initializeData initializes 1'] = {
|
||||
],
|
||||
"projects": [],
|
||||
"currentProject": null,
|
||||
"isInGlobalMode": false,
|
||||
"isAuthBrowserOpened": false
|
||||
},
|
||||
"isAuthBrowserOpened": false,
|
||||
"wizard": {
|
||||
"chosenTestingType": null,
|
||||
"chosenBundler": null,
|
||||
|
||||
@@ -10,7 +10,6 @@ import debugLib from 'debug'
|
||||
import { CoreDataShape, makeCoreData } from './data/coreDataShape'
|
||||
import { DataActions } from './DataActions'
|
||||
import {
|
||||
AppDataSource,
|
||||
GitDataSource,
|
||||
FileDataSource,
|
||||
ProjectDataSource,
|
||||
@@ -80,6 +79,10 @@ export class DataContext {
|
||||
return this._config.electronApi
|
||||
}
|
||||
|
||||
get isGlobalMode () {
|
||||
return !this.currentProject
|
||||
}
|
||||
|
||||
async initializeData () {
|
||||
const toAwait: Promise<any>[] = [
|
||||
// Fetch the browsers when the app starts, so we have some by
|
||||
@@ -177,11 +180,6 @@ export class DataContext {
|
||||
return new DataActions(this)
|
||||
}
|
||||
|
||||
@cached
|
||||
get app () {
|
||||
return new AppDataSource(this)
|
||||
}
|
||||
|
||||
get appData () {
|
||||
return this.coreData.app
|
||||
}
|
||||
|
||||
@@ -41,13 +41,13 @@ export class AuthActions {
|
||||
|
||||
async login () {
|
||||
this.setAuthenticatedUser(await this.authApi.logIn(({ browserOpened }) => {
|
||||
this.ctx.appData.isAuthBrowserOpened = browserOpened
|
||||
this.ctx.coreData.isAuthBrowserOpened = browserOpened
|
||||
}))
|
||||
}
|
||||
|
||||
async logout () {
|
||||
try {
|
||||
this.ctx.appData.isAuthBrowserOpened = false
|
||||
this.ctx.coreData.isAuthBrowserOpened = false
|
||||
await this.authApi.logOut()
|
||||
} catch {
|
||||
//
|
||||
|
||||
@@ -41,7 +41,6 @@ export class ProjectActions {
|
||||
await this.api.closeActiveProject()
|
||||
|
||||
// TODO(tim): Improve general state management w/ immutability (immer) & updater fn
|
||||
this.ctx.coreData.app.isInGlobalMode = true
|
||||
this.ctx.coreData.currentProject = null
|
||||
this.ctx.coreData.app.currentTestingType = null
|
||||
}
|
||||
|
||||
@@ -40,8 +40,6 @@ export interface ActiveProjectShape extends ProjectShape {
|
||||
export interface AppDataShape {
|
||||
browsers: ReadonlyArray<FoundBrowser> | null
|
||||
projects: ProjectShape[]
|
||||
isInGlobalMode: boolean
|
||||
isAuthBrowserOpened: boolean
|
||||
currentTestingType: Maybe<TestingTypeEnum>
|
||||
refreshingBrowsers: Promise<FoundBrowser[]> | null
|
||||
}
|
||||
@@ -77,6 +75,7 @@ export interface CoreDataShape {
|
||||
wizard: WizardDataShape
|
||||
user: AuthenticatedUserShape | null
|
||||
electron: ElectronShape
|
||||
isAuthBrowserOpened: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -93,9 +92,8 @@ export function makeCoreData (): CoreDataShape {
|
||||
refreshingBrowsers: null,
|
||||
browsers: null,
|
||||
projects: [],
|
||||
isInGlobalMode: false,
|
||||
isAuthBrowserOpened: false,
|
||||
},
|
||||
isAuthBrowserOpened: false,
|
||||
currentProject: null,
|
||||
wizard: {
|
||||
chosenTestingType: null,
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
import type { DataContext } from '..'
|
||||
|
||||
export class AppDataSource {
|
||||
constructor (private ctx: DataContext) {}
|
||||
|
||||
get isGlobalMode () {
|
||||
const hasGlobalModeArg = this.ctx.launchArgs.global ?? false
|
||||
const isMissingActiveProject = !this.ctx.currentProject
|
||||
|
||||
return hasGlobalModeArg || isMissingActiveProject
|
||||
}
|
||||
|
||||
get isAuthBrowserOpened () {
|
||||
return this.ctx.appData.isAuthBrowserOpened
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
/* eslint-disable padding-line-between-statements */
|
||||
// created by autobarrel, do not modify directly
|
||||
|
||||
export * from './AppDataSource'
|
||||
export * from './BrowserDataSource'
|
||||
export * from './CloudDataSource'
|
||||
export * from './ConfigDataSource'
|
||||
|
||||
@@ -12,9 +12,8 @@ export interface ClientTestContext {
|
||||
app: {
|
||||
currentBrowser: Browser | null
|
||||
browsers: Browser[] | null
|
||||
isInGlobalMode: boolean
|
||||
isAuthBrowserOpened: boolean
|
||||
}
|
||||
isAuthBrowserOpened: boolean
|
||||
wizard: {
|
||||
step: WizardStep
|
||||
canNavigateForward: boolean
|
||||
@@ -48,9 +47,8 @@ export function makeClientTestContext (): ClientTestContext {
|
||||
app: {
|
||||
browsers: stubBrowsers,
|
||||
currentBrowser: stubBrowsers[0],
|
||||
isInGlobalMode: false,
|
||||
isAuthBrowserOpened: false,
|
||||
},
|
||||
isAuthBrowserOpened: false,
|
||||
wizard: {
|
||||
step: 'configFiles',
|
||||
canNavigateForward: false,
|
||||
|
||||
@@ -6,7 +6,6 @@ import { makeCacheExchange } from '@packages/frontend-shared/src/graphql/urqlCli
|
||||
import { clientTestSchema } from './clientTestSchema'
|
||||
import type { ClientTestContext } from './clientTestContext'
|
||||
import { defaultTypeResolver, FieldNode, GraphQLFieldResolver, GraphQLResolveInfo, GraphQLTypeResolver, isNonNullType } from 'graphql'
|
||||
import { stubApp } from './stubgql-App'
|
||||
import { stubWizard } from './stubgql-Wizard'
|
||||
import type { CodegenTypeMap } from '../generated/test-graphql-types.gen'
|
||||
import type { MaybeResolver } from './clientTestUtils'
|
||||
@@ -20,7 +19,6 @@ import { CloudOrganizationStubs, CloudProjectStubs, CloudRecordKeyStubs, CloudRu
|
||||
type MaybeResolveMap = {[K in keyof CodegenTypeMap]: MaybeResolver<CodegenTypeMap[K]>}
|
||||
|
||||
const GQLStubRegistry: Partial<MaybeResolveMap> = {
|
||||
App: stubApp,
|
||||
Wizard: stubWizard,
|
||||
ProjectLike: stubProject,
|
||||
GlobalProject: stubGlobalProject,
|
||||
|
||||
-13
@@ -1,6 +1,3 @@
|
||||
import type { App } from '../generated/test-graphql-types.gen'
|
||||
import type { MaybeResolver } from './clientTestUtils'
|
||||
|
||||
export const longBrowsersList = [
|
||||
{
|
||||
name: 'electron',
|
||||
@@ -123,13 +120,3 @@ export const longBrowsersList = [
|
||||
majorVersion: '69',
|
||||
},
|
||||
] as const
|
||||
|
||||
export const stubApp: MaybeResolver<App> = {
|
||||
__typename: 'App',
|
||||
isInGlobalMode (source, args, ctx) {
|
||||
return Boolean(ctx.currentProject)
|
||||
},
|
||||
isAuthBrowserOpened (source, args, ctx) {
|
||||
return ctx.app.isAuthBrowserOpened
|
||||
},
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { Browser } from '../generated/test-graphql-types.gen'
|
||||
|
||||
import { testNodeId } from './clientTestUtils'
|
||||
import { longBrowsersList } from './stubgql-App'
|
||||
import { longBrowsersList } from './longBrowsersList'
|
||||
|
||||
export const stubBrowsers = longBrowsersList.map((browser, i): Browser => {
|
||||
return {
|
||||
|
||||
@@ -6,9 +6,6 @@ export const stubQuery: MaybeResolver<Query> = {
|
||||
dev () {
|
||||
return {}
|
||||
},
|
||||
app (source, args, ctx) {
|
||||
return ctx.app
|
||||
},
|
||||
wizard (source, args, ctx) {
|
||||
return ctx.wizard
|
||||
},
|
||||
@@ -18,4 +15,10 @@ export const stubQuery: MaybeResolver<Query> = {
|
||||
projects (soruce, args, ctx) {
|
||||
return ctx.projects
|
||||
},
|
||||
isAuthBrowserOpened (source, args, ctx) {
|
||||
return ctx.isAuthBrowserOpened
|
||||
},
|
||||
isInGlobalMode (source, args, ctx) {
|
||||
return !ctx.currentProject
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
import type { CodegenTypeMap, Wizard } from '../generated/test-graphql-types.gen'
|
||||
import { BUNDLERS, CODE_LANGUAGES, FRONTEND_FRAMEWORKS, TESTING_TYPES } from '@packages/types/src/constants'
|
||||
import { BUNDLERS, CODE_LANGUAGES, FRONTEND_FRAMEWORKS } from '@packages/types/src/constants'
|
||||
import { MaybeResolver, testNodeId } from './clientTestUtils'
|
||||
import dedent from 'dedent'
|
||||
|
||||
type Writeable<T> = { -readonly [P in keyof T]: T[P] };
|
||||
|
||||
export const allBundlers = BUNDLERS.map((bundler, idx) => {
|
||||
return {
|
||||
...testNodeId('WizardBundler'),
|
||||
@@ -75,12 +73,6 @@ export const stubWizard: MaybeResolver<Wizard> = {
|
||||
},
|
||||
],
|
||||
chosenTestingTypePluginsInitialized: false,
|
||||
testingTypes: (TESTING_TYPES as Writeable<typeof TESTING_TYPES>).map((type) => {
|
||||
return {
|
||||
...testNodeId('TestingTypeInfo'),
|
||||
...type,
|
||||
}
|
||||
}),
|
||||
frameworks: FRONTEND_FRAMEWORKS.map((framework, idx) => {
|
||||
// get around readonly errors
|
||||
const supportedBundlers = framework.supportedBundlers as unknown as Array<CodegenTypeMap['WizardBundler']>
|
||||
|
||||
@@ -61,9 +61,7 @@ fragment Auth on Query {
|
||||
email
|
||||
fullName
|
||||
}
|
||||
app {
|
||||
isAuthBrowserOpened
|
||||
}
|
||||
isAuthBrowserOpened
|
||||
}
|
||||
`
|
||||
|
||||
@@ -81,9 +79,7 @@ mutation Login {
|
||||
|
||||
gql`
|
||||
query BrowserOpened {
|
||||
app {
|
||||
isAuthBrowserOpened
|
||||
}
|
||||
isAuthBrowserOpened
|
||||
}
|
||||
`
|
||||
|
||||
@@ -102,8 +98,8 @@ const emit = defineEmits<{
|
||||
(event: 'continue', value: boolean): void
|
||||
}>()
|
||||
|
||||
const viewer = computed(() => props.gql?.cloudViewer)
|
||||
const isBrowserOpened = computed(() => props.gql?.app?.isAuthBrowserOpened)
|
||||
const viewer = computed(() => props.gql.cloudViewer)
|
||||
const isBrowserOpened = computed(() => props.gql.isAuthBrowserOpened)
|
||||
const isLoggingIn = computed(() => clickedOnce.value && !viewer.value)
|
||||
|
||||
const query = useQuery({
|
||||
|
||||
@@ -69,7 +69,7 @@ describe('<HeaderBarContent />', { viewportWidth: 1000, viewportHeight: 750 }, (
|
||||
cy.mountFragment(HeaderBar_HeaderBarContentFragmentDoc, {
|
||||
onResult: (result) => {
|
||||
result.__typename = 'Query'
|
||||
result.app.isAuthBrowserOpened = true
|
||||
result.isAuthBrowserOpened = true
|
||||
result.cloudViewer = cloudViewer
|
||||
result.cloudViewer.__typename = 'CloudUser'
|
||||
},
|
||||
|
||||
@@ -14,7 +14,7 @@ const mountSuccess = () => {
|
||||
cy.mountFragment(LoginModalFragmentDoc, {
|
||||
onResult: (result) => {
|
||||
result.__typename = 'Query'
|
||||
result.app.isAuthBrowserOpened = true
|
||||
result.isAuthBrowserOpened = true
|
||||
result.cloudViewer = cloudViewer
|
||||
result.cloudViewer.__typename = 'CloudUser'
|
||||
},
|
||||
@@ -43,7 +43,7 @@ describe('<LoginModal />', { viewportWidth: 1000, viewportHeight: 750 }, () => {
|
||||
cy.mountFragment(LoginModalFragmentDoc, {
|
||||
onResult: (result) => {
|
||||
result.__typename = 'Query'
|
||||
result.app.isAuthBrowserOpened = true
|
||||
result.isAuthBrowserOpened = true
|
||||
},
|
||||
render: (gqlVal) => <div class="resize overflow-auto border-current border-1 h-700px"><LoginModal gql={gqlVal} modelValue={true} /></div>,
|
||||
})
|
||||
|
||||
@@ -87,9 +87,7 @@ fragment LoginModal on Query {
|
||||
email
|
||||
fullName
|
||||
}
|
||||
app {
|
||||
isAuthBrowserOpened
|
||||
}
|
||||
isAuthBrowserOpened
|
||||
}
|
||||
`
|
||||
|
||||
|
||||
@@ -2,15 +2,6 @@
|
||||
### Do not make changes to this file directly
|
||||
|
||||
|
||||
"""Namespace for information related to the app"""
|
||||
type App {
|
||||
"""Whether the browser has been opened for auth or not"""
|
||||
isAuthBrowserOpened: Boolean!
|
||||
|
||||
"""Whether the app is in global mode or not"""
|
||||
isInGlobalMode: Boolean!
|
||||
}
|
||||
|
||||
"""Base error"""
|
||||
type BaseError {
|
||||
message: String
|
||||
@@ -545,7 +536,6 @@ type ProjectPreferences {
|
||||
|
||||
"""The root "Query" type containing all entry fields for our querying"""
|
||||
type Query {
|
||||
app: App!
|
||||
baseError: BaseError
|
||||
|
||||
"""An error related to finding a browser"""
|
||||
@@ -575,6 +565,12 @@ type Query {
|
||||
"""The state of any info related to local development of the runner"""
|
||||
dev: DevState!
|
||||
|
||||
"""Whether the browser has been opened for auth or not"""
|
||||
isAuthBrowserOpened: Boolean!
|
||||
|
||||
"""Whether the app is in global mode or not"""
|
||||
isInGlobalMode: Boolean!
|
||||
|
||||
"""All known projects for the app"""
|
||||
projects: [ProjectLike!]!
|
||||
|
||||
@@ -723,7 +719,6 @@ type Wizard {
|
||||
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
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { BUNDLERS, CODE_LANGUAGES, FRONTEND_FRAMEWORKS, TESTING_TYPES, WIZARD_STEPS } from '@packages/types'
|
||||
import { BUNDLERS, CODE_LANGUAGES, FRONTEND_FRAMEWORKS, WIZARD_STEPS } from '@packages/types'
|
||||
import { enumType } from 'nexus'
|
||||
|
||||
export const SupportedBundlerEnum = enumType({
|
||||
@@ -29,7 +29,7 @@ export const CodeLanguageEnum = enumType({
|
||||
|
||||
export const TestingTypeEnum = enumType({
|
||||
name: 'TestingTypeEnum',
|
||||
members: TESTING_TYPES.map((t) => t.type),
|
||||
members: ['e2e', 'component'],
|
||||
})
|
||||
|
||||
export const WizardStepEnum = enumType({
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
import { objectType } from 'nexus'
|
||||
|
||||
export const App = objectType({
|
||||
name: 'App',
|
||||
description: 'Namespace for information related to the app',
|
||||
definition (t) {
|
||||
t.nonNull.boolean('isInGlobalMode', {
|
||||
description: 'Whether the app is in global mode or not',
|
||||
resolve: (source, args, ctx) => {
|
||||
return ctx.app.isGlobalMode
|
||||
},
|
||||
})
|
||||
|
||||
t.nonNull.boolean('isAuthBrowserOpened', {
|
||||
description: 'Whether the browser has been opened for auth or not',
|
||||
})
|
||||
},
|
||||
sourceType: {
|
||||
module: '@packages/data-context/src/data/coreDataShape',
|
||||
export: 'AppDataShape',
|
||||
},
|
||||
})
|
||||
@@ -1,7 +1,6 @@
|
||||
import { objectType } from 'nexus'
|
||||
import { BaseError } from '.'
|
||||
import { ProjectLike } from '..'
|
||||
import { App } from './gql-App'
|
||||
import { CurrentProject } from './gql-CurrentProject'
|
||||
import { DevState } from './gql-DevState'
|
||||
import { Wizard } from './gql-Wizard'
|
||||
@@ -15,11 +14,6 @@ export const Query = objectType({
|
||||
resolve: (root, args, ctx) => ctx.baseError,
|
||||
})
|
||||
|
||||
t.nonNull.field('app', {
|
||||
type: App,
|
||||
resolve: (root, args, ctx) => ctx.appData,
|
||||
})
|
||||
|
||||
t.nonNull.field('wizard', {
|
||||
type: Wizard,
|
||||
description: 'Metadata about the wizard, null if we arent showing the wizard',
|
||||
@@ -50,5 +44,15 @@ export const Query = objectType({
|
||||
return ctx.wizardData.browserErrorMessage
|
||||
},
|
||||
})
|
||||
|
||||
t.nonNull.boolean('isInGlobalMode', {
|
||||
description: 'Whether the app is in global mode or not',
|
||||
resolve: (source, args, ctx) => !ctx.currentProject,
|
||||
})
|
||||
|
||||
t.nonNull.boolean('isAuthBrowserOpened', {
|
||||
description: 'Whether the browser has been opened for auth or not',
|
||||
resolve: (source, args, ctx) => ctx.coreData.isAuthBrowserOpened,
|
||||
})
|
||||
},
|
||||
})
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
import { TestingTypeInfo } from './gql-TestingTypeInfo'
|
||||
import { WizardBundler } from './gql-WizardBundler'
|
||||
import { WizardFrontendFramework } from './gql-WizardFrontendFramework'
|
||||
import { WizardNpmPackage } from './gql-WizardNpmPackage'
|
||||
import { objectType } from 'nexus'
|
||||
import { BUNDLERS, CODE_LANGUAGES, FRONTEND_FRAMEWORKS, TESTING_TYPES } from '@packages/types'
|
||||
import { BUNDLERS, CODE_LANGUAGES, FRONTEND_FRAMEWORKS } from '@packages/types'
|
||||
import { TestingTypeEnum, WizardStepEnum } from '../enumTypes/gql-WizardEnums'
|
||||
import { WizardCodeLanguage } from './gql-WizardCodeLanguage'
|
||||
import { WizardSampleConfigFile } from './gql-WizardSampleConfigFile'
|
||||
@@ -95,11 +94,6 @@ export const Wizard = objectType({
|
||||
resolve: (source) => source.chosenTestingType,
|
||||
})
|
||||
|
||||
t.nonNull.list.nonNull.field('testingTypes', {
|
||||
type: TestingTypeInfo,
|
||||
resolve: () => Array.from(TESTING_TYPES),
|
||||
})
|
||||
|
||||
t.string('title', {
|
||||
description: 'The title of the page, given the current step of the wizard',
|
||||
resolve: (source, args, ctx) => ctx.wizard.title ?? null,
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/* eslint-disable padding-line-between-statements */
|
||||
// created by autobarrel, do not modify directly
|
||||
|
||||
export * from './gql-App'
|
||||
export * from './gql-BaseError'
|
||||
export * from './gql-Browser'
|
||||
export * from './gql-CurrentProject'
|
||||
|
||||
@@ -19,9 +19,7 @@ import { AppQueryDocument, App_DevRelaunchDocument } from './generated/graphql'
|
||||
|
||||
gql`
|
||||
query AppQuery {
|
||||
app {
|
||||
__typename
|
||||
}
|
||||
__typename
|
||||
dev {
|
||||
needsRelaunch
|
||||
}
|
||||
@@ -81,7 +79,7 @@ watch(query.data, () => {
|
||||
|
||||
interval = window.setInterval(poll, 200)
|
||||
|
||||
const backendInitialized = computed(() => !!query.data?.value?.app)
|
||||
const backendInitialized = computed(() => !!query.data?.value?.__typename)
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<BaseError :gql="query.data.value.baseError" />
|
||||
</template>
|
||||
<template
|
||||
v-else-if="query.data.value.app.isInGlobalMode && !query.data.value?.currentProject"
|
||||
v-else-if="query.data.value.isInGlobalMode && !query.data.value?.currentProject"
|
||||
>
|
||||
<GlobalPage :gql="query.data.value" />
|
||||
</template>
|
||||
@@ -84,9 +84,7 @@ query MainLaunchpadQuery {
|
||||
...WizardHeader
|
||||
}
|
||||
|
||||
app {
|
||||
isInGlobalMode
|
||||
}
|
||||
isInGlobalMode
|
||||
...GlobalPage
|
||||
}
|
||||
`
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { OpenBrowserListFragmentDoc } from '../generated/graphql-test'
|
||||
import OpenBrowserList from './OpenBrowserList.vue'
|
||||
import { longBrowsersList } from '@packages/frontend-shared/cypress/support/mock-graphql/stubgql-App'
|
||||
import { longBrowsersList } from '@packages/frontend-shared/cypress/support/mock-graphql/longBrowsersList'
|
||||
|
||||
const launchButtonSelector = 'button[data-testid=launch-button]'
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import _ from 'lodash'
|
||||
import path from 'path'
|
||||
import Promise from 'bluebird'
|
||||
import deepDiff from 'return-deep-diff'
|
||||
import type { ResolvedConfigurationOptions, ResolvedFromConfig, ResolvedConfigurationOptionSource, TestingType } from '@packages/types'
|
||||
import type { ResolvedConfigurationOptions, ResolvedFromConfig, ResolvedConfigurationOptionSource } from '@packages/types'
|
||||
|
||||
import errors from './errors'
|
||||
import scaffold from './scaffold'
|
||||
@@ -14,11 +14,6 @@ import Debug from 'debug'
|
||||
import pathHelpers from './util/path_helpers'
|
||||
import findSystemNode from './util/find_system_node'
|
||||
|
||||
export interface ConfigSettingsConfig {
|
||||
testingType: TestingType
|
||||
configFile?: false | string
|
||||
}
|
||||
|
||||
const debug = Debug('cypress:server:config')
|
||||
|
||||
import { options, breakingOptions } from './config_options'
|
||||
|
||||
@@ -80,20 +80,6 @@ export const FRONTEND_FRAMEWORKS = [
|
||||
|
||||
export type FrontendFramework = typeof FRONTEND_FRAMEWORKS[number]
|
||||
|
||||
export const TESTING_TYPES = [
|
||||
{
|
||||
type: 'e2e',
|
||||
title: 'E2E Testing',
|
||||
description: 'Click here to configure end-to-end testing with Cypress.',
|
||||
}, {
|
||||
type: 'component',
|
||||
title: 'Component Testing',
|
||||
description: 'Click here to configure Component Testing with your choice of framework and dev server.',
|
||||
},
|
||||
] as const
|
||||
|
||||
export type TestingType = typeof TESTING_TYPES[number]
|
||||
|
||||
export const CODE_LANGUAGES = [
|
||||
{
|
||||
type: 'js',
|
||||
|
||||
Reference in New Issue
Block a user