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): launch project and runner with graphql #17460

Closed
wants to merge 27 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
6063d55
wip: launcher
lmiller1990 Jul 21, 2021
7672df2
Merge branch 'lmiller1990/remove-need-to-pass-project' into lmiller19…
lmiller1990 Jul 21, 2021
4ec9239
add browser gql endpoint
lmiller1990 Jul 22, 2021
9f11f0f
add server mutation
lmiller1990 Jul 22, 2021
bb6bb91
minimal code to launch browser
lmiller1990 Jul 22, 2021
83ea661
wip: launch e2e runner from graphql
lmiller1990 Jul 23, 2021
c2da5b1
merge in master
lmiller1990 Jul 23, 2021
e19d55d
set browser mutations
lmiller1990 Jul 23, 2021
e10e378
pass correct config
lmiller1990 Jul 23, 2021
095e58e
Merge branch 'unified-desktop-gui' into lmiller1990/launcher-with-gql
lmiller1990 Jul 23, 2021
f13dafb
Merge branch 'unified-desktop-gui' into lmiller1990/launcher-with-gql
lmiller1990 Jul 23, 2021
70fb9c5
Merge branch 'unified-desktop-gui' into lmiller1990/launcher-with-gql
lmiller1990 Jul 23, 2021
a1532a8
add comments
lmiller1990 Jul 23, 2021
23472b8
work on supporting CT
lmiller1990 Jul 23, 2021
361f2c5
chore: change ct to component everywhere for consistency
lmiller1990 Jul 23, 2021
b77e735
Merge branch 'lmiller1990/chore/change-ct-to-component' into lmiller1…
lmiller1990 Jul 23, 2021
1ad25e2
update testingType
lmiller1990 Jul 23, 2021
2a94fee
projectType -> testingType
lmiller1990 Jul 23, 2021
5a95d55
update types
lmiller1990 Jul 23, 2021
edd5cc2
Merge branch 'lmiller1990/chore/change-ct-to-component' into lmiller1…
lmiller1990 Jul 23, 2021
c148a66
update logic for setting browser
lmiller1990 Jul 23, 2021
9043098
update port for CT
lmiller1990 Jul 23, 2021
810a9f2
remove unused variable
lmiller1990 Jul 23, 2021
53b1670
update logic
lmiller1990 Jul 23, 2021
39d4a60
types
lmiller1990 Jul 23, 2021
552551d
types
lmiller1990 Jul 23, 2021
91eff8d
Merge branch 'unified-desktop-gui' into lmiller1990/launcher-with-gql
lmiller1990 Jul 26, 2021
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
6 changes: 3 additions & 3 deletions cli/types/cypress.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2717,13 +2717,13 @@ declare namespace Cypress {
* Override default config options for Component Testing runner.
* @default {}
*/
component: Omit<ResolvedConfigOptions, 'e2e' | 'component'>
component: Omit<ResolvedConfigOptions, TestingType>

/**
* Override default config options for E2E Testing runner.
* @default {}
*/
e2e: Omit<ResolvedConfigOptions, 'e2e' | 'component'>
e2e: Omit<ResolvedConfigOptions, TestingType>
}

/**
Expand Down Expand Up @@ -2809,7 +2809,7 @@ declare namespace Cypress {
/**
* All configuration items are optional.
*/
type CoreConfigOptions = Partial<Omit<ResolvedConfigOptions, 'e2e' | 'component'>>
type CoreConfigOptions = Partial<Omit<ResolvedConfigOptions, TestingType>>
type ConfigOptions = CoreConfigOptions & {e2e?: CoreConfigOptions, component?: CoreConfigOptions }

interface PluginConfigOptions extends ResolvedConfigOptions {
Expand Down
3 changes: 3 additions & 0 deletions packages/launchpad/cypress.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
"runMode": 2,
"openMode": 0
},
"env": {
"CypressInternal_UseInlineSpecList": true
},
"nodeVersion": "system",
"testFiles": "**/*.spec.{ts,tsx}",
"reporter": "../../node_modules/cypress-multi-reporters/index.js",
Expand Down
5 changes: 5 additions & 0 deletions packages/launchpad/cypress/integration/foo.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
describe('testing', () => {
it('might work', () => {
expect(1).to.eq(1)
})
})
4 changes: 2 additions & 2 deletions packages/launchpad/cypress/support/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

// Import commands.js using ES2015 syntax:

import 'virtual:windi.css'
import '../../src/main.scss'
// import 'virtual:windi.css'
// import '../../src/main.scss'

import './commands'
2 changes: 1 addition & 1 deletion packages/runner-ct/src/app/SpecContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ export const SpecContent = namedObserver('SpecContent', (props: SpecContentProps
},
)}
>
<Header {...props} runner='ct' />
<Header {...props} runner='component' />
{props.state.spec
? <Iframes {...props} />
: (
Expand Down
2 changes: 1 addition & 1 deletion packages/runner-ct/src/main.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ const Runner = {
const container = (
<Container
config={config}
runner='ct'
runner='component'
state={state}
App={App}
hasSpecFile={util.hasSpecFile}
Expand Down
4 changes: 2 additions & 2 deletions packages/runner-shared/src/container/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,11 @@ export class Container extends Component {
: this._noSpec()
}

if (this.props.runner === 'ct') {
if (this.props.runner === 'component') {
return this._app()
}

throw Error(`runner prop is required and must be 'e2e' or 'ct'. You passed: ${this.props.runner}.`)
throw Error(`runner prop is required and must be 'e2e' or 'component'. You passed: ${this.props.runner}.`)
}
}

Expand Down
4 changes: 2 additions & 2 deletions packages/runner-shared/src/event-manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,9 +99,9 @@ export const eventManager = {
rerun()
})

ws.on('specs:changed', ({ specs, projectType }) => {
ws.on('specs:changed', ({ specs, testingType }) => {
// do not emit the event if e2e runner is not displaying an inline spec list.
if (projectType === 'e2e' && state.useInlineSpecList === false) {
if (testingType === 'e2e' && state.useInlineSpecList === false) {
return
}

Expand Down
4 changes: 2 additions & 2 deletions packages/runner-shared/src/header/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ interface BaseState {
}

interface StateCT {
runner: 'ct'
runner: 'component'
state: {
screenshotting: boolean
} & BaseState
Expand Down Expand Up @@ -117,7 +117,7 @@ export class Header extends Component<HeaderProps> {
className={cs({
'showing-selector-playground': selectorPlaygroundModel.isOpen,
'showing-studio': studioRecorder.isOpen,
'display-none': this.props.runner === 'ct' && this.props.state.screenshotting,
'display-none': this.props.runner === 'component' && this.props.state.screenshotting,
})}
>
<div className='sel-url-wrap'>
Expand Down
2 changes: 1 addition & 1 deletion packages/server-ct/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const registerCheckForUpdates = () => {
const checkForUpdates = (initialLaunch) => {
Updater.check({
initialLaunch,
testingType: 'ct',
testingType: 'component',
onNewVersion: _.noop,
onNoNewVersion: _.noop,
})
Expand Down
2 changes: 1 addition & 1 deletion packages/server-ct/src/server-ct.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ type WarningErr = Record<string, any>

export class ServerCt extends ServerBase<SocketCt> {
open (config: Cfg, options: OpenServerOptions) {
return super.open(config, { ...options, projectType: 'ct' })
return super.open(config, { ...options, testingType: 'component' })
}

createServer (app, config, onWarning): Bluebird<[number, WarningErr?]> {
Expand Down
2 changes: 1 addition & 1 deletion packages/server-ct/test/unit/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ describe('index.spec', () => {
expect(stub_setInterval.firstCall.args[1]).eq(1000 * 60 * 60)
expect(Updater.check.callCount).eq(1)
expect(Updater.check.firstCall.args[0]).includes({
testingType: 'ct',
testingType: 'component',
initialLaunch: true,
})
})
Expand Down
87 changes: 87 additions & 0 deletions packages/server/lib/graphql/entities/Browsers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import { queryField, objectType, enumType, mutationField, nonNull, inputObjectType } from 'nexus'
import browsers from '@packages/server/lib/browsers'
import { projects } from '../../projects'

const BrowserName = enumType({
name: 'BrowserName',
members: ['electron', 'chrome', 'chromium', 'firefox', 'edge'],
})

const BrowserChannel = enumType({
name: 'BrowserChannel',
members: ['stable', 'canary', 'beta', 'dev', 'nightly'],
})

const BrowserFamily = enumType({
name: 'BrowserFamily',
members: ['chromium', 'firefox'],
})

const Browser = objectType({
name: 'Browser',
definition (t) {
t.nonNull.field('name', {
type: BrowserName,
})

t.nonNull.field('family', {
type: BrowserFamily,
})

t.nonNull.field('channel', {
type: BrowserChannel,
})

t.int('majorVersion')
t.int('minSupportedVersion')
t.nonNull.string('displayName')
t.nonNull.string('version')
t.nonNull.string('path')
},
})

const AllBrowsersOutput = objectType({
name: 'browsers',
definition (t) {
t.nonNull.list.field('all', {
type: Browser,
})

t.field('current', {
type: Browser,
})
},
})

export const allBrowsers = queryField((t) => {
t.nonNull.field('browsers', {
type: AllBrowsersOutput,
async resolve (_root, args, ctx) {
const all = projects.foundBrowsers ?? await browsers.get()

return {
all,
current: projects.currentBrowser as any, // types
}
},
})
})

const SetBrowserInput = inputObjectType({
name: 'SetBrowserInput',
definition (t) {
t.nonNull.string('path')
},
})

export const setBrowser = mutationField((t) => {
t.nonNull.field('setBrowser', {
type: Browser,
args: {
input: nonNull(SetBrowserInput),
},
async resolve (_root, args, ctx) {
return await projects.setBrowser(args.input) as any
},
})
})
16 changes: 16 additions & 0 deletions packages/server/lib/graphql/entities/Config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { queryField } from 'nexus'
import { Config } from './types'
import { projects } from '../../projects'

export const config = queryField((t) => {
t.nonNull.field('config', {
type: Config,
resolve (_root, args, ctx) {
if (!projects.openProject) {
return {}
}

return projects.openProject.getConfig()
},
})
})
21 changes: 18 additions & 3 deletions packages/server/lib/graphql/entities/Projects.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import { inputObjectType, nonNull, mutationField, queryField } from 'nexus'
import { projects } from '../../projects'
import { Project } from './types'
import { Project, TestingType } from './types'
import { formatProject } from '../utils'

const AddProjectInput = inputObjectType({
name: 'AddProjectInput',
definition (t) {
t.nonNull.string('projectRoot')
t.nonNull.string('testingType')
t.nonNull.field('testingType', {
type: TestingType,
})

t.nonNull.boolean('isCurrent')
},
})
Expand Down Expand Up @@ -42,7 +45,19 @@ export const InitializePlugins = mutationField((t) => {
})
})

export const addProject = mutationField((t) => {
export const InitializeServer = mutationField((t) => {
t.nonNull.field('initializeServer', {
type: Project,
async resolve (_root, args, ctx) {
// TODO: should we await here, or return a pending state to the client?
await projects.initializeServer()

return formatProject(projects.openProject!)
},
})
})

export const AddProject = mutationField((t) => {
t.nonNull.field('addProject', {
type: Project,
args: {
Expand Down
28 changes: 28 additions & 0 deletions packages/server/lib/graphql/entities/Runner.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { mutationField } from 'nexus'
import { projects } from '../../projects'
import { Project } from './types'
import { formatProject } from '../utils'

export const LaunchRunner = mutationField((t) => {
t.nonNull.field('launchRunner', {
type: Project,
async resolve (_root, args, ctx) {
// TODO: should we await here, or return a pending state to the client?
await projects.launchRunner()

return formatProject(projects.openProject!)
},
})
})

export const CloseRunner = mutationField((t) => {
t.nonNull.field('closeRunner', {
type: Project,
async resolve (_root, args, ctx) {
// TODO: should we await here, or return a pending state to the client?
await projects.closeRunner()

return formatProject(projects.openProject!)
},
})
})
6 changes: 6 additions & 0 deletions packages/server/lib/graphql/entities/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,9 @@ export * from './App'
export * from './Projects'

export * from './Wizard'

export * from './Browsers'

export * from './Config'

export * from './Runner'
39 changes: 33 additions & 6 deletions packages/server/lib/graphql/entities/types.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,55 @@
import { objectType, enumType } from 'nexus'

const PluginsState = enumType({
name: 'PluginsState',
const InitState = enumType({
name: 'InitState',
members: ['uninitialized', 'initializing', 'initialized', 'error'],
})

const InitPluginsStatus = objectType({
name: 'InitPluginsStatus',
export const TestingType = enumType({
name: 'TestingType',
members: ['component', 'e2e'],
})

const InitStatus = objectType({
name: 'InitStatus',
definition (t) {
t.nonNull.field('state', {
type: PluginsState,
type: InitState,
}),
t.string('message')
},
})

export const Config = objectType({
name: 'Config',
definition (t) {
t.string('baseUrl')
t.string('clientRoute')
t.string('namespace')
t.string('xhrRoute')
t.string('reporterRoute')
t.string('proxyUrl')
t.string('proxyServer')
t.int('port')
},
})

export const Project = objectType({
name: 'Project',
definition (t) {
t.nonNull.string('projectRoot')
t.nonNull.field('testingType', {
type: TestingType,
})

t.nonNull.boolean('isOpen')
t.nonNull.boolean('isCurrent')
t.field('plugins', {
type: InitPluginsStatus,
type: InitStatus,
})

t.field('server', {
type: InitStatus,
})
},
})
Loading