Skip to content

Commit b085679

Browse files
committed
Merge branch 'unified-desktop-gui' into tgriesser/unify/use-data-context
* unified-desktop-gui: chore: add percy to app and launchpad package (#18781) chore: update test refactor: move settings in app (#18729) feat: setup launchpad lifecycle (#18734)
2 parents 9419aa0 + e2735de commit b085679

File tree

100 files changed

+1575
-1070
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

100 files changed

+1575
-1070
lines changed

circle.yml

+5-1
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,10 @@ commands:
413413
CYPRESS_INTERNAL_FORCE_BROWSER_RELAUNCH='true' \
414414
CYPRESS_KONFIG_ENV=production \
415415
CYPRESS_RECORD_KEY=$TEST_LAUNCHPAD_RECORD_KEY \
416+
PERCY_PARALLEL_NONCE=$CIRCLE_WORKFLOW_ID \
417+
PERCY_ENABLE=${PERCY_TOKEN:-0} \
418+
PERCY_PARALLEL_TOTAL=-1 \
419+
yarn percy exec --parallel -- -- \
416420
yarn workspace @packages/<<parameters.package>> cypress:run:<<parameters.type>> --browser <<parameters.browser>> --record --parallel --group <<parameters.package>>-<<parameters.type>>
417421
- store_test_results:
418422
path: /tmp/cypress
@@ -1024,7 +1028,7 @@ jobs:
10241028
desktop-gui-component-tests,
10251029
cli-visual-tests,
10261030
runner-integration-tests-chrome,
1027-
runner-ct-integration-tests-chrome
1031+
runner-ct-integration-tests-chrome,
10281032
reporter-integration-tests,
10291033
- run: yarn percy build:finalize
10301034

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
describe('Settings', { viewportWidth: 1200 }, () => {
2+
beforeEach(() => {
3+
cy.setupE2E('component-tests')
4+
5+
cy.initializeApp()
6+
})
7+
8+
it('displays the settings for the current project', () => {
9+
cy.visitApp()
10+
cy.get('[href="#/settings"]').click()
11+
cy.findByText('Project Settings').click()
12+
13+
cy.get('[data-cy="settings-projectId"]')
14+
15+
.findByText('abc123')
16+
.should('be.visible')
17+
18+
cy.get('[data-cy="settings-config"]')
19+
.scrollIntoView()
20+
.should('be.visible')
21+
.contains('animationDistanceThreshold')
22+
})
23+
24+
it('displays the settings for the current device', () => {
25+
cy.visitApp()
26+
cy.get('[href="#/settings"]').click()
27+
cy.findByText('Device Settings').click()
28+
29+
cy.findByText('External Editor').should('be.visible')
30+
cy.findByText('Testing Preferences').should('be.visible')
31+
cy.findByText('Proxy Settings').should('be.visible')
32+
})
33+
})

packages/app/package.json

+2
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
"@iconify/vue": "3.0.0-beta.1",
2727
"@intlify/vite-plugin-vue-i18n": "2.4.0",
2828
"@packages/frontend-shared": "0.0.0-development",
29+
"@percy/cypress": "^3.1.0",
2930
"@testing-library/cypress": "8.0.0",
3031
"@types/faker": "5.5.8",
3132
"@urql/core": "2.3.1",
@@ -75,6 +76,7 @@
7576
"include": [
7677
"@headlessui/vue",
7778
"@iconify/iconify",
79+
"@percy/cypress",
7880
"@testing-library/cypress/add-commands",
7981
"@urql/exchange-execute",
8082
"@urql/vue",

packages/app/src/pages/Runs.vue

+2-2
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,12 @@
1414
import { gql, useQuery } from '@urql/vue'
1515
import { RunsDocument } from '../generated/graphql'
1616
import RunsSkeleton from '../runs/RunsSkeleton.vue'
17-
import RunsPage from '../runs/RunsPage.vue'
17+
import RunsPage from '../runs/RunsContainer.vue'
1818
import TransitionQuickFade from '@cy/components/transitions/TransitionQuickFade.vue'
1919
2020
gql`
2121
query Runs {
22-
...RunsPage
22+
...RunsContainer
2323
}`
2424
2525
const query = useQuery({ query: RunsDocument })

packages/app/src/pages/Settings.vue

+33-3
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,39 @@
11
<template>
2-
<div>
3-
<h2>Settings Page</h2>
4-
</div>
2+
<Button @click="reconfigure">
3+
Reconfigure
4+
</Button>
5+
<SettingsContainer
6+
v-if="query.data.value"
7+
:gql="query.data.value"
8+
/>
59
</template>
610

11+
<script lang="ts" setup>
12+
import { gql, useQuery, useMutation } from '@urql/vue'
13+
import Button from '@cy/components/Button.vue'
14+
import SettingsContainer from '../settings/SettingsContainer.vue'
15+
import { Settings_ReconfigureProjectDocument, SettingsDocument } from '../generated/graphql'
16+
17+
gql`
18+
query Settings {
19+
...SettingsContainer
20+
}`
21+
22+
gql`
23+
mutation Settings_ReconfigureProject {
24+
reconfigureProject
25+
}
26+
`
27+
28+
const query = useQuery({ query: SettingsDocument })
29+
30+
const openElectron = useMutation(Settings_ReconfigureProjectDocument)
31+
32+
function reconfigure () {
33+
openElectron.executeMutation({})
34+
}
35+
</script>
36+
737
<route>
838
{
939
name: "Settings Page",

packages/app/src/runs/RunsPage.spec.tsx renamed to packages/app/src/runs/RunsContainer.spec.tsx

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
import RunsPage from './RunsPage.vue'
2-
import { RunsPageFragmentDoc } from '../generated/graphql-test'
1+
import RunsContainer from './RunsContainer.vue'
2+
import { RunsContainerFragmentDoc } from '../generated/graphql-test'
33

4-
describe('<RunsPage />', { keystrokeDelay: 0 }, () => {
4+
describe('<RunsContainer />', { keystrokeDelay: 0 }, () => {
55
const cloudViewer = {
66
__typename: 'CloudUser',
77
id: '1',
@@ -10,12 +10,12 @@ describe('<RunsPage />', { keystrokeDelay: 0 }, () => {
1010
} as const
1111

1212
it('playground', () => {
13-
cy.mountFragment(RunsPageFragmentDoc, {
13+
cy.mountFragment(RunsContainerFragmentDoc, {
1414
onResult: (result) => {
1515
result.cloudViewer = cloudViewer
1616
},
1717
render (gqlVal) {
18-
return <RunsPage gql={gqlVal} />
18+
return <RunsContainer gql={gqlVal} />
1919
},
2020
})
2121
})

packages/app/src/runs/RunsPage.vue renamed to packages/app/src/runs/RunsContainer.vue

+6-6
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,13 @@
2222
<script lang="ts" setup>
2323
import { computed } from 'vue'
2424
import { gql } from '@urql/vue'
25-
import RunCard from '../runs/RunCard.vue'
26-
import RunsConnect from '../runs/RunsConnect.vue'
27-
import RunsEmpty from '../runs/RunsEmpty.vue'
28-
import type { RunsPageFragment } from '../generated/graphql'
25+
import RunCard from './RunCard.vue'
26+
import RunsConnect from './RunsConnect.vue'
27+
import RunsEmpty from './RunsEmpty.vue'
28+
import type { RunsContainerFragment } from '../generated/graphql'
2929
3030
gql`
31-
fragment RunsPage on Query {
31+
fragment RunsContainer on Query {
3232
app {
3333
activeProject {
3434
id
@@ -51,7 +51,7 @@ fragment RunsPage on Query {
5151
}`
5252
5353
const props = defineProps<{
54-
gql: RunsPageFragment
54+
gql: RunsContainerFragment
5555
}>()
5656
5757
const activeProject = computed(() => props.gql.app?.activeProject)

packages/app/src/runs/RunsEmpty.vue

+14-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
</p>
4040
<TerminalPrompt
4141
class="-ml-16px"
42-
command="cypress run --record --key <record-key>"
42+
:command="recordCommand"
4343
:project-name="projectName"
4444
/>
4545
</li>
@@ -62,6 +62,11 @@ fragment RunsEmpty on Project{
6262
title
6363
projectId
6464
configFilePath
65+
cloudProject {
66+
recordKeys {
67+
...RecordKey
68+
}
69+
}
6570
}
6671
`
6772
@@ -77,6 +82,14 @@ const projectIdCode = computed(() => {
7782
7883
const projectName = computed(() => props.gql.title)
7984
const configFilePath = computed(() => props.gql.configFilePath)
85+
const firstRecordKey = computed(() => {
86+
const allRecordKeys = props.gql.cloudProject?.recordKeys
87+
88+
return allRecordKeys?.[0] ?? '<record-key>'
89+
})
90+
const recordCommand = computed(() => {
91+
return `cypress run --record --key ${firstRecordKey.value}`
92+
})
8093
</script>
8194

8295
<style scoped lang="scss">
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import SettingsCard from './SettingsCard.vue'
2+
import IconLaptop from '~icons/mdi/laptop'
3+
4+
describe('<SettingsCard />', () => {
5+
const title = 'My Device Settings'
6+
const description = 'The configuration I\'m passing in.'
7+
const headerSelector = '[data-cy="collapsible-header"]'
8+
const collapsibleSelector = '[data-cy="collapsible"]'
9+
10+
it('renders', () => {
11+
const contentSelector = '[data-testid=content]'
12+
13+
cy.mount(() => (
14+
<div class="p-24px">
15+
<SettingsCard title={title} description={description} icon={IconLaptop} maxHeight="800px">
16+
<div data-testid="content">
17+
<p>The body of the content</p>
18+
</div>
19+
</SettingsCard>
20+
</div>
21+
))
22+
23+
cy.get(contentSelector).should('not.exist')
24+
cy.findByText(title).click()
25+
cy.get(contentSelector).should('be.visible')
26+
cy.findByText(title).click()
27+
.get(contentSelector).should('not.exist')
28+
29+
// expected aria and keyboard behavior with space and enter keys:
30+
cy.get(collapsibleSelector).should('be.focused')
31+
.get('body').type(' ')
32+
.get(contentSelector).should('be.visible')
33+
.get(headerSelector).should('have.attr', 'aria-expanded', 'true')
34+
.get('body').type(' ')
35+
.get(contentSelector).should('not.exist')
36+
.get(headerSelector).should('have.attr', 'aria-expanded', 'false')
37+
.get('body').type('{enter}')
38+
.get(contentSelector).should('be.visible')
39+
.get('body').type('{enter}')
40+
.get(contentSelector).should('not.exist')
41+
})
42+
43+
it('displays a nice focus state', () => {
44+
const title2 = 'Project Settings again'
45+
const description2 = 'Lorem ipsum dolor sit amet'
46+
47+
cy.mount(() => (
48+
<div class="p-24px">
49+
<SettingsCard title={title} description={description} icon={IconLaptop} maxHeight="800px">
50+
<div data-testid="content">
51+
<p>The body of the content</p>
52+
</div>
53+
</SettingsCard>
54+
<SettingsCard title={title2} description={description2} icon={IconLaptop} maxHeight="800px">
55+
<div data-testid="content">
56+
<p>Second content</p>
57+
</div>
58+
</SettingsCard>
59+
</div>
60+
))
61+
62+
cy.contains(collapsibleSelector, title).focus().type(' ')
63+
})
64+
})
+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
<template>
2+
<Collapsible
3+
class="block w-full mb-4 overflow-hidden border border-gray-100 rounded
4+
bg-light-50 hocus-default"
5+
:max-height="maxHeight"
6+
lazy
7+
>
8+
<template #target="{ open }">
9+
<ListRowHeader
10+
:class="{ 'border-b border-b-gray-100 rounded-b-none': open, 'bg-gray-50': true }"
11+
big-header
12+
>
13+
<template #icon>
14+
<component
15+
:is="icon"
16+
class="icon-dark-indigo-400 w-24px h-24px"
17+
/>
18+
</template>
19+
<template #header>
20+
{{ title }}
21+
</template>
22+
<template #description>
23+
{{ description }}
24+
</template>
25+
<template #right>
26+
<i-cy-chevron-down
27+
:class="{ 'rotate-180': open }"
28+
class="transform max-w-16px icon-dark-gray-400"
29+
/>
30+
</template>
31+
</ListRowHeader>
32+
</template>
33+
<div class="px-24px divide-y divide-gray-200 children:py-24px">
34+
<slot />
35+
</div>
36+
</Collapsible>
37+
</template>
38+
39+
<script lang="ts" setup>
40+
import type { FunctionalComponent, SVGAttributes } from 'vue'
41+
import Collapsible from '@cy/components/Collapsible.vue'
42+
import ListRowHeader from '@cy/components/ListRowHeader.vue'
43+
44+
defineProps<{
45+
title: string,
46+
description: string,
47+
icon: FunctionalComponent<SVGAttributes, {}>
48+
maxHeight: string
49+
}>()
50+
51+
</script>
52+
53+
<style lang="scss" scoped>
54+
.settings-card-header {
55+
grid-template-columns: auto auto 1fr auto;
56+
}
57+
</style>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { SettingsContainerFragmentDoc } from '../generated/graphql-test'
2+
import { defaultMessages } from '@cy/i18n'
3+
import SettingsContainer from './SettingsContainer.vue'
4+
5+
describe('<SettingsContainer />', () => {
6+
it('renders', () => {
7+
cy.viewport(900, 800)
8+
cy.mountFragment(SettingsContainerFragmentDoc, { render: (gql) => <SettingsContainer gql={gql} /> })
9+
10+
cy.contains('Project Settings').click()
11+
12+
cy.findByText(defaultMessages.settingsPage.projectId.title).should('be.visible')
13+
cy.findByText(defaultMessages.settingsPage.config.title).should('be.visible').click()
14+
})
15+
})

0 commit comments

Comments
 (0)