Skip to content

Commit

Permalink
feat(graphql): ability to update/query for appData (#19082)
Browse files Browse the repository at this point in the history
* move to ts

* refactor

* test

* type

* fix tests

* types

* simplify update preferences via graphql

* types

* simplify

* show config in editor

* fix test

* add description for mutation and update default prefernces

* update schema

* update docs

* update description of localSettings field

Co-authored-by: Mark Noonan <mark@cypress.io>
Co-authored-by: Mark Noonan <oddlyaromatic@gmail.com>
  • Loading branch information
3 people committed Nov 29, 2021
1 parent b9f8364 commit cc3be10
Show file tree
Hide file tree
Showing 29 changed files with 292 additions and 266 deletions.
2 changes: 0 additions & 2 deletions packages/app/src/runner/SpecRunner.vue
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@

<script lang="ts" setup>
import { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue'
import { useI18n } from '@cy/i18n'
import { REPORTER_ID, RUNNER_ID, getRunnerElement, getReporterElement, empty } from '../runner/utils'
import { gql } from '@urql/core'
import InlineSpecList from '../specs/InlineSpecList.vue'
Expand Down Expand Up @@ -103,7 +102,6 @@ const eventManager = getEventManager()
const autStore = useAutStore()
const screenshotStore = useScreenshotStore()
const runnerUiStore = useRunnerUiStore()
const { t } = useI18n()
const runnerPane = ref<HTMLDivElement>()
Expand Down
4 changes: 2 additions & 2 deletions packages/app/src/settings/device/ExternalEditorSettings.vue
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,15 @@ import { useMutation } from '@urql/vue'
gql`
mutation ExternalEditorSettings_SetPreferredEditorBinary ($value: String!) {
setPreferredEditorBinary (value: $value)
setPreferences (value: $value)
}`
const { t } = useI18n()
const setPreferredBinaryEditor = useMutation(ExternalEditorSettings_SetPreferredEditorBinaryDocument)
function handleChoseEditor (binary: string) {
setPreferredBinaryEditor.executeMutation({ value: binary })
setPreferredBinaryEditor.executeMutation({ value: JSON.stringify({ preferredEditorBinary: binary }) })
}
gql`
Expand Down
29 changes: 11 additions & 18 deletions packages/app/src/settings/device/TestingPreferences.vue
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
class="mx-8px"
:value="props.gql.localSettings.preferences[pref.id] ?? false"
:name="pref.title"
@update="(value) => pref.mutation.executeMutation({ value })"
@update="(value) => updatePref(pref.id, value)"
/>
</h4>
<p class="text-size-14px leading-24px text-gray-600">
Expand All @@ -37,9 +37,7 @@ import { useI18n } from '@cy/i18n'
import Switch from '@packages/frontend-shared/src/components/Switch.vue'
import { gql, useMutation } from '@urql/vue'
import {
SetAutoScrollingEnabledDocument,
SetUseDarkSidebarDocument,
SetWatchForSpecChangeDocument,
SetTestingPreferencesDocument,
} from '@packages/data-context/src/gen/all-operations.gen'
import type { TestingPreferencesFragment } from '../../generated/graphql'
Expand All @@ -58,41 +56,36 @@ fragment TestingPreferences on Query {
`
gql`
mutation SetAutoScrollingEnabled($value: Boolean!) {
setAutoScrollingEnabled(value: $value)
mutation SetTestingPreferences($value: String!) {
setPreferences (value: $value)
}`
gql`
mutation SetUseDarkSidebar($value: Boolean!) {
setUseDarkSidebar(value: $value)
}`
gql`
mutation SetWatchForSpecChange($value: Boolean!) {
setWatchForSpecChange(value: $value)
}`
const setPreferences = useMutation(SetTestingPreferencesDocument)
const prefs = [
{
id: 'autoScrollingEnabled',
title: t('settingsPage.testingPreferences.autoScrollingEnabled.title'),
mutation: useMutation(SetAutoScrollingEnabledDocument),
description: t('settingsPage.testingPreferences.autoScrollingEnabled.description'),
},
{
id: 'useDarkSidebar',
title: t('settingsPage.testingPreferences.useDarkSidebar.title'),
mutation: useMutation(SetUseDarkSidebarDocument),
description: t('settingsPage.testingPreferences.useDarkSidebar.description'),
},
{
id: 'watchForSpecChange',
title: t('settingsPage.testingPreferences.watchForSpecChange.title'),
mutation: useMutation(SetWatchForSpecChangeDocument),
description: t('settingsPage.testingPreferences.watchForSpecChange.description'),
},
] as const
function updatePref (preferenceId: typeof prefs[number]['id'], value: boolean) {
setPreferences.executeMutation({
value: JSON.stringify({ [preferenceId]: value }),
})
}
const props = defineProps<{
gql: TestingPreferencesFragment
}>()
Expand Down
71 changes: 29 additions & 42 deletions packages/app/src/specs/CreateSpecPage.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import Button from '@cy/components/Button.vue'
import CreateSpecPage from './CreateSpecPage.vue'
import { ref, Ref } from 'vue'
import { defaultMessages } from '@cy/i18n'
import type { TestingTypeEnum } from '../generated/graphql-test'
import { CreateSpecPageFragmentDoc } from '../generated/graphql-test'

const pageTitleSelector = '[data-testid=create-spec-page-title]'
const pageDescriptionSelector = '[data-testid=create-spec-page-description]'
Expand All @@ -14,14 +12,21 @@ const messages = defaultMessages.createSpec
describe('<CreateSpecPage />', () => {
describe('mounting in component type', () => {
beforeEach(() => {
cy.mount(() => (<div class="p-12"><CreateSpecPage gql={{
currentProject: {
id: 'id',
storybook: null,
codeGenGlob: '**.vue',
currentTestingType: 'component',
cy.mountFragment(CreateSpecPageFragmentDoc, {
onResult: (ctx) => {
ctx.currentProject = {
...ctx.currentProject,
id: 'id',
storybook: null,
configFileAbsolutePath: '/usr/bin/cypress.config.ts',
codeGenGlob: '**.vue',
currentTestingType: 'component',
}
},
render: (gql) => {
return <CreateSpecPage gql={gql} />
},
}} /></div>))
})
})

it('renders the "No Specs" footer', () => {
Expand All @@ -44,14 +49,21 @@ describe('<CreateSpecPage />', () => {

describe('mounting in e2e mode', () => {
beforeEach(() => {
cy.mount(() => (<div class="p-12"><CreateSpecPage gql={{
currentProject: {
id: 'id',
storybook: null,
codeGenGlob: '**.vue',
currentTestingType: 'e2e',
cy.mountFragment(CreateSpecPageFragmentDoc, {
onResult: (ctx) => {
ctx.currentProject = {
...ctx.currentProject,
configFileAbsolutePath: '/usr/bin/cypress.config.ts',
id: 'id',
storybook: null,
codeGenGlob: '**.vue',
currentTestingType: 'e2e',
}
},
render: (gql) => {
return <CreateSpecPage gql={gql} />
},
}} /></div>))
})
})

it('renders e2e mode', () => {
Expand All @@ -64,29 +76,4 @@ describe('<CreateSpecPage />', () => {
.get(pageDescriptionSelector).should('contain.text', messages.page.e2e.description)
})
})

it('playground', () => {
const testingType: Ref<TestingTypeEnum> = ref('component')

cy.mount(() => (
<div class="p-12 space-y-10 resize overflow-auto">
{ /* Testing Utils */ }
<Button variant="outline"
size="md"
// @ts-ignore
onClick={() => testingType.value = testingType.value === 'component' ? 'e2e' : 'component'}>
Toggle Testing Types
</Button>

{ /* Subject Under Test */ }
<CreateSpecPage gql={{
currentProject: {
id: 'id',
storybook: null,
codeGenGlob: '**.vue',
currentTestingType: testingType.value,
},
}} />
</div>))
})
})
59 changes: 57 additions & 2 deletions packages/app/src/specs/CreateSpecPage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
:gql="props.gql"
@close="closeModal"
/>
<div
v-if="props.gql.currentProject?.currentTestingType"
class="overflow-scroll text-center max-w-600px mx-auto py-40px"
Expand All @@ -29,6 +30,13 @@
@select="choose"
/>
<ChooseExternalEditorModal
:open="runnerUiStore.showChooseExternalEditorModal"
:gql="props.gql"
@close="runnerUiStore.setShowChooseExternalEditorModal(false)"
@selected="openFile"
/>
<div class="text-center border-t-1 pt-32px mt-32px">
<p
data-testid="no-specs-message"
Expand All @@ -42,7 +50,7 @@
prefix-icon-class="icon-light-gray-50 icon-dark-gray-400"
:prefix-icon="SettingsIcon"
class="mx-auto duration-300 hocus:ring-gray-50 hocus:border-gray-200"
@click.prevent=""
@click.prevent="showCypressConfigInIDE"
>
{{ t('createSpec.viewSpecPatternButton') }}
</Button>
Expand All @@ -57,29 +65,76 @@ import Button from '@cy/components/Button.vue'
import { ref } from 'vue'
import CreateSpecModal from './CreateSpecModal.vue'
import CreateSpecCards from './CreateSpecCards.vue'
import { gql } from '@urql/vue'
import { gql, useMutation } from '@urql/vue'
import type { CreateSpecPageFragment } from '../generated/graphql'
import { CreateSpecPage_OpenFileInIdeDocument } from '@packages/data-context/src/gen/all-operations.gen'
import { useRunnerUiStore } from '../store/runner-ui-store'
import ChooseExternalEditorModal from '@packages/frontend-shared/src/gql-components/ChooseExternalEditorModal.vue'
const { t } = useI18n()
gql`
fragment CreateSpecPage on Query {
...CreateSpecCards
...CreateSpecModal
...ChooseExternalEditor
currentProject {
id
currentTestingType
configFileAbsolutePath
}
localSettings {
preferences {
preferredEditorBinary
}
}
}
`
gql`
mutation CreateSpecPage_OpenFileInIDE ($input: FileDetailsInput!) {
openFileInIDE (input: $input)
}
`
const props = defineProps<{
gql: CreateSpecPageFragment
}>()
const openFileInIDE = useMutation(CreateSpecPage_OpenFileInIdeDocument)
const showModal = ref(false)
const generator = ref()
const openInIde = (absolute: string) => {
openFileInIDE.executeMutation({
input: {
absolute,
line: 1,
column: 1,
},
})
}
const runnerUiStore = useRunnerUiStore()
const openFile = () => {
runnerUiStore.setShowChooseExternalEditorModal(false)
if (props.gql.currentProject?.configFileAbsolutePath) {
openInIde(props.gql.currentProject.configFileAbsolutePath)
}
}
const showCypressConfigInIDE = () => {
if (props.gql.localSettings.preferences.preferredEditorBinary && props.gql.currentProject?.configFileAbsolutePath) {
openInIde(props.gql.currentProject.configFileAbsolutePath)
} else {
runnerUiStore.setShowChooseExternalEditorModal(true)
}
}
const closeModal = () => {
showModal.value = false
generator.value = null
Expand Down
24 changes: 15 additions & 9 deletions packages/data-context/src/actions/LocalSettingsActions.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,28 @@
import type { DevicePreferences, Editor } from '@packages/types'
import { AllowedState, defaultPreferences, Editor } from '@packages/types'
import pDefer from 'p-defer'

import type { DataContext } from '..'

export interface LocalSettingsApiShape {
setPreferredOpener(editor: Editor): Promise<void>
getAvailableEditors(): Promise<Editor[]>

getPreferences (): Promise<DevicePreferences>
setDevicePreference<K extends keyof DevicePreferences> (key: K, value: DevicePreferences[K]): Promise<void>
getPreferences (): Promise<AllowedState>
setPreferences (object: AllowedState): Promise<void>
}

export class LocalSettingsActions {
constructor (private ctx: DataContext) {}

setDevicePreference<K extends keyof DevicePreferences> (key: K, value: DevicePreferences[K]) {
setPreferences (stringifiedJson: string) {
const toJson = JSON.parse(stringifiedJson) as AllowedState

// update local data
this.ctx.coreData.localSettings.preferences[key] = value
for (const [key, value] of Object.entries(toJson)) {
this.ctx.coreData.localSettings.preferences[key as keyof AllowedState] = value as any
}

// persist to appData
return this.ctx._apis.localSettingsApi.setDevicePreference(key, value)
return this.ctx._apis.localSettingsApi.setPreferences(toJson)
}

async refreshLocalSettings () {
Expand All @@ -35,8 +38,11 @@ export class LocalSettingsActions {
const availableEditors = await this.ctx._apis.localSettingsApi.getAvailableEditors()

this.ctx.coreData.localSettings.availableEditors = availableEditors
this.ctx.coreData.localSettings.preferences = await this.ctx._apis.localSettingsApi.getPreferences()
this.ctx.coreData.localSettings.preferences = {
...defaultPreferences,
...(await this.ctx._apis.localSettingsApi.getPreferences()),
}

dfd.resolve(availableEditors)
dfd.resolve()
}
}
6 changes: 3 additions & 3 deletions packages/data-context/src/data/coreDataShape.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { BUNDLERS, FoundBrowser, FoundSpec, FullConfig, Preferences, DevicePreferences, devicePreferenceDefaults, Editor, Warning } from '@packages/types'
import { BUNDLERS, FoundBrowser, FoundSpec, FullConfig, Preferences, Editor, Warning, AllowedState } from '@packages/types'
import type { NexusGenEnums, TestingTypeEnum } from '@packages/graphql/src/gen/nxs.gen'
import type { BrowserWindow } from 'electron'
import type { ChildProcess } from 'child_process'
Expand All @@ -22,7 +22,7 @@ export interface DevStateShape {
export interface LocalSettingsDataShape {
refreshing: Promise<Editor[]> | null
availableEditors: Editor[]
preferences: DevicePreferences
preferences: AllowedState
}

export interface ConfigChildProcessShape {
Expand Down Expand Up @@ -117,7 +117,7 @@ export function makeCoreData (): CoreDataShape {
},
localSettings: {
availableEditors: [],
preferences: devicePreferenceDefaults,
preferences: {},
refreshing: null,
},
isAuthBrowserOpened: false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,11 +98,6 @@ const externalEditors = computed(() => {
return props.gql.localSettings.availableEditors?.map((x) => ({ ...x, icon: icons[x.id] })) || []
})
gql`
mutation SetPreferredEditorBinary ($value: String!) {
setPreferredEditorBinary (value: $value)
}`
gql`
fragment ChooseExternalEditor on Query {
localSettings {
Expand Down

2 comments on commit cc3be10

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on cc3be10 Nov 29, 2021

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/9.2.0/circle-10.0-release-cc3be10f73ef27dfb5221fb669e7c8b9b39e1b7a/cypress.tgz

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on cc3be10 Nov 29, 2021

Choose a reason for hiding this comment

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

Circle has built the darwin 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/9.2.0/circle-10.0-release-cc3be10f73ef27dfb5221fb669e7c8b9b39e1b7a/cypress.tgz

Please sign in to comment.