From 460c10b2e9545b43b2bded1c730bf4b5af5e0f28 Mon Sep 17 00:00:00 2001 From: Charles Wahome Date: Fri, 3 Nov 2023 12:43:07 +0300 Subject: [PATCH] Fix: show paths supported by a version (#2862) --- .../validation-context/ValidationProvider.tsx | 12 +++++------ src/app/utils/resources/resources-filter.ts | 21 +++++++++++++++---- .../auto-complete/suffix/SuffixRenderer.tsx | 2 +- .../suffix/documentation.spec.ts | 2 +- .../collection/postman.util.spec.ts | 2 +- .../resource-explorer.utils.spec.ts | 16 +++++++------- src/modules/suggestions/suggestions.ts | 2 +- src/types/resources.ts | 2 +- 8 files changed, 36 insertions(+), 23 deletions(-) diff --git a/src/app/services/context/validation-context/ValidationProvider.tsx b/src/app/services/context/validation-context/ValidationProvider.tsx index 935dc8fcb..60451d4df 100644 --- a/src/app/services/context/validation-context/ValidationProvider.tsx +++ b/src/app/services/context/validation-context/ValidationProvider.tsx @@ -15,27 +15,27 @@ interface ValidationProviderProps { export const ValidationProvider = ({ children }: ValidationProviderProps) => { const { resources } = useAppSelector((state) => state); - const base = getResourcesSupportedByVersion(resources.data.children, GRAPH_API_VERSIONS[0]); + const base = getResourcesSupportedByVersion(resources.data.children!, GRAPH_API_VERSIONS[0]); const [isValid, setIsValid] = useState(false); const [query, setQuery] = useState(''); const [validationError, setValidationError] = useState(''); const [versionedResources, setVersionedResources] = - useState(resources.data.children.length > 0 ? base : []); + useState(resources.data.children!.length > 0 ? base : []); const [version, setVersion] = useState(GRAPH_API_VERSIONS[0]); const { queryVersion } = parseSampleUrl(query); useEffect(() => { - if (resources.data.children.length > 0) { - setVersionedResources(getResourcesSupportedByVersion(resources.data.children, GRAPH_API_VERSIONS[0])); + if (resources.data.children!.length > 0) { + setVersionedResources(getResourcesSupportedByVersion(resources.data.children!, GRAPH_API_VERSIONS[0])); } }, [resources]) useEffect(() => { - if (version !== queryVersion && GRAPH_API_VERSIONS.includes(queryVersion) && resources.data.children.length > 0) { - setVersionedResources(getResourcesSupportedByVersion(resources.data.children, queryVersion)); + if (version !== queryVersion && GRAPH_API_VERSIONS.includes(queryVersion) && resources.data.children!.length > 0) { + setVersionedResources(getResourcesSupportedByVersion(resources.data.children!, queryVersion)); setVersion(queryVersion); } }, [query]); diff --git a/src/app/utils/resources/resources-filter.ts b/src/app/utils/resources/resources-filter.ts index 947595230..e0080d4f3 100644 --- a/src/app/utils/resources/resources-filter.ts +++ b/src/app/utils/resources/resources-filter.ts @@ -22,10 +22,23 @@ function getResourcesSupportedByVersion( } function versionExists(resource: IResource, version: string): boolean { - return resource && - resource.labels && - resource.labels.length > 0 && - resource.labels.some((k) => k.name === version); + if (!resource) { + return false; + } + + const hasLabels = resource.labels && resource.labels.length > 0; + const hasChildren = resource.children && resource.children.length > 0; + + if (!hasLabels && !hasChildren) { + return false; + } + + if (!hasLabels && hasChildren) { + const childLabels = resource.children?.map((child) => child.labels); + return childLabels?.some((child) => child?.some((label) => label.name === version)) || false; + } + + return resource.labels.some((k) => k.name === version); } function searchResources(haystack: IResource[], needle: string): IResource[] { diff --git a/src/app/views/query-runner/query-input/auto-complete/suffix/SuffixRenderer.tsx b/src/app/views/query-runner/query-input/auto-complete/suffix/SuffixRenderer.tsx index 1fcb4fd5b..82424db42 100644 --- a/src/app/views/query-runner/query-input/auto-complete/suffix/SuffixRenderer.tsx +++ b/src/app/views/query-runner/query-input/auto-complete/suffix/SuffixRenderer.tsx @@ -26,7 +26,7 @@ const SuffixRenderer = () => { const resourceDocumentationUrl = new DocumentationService({ sampleQuery, - source: resources.data.children + source: resources.data.children! }).getDocumentationLink(); const sampleDocumentationUrl = new DocumentationService({ diff --git a/src/app/views/query-runner/query-input/auto-complete/suffix/documentation.spec.ts b/src/app/views/query-runner/query-input/auto-complete/suffix/documentation.spec.ts index a1ae43d27..50b7ac8bf 100644 --- a/src/app/views/query-runner/query-input/auto-complete/suffix/documentation.spec.ts +++ b/src/app/views/query-runner/query-input/auto-complete/suffix/documentation.spec.ts @@ -20,7 +20,7 @@ describe('Tests suffix utilities', () => { query.sampleUrl = `https://graph.microsoft.com/v1.0/me/messages/${id}`; const docService = new DocumentationService({ sampleQuery: query, - source: resource.children + source: resource.children! }) const documentationUrl = docService.getDocumentationLink(); expect(documentationUrl).toBeDefined(); diff --git a/src/app/views/sidebar/resource-explorer/collection/postman.util.spec.ts b/src/app/views/sidebar/resource-explorer/collection/postman.util.spec.ts index 96b7e0212..effef9545 100644 --- a/src/app/views/sidebar/resource-explorer/collection/postman.util.spec.ts +++ b/src/app/views/sidebar/resource-explorer/collection/postman.util.spec.ts @@ -23,7 +23,7 @@ describe('Postman collection should', () => { function setupCollection() { const version = 'v1.0'; - const filtered = createResourcesList(resource.children, version)[0]; + const filtered = createResourcesList(resource.children!, version)[0]; const item: any = filtered.links[0]; const paths = getResourcePaths(item, version); const collection = generatePostmanCollection(paths); diff --git a/src/app/views/sidebar/resource-explorer/resource-explorer.utils.spec.ts b/src/app/views/sidebar/resource-explorer/resource-explorer.utils.spec.ts index 0a2d444f4..b353969af 100644 --- a/src/app/views/sidebar/resource-explorer/resource-explorer.utils.spec.ts +++ b/src/app/views/sidebar/resource-explorer/resource-explorer.utils.spec.ts @@ -15,12 +15,12 @@ describe('Resource payload should', () => { }); it('return children with version v1.0', async () => { - const resources = getResourcesSupportedByVersion(resource.children, 'v1.0'); + const resources = getResourcesSupportedByVersion(resource.children!, 'v1.0'); expect(resources.length).toBeGreaterThan(0); }); it('return links with version v1.0', async () => { - const filtered = createResourcesList(resource.children, 'v1.0')[0]; + const filtered = createResourcesList(resource.children!, 'v1.0')[0]; expect(filtered.links.length).toBeGreaterThan(0); }); @@ -31,7 +31,7 @@ describe('Resource payload should', () => { const currentTree = getCurrentTree({ paths, level, - resourceItems: resource.children, + resourceItems: resource.children!, version }); expect(currentTree).not.toBeNull(); @@ -39,7 +39,7 @@ describe('Resource payload should', () => { it('return available methods', async () => { const version = 'v1.0'; - const filtered = createResourcesList(resource.children, version)[0]; + const filtered = createResourcesList(resource.children!, version)[0]; const resourceLink = filtered.links[0]; const availableMethods = getAvailableMethods(resourceLink.labels, version); expect(availableMethods).not.toBeNull(); @@ -58,7 +58,7 @@ describe('Resource payload should', () => { const currentTree = getCurrentTree({ paths, level, - resourceItems: resource.children, + resourceItems: resource.children!, version }); const link = currentTree.links[0]; @@ -68,7 +68,7 @@ describe('Resource payload should', () => { it('return a flattened list of links', async () => { const version = 'v1.0'; - const filtered = createResourcesList(resource.children, version)[0]; + const filtered = createResourcesList(resource.children!, version)[0]; const item: any = filtered.links[0]; const paths = getResourcePaths(item, version); expect(paths.length).toBeGreaterThan(0); @@ -84,7 +84,7 @@ describe('Resource payload should', () => { }); describe('Resource filter should', () => { - const resources = getResourcesSupportedByVersion(resource.children, 'v1.0'); + const resources = getResourcesSupportedByVersion(resource.children!, 'v1.0'); const messageId = 'AAMkAGFkNWI1Njg3LWZmNTUtNDZjOS04ZTM2LTc5ZTc5ZjFlNTM4ZgB1SyTR4EQuQIAbWVtP3x1LBwD4_HsJDyJ8QAAA='; @@ -109,7 +109,7 @@ describe('Resource filter should', () => { const setWithId = getMatchingResourceForUrl(requestUrl, resources)!; const setWithPlaceholder = getMatchingResourceForUrl(baseUrl, resources)!; - expect(setWithId.children.length).toBe(setWithPlaceholder.children.length); + expect(setWithId.children?.length).toBe(setWithPlaceholder.children?.length); }); }); diff --git a/src/modules/suggestions/suggestions.ts b/src/modules/suggestions/suggestions.ts index cb5ea1a4a..6026f4616 100644 --- a/src/modules/suggestions/suggestions.ts +++ b/src/modules/suggestions/suggestions.ts @@ -46,7 +46,7 @@ class Suggestions implements ISuggestions { return this.createOpenApiResponse(versionedResources, url); } else { const matching = getMatchingResourceForUrl(url, versionedResources); - if (matching && matching.children.length > 0) { + if (matching && matching.children && matching.children.length > 0) { return this.createOpenApiResponse(matching.children, url) } } diff --git a/src/types/resources.ts b/src/types/resources.ts index 6f218d9b9..98e8893cd 100644 --- a/src/types/resources.ts +++ b/src/types/resources.ts @@ -5,7 +5,7 @@ export type Method = 'GET' | 'POST' | 'PATCH' | 'PUT' | 'DELETE'; export interface IResource { segment: string; labels: IResourceLabel[]; - children: IResource[]; + children?: IResource[]; } export interface IResourceLabel {