From 0301cfe83c8116d8caac948649ebb884592da588 Mon Sep 17 00:00:00 2001 From: Dan Bjorge Date: Tue, 6 Dec 2022 14:09:11 -0500 Subject: [PATCH] chore(null): null strictness for injected/components, /visualizations, deps (#6244) #### Details This PR continues the work from #6226 and #6223, adding another layer of injected files to the strict null check list. The only case with a notable behavioral change is that axe-core technically documents in its typings that it's allowed to omit a "how to fix" section from results, but if it were to actually do so, our cards UI would currently crash. I don't think axe-core actually omits that info in practice (I suspect it's there to accomodate custom rules), but now if it were to do so, we'd omit the section from the card rather than crashing (similar to how we handle results with missing snippets). This ended up enabling a *lot* of files to be autoadded! It brings us from ~72% null-strict to ~78% ```markdown ## Web strict-null progress **78%** complete (**1210**/1561 non-test files) *Contribute at [#2869](https://github.com/microsoft/accessibility-insights-web/issues/2869). Last update: Mon Dec 05 2022* Done in 1.00s. ``` ##### Motivation #2869 ##### Context n/a #### Pull request checklist - [x] Addresses an existing issue: #2869 - [x] Ran `yarn null:autoadd` - [x] Ran `yarn fastpass` - [x] Added/updated relevant unit test(s) (and ran `yarn test`) - [x] Verified code coverage for the changes made. Check coverage report at: `/test-results/unit/coverage` - [x] PR title *AND* final merge commit title both start with a semantic tag (`fix:`, `chore:`, `feat(feature-name):`, `refactor:`). See `CONTRIBUTING.md`. - [n/a] (UI changes only) Added screenshots/GIFs to description above - [n/a] (UI changes only) Verified usability with NVDA/JAWS --- .../issues/get-notification-message.ts | 4 +- .../assessment-visualization-configuration.ts | 2 +- src/common/target-helper.ts | 23 +++-- .../types/create-issue-details-text-data.ts | 2 +- src/injected/analyzers/analyzer.ts | 3 +- .../analyzers/batched-rule-analyzer.ts | 8 +- src/injected/analyzers/rule-analyzer.ts | 5 +- src/injected/analyzers/tab-stops-analyzer.ts | 2 +- src/injected/components/command-bar.tsx | 4 +- src/injected/components/details-dialog.tsx | 38 +++++--- src/injected/details-dialog-handler.ts | 2 +- src/injected/main-window-context.ts | 6 +- src/injected/visualization/drawer-provider.ts | 7 +- src/injected/visualization/formatter.ts | 3 + .../visualization/highlight-box-formatter.ts | 2 +- src/injected/visualization/svg-drawer.ts | 41 +++++---- .../visualization/tab-stops-formatter.ts | 21 ++--- ...reate-issue-details-builder-for-unified.ts | 16 +++- .../common/create-issue-details-builder.ts | 16 +++- .../analyzers/batched-rule-analyzer.test.ts | 2 +- .../injected/visualization/svg-drawer.test.ts | 36 ++++---- .../visualization/tab-stops-formatter.test.ts | 10 +- tsconfig.strictNullChecks.json | 92 +++++++++++-------- 23 files changed, 198 insertions(+), 147 deletions(-) diff --git a/src/ad-hoc-visualizations/issues/get-notification-message.ts b/src/ad-hoc-visualizations/issues/get-notification-message.ts index 2bcbab76366..b848f70bd8f 100644 --- a/src/ad-hoc-visualizations/issues/get-notification-message.ts +++ b/src/ad-hoc-visualizations/issues/get-notification-message.ts @@ -6,9 +6,9 @@ import { DictionaryStringTo } from 'types/common-types'; export const getNotificationMessage = ( selectorMap: DictionaryStringTo, - warnings: ScanIncompleteWarningId[], + warnings?: ScanIncompleteWarningId[], ) => { - if (isEmpty(selectorMap) && isEmpty(warnings)) { + if (warnings == null || (isEmpty(selectorMap) && isEmpty(warnings))) { return 'Congratulations!\n\nAutomated checks found no issues on this page.'; } diff --git a/src/common/configs/assessment-visualization-configuration.ts b/src/common/configs/assessment-visualization-configuration.ts index 9acbf636738..383994fe7a7 100644 --- a/src/common/configs/assessment-visualization-configuration.ts +++ b/src/common/configs/assessment-visualization-configuration.ts @@ -39,7 +39,7 @@ export interface AssessmentVisualizationConfiguration { selectorMap: DictionaryStringTo, testStep?: string, warnings?: ScanIncompleteWarningId[], - ) => string; + ) => string | null; getDrawer: (provider: DrawerProvider, testStep?: string) => Drawer; getSwitchToTargetTabOnScan: (testStep?: string) => boolean; getInstanceIdentiferGenerator: ( diff --git a/src/common/target-helper.ts b/src/common/target-helper.ts index d6541c2809a..3d54b9c951a 100644 --- a/src/common/target-helper.ts +++ b/src/common/target-helper.ts @@ -59,12 +59,15 @@ export class TargetHelper { } }; - public static getTargetFromSelector = (selector: string): Target | undefined => { + // This returns undefined for undefined input for compatibility with non-strict-null-compatible + // usages that we haven't investigated yet. The "!selector" clause can/should be removed once + // #2869 is complete. + public static getTargetFromSelector = (selector: string): Target => { if (selector === '') { return []; } if (!selector) { - return; + return undefined!; } const selectors: string[] = selector.split(';'); const shadowDomSelectors = selectors.map(selectors => { @@ -78,14 +81,14 @@ export class TargetHelper { return shadowDomSelectors; }; - public static getSelectorFromTarget = (target: Target): string | undefined => { - if (target) { - return target - .map((targets: string | string[]) => - typeof targets === 'string' ? targets : targets.join(','), - ) - .join(';'); - } + // This returns undefined for undefined input for compatibility with non-strict-null-compatible + // usages that we haven't investigated yet. The ?s can/should be removed once #2869 is complete. + public static getSelectorFromTarget = (target: Target): string => { + return target + ?.map((targets: string | string[]) => + typeof targets === 'string' ? targets : targets.join(','), + ) + ?.join(';'); }; public static getSelectorFromTargetElement = ( diff --git a/src/common/types/create-issue-details-text-data.ts b/src/common/types/create-issue-details-text-data.ts index bb51932afc9..65c1def88b1 100644 --- a/src/common/types/create-issue-details-text-data.ts +++ b/src/common/types/create-issue-details-text-data.ts @@ -17,6 +17,6 @@ export interface CreateIssueDetailsTextData { identifier: string; conciseName: string; }; - howToFixSummary: string; + howToFixSummary?: string; snippet?: string; } diff --git a/src/injected/analyzers/analyzer.ts b/src/injected/analyzers/analyzer.ts index 825b8bb20c1..635eb7bd538 100644 --- a/src/injected/analyzers/analyzer.ts +++ b/src/injected/analyzers/analyzer.ts @@ -43,7 +43,8 @@ export interface AnalyzerConfiguration { } export interface RuleAnalyzerConfiguration extends AnalyzerConfiguration { - rules: string[]; + // null implies "the scanner's default rule set" + rules: string[] | null; resultProcessor: ( scanner: ScannerUtils, ) => (results: ScanResults) => DictionaryStringTo; diff --git a/src/injected/analyzers/batched-rule-analyzer.ts b/src/injected/analyzers/batched-rule-analyzer.ts index 672e41c4873..2d82652863f 100644 --- a/src/injected/analyzers/batched-rule-analyzer.ts +++ b/src/injected/analyzers/batched-rule-analyzer.ts @@ -12,7 +12,10 @@ import { ScannerUtils } from '../scanner-utils'; import { RuleAnalyzerConfiguration } from './analyzer'; import { RuleAnalyzer } from './rule-analyzer'; -export type IResultRuleFilter = (results: ScanResults, rules: string[]) => ScanResults; +export type IResultRuleFilter = ( + results: ScanResults | undefined, + rules: string[] | null, +) => ScanResults; export class BatchedRuleAnalyzer extends RuleAnalyzer { private static batchConfigs: RuleAnalyzerConfiguration[] = []; @@ -42,7 +45,8 @@ export class BatchedRuleAnalyzer extends RuleAnalyzer { BatchedRuleAnalyzer.batchConfigs.push(config); } - protected getRulesToRun(): string[] { + // null implies "the scanner's default rule set" + protected getRulesToRun(): string[] | null { return null; } diff --git a/src/injected/analyzers/rule-analyzer.ts b/src/injected/analyzers/rule-analyzer.ts index 2c8859d31e4..ca1d28193e6 100644 --- a/src/injected/analyzers/rule-analyzer.ts +++ b/src/injected/analyzers/rule-analyzer.ts @@ -43,7 +43,7 @@ export class RuleAnalyzer extends BaseAnalyzer { const exclude = scopingState[ScopingInputTypes.exclude]; const scanOptions: ScanOptions = { - testsToRun: this.getRulesToRun(), + testsToRun: this.getRulesToRun() ?? undefined, include: include, exclude: exclude, }; @@ -65,7 +65,8 @@ export class RuleAnalyzer extends BaseAnalyzer { }); }; - protected getRulesToRun(): string[] { + // null implies "the scanner's default rule set" + protected getRulesToRun(): string[] | null { return this.config.rules; } diff --git a/src/injected/analyzers/tab-stops-analyzer.ts b/src/injected/analyzers/tab-stops-analyzer.ts index 0cb2ec5e226..b4b56df5305 100644 --- a/src/injected/analyzers/tab-stops-analyzer.ts +++ b/src/injected/analyzers/tab-stops-analyzer.ts @@ -27,7 +27,7 @@ export class TabStopsAnalyzer extends BaseAnalyzer { scanIncompleteWarningDetector: ScanIncompleteWarningDetector, logger: Logger, private readonly tabStopsDoneAnalyzingTracker: TabStopsDoneAnalyzingTracker, - private readonly tabStopsRequirementResultProcessor: TabStopsRequirementResultProcessor, + private readonly tabStopsRequirementResultProcessor: TabStopsRequirementResultProcessor | null, private readonly debounceImpl: typeof debounce = debounce, ) { super(config, sendMessageDelegate, scanIncompleteWarningDetector, logger); diff --git a/src/injected/components/command-bar.tsx b/src/injected/components/command-bar.tsx index 73c9b3a3335..c8456a134ba 100644 --- a/src/injected/components/command-bar.tsx +++ b/src/injected/components/command-bar.tsx @@ -97,7 +97,7 @@ export const CommandBar = NamedFC('CommandBar', props => { ); }; - const renderInspectMessage = (): JSX.Element => { + const renderInspectMessage = (): JSX.Element | undefined => { if (props.shouldShowInspectButtonMessage()) { return (
@@ -107,7 +107,7 @@ export const CommandBar = NamedFC('CommandBar', props => { } }; - const renderCopyIssueDetailsMessage = (): JSX.Element => { + const renderCopyIssueDetailsMessage = (): JSX.Element | undefined => { if (props.shouldShowInsecureOriginPageMessage) { return (
diff --git a/src/injected/components/details-dialog.tsx b/src/injected/components/details-dialog.tsx index 3ec9bc8cbe2..9d4483e7e75 100644 --- a/src/injected/components/details-dialog.tsx +++ b/src/injected/components/details-dialog.tsx @@ -206,27 +206,33 @@ export class DetailsDialog extends React.Component { - if (url.indexOf('://') >= 0) { - return url; - } else { - const { browserAdapter } = this.props.deps; - return browserAdapter.getUrl(url); - } - }; + private renderRuleLink(rule: DecoratedAxeNodeResult): JSX.Element { + const url = rule.helpUrl; + if (url == null) { + return <>rule.ruleId; + } + + let sanitizedUrl = url; + if (url.indexOf('://') < 0) { + const { browserAdapter } = this.props.deps; + sanitizedUrl = browserAdapter.getUrl(url); + } + return {rule.ruleId}; + } + + private renderRuleName(rule: DecoratedAxeNodeResult): JSX.Element { const ruleNameID = 'rule-name'; return (
{this.renderSectionTitle('Rule name', ruleNameID)} - {rule.ruleId} + {this.renderRuleLink(rule)}
); } - private renderSuccessCriteria(ruleGuidanceLinks: HyperlinkDefinition[]): JSX.Element { + private renderSuccessCriteria(ruleGuidanceLinks: HyperlinkDefinition[]): JSX.Element | null { if (isEmpty(ruleGuidanceLinks)) { return null; } @@ -257,18 +263,22 @@ export class DetailsDialog extends React.Component
@@ -279,7 +289,7 @@ export class DetailsDialog extends React.Component {this.renderRuleName(rule)} - {this.renderSuccessCriteria(rule.guidanceLinks)} + {this.renderSuccessCriteria(rule.guidanceLinks ?? [])} {this.renderPathSelector()} {this.renderCommandBar()} {this.renderFixInstructions(rule)} diff --git a/src/injected/details-dialog-handler.ts b/src/injected/details-dialog-handler.ts index 7520ce6ba54..a1fa4d1d590 100644 --- a/src/injected/details-dialog-handler.ts +++ b/src/injected/details-dialog-handler.ts @@ -112,7 +112,7 @@ export class DetailsDialogHandler { return; } - let parentLayer = dialogContainer; + let parentLayer: HTMLElement | null = dialogContainer; while (parentLayer != null) { if (parentLayer.classList.contains('ms-Layer--fixed')) { diff --git a/src/injected/main-window-context.ts b/src/injected/main-window-context.ts index d18d6cac559..9b658ccdf2c 100644 --- a/src/injected/main-window-context.ts +++ b/src/injected/main-window-context.ts @@ -64,7 +64,7 @@ export class MainWindowContext { toolData: ToolData, issueFilingServiceProvider: IssueFilingServiceProvider, ): void { - window.mainWindowContext = new MainWindowContext( + window['mainWindowContext'] = new MainWindowContext( devToolStore, userConfigStore, devToolActionMessageCreator, @@ -77,9 +77,9 @@ export class MainWindowContext { } public static fromWindow(windowObj: Window): MainWindowContext { - if (windowObj.mainWindowContext == null) { + if (windowObj['mainWindowContext'] == null) { throw new Error('No window.mainWindowContext found'); } - return windowObj.mainWindowContext; + return windowObj['mainWindowContext']; } } diff --git a/src/injected/visualization/drawer-provider.ts b/src/injected/visualization/drawer-provider.ts index 4b407e66b68..ae7f2d2f154 100644 --- a/src/injected/visualization/drawer-provider.ts +++ b/src/injected/visualization/drawer-provider.ts @@ -9,7 +9,6 @@ import { TableHeadersAttributeFormatter } from 'injected/visualization/table-hea import { BrowserAdapter } from '../../common/browser-adapters/browser-adapter'; import { HTMLElementUtils } from '../../common/html-element-utils'; import { TabbableElementsHelper } from '../../common/tabbable-elements-helper'; -import { DeepPartial } from '../../common/types/deep-partial'; import { WindowUtils } from '../../common/window-utils'; import { ClientUtils } from '../client-utils'; import { DetailsDialogHandler } from '../details-dialog-handler'; @@ -19,7 +18,7 @@ import { CenterPositionCalculator } from './center-position-calculator'; import { CustomWidgetsFormatter } from './custom-widgets-formatter'; import { Drawer } from './drawer'; import { DrawerUtils } from './drawer-utils'; -import { Formatter, SVGDrawerConfiguration } from './formatter'; +import { Formatter, IPartialSVGDrawerConfiguration } from './formatter'; import { FrameFormatter } from './frame-formatter'; import { HeadingFormatter } from './heading-formatter'; import { HighlightBoxDrawer } from './highlight-box-drawer'; @@ -35,8 +34,6 @@ import { SVGShapeFactory } from './svg-shape-factory'; import { SVGSolidShadowFilterFactory } from './svg-solid-shadow-filter-factory'; import { TabStopsFormatter } from './tab-stops-formatter'; -export type IPartialSVGDrawerConfiguration = DeepPartial; - export class DrawerProvider { constructor( private readonly htmlElementUtils: HTMLElementUtils, @@ -60,7 +57,7 @@ export class DrawerProvider { return new SingleTargetDrawer(this.drawerUtils, new SingleTargetFormatter(className)); } - public createSVGDrawer(config: IPartialSVGDrawerConfiguration = null): Drawer { + public createSVGDrawer(config: IPartialSVGDrawerConfiguration | null = null): Drawer { const tabbableElementsHelper = new TabbableElementsHelper(this.htmlElementUtils); const centerPositionCalculator = new CenterPositionCalculator( this.drawerUtils, diff --git a/src/injected/visualization/formatter.ts b/src/injected/visualization/formatter.ts index a3e1cd51565..6c48c370b14 100644 --- a/src/injected/visualization/formatter.ts +++ b/src/injected/visualization/formatter.ts @@ -1,5 +1,6 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +import { DeepPartial } from 'common/types/deep-partial'; import { BoundingRect } from '../bounding-rect'; import { DialogRenderer } from '../dialog-renderer'; import { AxeResultsWithFrameLevel } from '../frameCommunicators/html-element-axe-results-helper'; @@ -72,6 +73,8 @@ export interface SVGDrawerConfiguration { failureBoxConfig: FailureBoxConfig; } +export type IPartialSVGDrawerConfiguration = DeepPartial; + export interface SingleTargetDrawerConfiguration { injectedClassName: string; } diff --git a/src/injected/visualization/highlight-box-formatter.ts b/src/injected/visualization/highlight-box-formatter.ts index 9ef713a4787..75448ae5b64 100644 --- a/src/injected/visualization/highlight-box-formatter.ts +++ b/src/injected/visualization/highlight-box-formatter.ts @@ -11,7 +11,7 @@ export class HighlightBoxFormatter extends FailureInstanceFormatter { super(); } - public getDialogRenderer(): DialogRenderer { + public getDialogRenderer(): DialogRenderer | null { return null; } diff --git a/src/injected/visualization/svg-drawer.ts b/src/injected/visualization/svg-drawer.ts index 0319e7a30b6..bdb76609350 100644 --- a/src/injected/visualization/svg-drawer.ts +++ b/src/injected/visualization/svg-drawer.ts @@ -91,11 +91,12 @@ export class SVGDrawer extends BaseDrawer { newStateElement: TabStopVisualizationInstance, dom: Document, ): TabbedItem { - const element = TargetHelper.getTargetElement( - newStateElement.target, - dom, - newStateElement.target.length - 1, - ); + const element = + TargetHelper.getTargetElement( + newStateElement.target, + dom, + newStateElement.target.length - 1, + ) ?? null; const selector = TargetHelper.getSelectorFromTargetElement( newStateElement.target, newStateElement.target.length - 1, @@ -105,7 +106,7 @@ export class SVGDrawer extends BaseDrawer { element, selector, tabOrder: newStateElement.propertyBag.tabOrder, - focusIndicator: oldStateElement ? oldStateElement.focusIndicator : null, + focusIndicator: oldStateElement ? oldStateElement.focusIndicator : undefined, isFailure: newStateElement.isFailure, itemType: newStateElement.itemType, }; @@ -133,7 +134,7 @@ export class SVGDrawer extends BaseDrawer { this.setSVGSize(); const defs = this.createDefsAndFilterElement(); this.SVGContainer.appendChild(defs); - this.containerElement.appendChild(this.SVGContainer); + this.containerElement!.appendChild(this.SVGContainer); } private createDefsAndFilterElement(): Element { @@ -177,13 +178,13 @@ export class SVGDrawer extends BaseDrawer { items: TabbedItem[], curElementIndex: number, isLastItem: boolean, - ): FocusIndicator { + ): FocusIndicator | undefined { const item = items[curElementIndex]; - const centerPosition: Point = this.centerPositionCalculator.getElementCenterPosition( + const centerPosition: Point | null = this.centerPositionCalculator.getElementCenterPosition( item.element, ); - if (centerPosition == null) { + if (item.element == null || centerPosition == null) { return; } @@ -202,26 +203,26 @@ export class SVGDrawer extends BaseDrawer { const newCircle = this.svgShapeFactory.createCircle(centerPosition, circleConfiguration); const newLabel = isLastItem || !showTabIndexedLabel - ? null + ? undefined : this.svgShapeFactory.createTabIndexLabel( centerPosition, drawerConfig.tabIndexLabel, item.tabOrder.toString(), ); - const newLine: Element = this.createLinesInTabOrderVisualization( + const newLine: Element | null = this.createLinesInTabOrderVisualization( items, curElementIndex, isLastItem, drawerConfig, centerPosition, - showSolidFocusLine, + showSolidFocusLine ?? false, ); const focusIndicator: FocusIndicator = { circle: newCircle, tabIndexLabel: newLabel, - line: newLine, + line: newLine ?? undefined, }; return focusIndicator; @@ -234,7 +235,7 @@ export class SVGDrawer extends BaseDrawer { drawerConfig: SVGDrawerConfiguration, centerPosition: Point, showSolidFocusLine: boolean, - ): Element { + ): Element | null { const circleConfiguration = isLastItem ? drawerConfig.focusedCircle : drawerConfig.circle; if (this.shouldBreakGraph(items, curElementIndex)) { @@ -266,12 +267,12 @@ export class SVGDrawer extends BaseDrawer { ); } - private createFocusIndicatorForFailure(item: TabbedItem): FocusIndicator { - const centerPosition: Point = this.centerPositionCalculator.getElementCenterPosition( + private createFocusIndicatorForFailure(item: TabbedItem): FocusIndicator | undefined { + const centerPosition: Point | null = this.centerPositionCalculator.getElementCenterPosition( item.element, ); - if (centerPosition == null) { + if (item.element == null || centerPosition == null) { return; } @@ -317,7 +318,7 @@ export class SVGDrawer extends BaseDrawer { ); } - private removeFocusIndicator(focusIndicator: FocusIndicator): void { + private removeFocusIndicator(focusIndicator?: FocusIndicator): void { if (!focusIndicator) { return; } @@ -364,7 +365,7 @@ export class SVGDrawer extends BaseDrawer { }); const result = chain(this.allVisualizedItems) - .filter((element: TabbedItem) => element.shouldRedraw) + .filter((element: TabbedItem) => element.shouldRedraw ?? false) .map(tabbed => chain(tabbed.focusIndicator).values().compact().value()) .flatten() .value(); diff --git a/src/injected/visualization/tab-stops-formatter.ts b/src/injected/visualization/tab-stops-formatter.ts index 79c293a11c8..4babf345a15 100644 --- a/src/injected/visualization/tab-stops-formatter.ts +++ b/src/injected/visualization/tab-stops-formatter.ts @@ -3,15 +3,14 @@ import { HtmlElementAxeResults } from 'common/types/store-data/visualization-scan-result-data'; import { assign } from 'lodash'; import { DialogRenderer } from '../dialog-renderer'; -import { IPartialSVGDrawerConfiguration } from './drawer-provider'; -import { Formatter, SVGDrawerConfiguration } from './formatter'; +import { Formatter, IPartialSVGDrawerConfiguration, SVGDrawerConfiguration } from './formatter'; export class TabStopsFormatter implements Formatter { private static readonly ELLIPSE_RX_CALCULATOR_OFFSET: number = 1.3; private static readonly ELLIPSE_RX_CALCULATOR_SLOPE: number = 4.2; - private givenConfiguration: IPartialSVGDrawerConfiguration; + private givenConfiguration: IPartialSVGDrawerConfiguration | null; - constructor(givenConfiguration?: IPartialSVGDrawerConfiguration) { + constructor(givenConfiguration: IPartialSVGDrawerConfiguration | null) { this.givenConfiguration = givenConfiguration; } @@ -22,7 +21,7 @@ export class TabStopsFormatter implements Formatter { let ellipseRx: number = 16; const tabindex = element.getAttribute('tabindex'); if (tabindex && parseInt(tabindex, 10) > 0) { - const stringLength: number = element.getAttribute('tabindex').length; + const stringLength: number = tabindex.length; if (stringLength > 3) { ellipseRx = this.calculateEllipseRx(stringLength); } @@ -92,12 +91,10 @@ export class TabStopsFormatter implements Formatter { return config; } - Object.keys(this.givenConfiguration).forEach( - (svgPartConfigKey: keyof SVGDrawerConfiguration) => { - const configAdditions = this.givenConfiguration[svgPartConfigKey]; - assign(config[svgPartConfigKey], configAdditions); - }, - ); + for (const svgPartConfigKey in this.givenConfiguration) { + const configAdditions = this.givenConfiguration[svgPartConfigKey]; + assign(config[svgPartConfigKey], configAdditions); + } return config; } @@ -109,7 +106,7 @@ export class TabStopsFormatter implements Formatter { ); } - public getDialogRenderer(): DialogRenderer { + public getDialogRenderer(): DialogRenderer | null { return null; } } diff --git a/src/issue-filing/common/create-issue-details-builder-for-unified.ts b/src/issue-filing/common/create-issue-details-builder-for-unified.ts index f3516097382..ef84adba091 100644 --- a/src/issue-filing/common/create-issue-details-builder-for-unified.ts +++ b/src/issue-filing/common/create-issue-details-builder-for-unified.ts @@ -11,7 +11,7 @@ export const createIssueDetailsBuilderForUnified = ( ): IssueDetailsBuilder => { const getter = (toolData: ToolData, data: CreateIssueDetailsTextData): string => { const { - howToFixSection, + howToFixSection: howToFixSummary, link, sectionHeader, snippet, @@ -33,6 +33,15 @@ export const createIssueDetailsBuilderForUnified = ( ] : []; + const howToFixSection = data.howToFixSummary + ? [ + sectionHeader('How to fix'), + sectionHeaderSeparator(), + howToFixSummary(data.howToFixSummary), + sectionSeparator(), + ] + : []; + const ruleDetailsSection = () => { const { description, url, id } = data.rule; if (description && url && id) { @@ -59,10 +68,7 @@ export const createIssueDetailsBuilderForUnified = ( ...snippetSection, - sectionHeader('How to fix'), - sectionHeaderSeparator(), - howToFixSection(data.howToFixSummary), - sectionSeparator(), + ...howToFixSection, sectionHeader('Environment'), sectionHeaderSeparator(), diff --git a/src/issue-filing/common/create-issue-details-builder.ts b/src/issue-filing/common/create-issue-details-builder.ts index 1ca993b33ba..53547f3eaa8 100644 --- a/src/issue-filing/common/create-issue-details-builder.ts +++ b/src/issue-filing/common/create-issue-details-builder.ts @@ -9,7 +9,7 @@ import { MarkupFormatter } from './markup/markup-formatter'; export const createIssueDetailsBuilder = (markup: MarkupFormatter): IssueDetailsBuilder => { const getter = (toolData: ToolData, data: CreateIssueDetailsTextData): string => { const { - howToFixSection, + howToFixSection: howToFixSummary, link, sectionHeader, snippet, @@ -31,6 +31,15 @@ export const createIssueDetailsBuilder = (markup: MarkupFormatter): IssueDetails ] : []; + const howToFixSection = data.howToFixSummary + ? [ + sectionHeader('How to fix'), + sectionHeaderSeparator(), + howToFixSummary(data.howToFixSummary), + sectionSeparator(), + ] + : []; + const ruleDetailsSection = () => { const { description, url, id } = data.rule; if (description && url && id) { @@ -57,10 +66,7 @@ export const createIssueDetailsBuilder = (markup: MarkupFormatter): IssueDetails ...snippetSection, - sectionHeader('How to fix'), - sectionHeaderSeparator(), - howToFixSection(data.howToFixSummary), - sectionSeparator(), + ...howToFixSection, sectionHeader('Environment'), sectionHeaderSeparator(), diff --git a/src/tests/unit/tests/injected/analyzers/batched-rule-analyzer.test.ts b/src/tests/unit/tests/injected/analyzers/batched-rule-analyzer.test.ts index 98ef001e478..230338b92cf 100644 --- a/src/tests/unit/tests/injected/analyzers/batched-rule-analyzer.test.ts +++ b/src/tests/unit/tests/injected/analyzers/batched-rule-analyzer.test.ts @@ -110,7 +110,7 @@ describe('BatchedRuleAnalyzer', () => { id: ruleTwo, } as RuleResult; - setupScannerUtilsMock(null, Times.exactly(2)); + setupScannerUtilsMock(undefined, Times.exactly(2)); const testSubjectOne = createAnalyzer(configOne); const testSubjectTwo = createAnalyzer(configTwo); diff --git a/src/tests/unit/tests/injected/visualization/svg-drawer.test.ts b/src/tests/unit/tests/injected/visualization/svg-drawer.test.ts index 25902f65c42..e84f02cf668 100644 --- a/src/tests/unit/tests/injected/visualization/svg-drawer.test.ts +++ b/src/tests/unit/tests/injected/visualization/svg-drawer.test.ts @@ -65,7 +65,7 @@ describe('SVGDrawer', () => { { element: fakeDocument.querySelector('#id1'), tabOrder: 1, - focusIndicator: null, + focusIndicator: undefined, shouldRedraw: true, selector: '#id1', itemType: undefined, @@ -74,7 +74,7 @@ describe('SVGDrawer', () => { { element: fakeDocument.querySelector('#id2'), tabOrder: undefined, - focusIndicator: null, + focusIndicator: undefined, shouldRedraw: true, selector: '#id2', itemType: TabbedItemType.MissingItem, @@ -83,7 +83,7 @@ describe('SVGDrawer', () => { { element: fakeDocument.querySelector('#id3'), tabOrder: 2, - focusIndicator: null, + focusIndicator: undefined, shouldRedraw: true, selector: '#id3', itemType: undefined, @@ -145,7 +145,7 @@ describe('SVGDrawer', () => { { element: element, tabOrder: 1, - focusIndicator: null, + focusIndicator: undefined, shouldRedraw: true, selector: '#id1', itemType: undefined, @@ -195,7 +195,7 @@ describe('SVGDrawer', () => { { element: element1, tabOrder: 1, - focusIndicator: null, + focusIndicator: undefined, shouldRedraw: true, selector: '#id1', isFailure: false, @@ -207,7 +207,7 @@ describe('SVGDrawer', () => { { element: element1, tabOrder: 1, - focusIndicator: null, + focusIndicator: undefined, shouldRedraw: false, selector: '#id1', itemType: undefined, @@ -216,7 +216,7 @@ describe('SVGDrawer', () => { { element: element2, tabOrder: 2, - focusIndicator: null, + focusIndicator: undefined, shouldRedraw: true, selector: '#id2', itemType: undefined, @@ -280,7 +280,7 @@ describe('SVGDrawer', () => { { element: element1, tabOrder: 1, - focusIndicator: null, + focusIndicator: undefined, shouldRedraw: false, selector: '#id1', itemType: undefined, @@ -289,7 +289,7 @@ describe('SVGDrawer', () => { { element: element2, tabOrder: 2, - focusIndicator: null, + focusIndicator: undefined, shouldRedraw: true, selector: '#id2', itemType: undefined, @@ -298,7 +298,7 @@ describe('SVGDrawer', () => { { element: element3, tabOrder: undefined, - focusIndicator: null, + focusIndicator: undefined, shouldRedraw: true, selector: '#id3', itemType: undefined, @@ -307,7 +307,7 @@ describe('SVGDrawer', () => { { element: element4, tabOrder: 3, - focusIndicator: null, + focusIndicator: undefined, shouldRedraw: true, selector: '#id4', itemType: undefined, @@ -391,7 +391,7 @@ describe('SVGDrawer', () => { { element: element1, tabOrder: 1, - focusIndicator: null, + focusIndicator: undefined, shouldRedraw: true, selector: '#id1', itemType: undefined, @@ -400,7 +400,7 @@ describe('SVGDrawer', () => { { element: element3, tabOrder: 2, - focusIndicator: null, + focusIndicator: undefined, shouldRedraw: true, selector: '#id3', itemType: undefined, @@ -409,7 +409,7 @@ describe('SVGDrawer', () => { { element: element4, tabOrder: 3, - focusIndicator: null, + focusIndicator: undefined, shouldRedraw: true, selector: '#id4', itemType: undefined, @@ -421,7 +421,7 @@ describe('SVGDrawer', () => { { element: element1, tabOrder: 1, - focusIndicator: null, + focusIndicator: undefined, shouldRedraw: false, selector: '#id1', itemType: undefined, @@ -430,7 +430,7 @@ describe('SVGDrawer', () => { { element: element2, tabOrder: 2, - focusIndicator: null, + focusIndicator: undefined, shouldRedraw: true, selector: '#id2', itemType: undefined, @@ -439,7 +439,7 @@ describe('SVGDrawer', () => { { element: element3, tabOrder: 3, - focusIndicator: null, + focusIndicator: undefined, shouldRedraw: true, selector: '#id3', itemType: undefined, @@ -448,7 +448,7 @@ describe('SVGDrawer', () => { { element: element4, tabOrder: 4, - focusIndicator: null, + focusIndicator: undefined, shouldRedraw: true, selector: '#id4', itemType: undefined, diff --git a/src/tests/unit/tests/injected/visualization/tab-stops-formatter.test.ts b/src/tests/unit/tests/injected/visualization/tab-stops-formatter.test.ts index b9976bb7c26..991781f6b28 100644 --- a/src/tests/unit/tests/injected/visualization/tab-stops-formatter.test.ts +++ b/src/tests/unit/tests/injected/visualization/tab-stops-formatter.test.ts @@ -1,8 +1,10 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import { IPartialSVGDrawerConfiguration } from '../../../../../injected/visualization/drawer-provider'; -import { SVGDrawerConfiguration } from '../../../../../injected/visualization/formatter'; -import { TabStopsFormatter } from '../../../../../injected/visualization/tab-stops-formatter'; +import { + IPartialSVGDrawerConfiguration, + SVGDrawerConfiguration, +} from 'injected/visualization/formatter'; +import { TabStopsFormatter } from 'injected/visualization/tab-stops-formatter'; describe('TabStopsFormatterTests', () => { let testSubject: TabStopsFormatter; @@ -74,7 +76,7 @@ describe('TabStopsFormatterTests', () => { } beforeEach(() => { - testSubject = new TabStopsFormatter(); + testSubject = new TabStopsFormatter(null); sandbox = document.createElement('div'); document.body.appendChild(sandbox); }); diff --git a/tsconfig.strictNullChecks.json b/tsconfig.strictNullChecks.json index 31e592f8e75..0a5baab57d6 100644 --- a/tsconfig.strictNullChecks.json +++ b/tsconfig.strictNullChecks.json @@ -29,6 +29,7 @@ "./src/DetailsView/components/load-assessment-dialog.tsx", "./src/DetailsView/components/narrow-mode-detector.tsx", "./src/DetailsView/components/nav-link-button.tsx", + "./src/DetailsView/components/next-requirement-button.tsx", "./src/DetailsView/components/no-displayable-preview-features-message.tsx", "./src/DetailsView/components/overview-content/help-links.tsx", "./src/DetailsView/components/overview-content/overview-heading.tsx", @@ -40,6 +41,7 @@ "./src/DetailsView/components/save-assessment-button-factory.tsx", "./src/DetailsView/components/save-assessment-button.tsx", "./src/DetailsView/components/scan-incomplete-warning.tsx", + "./src/DetailsView/components/should-show-report-export-button.ts", "./src/DetailsView/components/static-content-details-view.tsx", "./src/DetailsView/components/switcher.tsx", "./src/DetailsView/components/tab-stops/failed-instance-panel.tsx", @@ -59,45 +61,63 @@ "./src/DetailsView/details-view-init-with-react-devtools.ts", "./src/DetailsView/handlers/allurls-permission-handler.ts", "./src/DetailsView/handlers/details-view-toggle-click-handler-factory.ts", + "./src/DetailsView/handlers/get-document-title.ts", "./src/DetailsView/handlers/master-checkbox-config-provider.ts", "./src/DetailsView/no-content-available-view-renderer.tsx", "./src/DetailsView/tab-stops-failed-counter.ts", "./src/DetailsView/tab-stops-requirement-instances-collapsible-content.tsx", "./src/DetailsView/tab-stops-requirement-result.ts", - "./src/ad-hoc-visualizations/issues/get-notification-message.ts", + "./src/assessments/adaptable-content/test-steps/high-contrast-mode.tsx", + "./src/assessments/adaptable-content/test-steps/hover-focus-content.tsx", + "./src/assessments/adaptable-content/test-steps/orientation.tsx", + "./src/assessments/adaptable-content/test-steps/reflow.tsx", + "./src/assessments/adaptable-content/test-steps/resize-text.tsx", "./src/assessments/adaptable-content/test-steps/test-step.ts", "./src/assessments/assessment-default-message-generator.tsx", - "./src/assessments/audio-video-only/test-steps/test-steps.ts", "./src/assessments/auto-pass-if-no-results.ts", + "./src/assessments/color/test-steps/auditory-cues.tsx", + "./src/assessments/color/test-steps/flashing.tsx", + "./src/assessments/color/test-steps/sensory-characteristics.tsx", "./src/assessments/color/test-steps/test-steps.tsx", "./src/assessments/contrast/test-steps/test-steps.ts", "./src/assessments/custom-widgets/custom-widgets-column-renderer-factory.tsx", "./src/assessments/custom-widgets/custom-widgets-column-renderer.tsx", "./src/assessments/custom-widgets/design-pattern.ts", "./src/assessments/custom-widgets/test-steps/test-steps.ts", - "./src/assessments/errors/test-steps/test-steps.ts", "./src/assessments/headings/test-steps/test-steps.ts", + "./src/assessments/images/test-steps/captchas.tsx", "./src/assessments/images/test-steps/test-steps.ts", + "./src/assessments/keyboard-interaction/test-steps/character-key-shortcuts.tsx", + "./src/assessments/keyboard-interaction/test-steps/no-keyboard-traps.tsx", + "./src/assessments/keyboard-interaction/test-steps/no-keystroke-timings.tsx", + "./src/assessments/keyboard-interaction/test-steps/on-focus.tsx", + "./src/assessments/keyboard-interaction/test-steps/on-input.tsx", "./src/assessments/keyboard-interaction/test-steps/test-steps.ts", "./src/assessments/landmarks/does-result-have-main-role.ts", "./src/assessments/landmarks/test-steps/test-steps.ts", - "./src/assessments/language/test-steps/test-steps.ts", "./src/assessments/links/test-steps/test-steps.ts", - "./src/assessments/live-multimedia/test-steps/test-steps.ts", "./src/assessments/markup.tsx", "./src/assessments/medium-pass-requirements.ts", "./src/assessments/native-widgets/test-steps/test-steps.ts", "./src/assessments/page/pagetitle-instance-details-column-renderer.tsx", + "./src/assessments/page/test-steps/general-navigation.tsx", + "./src/assessments/page/test-steps/page-title.tsx", "./src/assessments/page/test-steps/test-steps.ts", - "./src/assessments/parsing/test-steps/test-steps.ts", - "./src/assessments/pointer-motion/test-steps/test-steps.ts", - "./src/assessments/prerecorded-multimedia/test-steps/test-steps.ts", - "./src/assessments/repetitive-content/test-steps/test-steps.ts", + "./src/assessments/semantics/test-steps/emphasis.tsx", + "./src/assessments/semantics/test-steps/letter-spacing.tsx", + "./src/assessments/semantics/test-steps/lists.tsx", + "./src/assessments/semantics/test-steps/quotes.tsx", + "./src/assessments/semantics/test-steps/table-semantics.tsx", "./src/assessments/semantics/test-steps/test-steps.ts", + "./src/assessments/sequence/test-steps/columns.tsx", + "./src/assessments/sequence/test-steps/layout-tables.tsx", "./src/assessments/sequence/test-steps/test-steps.ts", - "./src/assessments/timed-events/test-steps/test-steps.ts", "./src/assessments/types/instance-table-data.ts", "./src/assessments/types/report-instance-field.ts", + "./src/assessments/types/requirement.ts", + "./src/assessments/visible-focus-order/test-steps/closing-content.tsx", + "./src/assessments/visible-focus-order/test-steps/modal-dialogs.tsx", + "./src/assessments/visible-focus-order/test-steps/revealing-content.tsx", "./src/assessments/visible-focus-order/test-steps/test-steps.ts", "./src/background/IndexedDBDataKeys.ts", "./src/background/actions/action-hub.ts", @@ -247,9 +267,12 @@ "./src/common/components/visualization-toggle.tsx", "./src/common/components/with-store-subscription.tsx", "./src/common/configs/a11y-insights-rule-resources.ts", + "./src/common/configs/assessment-visualization-configuration.ts", "./src/common/configs/inspect-configuration-factory.ts", "./src/common/configs/test-mode.ts", "./src/common/configs/unified-result-property-configurations.tsx", + "./src/common/configs/visualization-configuration-factory.ts", + "./src/common/configs/visualization-configuration.ts", "./src/common/date-provider.ts", "./src/common/document-manipulator.ts", "./src/common/dropdown-click-handler.ts", @@ -346,8 +369,11 @@ "./src/electron/views/results/components/title-bar.tsx", "./src/electron/views/root-container/components/platform-body-class-modifier.tsx", "./src/injected/all-frame-runner.ts", + "./src/injected/analyzer-state-update-handler.ts", + "./src/injected/analyzers/analyzer-provider.ts", "./src/injected/analyzers/analyzer.ts", "./src/injected/analyzers/base-analyzer.ts", + "./src/injected/analyzers/batched-rule-analyzer.ts", "./src/injected/analyzers/filter-results.ts", "./src/injected/analyzers/focus-traps-handler.ts", "./src/injected/analyzers/get-analyzer-message-types.ts", @@ -362,6 +388,8 @@ "./src/injected/client-store-listener.ts", "./src/injected/client-utils.ts", "./src/injected/constants.ts", + "./src/injected/details-dialog-handler.ts", + "./src/injected/dialog-renderer-impl.tsx", "./src/injected/dialog-renderer.ts", "./src/injected/element-based-view-model-creator.ts", "./src/injected/element-finder-by-path.ts", @@ -373,6 +401,9 @@ "./src/injected/get-decorated-axe-node.ts", "./src/injected/iframe-detector.ts", "./src/injected/inspect-controller.ts", + "./src/injected/is-visualization-enabled.ts", + "./src/injected/layered-details-dialog-component.tsx", + "./src/injected/main-window-context.ts", "./src/injected/path-snippet-controller.ts", "./src/injected/scan-incomplete-warning-detector.ts", "./src/injected/scanner-utils.ts", @@ -389,38 +420,14 @@ "./src/injected/target-page-action-message-creator.ts", "./src/injected/visualization-instance-processor.ts", "./src/injected/visualization-needs-update.ts", - "./src/injected/visualization/accessible-names-formatter.ts", - "./src/injected/visualization/base-drawer.ts", - "./src/injected/visualization/center-position-calculator.ts", - "./src/injected/visualization/drawer-utils.ts", - "./src/injected/visualization/drawer.ts", - "./src/injected/visualization/failure-instance-formatter.ts", - "./src/injected/visualization/focus-indicator-creator.ts", - "./src/injected/visualization/focus-indicator.ts", - "./src/injected/visualization/formatter.ts", - "./src/injected/visualization/frame-formatter.ts", - "./src/injected/visualization/get-cell-and-header-elements.ts", - "./src/injected/visualization/get-visualization-instances-for-tab-stops.ts", - "./src/injected/visualization/heading-formatter.ts", - "./src/injected/visualization/highlight-box-drawer.ts", - "./src/injected/visualization/highlight-box.tsx", - "./src/injected/visualization/landmark-formatter.ts", - "./src/injected/visualization/null-drawer.ts", - "./src/injected/visualization/point.ts", - "./src/injected/visualization/root-container-creator.ts", - "./src/injected/visualization/single-target-drawer.ts", - "./src/injected/visualization/single-target-formatter.ts", - "./src/injected/visualization/svg-constants.ts", - "./src/injected/visualization/svg-shape-factory.ts", - "./src/injected/visualization/svg-solid-shadow-filter-factory.ts", - "./src/injected/visualization/tabbed-item.ts", - "./src/injected/visualization/table-headers-formatter.ts", + "./src/injected/visualization-type-drawer-registrar.ts", "./src/issue-filing/common/create-issue-details-builder-for-unified.ts", "./src/issue-filing/common/create-issue-details-builder.ts", "./src/issue-filing/common/create-settings-getter.ts", "./src/issue-filing/common/http-query-builder.ts", "./src/issue-filing/common/issue-details-builder.ts", "./src/issue-filing/common/issue-filing-url-string-utils.ts", + "./src/issue-filing/rule-result-to-issue-filing-data.ts", "./src/issue-filing/services/azure-boards/azure-boards-issue-filing-settings.tsx", "./src/issue-filing/services/azure-boards/create-azure-boards-issue-filing-url.ts", "./src/issue-filing/services/github/create-github-issue-filing-url.ts", @@ -432,6 +439,7 @@ "./src/popup/components/header.tsx", "./src/popup/components/launch-pad-item-row.tsx", "./src/popup/components/launch-pad.tsx", + "./src/popup/handlers/diagnostic-view-toggle-click-handler.ts", "./src/popup/incompatible-browser-renderer.tsx", "./src/popup/popup-init-with-react-devtools.ts", "./src/popup/target-tab-finder.ts", @@ -564,9 +572,19 @@ "src/DetailsView/components/details-view-overlay/settings-panel/**/*", "src/DetailsView/components/no-content-available/**/*", "src/Devtools/**/*", + "src/ad-hoc-visualizations/**/*", "src/ad-hoc-visualizations/calculated-tab-stops/**/*", + "src/assessments/audio-video-only/test-steps/**/*", "src/assessments/common/**/*", + "src/assessments/errors/test-steps/**/*", "src/assessments/language/common/**/*", + "src/assessments/language/test-steps/**/*", + "src/assessments/live-multimedia/test-steps/**/*", + "src/assessments/parsing/test-steps/**/*", + "src/assessments/pointer-motion/test-steps/**/*", + "src/assessments/prerecorded-multimedia/test-steps/**/*", + "src/assessments/repetitive-content/test-steps/**/*", + "src/assessments/timed-events/test-steps/**/*", "src/background/global-action-creators/registrar/**/*", "src/background/injector/**/*", "src/common/action/**/*", @@ -607,8 +625,10 @@ "src/fast-pass/**/*", "src/icons/**/*", "src/injected/adapters/**/*", + "src/injected/components/**/*", "src/injected/frameCommunicators/**/*", "src/injected/styles/**/*", + "src/injected/visualization/**/*", "src/issue-filing/common/markup/**/*", "src/packages/accessibility-insights-ui/**/*", "src/popup/Styles/**/*",