Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(launchpad): detect if runner is set up and change UI accordingly #17934

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 15 additions & 4 deletions packages/graphql/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,15 @@ scalar JSON @specifiedBy(url: "http://www.ecma-international.org/publications/fi

"""A Cypress project is a container"""
type LocalProject {
"""
Whether the user has configured component testing. Based on the existance of a 'component' key in their cypress.json
"""
hasSetupComponentTesting: Boolean!

"""
Whether the user has configured e2e testing or not, based on the existance of a 'component' key in their cypress.json
"""
hasSetupE2ETesting: Boolean!
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, love the descriptive graphql fields 👍

id: ID!

"""Used to associate project with Cypress cloud"""
Expand Down Expand Up @@ -172,7 +181,7 @@ type Query {
viewer: Viewer

"""Metadata about the wizard, null if we arent showing the wizard"""
wizard: Wizard
wizard: Wizard!
}

type ResolvedBooleanOption {
Expand All @@ -187,9 +196,11 @@ type ResolvedConfig {
baseUrl: ResolvedStringOption
blockHosts: ResolvedStringOption
chromeWebSecurity: ResolvedBooleanOption
component: ResolvedConfig
componentFolder: ResolvedStringOption
defaultCommandTimeout: ResolvedNumberOption
downloadsFolder: ResolvedStringOption
e2e: ResolvedConfig
env: ResolvedJsonOption
execTimeout: ResolvedNumberOption
experimentalFetchPolyfill: ResolvedBooleanOption
Expand Down Expand Up @@ -326,9 +337,9 @@ enum TestingTypeEnum {
}

type TestingTypeInfo {
description: String
description: String!
id: TestingTypeEnum!
title: String
title: String!
}

"""Namespace for information related to the viewer"""
Expand Down Expand Up @@ -376,7 +387,7 @@ type Wizard {
The testing type we are setting in the wizard, null if this has not been chosen
"""
testingType: TestingTypeEnum
testingTypes: [TestingTypeInfo!]
testingTypes: [TestingTypeInfo!]!

"""The title of the page, given the current step of the wizard"""
title: String
Expand Down
6 changes: 3 additions & 3 deletions packages/graphql/src/constants/wizardConstants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,8 @@ export const TestingTypeNames: Record<TestingType, string> = {
}

export const TestingTypeDescriptions: Record<TestingType, string> = {
component: 'Aenean lacinia bibendum nulla sed consectetur. Morbi leo risus, porta ac consectetur ac, vestibulum at eros. Integer posuere erat a ante venenatis dapibus posuere velit aliquet. Aenean lacinia bibendum nulla sed consectetur.',
e2e: 'Aenean lacinia bibendum nulla sed consectetur. Morbi leo risus, porta ac consectetur ac, vestibulum at eros. Integer posuere erat a ante venenatis dapibus posuere velit aliquet. Aenean lacinia bibendum nulla sed consectetur.',
component: 'Click here to configure Component Testing with your choice of framework and dev server.',
e2e: 'Click here to configure end-to-end testing with Cypress.',
}

export const NAV_ITEM = [
Expand Down Expand Up @@ -113,7 +113,7 @@ export const NAV_ITEM_INFO: Record<NavItem, NavItemDetails> = {
displayName: 'Settings',
iconPath: 'clarity/settings-line',
},
}
} as const

export type WizardStep = typeof WIZARD_STEP[number]

Expand Down
4 changes: 2 additions & 2 deletions packages/graphql/src/entities/DashboardProject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export class DashboardProject extends Project {
const projectId = await this.projectId()

if (!projectId) {
return null
throw Error('projectId required to fetch runs')
}

const result = await this.context.actions.getRuns({
Expand All @@ -36,7 +36,7 @@ export class DashboardProject extends Project {
const projectId = await this.projectId()

if (!projectId) {
return null
throw Error('projectId required to fetch runs')
}

const result = await this.context.actions.getRecordKeys({
Expand Down
32 changes: 32 additions & 0 deletions packages/graphql/src/entities/LocalProject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,36 @@ export class LocalProject extends Project {

return new ResolvedConfig(cfg.resolved)
}

@nxs.field.nonNull.boolean({
description: `Whether the user has configured component testing. Based on the existance of a 'component' key in their cypress.json`,
})
get hasSetupComponentTesting (): NxsResult<'LocalProject', 'hasSetupComponentTesting'> {
// default is {}
// assume if 1 or more key has been configured, CT has been setup
let config: ReturnType<LocalProject['resolvedConfig']>

if (!(config = this.resolvedConfig())) {
return false
}

// default is {}
// assume if 1 or more key has been configured, CT has been setup
return Object.keys(config.resolvedConfig.component?.value).length > 0 ?? false
}

@nxs.field.nonNull.boolean({
description: `Whether the user has configured e2e testing or not, based on the existance of a 'component' key in their cypress.json`,
})
get hasSetupE2ETesting (): NxsResult<'LocalProject', 'hasSetupE2ETesting'> {
let config: ReturnType<LocalProject['resolvedConfig']>

if (!(config = this.resolvedConfig())) {
return false
}

// default is {}
// assume if 1 or more key has been configured, E2E has been setup
return Object.keys(config.resolvedConfig.e2e?.value).length > 0 ?? false
}
}
8 changes: 4 additions & 4 deletions packages/graphql/src/entities/Project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,24 +9,24 @@ export class Project implements ProjectContract {
constructor (private _projectRoot: string, protected ctx: BaseContext) {}

@nxs.field.nonNull.id()
id (): NxsResult<'Project', 'id'> {
id (): NxsResult<'LocalProject', 'id'> {
return this.projectRoot
}

@nxs.field.nonNull.string()
title (): NxsResult<'Project', 'title'> {
title (): NxsResult<'LocalProject', 'title'> {
return 'Title'
}

@nxs.field.string({
description: 'Used to associate project with Cypress cloud',
})
async projectId (): Promise<NxsResult<'Project', 'projectId'>> {
async projectId (): Promise<NxsResult<'LocalProject', 'projectId'>> {
return await this.ctx.actions.getProjectId(this.projectRoot)
}

@nxs.field.nonNull.string()
get projectRoot (): NxsResult<'Project', 'projectRoot'> {
get projectRoot (): NxsResult<'LocalProject', 'projectRoot'> {
return this._projectRoot
}
}
2 changes: 1 addition & 1 deletion packages/graphql/src/entities/Query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export class Query {
return ctx.viewer ?? null
}

@nxs.field.type(() => Wizard, {
@nxs.field.nonNull.type(() => Wizard, {
description: 'Metadata about the wizard, null if we arent showing the wizard',
})
wizard (args: unknown, ctx: NexusGenTypes['context']): NxsQueryResult<'wizard'> {
Expand Down
29 changes: 27 additions & 2 deletions packages/graphql/src/entities/ResolvedConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,33 @@ export class ResolvedJsonOption extends ResolvedOptionBase {
description: 'Resolve config for a project',
})
export class ResolvedConfig {
constructor (private resolvedConfig: ResolvedConfigurationOptions) {
debug('Created new ResolvedConfig %o', resolvedConfig)
resolvedConfig: ResolvedConfigurationOptions

constructor (_resolvedConfig: ResolvedConfigurationOptions) {
debug('Created new ResolvedConfig %o', _resolvedConfig)
this.resolvedConfig = _resolvedConfig
}

@nxs.field.type(() => ResolvedConfig)
get component (): NxsResult<'ResolvedConfig', 'e2e'> {
const runnerSpecificConfig = this.resolvedConfig.component?.value ?? null

if (!runnerSpecificConfig) {
return null
}

return new ResolvedConfig(runnerSpecificConfig)
}

@nxs.field.type(() => ResolvedConfig)
get e2e (): NxsResult<'ResolvedConfig', 'e2e'> {
const runnerSpecificConfig = this.resolvedConfig.e2e?.value ?? null

if (!runnerSpecificConfig) {
return null
}

return new ResolvedConfig(runnerSpecificConfig)
}

@nxs.field.type(() => ResolvedStringOption)
Expand Down
8 changes: 4 additions & 4 deletions packages/graphql/src/entities/TestingTypeInfo.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
import { nxs, NxsResult } from 'nexus-decorators'
import { TestingTypeEnum, TestingType as _TestingType, TestingTypeNames, TestingTypeDescriptions } from '../constants'
import { TestingTypeEnum, TestingType, TestingTypeNames, TestingTypeDescriptions } from '../constants'

@nxs.objectType()
export class TestingTypeInfo {
constructor (private _id: _TestingType) {}
constructor (private _id: TestingType) {}

@nxs.field.nonNull.type(() => TestingTypeEnum)
get id (): NxsResult<'TestingTypeInfo', 'id'> {
return this._id
}

@nxs.field.string()
@nxs.field.nonNull.string()
get title (): NxsResult<'TestingTypeInfo', 'title'> {
return TestingTypeNames[this.id]
}

@nxs.field.string()
@nxs.field.nonNull.string()
get description (): NxsResult<'TestingTypeInfo', 'description'> {
return TestingTypeDescriptions[this.id]
}
Expand Down
2 changes: 1 addition & 1 deletion packages/graphql/src/entities/Wizard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ export class Wizard {
return this.chosenTestingType
}

@nxs.field.list.nonNull.type(() => TestingTypeInfo)
@nxs.field.nonNull.list.nonNull.type(() => TestingTypeInfo)
testingTypes (): NxsResult<'Wizard', 'testingTypes'> {
return TESTING_TYPES.map((t) => new TestingTypeInfo(t))
}
Expand Down
16 changes: 12 additions & 4 deletions packages/graphql/src/gen/nxs.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,8 @@ export interface NexusGenFieldTypes {
title: string; // String!
}
LocalProject: { // field return type
hasSetupComponentTesting: boolean; // Boolean!
hasSetupE2ETesting: boolean; // Boolean!
id: string; // ID!
projectId: string | null; // String
projectRoot: string; // String!
Expand Down Expand Up @@ -186,7 +188,7 @@ export interface NexusGenFieldTypes {
app: NexusGenRootTypes['App']; // App!
navigationMenu: NexusGenRootTypes['NavigationMenu'] | null; // NavigationMenu
viewer: NexusGenRootTypes['Viewer'] | null; // Viewer
wizard: NexusGenRootTypes['Wizard'] | null; // Wizard
wizard: NexusGenRootTypes['Wizard']; // Wizard!
}
ResolvedBooleanOption: { // field return type
from: NexusGenEnums['ResolvedConfigOption'] | null; // ResolvedConfigOption
Expand All @@ -198,9 +200,11 @@ export interface NexusGenFieldTypes {
baseUrl: NexusGenRootTypes['ResolvedStringOption'] | null; // ResolvedStringOption
blockHosts: NexusGenRootTypes['ResolvedStringOption'] | null; // ResolvedStringOption
chromeWebSecurity: NexusGenRootTypes['ResolvedBooleanOption'] | null; // ResolvedBooleanOption
component: NexusGenRootTypes['ResolvedConfig'] | null; // ResolvedConfig
componentFolder: NexusGenRootTypes['ResolvedStringOption'] | null; // ResolvedStringOption
defaultCommandTimeout: NexusGenRootTypes['ResolvedNumberOption'] | null; // ResolvedNumberOption
downloadsFolder: NexusGenRootTypes['ResolvedStringOption'] | null; // ResolvedStringOption
e2e: NexusGenRootTypes['ResolvedConfig'] | null; // ResolvedConfig
env: NexusGenRootTypes['ResolvedJsonOption'] | null; // ResolvedJsonOption
execTimeout: NexusGenRootTypes['ResolvedNumberOption'] | null; // ResolvedNumberOption
experimentalFetchPolyfill: NexusGenRootTypes['ResolvedBooleanOption'] | null; // ResolvedBooleanOption
Expand Down Expand Up @@ -286,9 +290,9 @@ export interface NexusGenFieldTypes {
totalSkipped: number | null; // Int
}
TestingTypeInfo: { // field return type
description: string | null; // String
description: string; // String!
id: NexusGenEnums['TestingTypeEnum']; // TestingTypeEnum!
title: string | null; // String
title: string; // String!
}
Viewer: { // field return type
authToken: string; // String!
Expand All @@ -309,7 +313,7 @@ export interface NexusGenFieldTypes {
sampleCode: string | null; // String
step: NexusGenEnums['WizardStep']; // WizardStep!
testingType: NexusGenEnums['TestingTypeEnum'] | null; // TestingTypeEnum
testingTypes: NexusGenRootTypes['TestingTypeInfo'][] | null; // [TestingTypeInfo!]
testingTypes: NexusGenRootTypes['TestingTypeInfo'][]; // [TestingTypeInfo!]!
title: string | null; // String
}
WizardBundler: { // field return type
Expand Down Expand Up @@ -355,6 +359,8 @@ export interface NexusGenFieldTypeNames {
title: 'String'
}
LocalProject: { // field return type name
hasSetupComponentTesting: 'Boolean'
hasSetupE2ETesting: 'Boolean'
id: 'ID'
projectId: 'String'
projectRoot: 'String'
Expand Down Expand Up @@ -409,9 +415,11 @@ export interface NexusGenFieldTypeNames {
baseUrl: 'ResolvedStringOption'
blockHosts: 'ResolvedStringOption'
chromeWebSecurity: 'ResolvedBooleanOption'
component: 'ResolvedConfig'
componentFolder: 'ResolvedStringOption'
defaultCommandTimeout: 'ResolvedNumberOption'
downloadsFolder: 'ResolvedStringOption'
e2e: 'ResolvedConfig'
env: 'ResolvedJsonOption'
execTimeout: 'ResolvedNumberOption'
experimentalFetchPolyfill: 'ResolvedBooleanOption'
Expand Down
19 changes: 11 additions & 8 deletions packages/graphql/test/integration/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ interface TestContextInjectionOptions {
wizard?: Wizard
launchArgs?: LaunchArgs
launchOptions?: OpenProjectLaunchOptions
Actions?: typeof TestActions
}

export class TestActions extends BaseActions {
Expand All @@ -20,6 +21,14 @@ export class TestActions extends BaseActions {
installDependencies () {}
createConfigFile () {}

async launchOpenProject () {}
resolveOpenProjectConfig (): FullConfig {
return {
projectRoot: '/root/path',
resolved: {},
}
}

addProject (projectRoot: string) {
return new LocalProject(projectRoot, this.ctx)
}
Expand All @@ -46,13 +55,7 @@ export class TestActions extends BaseActions {
return []
}

async launchOpenProject () {}
async initializeOpenProject () {}
resolveOpenProjectConfig (): FullConfig {
return {
resolved: {},
}
}

async getBrowsers () {
const browser: FoundBrowser = {
Expand All @@ -77,7 +80,7 @@ export class TestContext extends BaseContext {
readonly actions: BaseActions
viewer = null

constructor ({ wizard, launchArgs, launchOptions }: TestContextInjectionOptions = {}) {
constructor ({ wizard, launchArgs, launchOptions, Actions }: TestContextInjectionOptions = {}) {
super(launchArgs || {
config: {},
cwd: '/current/working/dir',
Expand All @@ -90,7 +93,7 @@ export class TestContext extends BaseContext {
os: 'linux',
}, launchOptions || {})

this.actions = new TestActions(this)
this.actions = Actions ? new Actions(this) : new TestActions(this)
if (wizard) {
this.wizard = wizard
}
Expand Down
Loading