Skip to content

Commit

Permalink
fix: disable ct testing when run via binary (#21540)
Browse files Browse the repository at this point in the history
  • Loading branch information
ZachJW34 authored May 20, 2022
1 parent 87eec2b commit 0e32352
Show file tree
Hide file tree
Showing 13 changed files with 114 additions and 59 deletions.
1 change: 0 additions & 1 deletion packages/app/src/navigation/SwitchTestingTypeModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
>
<TestingTypePicker
:gql="props.gql"
:is-app="true"
@pick="handleTestingType"
/>
</StandardModal>
Expand Down
4 changes: 2 additions & 2 deletions packages/frontend-shared/cypress/e2e/e2ePluginSetup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ async function makeE2ETasks () {
// which probably needs a bit of refactoring / consolidating
const cliOptions = await cli.parseOpenCommand(['open', ...openArgv])
const processedArgv = cliOpen.processOpenOptions(cliOptions)
const modeOptions = argUtils.toObject(processedArgv)
const modeOptions = { ...argUtils.toObject(processedArgv), invokedFromCli: true }

// Reset the state of the context
await ctx.reinitializeCypress(modeOptions)
Expand All @@ -316,7 +316,7 @@ async function makeE2ETasks () {
// which probably needs a bit of refactoring / consolidating
const cliOptions = await cli.parseOpenCommand(['open', ...openArgv])
const processedArgv = cliOpen.processOpenOptions(cliOptions)
const modeOptions = argUtils.toObject(processedArgv)
const modeOptions = { ...argUtils.toObject(processedArgv), invokedFromCli: true }

// Reset the state of the context
await ctx.reinitializeCypress(modeOptions)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ export const stubQuery: MaybeResolver<Query> = {
isInGlobalMode (source, args, ctx) {
return !ctx.currentProject
},
invokedFromCli (source, args, ctx) {
return true
},
baseError (source, args, ctx) {
return {}
},
Expand Down
2 changes: 1 addition & 1 deletion packages/frontend-shared/src/components/Card.cy.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ describe('Card', { viewportHeight: 400 }, () => {
// we can't actually click it

cy.get('[data-cy="card"]')
.should('have.css', 'pointer-events', 'none')
.should('have.css', 'cursor', 'default')

cy.get('@clickSpy').should('not.have.been.called')

Expand Down
21 changes: 11 additions & 10 deletions packages/frontend-shared/src/components/Card.vue
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
<template>
<div
class="relative rounded cursor-pointer h-auto outline-none border-1
text-center block group focus-within-default hocus-default
class="rounded h-auto outline-none border-1 text-center
relative block group
children:hyphens-manual"
:class="{
'bg-gray-50 border-gray-100 pointer-events-none': disabled
'bg-gray-50 border-gray-100 cursor-default': disabled,
'cursor-pointer focus-within-default hocus-default': !disabled
}"
data-cy="card"
@click="emits('click')"
@click="!disabled && emits('click')"
>
<div
v-if="title === t('testingType.component.name')"
class="ribbon absolute top-0 right-0 text-teal-600"
class="top-0 right-0 text-teal-600 ribbon absolute"
aria-hidden="true"
>
{{ t('versions.beta') }}
Expand All @@ -23,14 +24,14 @@
<component
:is="hoverIcon"
v-if="hoverIcon"
class="opacity-0 absolute group-focus:opacity-100 group-hover:opacity-100"
:class="iconClass"
class="opacity-0 absolute"
:class="[iconClass, {'group-hover:opacity-100 group-focus:opacity-100': !disabled}]"
data-cy="card-icon"
/>
<component
:is="icon"
class="opacity-100"
:class="[ hoverIcon ? 'group-hover:opacity-0' : undefined,
:class="[ hoverIcon && !disabled ? 'group-hover:opacity-0' : undefined,
iconClass]
"
data-cy="card-icon"
Expand All @@ -41,14 +42,14 @@
<button
class="font-medium mx-8px mb-8px text-indigo-500 text-18px leading-24px focus:outline-transparent"
:class="{
'text-gray-700': disabled
'text-gray-700 cursor-default': disabled
}"
:disabled="disabled"
>
{{ title }}
</button>
<p class="tracking-tight text-gray-600 text-14px leading-20px">
{{ description }}
<slot>{{ description }}</slot>
</p>
<slot name="footer" />
<div
Expand Down
18 changes: 11 additions & 7 deletions packages/frontend-shared/src/gql-components/StatusBadge.cy.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,24 @@ import Button from '../components/Button.vue'
describe('<StatusBadge />', () => {
it('renders and toggles', { viewportWidth: 500, viewportHeight: 200 }, () => {
const status = ref(false)
const title = ref('not configured')

function onClick () {
status.value = !status.value
title.value = 'configured'
}

cy.mount(() => (
<div class="p-6">
<StatusBadge
titleOn="configured"
titleOff="not configured"
title={title.value}
status={status.value}
testingType='component'
isRunning={false}
isApp={false}
/>
<br /><br />
{// @ts-ignore
}<Button onClick={() => status.value = !status.value}>toggle</Button>
{
// @ts-ignore
<Button onClick={onClick}>toggle</Button>
}
</div>
))

Expand Down
36 changes: 11 additions & 25 deletions packages/frontend-shared/src/gql-components/StatusBadge.vue
Original file line number Diff line number Diff line change
@@ -1,35 +1,21 @@
<template>
<template v-if="props.status">
<div class="border rounded-full font-medium p-5px pr-16px text-size-14px text-jade-500 leading-20px inline-flex items-center relative">
<i-cy-grommet_x16
class="h-16px mr-4px ml-4px w-16px icon-light-jade-400 icon-dark-jade-400"
/>
{{ props.titleOn }}
</div>
</template>
<template v-else>
<span
class="border rounded-full font-medium p-5px pr-16px text-size-14px text-gray-600 leading-20px inline-flex items-center"
>
<i-cy-grommet_x16
class="h-16px mx-4px w-16px icon-dark-gray-200 icon-dark-gray-50"
/>
{{ props.titleOff }}
</span>
</template>
<div
class="border rounded-full font-medium p-5px pr-16px text-size-14px leading-20px inline-flex items-center relative"
:class="{'text-jade-500': props.status, 'text-gray-600': !props.status}"
>
<i-cy-grommet_x16
class="h-16px mr-4px ml-4px w-16px"
:class="{'icon-light-jade-400 icon-dark-jade-400': props.status, 'icon-dark-gray-200 icon-dark-gray-50': !props.status}"
/>
{{ props.title }}
</div>
</template>

<script lang="ts" setup>
import type { TestingTypeEnum } from '../generated/graphql'
const props = defineProps<{
status: boolean
titleOn: string
titleOff: string
testingType: TestingTypeEnum
isRunning: boolean
isApp: boolean
title: string
}>()
</script>
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import TestingTypePicker from './TestingTypePicker.vue'
import { TestingTypePickerFragmentDoc } from '../generated/graphql-test'
import { defaultMessages } from '@cy/i18n'

const { component, e2e } = defaultMessages.testingType
const { component, e2e, componentDisabled } = defaultMessages.testingType

describe('TestingTypePicker', () => {
it('renders "configured" and "not configured" states', () => {
Expand All @@ -16,7 +16,7 @@ describe('TestingTypePicker', () => {
}
},
render: (gql) => {
return <TestingTypePicker gql={gql} onPick={pick} isApp={false}/>
return <TestingTypePicker gql={gql} onPick={pick}/>
},
})

Expand All @@ -40,4 +40,27 @@ describe('TestingTypePicker', () => {

cy.percySnapshot('after click - focus')
})

it('shows disabled ct when not invoked from cli', () => {
cy.mountFragment(TestingTypePickerFragmentDoc, {
onResult (result) {
result.invokedFromCli = false
},
render: (gql) => {
return <TestingTypePicker gql={gql} onPick={cy.spy().as('pick')}/>
},
})

cy.get('[data-cy-testingtype="component"]').within(() => {
cy.contains(component.name).should('be.visible')
cy.contains(componentDisabled.description.replace('{0}', componentDisabled.link)).should('be.visible')
cy.contains(defaultMessages.setupPage.testingCard.disabled).should('be.visible')

cy.contains(componentDisabled.link).should('have.attr', 'href', 'https://on.cypress.io/installing-cypress')
}).click()

cy.get('@pick').should('not.have.been.called')

cy.percySnapshot()
})
})
43 changes: 34 additions & 9 deletions packages/frontend-shared/src/gql-components/TestingTypePicker.vue
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,30 @@
:icon="tt.icon"
:hover-icon="tt.iconSolid"
:icon-size="64"
:disabled="tt.status === 'disabled'"
variant="jade"
@click="emits('pick', tt.key, currentTestingType)"
@keyup.enter="emits('pick', tt.key, currentTestingType)"
@keyup.space="emits('pick', tt.key, currentTestingType)"
>
<template
v-if="tt.key === 'component' && tt.status === 'disabled'"
#default
>
<i18n-t
scope="global"
keypath="testingType.componentDisabled.description"
>
<ExternalLink href="https://on.cypress.io/installing-cypress">
{{ t('testingType.componentDisabled.link') }}
</ExternalLink>
</i18n-t>
</template>
<template #footer>
<StatusBadge
class="mt-16px"
:title-on="tt.key === currentTestingType ? t('setupPage.testingCard.running') : t('setupPage.testingCard.configured')"
:title-off="t('setupPage.testingCard.notConfigured')"
:status="tt.configured || false"
:testing-type="tt.key"
:is-running="tt.key === currentTestingType"
:is-app="props.isApp"
:title="t(`setupPage.testingCard.${tt.status}`)"
:status="tt.status === 'configured' || tt.status === 'running'"
@choose-a-browser="emits('pick', tt.key, currentTestingType)"
/>
</template>
Expand All @@ -45,6 +55,7 @@ import IconComponent from '~icons/cy/testing-type-component_x64.svg'
import IconComponentSolid from '~icons/cy/testing-type-component-solid_x64.svg'
import { useI18n } from '@cy/i18n'
import { computed } from 'vue'
import ExternalLink from './ExternalLink.vue'
const { t } = useI18n()
Expand All @@ -56,18 +67,32 @@ fragment TestingTypePicker on Query {
isE2EConfigured
currentTestingType
}
invokedFromCli
}
`
const props = defineProps<{
gql: TestingTypePickerFragment
isApp: boolean
}>()
const emits = defineEmits<{
(eventName: 'pick', testingType: TestingTypeEnum, currentTestingType: TestingTypeEnum): void
}>()
const e2eStatus = computed(() => {
if (!props.gql.currentProject?.isE2EConfigured) return 'notConfigured'
return props.gql.currentProject.currentTestingType === 'e2e' ? 'running' : 'configured'
})
const componentStatus = computed(() => {
if (!props.gql.invokedFromCli) return 'disabled'
if (!props.gql.currentProject?.isCTConfigured) return 'notConfigured'
return props.gql.currentProject.currentTestingType === 'component' ? 'running' : 'configured'
})
const testingTypes = computed(() => {
return [
{
Expand All @@ -76,15 +101,15 @@ const testingTypes = computed(() => {
description: t('testingType.e2e.description'),
icon: IconE2E,
iconSolid: IconE2ESolid,
configured: props.gql.currentProject?.isE2EConfigured,
status: e2eStatus.value,
},
{
key: 'component',
name: t('testingType.component.name'),
description: t('testingType.component.description'),
icon: IconComponent,
iconSolid: IconComponentSolid,
configured: props.gql.currentProject?.isCTConfigured,
status: componentStatus.value,
},
] as const
})
Expand Down
7 changes: 6 additions & 1 deletion packages/frontend-shared/src/locales/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,8 @@
"notConfigured": "Not Configured",
"running": "Running",
"chooseABrowser": "Choose a Browser",
"reconfigure": "Reconfigure"
"reconfigure": "Reconfigure",
"disabled": "Disabled"
}
},
"globalPage": {
Expand Down Expand Up @@ -520,6 +521,10 @@
"component": {
"name": "Component Testing",
"description": "Build and test your components from your design system in isolation in order to ensure each state matches your expectations."
},
"componentDisabled": {
"description": "To test your components you must {0} as an NPM dependency for this project.",
"link": "install Cypress"
}
},
"migration": {
Expand Down
5 changes: 5 additions & 0 deletions packages/graphql/schemas/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -1218,6 +1218,11 @@ type Query {
"""The state of any info related to local development of the runner"""
dev: DevState!

"""
Whether the app was invoked from the CLI, false if user is using the binary directly (not invoked from package manager e.g. npm)
"""
invokedFromCli: Boolean!

"""Whether the app is in global mode or not"""
isInGlobalMode: Boolean!

Expand Down
5 changes: 5 additions & 0 deletions packages/graphql/src/schemaTypes/objectTypes/gql-Query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,11 @@ export const Query = objectType({
resolve: (_, args, ctx) => ctx.coreData.scaffoldedFiles,
})

t.nonNull.boolean('invokedFromCli', {
description: 'Whether the app was invoked from the CLI, false if user is using the binary directly (not invoked from package manager e.g. npm)',
resolve: (source, args, ctx) => Boolean(ctx.modeOptions.invokedFromCli),
})

t.field('node', {
type: 'Node',
args: {
Expand Down
1 change: 0 additions & 1 deletion packages/launchpad/src/setup/TestingTypeCards.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
<template>
<TestingTypePicker
:gql="props.gql"
:is-app="false"
@pick="selectTestingType"
/>
</template>
Expand Down

2 comments on commit 0e32352

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on 0e32352 May 20, 2022

Choose a reason for hiding this comment

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

Circle has built the linux x64 version of the Test Runner.

Learn more about this pre-release platform-specific build at https://on.cypress.io/installing-cypress#Install-pre-release-version.

Run this command to install the pre-release locally:

npm install https://cdn.cypress.io/beta/npm/10.0.0/linux-x64/10.0-release-0e32352cbe3e06c6218007049ee16111503dad63/cypress.tgz

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on 0e32352 May 20, 2022

Choose a reason for hiding this comment

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

Circle has built the win32 x64 version of the Test Runner.

Learn more about this pre-release platform-specific build at https://on.cypress.io/installing-cypress#Install-pre-release-version.

Run this command to install the pre-release locally:

npm install https://cdn.cypress.io/beta/npm/10.0.0/win32-x64/10.0-release-0e32352cbe3e06c6218007049ee16111503dad63/cypress.tgz

Please sign in to comment.