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

chore: move non-shared code from frontend-shared to app #24674

Merged
merged 12 commits into from Nov 16, 2022
1 change: 0 additions & 1 deletion packages/app/src/composables/useSpecFilter.ts
Expand Up @@ -25,7 +25,6 @@ export function useSpecFilter (savedFilter?: string) {

function setSpecFilter (specFilter: string) {
if (specStore.specFilter !== specFilter) {
specStore.setSpecFilter(specFilter)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Unused, this was not doing anything but saving the specFilter in the store for no reason.

saveSpecFilter.executeMutation({ value: JSON.stringify({ specFilter }) })
}
}
Expand Down
2 changes: 1 addition & 1 deletion packages/app/src/specs/InlineSpecList.vue
Expand Up @@ -29,7 +29,7 @@ import InlineSpecListHeader from './InlineSpecListHeader.vue'
import InlineSpecListTree from './InlineSpecListTree.vue'
import CreateSpecModal from './CreateSpecModal.vue'
import { fuzzySortSpecs, makeFuzzyFoundSpec, useCachedSpecs } from './spec-utils'
import type { FuzzyFoundSpec } from './spec-utils'
import type { FuzzyFoundSpec } from './tree/useCollapsibleTree'
import { useSpecFilter } from '../composables/useSpecFilter'

gql`
Expand Down
2 changes: 1 addition & 1 deletion packages/app/src/specs/InlineSpecListTree.cy.tsx
@@ -1,7 +1,7 @@
import type { FuzzyFoundSpec } from './spec-utils'
import { ref } from 'vue'
import { useSpecStore } from '../store'
import InlineSpecListTree from './InlineSpecListTree.vue'
import type { FuzzyFoundSpec } from './tree/useCollapsibleTree'

describe('InlineSpecListTree', () => {
let foundSpecs: FuzzyFoundSpec[]
Expand Down
9 changes: 3 additions & 6 deletions packages/app/src/specs/InlineSpecListTree.vue
Expand Up @@ -60,17 +60,14 @@
</template>

<script setup lang="ts">
import { useCollapsibleTree } from '@packages/frontend-shared/src/composables/useCollapsibleTree'
import type { UseCollapsibleTreeNode } from '@packages/frontend-shared/src/composables/useCollapsibleTree'
import { buildSpecTree } from './spec-utils'
import type { SpecTreeNode, FuzzyFoundSpec } from './spec-utils'
import { UseCollapsibleTreeNode, useCollapsibleTree, SpecTreeNode, FuzzyFoundSpec, buildSpecTree } from './tree/useCollapsibleTree'
import SpecFileItem from './SpecFileItem.vue'
import { computed, watch, onMounted } from 'vue'
import DirectoryItem from './DirectoryItem.vue'
import { RouterLink, useRouter } from 'vue-router'
import { useSpecStore } from '../store'
import { useVirtualList } from '@packages/frontend-shared/src/composables/useVirtualList'
import { useVirtualListNavigation } from '@packages/frontend-shared/src/composables/useVirtualListNavigation'
import { useVirtualList } from './tree/useVirtualList'
import { useVirtualListNavigation } from './tree/useVirtualListNavigation'
import { useStudioStore } from '../store/studio-store'

const props = defineProps<{
Expand Down
7 changes: 3 additions & 4 deletions packages/app/src/specs/SpecsList.vue
Expand Up @@ -183,12 +183,11 @@ import { gql, useSubscription } from '@urql/vue'
import { computed, ref, toRef, watch } from 'vue'
import { Specs_SpecsListFragment, SpecsList_GitInfoUpdatedDocument, SpecsListFragment } from '../generated/graphql'
import { useI18n } from '@cy/i18n'
import { buildSpecTree, fuzzySortSpecs, makeFuzzyFoundSpec, useCachedSpecs } from './spec-utils'
import type { FuzzyFoundSpec } from './spec-utils'
import { useCollapsibleTree } from '@packages/frontend-shared/src/composables/useCollapsibleTree'
import { buildSpecTree, FuzzyFoundSpec, useCollapsibleTree } from './tree/useCollapsibleTree'
import { fuzzySortSpecs, makeFuzzyFoundSpec, useCachedSpecs } from './spec-utils'
import RowDirectory from './RowDirectory.vue'
import SpecItem from './SpecItem.vue'
import { useVirtualList } from '@packages/frontend-shared/src/composables/useVirtualList'
import { useVirtualList } from './tree/useVirtualList'
Copy link
Contributor

Choose a reason for hiding this comment

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

Since this has been backported to VueUse, do we want to try using the VueUse implementation: https://vueuse.org/core/usevirtuallist/#usevirtuallist

I wonder if we have diverged or if this will just work.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Nice, we should do this. Not right here, though -- I don't want to introduce any risk or change to code in this PR where possible - this is a quick reshuffling of things.

import NoResults from '@cy/components/NoResults.vue'
import SpecPatternModal from '../components/SpecPatternModal.vue'
import { useOnline, useResizeObserver } from '@vueuse/core'
Expand Down
Expand Up @@ -58,8 +58,8 @@
import { gql, useMutation } from '@urql/vue'
import { ScaffoldGeneratorStepOne_ScaffoldIntegrationDocument } from '../../../generated/graphql'
import { computed, onMounted } from 'vue'
import { buildSpecTree } from '../../spec-utils'
import { useCollapsibleTree } from '@packages/frontend-shared/src/composables/useCollapsibleTree'
import { buildSpecTree } from '../../../specs/tree/useCollapsibleTree'
import { useCollapsibleTree } from '../../tree/useCollapsibleTree'
import StandardModalFooter from '@cy/components/StandardModalFooter.vue'
import Button from '@cy/components/Button.vue'
import { useI18n } from '@cy/i18n'
Expand Down
122 changes: 1 addition & 121 deletions packages/app/src/specs/spec-utils.ts
Expand Up @@ -2,127 +2,7 @@ import fuzzySort from 'fuzzysort'
import type { FoundSpec } from '@packages/types'
import { ComputedRef, Ref, ref, watch } from 'vue'
import _ from 'lodash'
import { getRunnerConfigFromWindow } from '../runner'

// Platform may not be available when this file is loaded (e.g. during component our component tests) so
// we defer loading it until it's used
let platform
const getPlatform = (): string => {
if (!platform) {
platform = getRunnerConfigFromWindow().platform
}

return platform
}
const getRegexSeparator = () => getPlatform() === 'win32' ? /\\/ : /\//
const getSeparator = () => getPlatform() === 'win32' ? '\\' : '/'

export type FuzzyFoundSpec<T = FoundSpec> = T & {
fuzzyIndexes: {
relative: number[]
baseName: number[]
}
}

export type SpecTreeNode<T extends FoundSpec = FoundSpec> = {
id: string
name: string
children: SpecTreeNode<T>[]
isLeaf: boolean
parent?: SpecTreeNode<T>
data?: T
highlightIndexes: number[]
}

export function buildSpecTree<T extends FoundSpec> (specs: FoundSpec[], root: SpecTreeNode<T> = { name: '', isLeaf: false, children: [], id: '', highlightIndexes: [] }): SpecTreeNode<T> {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

spec-utils ended up a dumping ground for random things - many of these functions have one very specific purpose, which is to build the spec tree (not just utils) so I moved them to a more accurately named file.

specs.forEach((spec) => buildSpecTreeRecursive(spec.relative, root, spec))
collapseEmptyChildren(root)

return root
}

export function buildSpecTreeRecursive<T extends FoundSpec> (path: string, tree: SpecTreeNode<T>, data?: T) {
const [firstFile, ...rest] = path.split(getRegexSeparator())
const id = tree.id ? [tree.id, firstFile].join(getSeparator()) : firstFile

const newNode: SpecTreeNode<T> = { name: firstFile, isLeaf: false, children: [], parent: tree, data, id, highlightIndexes: [] }

if (rest.length < 1) {
newNode.isLeaf = true
newNode.highlightIndexes = getHighlightIndexes(newNode)

tree.children.push(newNode)

return tree
}

const foundChild = tree.children.find((child) => child.name === firstFile)

if (foundChild) {
buildSpecTreeRecursive(rest.join(getSeparator()), foundChild, data)

return tree
}

newNode.highlightIndexes = getHighlightIndexes(newNode)
const newTree = buildSpecTreeRecursive(rest.join(getSeparator()), newNode, data)

tree.children.push(newTree)

return tree
}

function collapseEmptyChildren<T extends FoundSpec> (node: SpecTreeNode<T>) {
for (const child of node.children) {
collapseEmptyChildren(child)
}
if (node.isLeaf) {
return
}

// Root name of our tree is '/'. We don't want to collapse into the root node
// so we check node.parent.parent
if (node.parent && node.parent.parent && (node.parent.children.length === 1)) {
node.parent.name = [node.parent.name, node.name].join(getSeparator())
node.parent.id = [node.parent.id, node.name].join(getSeparator())
node.parent.children = node.children
node.parent.highlightIndexes = getHighlightIndexes(node.parent)
}

return
}

// Given a node, return the indexes of the characters that should be highlighted
// The indexes are matched to the `relative` and `baseName` keys of FoundSpec, and
// depending on whether the node is a leaf or not, the indexes are normalized to the position
// of the node's location in the tree.
// If a search of "src/comp" is given with indexes [0,1,2,3,4,5,6,7], the indexes will be split
// into [0,1,2] and [4,5,6,7] corresponding with a
// - src
// - components
// - index.ts
// tree (given that src/comp is not collapsed)
function getHighlightIndexes <T extends FoundSpec> (node: SpecTreeNode<T>) {
if (!(node.data as any)?.fuzzyIndexes) {
return []
}

const { relative: relativeIndexes, baseName: baseNameIndexes } = (node.data as FuzzyFoundSpec<T>).fuzzyIndexes

// When there is a full (or close to) relative match, baseName will no longer match.
// If we have indexes for baseName we show them, otherwise we pull from relative to derive
// baseName indexes
if (node.isLeaf && baseNameIndexes.length > 0) {
return baseNameIndexes
}

const maxIndex = node.id.length - 1
const minIndex = maxIndex - node.name.length + 1

const res = relativeIndexes.filter((index) => index >= minIndex && index <= maxIndex)

return res.map((idx) => idx - minIndex)
}
import { FuzzyFoundSpec, getPlatform } from './tree/useCollapsibleTree'

export function fuzzySortSpecs <T extends FuzzyFoundSpec> (specs: T[], searchValue: string) {
const normalizedSearchValue = getPlatform() === 'win32' ? searchValue.replaceAll('/', '\\') : searchValue
Expand Down