From 39d445fbe521d72f245a9238d3161174cf11716c Mon Sep 17 00:00:00 2001 From: Revanshu Paliwal Date: Tue, 26 Apr 2022 14:05:19 +0200 Subject: [PATCH] SONAR-15257 Adding aria attributes to code page --- .../js/apps/code/__tests__/utils-test.tsx | 9 ++ .../js/apps/code/components/ComponentName.tsx | 139 +++++++++--------- .../__tests__/ComponentName-test.tsx | 10 +- .../__snapshots__/ComponentName-test.tsx.snap | 5 + .../sonar-web/src/main/js/apps/code/utils.ts | 15 ++ .../src/main/js/components/icons/Icon.tsx | 4 + .../js/components/icons/QualifierIcon.tsx | 46 +++--- .../resources/org/sonar/l10n/core.properties | 1 + 8 files changed, 132 insertions(+), 97 deletions(-) diff --git a/server/sonar-web/src/main/js/apps/code/__tests__/utils-test.tsx b/server/sonar-web/src/main/js/apps/code/__tests__/utils-test.tsx index 4e73d7db90f..88c9cbe9555 100644 --- a/server/sonar-web/src/main/js/apps/code/__tests__/utils-test.tsx +++ b/server/sonar-web/src/main/js/apps/code/__tests__/utils-test.tsx @@ -28,6 +28,7 @@ import { import { getCodeMetrics, loadMoreChildren, + mostCommonPrefix, retrieveComponent, retrieveComponentChildren } from '../utils'; @@ -142,3 +143,11 @@ describe('loadMoreChildren', () => { expect(getComponentBreadcrumbs).toHaveBeenCalledWith('key'); }); }); + +describe('#mostCommonPrefix', () => { + it('should correctly find the common path prefix', () => { + expect(mostCommonPrefix(['src/main/ts/tests', 'src/main/java/tests'])).toEqual('src/main/'); + expect(mostCommonPrefix(['src/main/ts/app', 'src/main/ts/app'])).toEqual('src/main/ts/'); + expect(mostCommonPrefix(['src/main/ts', 'lib/main/ts'])).toEqual(''); + }); +}); diff --git a/server/sonar-web/src/main/js/apps/code/components/ComponentName.tsx b/server/sonar-web/src/main/js/apps/code/components/ComponentName.tsx index 4f0b760f184..c555d2e1366 100644 --- a/server/sonar-web/src/main/js/apps/code/components/ComponentName.tsx +++ b/server/sonar-web/src/main/js/apps/code/components/ComponentName.tsx @@ -33,6 +33,7 @@ import { isProject } from '../../../types/component'; import { ComponentMeasure } from '../../../types/types'; +import { mostCommonPrefix } from '../utils'; export function getTooltip(component: ComponentMeasure) { const isFile = component.qualifier === 'FIL' || component.qualifier === 'UTS'; @@ -44,21 +45,6 @@ export function getTooltip(component: ComponentMeasure) { return [component.name, component.key, component.branch].filter(s => !!s).join('\n\n'); } -export function mostCommonPrefix(strings: string[]) { - const sortedStrings = strings.slice(0).sort(); - const firstString = sortedStrings[0]; - const firstStringLength = firstString.length; - const lastString = sortedStrings[sortedStrings.length - 1]; - let i = 0; - while (i < firstStringLength && firstString.charAt(i) === lastString.charAt(i)) { - i++; - } - const prefix = firstString.substr(0, i); - const prefixTokens = prefix.split(/[\s\\/]/); - const lastPrefixPart = prefixTokens[prefixTokens.length - 1]; - return prefix.substr(0, prefix.length - lastPrefixPart.length); -} - export interface Props { branchLike?: BranchLike; canBrowse?: boolean; @@ -76,21 +62,58 @@ export default function ComponentName({ previous, canBrowse = false }: Props) { - const areBothDirs = component.qualifier === 'DIR' && previous && previous.qualifier === 'DIR'; - const prefix = - areBothDirs && previous !== undefined - ? mostCommonPrefix([component.name + '/', previous.name + '/']) - : ''; - const name = prefix ? ( - - {prefix} - {component.name.substr(prefix.length)} + const ariaLabel = unclickable ? translate('code.parent_folder') : undefined; + + if ( + [ComponentQualifier.Application, ComponentQualifier.Portfolio].includes( + rootComponent.qualifier as ComponentQualifier + ) && + [ComponentQualifier.Application, ComponentQualifier.Project].includes( + component.qualifier as ComponentQualifier + ) + ) { + return ( + + + {renderNameWithIcon( + branchLike, + component, + previous, + rootComponent, + unclickable, + canBrowse + )} + + {component.branch ? ( + + + {component.branch} + + ) : ( + {translate('branches.main_branch')} + )} + + ); + } + return ( + + {renderNameWithIcon(branchLike, component, previous, rootComponent, unclickable, canBrowse)} - ) : ( - component.name ); +} - let inner = null; +function renderNameWithIcon( + branchLike: BranchLike | undefined, + component: ComponentMeasure, + previous: ComponentMeasure | undefined, + rootComponent: ComponentMeasure, + unclickable = false, + canBrowse = false +) { + const name = renderName(component, previous); if ( !unclickable && @@ -103,7 +126,7 @@ export default function ComponentName({ ) ? component.branch : undefined; - inner = ( + return ( {name} ); - } else { - inner = ( - - {name} - - ); } + return ( + + {name} + + ); +} - if ( - [ComponentQualifier.Application, ComponentQualifier.Portfolio].includes( - rootComponent.qualifier as ComponentQualifier - ) && - [ComponentQualifier.Application, ComponentQualifier.Project].includes( - component.qualifier as ComponentQualifier - ) - ) { - return ( - - - {inner} - - {component.branch ? ( - - - {component.branch} - - ) : ( - {translate('branches.main_branch')} - )} - - ); - } else { - return ( - - {inner} - - ); - } +function renderName(component: ComponentMeasure, previous: ComponentMeasure | undefined) { + const areBothDirs = component.qualifier === 'DIR' && previous && previous.qualifier === 'DIR'; + const prefix = + areBothDirs && previous !== undefined + ? mostCommonPrefix([component.name + '/', previous.name + '/']) + : ''; + return prefix ? ( + + {prefix} + {component.name.slice(prefix.length)} + + ) : ( + component.name + ); } diff --git a/server/sonar-web/src/main/js/apps/code/components/__tests__/ComponentName-test.tsx b/server/sonar-web/src/main/js/apps/code/components/__tests__/ComponentName-test.tsx index 49831b96a96..7d0d3c0ddb9 100644 --- a/server/sonar-web/src/main/js/apps/code/components/__tests__/ComponentName-test.tsx +++ b/server/sonar-web/src/main/js/apps/code/components/__tests__/ComponentName-test.tsx @@ -22,7 +22,7 @@ import * as React from 'react'; import { mockMainBranch } from '../../../../helpers/mocks/branch-like'; import { mockComponentMeasure } from '../../../../helpers/mocks/component'; import { ComponentQualifier } from '../../../../types/component'; -import ComponentName, { getTooltip, mostCommonPrefix, Props } from '../ComponentName'; +import ComponentName, { getTooltip, Props } from '../ComponentName'; describe('#getTooltip', () => { it('should correctly format component information', () => { @@ -33,14 +33,6 @@ describe('#getTooltip', () => { }); }); -describe('#mostCommonPrefix', () => { - it('should correctly find the common path prefix', () => { - expect(mostCommonPrefix(['src/main/ts/tests', 'src/main/java/tests'])).toEqual('src/main/'); - expect(mostCommonPrefix(['src/main/ts/app', 'src/main/ts/app'])).toEqual('src/main/ts/'); - expect(mostCommonPrefix(['src/main/ts', 'lib/main/ts'])).toEqual(''); - }); -}); - describe('#ComponentName', () => { it('should render correctly for files', () => { expect(shallowRender()).toMatchSnapshot(); diff --git a/server/sonar-web/src/main/js/apps/code/components/__tests__/__snapshots__/ComponentName-test.tsx.snap b/server/sonar-web/src/main/js/apps/code/components/__tests__/__snapshots__/ComponentName-test.tsx.snap index d045ac05387..1b2109af89b 100644 --- a/server/sonar-web/src/main/js/apps/code/components/__tests__/__snapshots__/ComponentName-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/code/components/__tests__/__snapshots__/ComponentName-test.tsx.snap @@ -2,6 +2,7 @@ exports[`#ComponentName should render breadcrumb correctly for APP 1`] = ` + + + + + + + + +