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: create from React component UI #24982

Merged
Merged
Show file tree
Hide file tree
Changes from 50 commits
Commits
Show all changes
75 commits
Select commit Hold shift + click to select a range
6c24bfa
feat: WIP server logic for create from React component
astone123 Nov 29, 2022
2948dd7
feat: add more tests; error handling
astone123 Nov 29, 2022
6468430
feat: WIP create from React UI
astone123 Nov 30, 2022
73cb71f
feat: PR feedback [run CI]
astone123 Dec 1, 2022
0dbd568
Resolve conflicts
astone123 Dec 1, 2022
0f4e836
feat: try committing snapshot cache changes [run ci]
astone123 Dec 1, 2022
d763e1f
feat: try re-generating snapshot [run ci]
astone123 Dec 1, 2022
a2626df
fix build
ryanthemanuel Dec 1, 2022
6eabeb3
regenerate cache on darwin
ryanthemanuel Dec 1, 2022
6ba1695
update caches
ryanthemanuel Dec 1, 2022
9389037
Revert "feat: try re-generating snapshot [run ci]"
astone123 Dec 1, 2022
d4e4c7d
Merge branch 'feature/create-from-react-component' into astone123/cre…
lmiller1990 Dec 2, 2022
a48491d
fix typing error
lmiller1990 Dec 2, 2022
00e7819
types
lmiller1990 Dec 2, 2022
df027ff
fix test
lmiller1990 Dec 2, 2022
b32560f
chore: try using react-docgen@6.0.0-alpha.3
lmiller1990 Dec 2, 2022
89b823a
update test
lmiller1990 Dec 2, 2022
2f3ffcb
regen linux snapshot
lmiller1990 Dec 2, 2022
a631284
update snapshots for darwin
lmiller1990 Dec 2, 2022
dbb5b3e
re-gen linux snapshot
lmiller1990 Dec 2, 2022
4ad474c
Merge branch 'astone123/create-from-react-server' of https://github.c…
lmiller1990 Dec 2, 2022
c0382fa
yarn install
lmiller1990 Dec 2, 2022
7456bb7
update snapshots
lmiller1990 Dec 2, 2022
fadb8d9
update snapshot metadata
lmiller1990 Dec 2, 2022
6d502b1
update snapshots due to babel deps changing slightly
lmiller1990 Dec 2, 2022
f60ac0a
make react docgen a dep
lmiller1990 Dec 2, 2022
bd398ed
update tests
lmiller1990 Dec 2, 2022
9510a85
revert
lmiller1990 Dec 2, 2022
77a4942
snapshots again??
lmiller1990 Dec 2, 2022
f9e8af7
revert
lmiller1990 Dec 2, 2022
68d5c87
update
lmiller1990 Dec 2, 2022
281da0a
update
lmiller1990 Dec 2, 2022
e4410b1
try change snapshot
lmiller1990 Dec 2, 2022
f12efca
change snap
lmiller1990 Dec 2, 2022
e857b8f
update snap
lmiller1990 Dec 2, 2022
c070f96
feat: remove unnecessary ts-ignore
astone123 Dec 2, 2022
cb381e9
Merge branch 'astone123/create-from-react-server' of github.com:cypre…
astone123 Dec 2, 2022
cd65233
feat: add more test cases
astone123 Dec 2, 2022
205e185
Merge branch 'astone123/create-from-react-server' of github.com:cypre…
astone123 Dec 2, 2022
9449d66
feat: create CodegenActions; other minor refactors
astone123 Dec 5, 2022
2b03c33
Merge branch 'astone123/create-from-react-server' of github.com:cypre…
astone123 Dec 5, 2022
f979f48
feat: continue UI work
astone123 Dec 5, 2022
da5bfda
Merge branch 'feature/create-from-react-component' of github.com:cypr…
astone123 Dec 5, 2022
16df37a
feat: ignore config and Cypress-related files
astone123 Dec 6, 2022
19fac18
feat: PR feedback
astone123 Dec 6, 2022
ab6f8c0
Merge branch 'feature/create-from-react-component' of github.com:cypr…
astone123 Dec 7, 2022
c4749b9
update Vue component link
astone123 Dec 7, 2022
544a651
merge in default export work
astone123 Dec 7, 2022
dbea144
consolidate graphql queries
astone123 Dec 7, 2022
50a9c15
other misc feedback
astone123 Dec 7, 2022
367eaa7
use network-only policy to fetch files; include cypress/ dir for code…
astone123 Dec 7, 2022
5debd39
add basic e2e test
astone123 Dec 7, 2022
b469af7
fix app integration tests
astone123 Dec 7, 2022
18d2545
refactor and fix app component and webpack dev server tests
astone123 Dec 8, 2022
1d745e9
add error state; fix unit tests [skip ci]
astone123 Dec 8, 2022
84fb446
simplify generator show logic [skip ci]
astone123 Dec 8, 2022
27ae647
more testing
astone123 Dec 8, 2022
f10b034
fix types
astone123 Dec 8, 2022
2d30c0f
style updates [skip ci]
astone123 Dec 8, 2022
101f964
fix error state [skip ci]
astone123 Dec 9, 2022
595fe0d
fix list padding [skip ci]
astone123 Dec 9, 2022
156c800
use slots (#25079)
lmiller1990 Dec 9, 2022
d504825
add more tests; fix unit tests
astone123 Dec 9, 2022
a44ed45
fix types
astone123 Dec 9, 2022
43d73f0
fix test describe
astone123 Dec 9, 2022
165fbfe
add percy snapshots for new list
astone123 Dec 9, 2022
f1c7a07
update trouble rendering banner link [skip ci]
astone123 Dec 9, 2022
7bf5c7e
use collapsible component
astone123 Dec 9, 2022
766419d
use button for component list items
astone123 Dec 9, 2022
b55c4fa
fix tests
astone123 Dec 9, 2022
48081eb
Merge branch 'feature/create-from-react-component' of github.com:cypr…
astone123 Dec 9, 2022
49c7ed7
build binaries
astone123 Dec 9, 2022
a582866
revert changes to circle config
astone123 Dec 12, 2022
1670c94
remove eslintignore and extra loading div [skip ci] because we know i…
astone123 Dec 13, 2022
d243608
revert changes to framework glob patterns [skip ci]
astone123 Dec 13, 2022
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
4 changes: 4 additions & 0 deletions packages/app/src/paths.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,7 @@ export function getPathForPlatform (posixPath?: string) {

return posixPath
}

export function posixify (path: string): string {
return path.replace(/\\/g, '/')
}
4 changes: 4 additions & 0 deletions packages/app/src/specs/CreateSpecModal.cy.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ describe('<CreateSpecModal />', () => {
__typename: 'CodeGenGlobs',
component: '**.vue',
},
codeGenFramework: 'vue',
currentTestingType: 'component',
configFile: 'cypress.config.js',
configFileAbsolutePath: '/path/to/cypress.config.js',
Expand Down Expand Up @@ -115,6 +116,7 @@ describe('Modal Text Input', () => {
__typename: 'CodeGenGlobs',
component: '**.vue',
},
codeGenFramework: 'vue',
currentTestingType: 'component',
configFile: 'cypress.config.js',
configFileAbsolutePath: '/path/to/cypress.config.js',
Expand Down Expand Up @@ -163,6 +165,7 @@ describe('Modal Text Input', () => {
__typename: 'CodeGenGlobs',
component: '**.vue',
},
codeGenFramework: 'vue',
currentTestingType: 'component',
configFile: 'cypress.config.js',
configFileAbsolutePath: '/path/to/cypress.config.js',
Expand Down Expand Up @@ -215,6 +218,7 @@ describe('playground', () => {
__typename: 'CodeGenGlobs',
component: '**.vue',
},
codeGenFramework: 'vue',
currentTestingType: 'component',
configFile: 'cypress.config.js',
configFileAbsolutePath: '/path/to/cypress.config.js',
Expand Down
13 changes: 12 additions & 1 deletion packages/app/src/specs/CreateSpecModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
</StandardModal>
</template>

<script lang ="ts" setup>
<script lang="ts" setup>
import { generators, getFilteredGeneratorList } from './generators'
import type { GeneratorId } from './generators'
import { DialogOverlay } from '@headlessui/vue'
Expand Down Expand Up @@ -71,6 +71,17 @@ const emits = defineEmits<{
// to have a different key for the generator
const iteration = ref(0)

gql`
fragment ComponentGeneratorStepOne_codeGenGlob on CurrentProject {
id
codeGenGlobs {
id
component
}
codeGenFramework
}
`

gql`
fragment CreateSpecModal on Query {
...CreateSpecCards
Expand Down
5 changes: 3 additions & 2 deletions packages/app/src/specs/InlineSpecListTree.vue
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
'before:border-r-indigo-300': isCurrentSpec(row.data),
'before:focus:border-r-indigo-300 before:focus-visible:border-r-transparent before:hover:border-r-indigo-300': !isCurrentSpec(row.data)
}"
:to="{ path: '/specs/runner', query: { file: row.data.data?.relative?.replace(/\\/g, '/') } }"
:to="{ path: '/specs/runner', query: { file: posixify(row.data.data?.relative) } }"
@focus="resetFocusIfNecessary(row, row.index)"
@click.capture.prevent="submit(row.data, row.index)"
@keydown.enter.space.prevent.stop="submit(row.data, row.index)"
Expand Down Expand Up @@ -81,6 +81,7 @@ import { useVirtualListNavigation } from './tree/useVirtualListNavigation'
import { useStudioStore } from '../store/studio-store'
import InlineRunAllSpecs from './InlineRunAllSpecs.vue'
import { useRunAllSpecsStore } from '../store/run-all-specs-store'
import { posixify } from '../paths'

const props = defineProps<{
specs: FuzzyFoundSpec[]
Expand Down Expand Up @@ -137,7 +138,7 @@ const submit = (row: UseCollapsibleTreeNode<SpecTreeNode<FuzzyFoundSpec>>, idx:
return
}

router.push({ path: '/specs/runner', query: { file: row.data.relative.replace(/\\/g, '/') } })
router.push({ path: '/specs/runner', query: { file: posixify(row.data.relative) } })
} else {
row.toggle()
}
Expand Down
3 changes: 2 additions & 1 deletion packages/app/src/specs/SpecsList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@
:is-leaf="row.data.isLeaf"
:is-project-connected="projectConnectionStatus === 'CONNECTED'"
:grid-columns="row.data.isLeaf ? tableGridColumns : 'grid-cols-[1fr]'"
:route="{ path: '/specs/runner', query: { file: row.data.data?.relative?.replace(/\\/g, '/') } }"
:route="{ path: '/specs/runner', query: { file: posixify(row.data.data?.relative || '') } }"
@toggleRow="row.data.toggle"
>
<template #file>
Expand Down Expand Up @@ -216,6 +216,7 @@ import { useRequestAccess } from '../composables/useRequestAccess'
import { useLoginConnectStore } from '@packages/frontend-shared/src/store/login-connect-store'
import SpecsRunAllSpecs from './SpecsRunAllSpecs.vue'
import { useRunAllSpecsStore } from '../store/run-all-specs-store'
import { posixify } from '../paths'

const { openLoginConnectModal } = useLoginConnectStore()

Expand Down
3 changes: 2 additions & 1 deletion packages/app/src/specs/generators/EmptyGenerator.vue
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@
:to="{
name: 'SpecRunner',
query: {
file: result.file.relative?.replace(/\\/g, '/')
file: posixify(result.file.relative)
},
params: props.type === 'component' || props.type === 'componentEmpty'
? {
Expand Down Expand Up @@ -140,6 +140,7 @@ import StandardModalFooter from '@packages/frontend-shared/src/components/Standa
import GeneratorSuccess from './GeneratorSuccess.vue'
import TestResultsIcon from '~icons/cy/test-results_x24.svg'
import PlusButtonIcon from '~icons/cy/add-large_x16.svg'
import { posixify } from '../../paths'

const props = defineProps<{
title: string
Expand Down
172 changes: 172 additions & 0 deletions packages/app/src/specs/generators/ExpandableFileChooser.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
<!--
/**==============================================
* * ExpandableFileChooser.vue
* Filter a list of files by a mix of glob pattern
* and a search string that includes a file's relative
* path.
*
* When clicked, the files will expand to display the
* #expanded-content slot.
*
* Features to note: debouncing + loading + row expanding
* ==============================================
* * Debouncing
*
* ? To prevent calling update too frequently we debounce
* ? both the "No Results" UI and the update event
*
* ============================================**/
-->

<template>
<CreateSpecModalBody
variant="bare"
class="bg-white flex flex-col px-24px
relative"
>
<FileMatch
ref="fileMatchRef"
v-model:pattern="filePathSearch"
v-model:extensionPattern="localExtensionPattern"
class="bg-white pt-24px pb-12px top-0px z-10 sticky"
:matches="matches"
>
<template
v-if="loading"
#matches
>
<i-cy-loading_x16 class="h-24px mr-10px animate-spin w-24px" />
</template>
</FileMatch>

<div
v-show="loading"
astone123 marked this conversation as resolved.
Show resolved Hide resolved
data-testid="loading"
>
<!-- TODO(ryan) UNIFY-865: Get mocks for a loading state here -->
Loading
</div>
<ExpandableFileList
v-show="!loading"
:style="{ paddingTop: `${fileMatchHeight + 36}px` }"
class="right-24px left-24px absolute"
:files="filteredFiles"
:search="filePathSearch"
>
<template #expanded-content="{file}">
<ReactComponentList
astone123 marked this conversation as resolved.
Show resolved Hide resolved
:file="file"
@selectItem="selectItem"
/>
</template>
<template #no-results>
<NoResults
empty-search
:search-term="noResults.search"
:message="noResults.message"
@clear="noResults.clear"
/>
</template>
</ExpandableFileList>
</CreateSpecModalBody>
</template>

<script setup lang="ts">
import { computed, ref } from 'vue'
import { debouncedWatch, useDebounce, useElementSize } from '@vueuse/core'
import { useI18n } from '@cy/i18n'

import NoResults from '@cy/components/NoResults.vue'
import CreateSpecModalBody from './CreateSpecModalBody.vue'
import ExpandableFileList from './ExpandableFileList.vue'
import FileMatch from '../../components/FileMatch.vue'
import ReactComponentList from './component/ReactComponentList.vue'
import { gql } from '@urql/core'
import type { FileParts } from '@packages/data-context/src/gen/graphcache-config.gen'
import type { FileListItemFragment } from '../../generated/graphql'

const props = withDefaults(defineProps<{
files: FileParts[]
extensionPattern: string
loading?: boolean
}>(), {

loading: false,
})

const { t } = useI18n()

gql`
fragment FileChooser on FileParts {
relative
id
...FileListItem
}
`

const emits = defineEmits<{
(eventName: 'selectItem', value: {file: FileListItemFragment, item: any})
(eventName: 'update:extensionPattern', value: string)
}>()

// eslint-disable-next-line
const initialExtensionPattern = props.extensionPattern
const localExtensionPattern = ref(props.extensionPattern)
const filePathSearch = ref('')

const selectItem = ({ file, item }) => {
emits('selectItem', { file, item })
}

///*------- Styling -------*/

// For the FileList to be searchable without jumping to the top of the
// FileMatcher's top when focused, we need to use some manual layout.
// If we concede on position: sticky for the FileMatcher or on making the
// FileList accessible, we could position the FileList relatively.
const fileMatchRef = ref(null)
const { height: fileMatchHeight } = useElementSize(fileMatchRef)

///*------- Debounce -------*/

const debounce = 200
const debouncedExtensionPattern = useDebounce(localExtensionPattern, debounce)

debouncedWatch(localExtensionPattern, (value) => {
emits('update:extensionPattern', value)
}, { debounce })

///*------- Searching files -------*/

const filteredFiles = computed(() => {
return props.files?.filter((file) => {
return file.relative.toLowerCase().includes(filePathSearch.value.toLowerCase())
})
})

///*------- Matches Indicator -------*/

const matches = computed(() => {
return {
total: props.files.length,
found: filteredFiles.value.length,
}
})

///*------- No Results Options -------*/

const noResults = computed(() => {
return {
search: filePathSearch.value || debouncedExtensionPattern.value,
message: filePathSearch.value ? t('noResults.defaultMessage') : t('components.fileSearch.noMatchesForExtension'),
clear: () => {
if (filePathSearch.value) {
filePathSearch.value = ''
} else {
localExtensionPattern.value = initialExtensionPattern
}
},
}
})

</script>
97 changes: 97 additions & 0 deletions packages/app/src/specs/generators/ExpandableFileList.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
<template>
<div class="h-full">
<div
v-if="files.length"
class="h-full relative"
tabindex="0"
>
<ul class="h-full">
astone123 marked this conversation as resolved.
Show resolved Hide resolved
<!-- TODO: UNIFY-864 - up arrow and down arrow navigation -->
<li
v-for="file in files"
:key="file.id"
>
<div
class="cursor-pointer flex border-b-1 border-b-gray-50 leading-normal text-16px gap-8px
group items-center last last:py-0 last:items-start children:h-40px children:py-8px"
data-cy="file-list-row"
@click="() => toggleExpandRow(file.id)"
>
<i-cy-chevron-down-small_x16
class="
mr-8px text-sm icon-dark-gray-300
group-hocus:(icon-dark-gray-700)
"
:class="{'transform rotate-270': !isRowExpanded(file.id)}"
/>
<i-cy-document-blank_x16 class="min-w-16px min-h-16px icon-light-gray-50 icon-dark-gray-300" />
<div class="h-full inline-flex whitespace-nowrap items-center overflow-hidden">
<span
class="font-medium text-indigo-500
group-hocus:text-indigo-500"
>{{
name(file) }}</span>
<span class="font-light text-gray-400">{{ file.fileExtension }}</span>
<span class="font-light ml-20px opacity-0 text-gray-600 duration-200 truncate group-hocus:opacity-60">{{ file.relative }}</span>
</div>
</div>
<div v-if="isRowExpanded(file.id)">
<slot
:file="file"
name="expanded-content"
/>
</div>
</li>
</ul>
</div>
<div
v-else
class="flex h-full items-center justify-center"
>
<slot name="no-results" />
</div>
</div>
</template>

<script setup lang="ts">
import { gql } from '@urql/vue'
import { ref } from 'vue'
import type { FileListItemFragment } from '../../generated/graphql'

gql`
fragment FileListItem on FileParts {
id
relative
fileName
fileExtension
baseName
}
`

defineProps<{
files: FileListItemFragment[]
}>()

defineEmits<{
(eventName: 'selectItem', value: {file: FileListItemFragment, item: any})
}>()

const expandedRowId = ref<string>('')

function isRowExpanded (id: string) {
return (expandedRowId.value === id)
}

function toggleExpandRow (id: string) {
if (expandedRowId.value === id) {
expandedRowId.value = ''
} else {
expandedRowId.value = id
}
}

// [...all].vue returns as [ when using the normal fileName
const name = (file) => {
return file.baseName.replace(file.fileExtension, '')
}
</script>
Loading