From 7d592865b17197175e23ce1cb6de6d1ce4ea6444 Mon Sep 17 00:00:00 2001
From: Wahaj <32555133+waabid@users.noreply.github.com>
Date: Thu, 14 May 2020 14:16:51 -0700
Subject: [PATCH 01/15] feat(nav-bar-content): adding requirement table section
(#2681)
---
.../left-nav/requirement-table-section.tsx | 86 +++++++++++++++++++
.../requirement-table-section.test.tsx.snap | 64 ++++++++++++++
.../requirement-table-section.test.tsx | 84 ++++++++++++++++++
3 files changed, 234 insertions(+)
create mode 100644 src/DetailsView/components/left-nav/requirement-table-section.tsx
create mode 100644 src/tests/unit/tests/DetailsView/components/left-nav/__snapshots__/requirement-table-section.test.tsx.snap
create mode 100644 src/tests/unit/tests/DetailsView/components/left-nav/requirement-table-section.test.tsx
diff --git a/src/DetailsView/components/left-nav/requirement-table-section.tsx b/src/DetailsView/components/left-nav/requirement-table-section.tsx
new file mode 100644
index 00000000000..91cd7adfa28
--- /dev/null
+++ b/src/DetailsView/components/left-nav/requirement-table-section.tsx
@@ -0,0 +1,86 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+import { AssessmentDefaultMessageGenerator } from 'assessments/assessment-default-message-generator';
+import { AssessmentsProvider } from 'assessments/types/assessments-provider';
+import { Requirement } from 'assessments/types/requirement';
+import { NamedFC } from 'common/react/named-fc';
+import {
+ AssessmentNavState,
+ GeneratedAssessmentInstance,
+ ManualTestStepResult,
+} from 'common/types/store-data/assessment-result-data';
+import { FeatureFlagStoreData } from 'common/types/store-data/feature-flag-store-data';
+import { PathSnippetStoreData } from 'common/types/store-data/path-snippet-store-data';
+import { AssessmentInstanceTable } from 'DetailsView/components/assessment-instance-table';
+import { ManualTestStepView } from 'DetailsView/components/manual-test-step-view';
+import { AssessmentInstanceTableHandler } from 'DetailsView/handlers/assessment-instance-table-handler';
+import { Spinner, SpinnerSize } from 'office-ui-fabric-react';
+import * as React from 'react';
+import { DictionaryStringTo } from 'types/common-types';
+
+export type RequirementTableSectionProps = {
+ assessmentNavState: AssessmentNavState;
+ requirement: Requirement;
+ instancesMap: DictionaryStringTo;
+ assessmentInstanceTableHandler: AssessmentInstanceTableHandler;
+ assessmentsProvider: AssessmentsProvider;
+ featureFlagStoreData: FeatureFlagStoreData;
+ pathSnippetStoreData: PathSnippetStoreData;
+ scanningInProgress: boolean;
+ manualRequirementResultMap: DictionaryStringTo;
+ assessmentDefaultMessageGenerator: AssessmentDefaultMessageGenerator;
+ isRequirementScanned: boolean;
+ selectedRequirementHasVisualHelper: boolean;
+};
+
+export const RequirementTableSection = NamedFC(
+ 'RequirementTableSection',
+ props => {
+ if (props.requirement.isManual) {
+ return (
+
+ );
+ }
+
+ if (props.scanningInProgress) {
+ return (
+
+ );
+ }
+
+ const renderScanCompleteAlert = () => {
+ if (!props.requirement.isManual && props.isRequirementScanned) {
+ return ;
+ }
+ };
+
+ return (
+
+ {renderScanCompleteAlert()}
+ Instances
+
+
+ );
+ },
+);
diff --git a/src/tests/unit/tests/DetailsView/components/left-nav/__snapshots__/requirement-table-section.test.tsx.snap b/src/tests/unit/tests/DetailsView/components/left-nav/__snapshots__/requirement-table-section.test.tsx.snap
new file mode 100644
index 00000000000..7bc3fac42a5
--- /dev/null
+++ b/src/tests/unit/tests/DetailsView/components/left-nav/__snapshots__/requirement-table-section.test.tsx.snap
@@ -0,0 +1,64 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`RequirementTableSection render ManualTestStepView when requirement is manual 1`] = `
+
+`;
+
+exports[`RequirementTableSection render Spinner when scanning in progress 1`] = `
+
+`;
+
+exports[`RequirementTableSection render instance table 1`] = `
+
+
+ Instances
+
+
+
+`;
diff --git a/src/tests/unit/tests/DetailsView/components/left-nav/requirement-table-section.test.tsx b/src/tests/unit/tests/DetailsView/components/left-nav/requirement-table-section.test.tsx
new file mode 100644
index 00000000000..4be15f5f700
--- /dev/null
+++ b/src/tests/unit/tests/DetailsView/components/left-nav/requirement-table-section.test.tsx
@@ -0,0 +1,84 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+import { AssessmentsProvider } from 'assessments/types/assessments-provider';
+import { Requirement } from 'assessments/types/requirement';
+import { ManualTestStepResult } from 'common/types/store-data/assessment-result-data';
+import { FeatureFlagStoreData } from 'common/types/store-data/feature-flag-store-data';
+import { PathSnippetStoreData } from 'common/types/store-data/path-snippet-store-data';
+import {
+ RequirementTableSection,
+ RequirementTableSectionProps,
+} from 'DetailsView/components/left-nav/requirement-table-section';
+import { AssessmentInstanceTableHandler } from 'DetailsView/handlers/assessment-instance-table-handler';
+import { shallow } from 'enzyme';
+import * as React from 'react';
+import { DictionaryStringTo } from 'types/common-types';
+
+describe('RequirementTableSection', () => {
+ let props: RequirementTableSectionProps;
+ let manualRequirementResultMapStub: DictionaryStringTo;
+ let assessmentInstanceTableHandlerStub: AssessmentInstanceTableHandler;
+ let assessmentProviderStub: AssessmentsProvider;
+ let featureFlagStoreDataStub: FeatureFlagStoreData;
+ let pathSnippetStoreDataStub: PathSnippetStoreData;
+
+ beforeEach(() => {
+ assessmentInstanceTableHandlerStub = {
+ changeRequirementStatus: null,
+ } as AssessmentInstanceTableHandler;
+ manualRequirementResultMapStub = {
+ 'some manual test step result id': null,
+ };
+ assessmentProviderStub = {
+ all: null,
+ } as AssessmentsProvider;
+ featureFlagStoreDataStub = {
+ 'some feature flag': true,
+ };
+ pathSnippetStoreDataStub = {
+ path: null,
+ } as PathSnippetStoreData;
+
+ props = {
+ assessmentNavState: {
+ selectedTestSubview: 'some test view',
+ selectedTestType: -1,
+ },
+ manualRequirementResultMap: manualRequirementResultMapStub,
+ assessmentInstanceTableHandler: assessmentInstanceTableHandlerStub,
+ assessmentsProvider: assessmentProviderStub,
+ featureFlagStoreData: featureFlagStoreDataStub,
+ pathSnippetStoreData: pathSnippetStoreDataStub,
+ requirement: {
+ isManual: false,
+ getDefaultMessage: _ => null,
+ renderInstanceTableHeader: (_, a) => null,
+ },
+ } as RequirementTableSectionProps;
+ });
+
+ test('render ManualTestStepView when requirement is manual', () => {
+ props.requirement = {
+ isManual: true,
+ } as Requirement;
+
+ const testObject = shallow();
+
+ expect(testObject.getElement()).toMatchSnapshot();
+ });
+
+ test('render Spinner when scanning in progress', () => {
+ props.scanningInProgress = true;
+
+ const testObject = shallow();
+
+ expect(testObject.getElement()).toMatchSnapshot();
+ });
+
+ test('render instance table', () => {
+ const testObject = shallow();
+
+ expect(testObject.getElement()).toMatchSnapshot();
+ });
+});
From 010f34e1d2936e2415f530f928d99caaf4860837 Mon Sep 17 00:00:00 2001
From: Dan Bjorge
Date: Thu, 14 May 2020 14:58:34 -0700
Subject: [PATCH 02/15] fix: auto-pass main landmark requirements for
no-landmark pages (#2644)
#### Description of changes
#2521 tracks an issue where it wasn't clear what the expectations on a user were for testing the Landmarks "primary content" and "no repeating content" requirements on pages with no landmarks.
The proposed fix for that was a text update + making the requirements pass automatically on pages that have no landmarks.
This fix involves a significant bit of new behavior. We wanted to *keep* the 2 requirements in question as manual requirements, not assisted requirements, since it's possible for a page to have no main landmarks and for a user to need to manually enter a failure not associated with any instance we might show in an instance list. However, this is the first time we're assigning auto-pass behavior to a manual test; in all other cases where we support auto-pass, it works by looking for an assisted requirement with no matching instances.
This new behavior is especially challenging because the set of instances required for auto-passing ("are there **any** landmarks on the page?") is different from the set of instances required for visualization ("what are all the **main** landmarks on the page?").
To support this, I've added 2 new features to `AssessmentStore`'s `Requirement` processing:
* A new `isVisualizationSupportedForResult` property which `Requirement`s can use to indicate that certain results returned by their analyzers should not support being visualized (by default, all results support visualization)
* A new `getInitialManualTestStatus` property which manual `Requirement`s can use to infer an initial pass/fail state after scanning for results (by default, a manual requirement is put in the UNKNOWN state regardless of analysis results)
These are used by the updated requirements by updating their analyzers to use the `unique-landmark` rule to look for *all* landmarks instead of the old behavior of looking only for main landmarks, use `isVisualizationSupportedForResult` to only visualize the main landmarks (like before), and use `getInitialManualTestStatus` to set a "PASS" status if the scan completes and there are no instances with the landmark role data from the `unique-landmark` rule.
New behavior:
**no landmarks: "Primary content" and "No repeating content" automatically pass**
![screen recording of no-landmarks interactions](https://user-images.githubusercontent.com/376284/81753659-1ef3ea00-9469-11ea-8646-e394ffff61de.gif)
**only non-main landmarks: "Primary content" and "No repeating content" don't auto-pass and show no matching instances to visualize**
![screen recording of banner-landmark-only interactions](https://user-images.githubusercontent.com/376284/81753648-1ac7cc80-9469-11ea-9c90-05f8d7243088.gif)
**Mix of main and non-main landmarks: "Primary content" and "No repeating content" don't auto-pass and visualize only the main landmark**
![screen recording of mixed-landmarks interactions](https://user-images.githubusercontent.com/376284/81753619-0a175680-9469-11ea-9d6e-40131889cf46.gif)
#### Pull request checklist
- [x] Addresses an existing issue: #2521
- [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`.
- [x] (UI changes only) Added screenshots/GIFs to description above
- [x] (UI changes only) Verified usability with NVDA/JAWS
---
...ssessment-visualization-enabled-toggle.tsx | 17 +-
src/assessments/assessment-builder.tsx | 20 +
.../landmarks/auto-pass-if-no-landmarks.ts | 14 +
.../landmarks/does-result-have-main-role.ts | 13 +
.../test-steps/no-repeating-content.tsx | 38 +-
.../landmarks/test-steps/primary-content.tsx | 42 +-
src/assessments/types/requirement.ts | 8 +
src/background/assessment-data-converter.ts | 7 +
src/background/stores/assessment-store.ts | 58 +-
.../store-data/assessment-result-data.ts | 1 +
src/scanner/custom-rule-configurations.ts | 2 -
src/scanner/custom-rules/landmark-rule.ts | 15 -
.../visual-helper-toggle-config-builder.ts | 32 +-
...ment-visualization-enabled-toggle.test.tsx | 324 ++++++-----
.../auto-pass-if-no-landmarks.test.ts | 40 ++
.../does-result-have-main-role.test.ts | 71 +++
.../assessment-data-converter.test.ts | 543 +++++++++---------
.../assessment-store.test.ts.snap | 4 +-
.../stores/assessment-store.test.ts | 316 ++++++++--
.../custom-rules/landmark-role.test.ts | 14 -
20 files changed, 1049 insertions(+), 530 deletions(-)
create mode 100644 src/assessments/landmarks/auto-pass-if-no-landmarks.ts
create mode 100644 src/assessments/landmarks/does-result-have-main-role.ts
delete mode 100644 src/scanner/custom-rules/landmark-rule.ts
create mode 100644 src/tests/unit/tests/assessments/landmarks/auto-pass-if-no-landmarks.test.ts
create mode 100644 src/tests/unit/tests/assessments/landmarks/does-result-have-main-role.test.ts
delete mode 100644 src/tests/unit/tests/scanner/custom-rules/landmark-role.test.ts
diff --git a/src/DetailsView/components/assessment-visualization-enabled-toggle.tsx b/src/DetailsView/components/assessment-visualization-enabled-toggle.tsx
index d3ef06bcf53..461e78ad1c3 100644
--- a/src/DetailsView/components/assessment-visualization-enabled-toggle.tsx
+++ b/src/DetailsView/components/assessment-visualization-enabled-toggle.tsx
@@ -1,13 +1,12 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
import { GeneratedAssessmentInstance } from 'common/types/store-data/assessment-result-data';
-import { isEmpty } from 'lodash';
import { BaseVisualHelperToggle } from './base-visual-helper-toggle';
export class AssessmentVisualizationEnabledToggle extends BaseVisualHelperToggle {
- protected isDisabled(filteredInstances: GeneratedAssessmentInstance<{}, {}>[]): boolean {
- return isEmpty(filteredInstances);
+ protected isDisabled(instances: GeneratedAssessmentInstance<{}, {}>[]): boolean {
+ return !this.isAnyInstanceVisualizable(instances);
}
protected isChecked(instances: GeneratedAssessmentInstance<{}, {}>[]): boolean {
@@ -28,10 +27,16 @@ export class AssessmentVisualizationEnabledToggle extends BaseVisualHelperToggle
};
private isAnyInstanceVisible(instances: GeneratedAssessmentInstance<{}, {}>[]): boolean {
+ const testStep = this.props.assessmentNavState.selectedTestSubview;
return instances.some(
- instance =>
- instance.testStepResults[this.props.assessmentNavState.selectedTestSubview]
- .isVisualizationEnabled,
+ instance => instance.testStepResults[testStep].isVisualizationEnabled,
+ );
+ }
+
+ private isAnyInstanceVisualizable(instances: GeneratedAssessmentInstance<{}, {}>[]): boolean {
+ const testStep = this.props.assessmentNavState.selectedTestSubview;
+ return instances.some(
+ instance => instance.testStepResults[testStep].isVisualizationSupported,
);
}
}
diff --git a/src/assessments/assessment-builder.tsx b/src/assessments/assessment-builder.tsx
index b150d41e3b5..a01c3f3bed5 100644
--- a/src/assessments/assessment-builder.tsx
+++ b/src/assessments/assessment-builder.tsx
@@ -10,6 +10,7 @@ import { RequirementComparer } from 'common/assessment/requirement-comparer';
import { AssessmentVisualizationConfiguration } from 'common/configs/assessment-visualization-configuration';
import { Messages } from 'common/messages';
import { ManualTestStatus } from 'common/types/manual-test-status';
+import { InstanceIdToInstanceDataMap } from 'common/types/store-data/assessment-result-data';
import { FeatureFlagStoreData } from 'common/types/store-data/feature-flag-store-data';
import { AssessmentScanData, ScanData } from 'common/types/store-data/visualization-store-data';
import {
@@ -52,6 +53,15 @@ export class AssessmentBuilder {
requirement.getInstanceStatus = AssessmentBuilder.getInstanceStatus;
}
+ if (!requirement.getInitialManualTestStatus) {
+ requirement.getInitialManualTestStatus = AssessmentBuilder.getInitialManualTestStatus;
+ }
+
+ if (!requirement.isVisualizationSupportedForResult) {
+ requirement.isVisualizationSupportedForResult =
+ AssessmentBuilder.isVisualizationSupportedForResult;
+ }
+
if (!requirement.getInstanceStatusColumns) {
requirement.getInstanceStatusColumns = AssessmentBuilder.getInstanceStatusColumns;
}
@@ -75,6 +85,16 @@ export class AssessmentBuilder {
return ManualTestStatus.UNKNOWN;
}
+ private static getInitialManualTestStatus(
+ instances: InstanceIdToInstanceDataMap,
+ ): ManualTestStatus {
+ return ManualTestStatus.UNKNOWN;
+ }
+
+ private static isVisualizationSupportedForResult(result: DecoratedAxeNodeResult): boolean {
+ return true;
+ }
+
private static getInstanceStatusColumns(): Readonly[] {
return [
{
diff --git a/src/assessments/landmarks/auto-pass-if-no-landmarks.ts b/src/assessments/landmarks/auto-pass-if-no-landmarks.ts
new file mode 100644
index 00000000000..4a2d28673a8
--- /dev/null
+++ b/src/assessments/landmarks/auto-pass-if-no-landmarks.ts
@@ -0,0 +1,14 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+import { ManualTestStatus } from 'common/types/manual-test-status';
+import { InstanceIdToInstanceDataMap } from 'common/types/store-data/assessment-result-data';
+import { some } from 'lodash';
+
+export function autoPassIfNoLandmarks(instanceData: InstanceIdToInstanceDataMap): ManualTestStatus {
+ const someInstanceHasLandmarkRole = some(
+ Object.values(instanceData),
+ instance => instance.propertyBag != null && instance.propertyBag['role'] != null,
+ );
+
+ return someInstanceHasLandmarkRole ? ManualTestStatus.UNKNOWN : ManualTestStatus.PASS;
+}
diff --git a/src/assessments/landmarks/does-result-have-main-role.ts b/src/assessments/landmarks/does-result-have-main-role.ts
new file mode 100644
index 00000000000..5a99b888217
--- /dev/null
+++ b/src/assessments/landmarks/does-result-have-main-role.ts
@@ -0,0 +1,13 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+import { DecoratedAxeNodeResult } from 'injected/scanner-utils';
+import { some } from 'lodash';
+
+export function doesResultHaveMainRole(result: DecoratedAxeNodeResult): boolean {
+ // This 'role' data is populated by the unique-landmark rule, which considers
+ // both explicit role attributes and implicit roles based on tag name
+ return (
+ some(result.any, checkResult => checkResult.data['role'] === 'main') ||
+ some(result.all, checkResult => checkResult.data['role'] === 'main')
+ );
+}
diff --git a/src/assessments/landmarks/test-steps/no-repeating-content.tsx b/src/assessments/landmarks/test-steps/no-repeating-content.tsx
index 9a0a84860b5..f10f2c03485 100644
--- a/src/assessments/landmarks/test-steps/no-repeating-content.tsx
+++ b/src/assessments/landmarks/test-steps/no-repeating-content.tsx
@@ -2,6 +2,7 @@
// Licensed under the MIT License.
import * as React from 'react';
+import { doesResultHaveMainRole } from 'assessments/landmarks/does-result-have-main-role';
import { VisualizationType } from 'common/types/visualization-type';
import { link } from 'content/link';
import * as content from 'content/test/landmarks/no-repeating-content';
@@ -10,10 +11,14 @@ import { AnalyzerConfigurationFactory } from '../../common/analyzer-configuratio
import { ManualTestRecordYourResults } from '../../common/manual-test-record-your-results';
import * as Markup from '../../markup';
import { Requirement } from '../../types/requirement';
+import { autoPassIfNoLandmarks } from '../auto-pass-if-no-landmarks';
import { LandmarkTestStep } from './test-steps';
const description: JSX.Element = (
- The main landmark must not contain any blocks of content that repeat across pages.
+
+ The main landmark must not contain any blocks of content
+ that repeat across pages.
+
);
const howToTest: JSX.Element = (
@@ -22,10 +27,33 @@ const howToTest: JSX.Element = (
The visual helper for this requirement highlights the page's{' '}
main landmark.
+
+
+ Note: If no landmarks are found, this requirement will automatically be marked as
+ pass.
+
+
-
- In the target page, examine the main landmark to verify that it does not contain any
- blocks of content that repeat across pages (e.g., site-wide navigation links).
+
Examine the target page to verify that all of the following are true:
+
+ -
+ The page has exactly one main landmark,
+ and
+
+ -
+ The main landmark does not contain any
+ blocks of content that repeat across pages (such as site-wide navigation
+ links).
+
+
+
+ Exception: If a page has nested document or{' '}
+ application roles (typically applied to{' '}
+ or elements),
+ each nested document or application may also{' '}
+ have one main landmark.
+
@@ -38,11 +66,13 @@ export const NoRepeatingContent: Requirement = {
description,
howToTest,
isManual: true,
+ getInitialManualTestStatus: autoPassIfNoLandmarks,
+ isVisualizationSupportedForResult: doesResultHaveMainRole,
guidanceLinks: [link.WCAG_1_3_1, link.WCAG_2_4_1],
getAnalyzer: provider =>
provider.createRuleAnalyzer(
AnalyzerConfigurationFactory.forScanner({
- rules: ['main-landmark'],
+ rules: ['unique-landmark'],
key: LandmarkTestStep.noRepeatingContent,
testType: VisualizationType.LandmarksAssessment,
}),
diff --git a/src/assessments/landmarks/test-steps/primary-content.tsx b/src/assessments/landmarks/test-steps/primary-content.tsx
index 6f13b711e4f..f76a938feac 100644
--- a/src/assessments/landmarks/test-steps/primary-content.tsx
+++ b/src/assessments/landmarks/test-steps/primary-content.tsx
@@ -2,6 +2,7 @@
// Licensed under the MIT License.
import * as React from 'react';
+import { doesResultHaveMainRole } from 'assessments/landmarks/does-result-have-main-role';
import { VisualizationType } from 'common/types/visualization-type';
import { link } from 'content/link';
import * as content from 'content/test/landmarks/primary-content';
@@ -10,19 +11,48 @@ import { AnalyzerConfigurationFactory } from '../../common/analyzer-configuratio
import { ManualTestRecordYourResults } from '../../common/manual-test-record-your-results';
import * as Markup from '../../markup';
import { Requirement } from '../../types/requirement';
+import { autoPassIfNoLandmarks } from '../auto-pass-if-no-landmarks';
import { LandmarkTestStep } from './test-steps';
const description: JSX.Element = (
- The main landmark must contain all of the page's primary content.
+
+ The main landmark must contain all of the page's primary
+ content.
+
);
const howToTest: JSX.Element = (
-
The visual helper for this requirement highlights the page's main landmark.
+
+ The visual helper for this requirement highlights the page's{' '}
+ main landmark.
+
+
+
+ Note: If no landmarks are found, this requirement will automatically be marked as
+ pass.
+
+
-
- In the target page, examine the main landmark to
- verify that it contains all of the page's primary content.
+
Examine the target page to verify that all of the following are true:
+
+ -
+ The page has exactly one main landmark,
+ and
+
+ -
+ The main landmark contains all of the
+ page's primary content.
+
+
+
+ Exception: If a page has nested document or{' '}
+ application roles (typically applied to{' '}
+ or elements),
+ each nested document or application may also{' '}
+ have one main landmark.
+
@@ -35,11 +65,13 @@ export const PrimaryContent: Requirement = {
description,
howToTest,
isManual: true,
+ getInitialManualTestStatus: autoPassIfNoLandmarks,
+ isVisualizationSupportedForResult: doesResultHaveMainRole,
guidanceLinks: [link.WCAG_1_3_1, link.WCAG_2_4_1],
getAnalyzer: provider =>
provider.createRuleAnalyzer(
AnalyzerConfigurationFactory.forScanner({
- rules: ['main-landmark'],
+ rules: ['unique-landmark'],
key: LandmarkTestStep.primaryContent,
testType: VisualizationType.LandmarksAssessment,
}),
diff --git a/src/assessments/types/requirement.ts b/src/assessments/types/requirement.ts
index 2656094ff08..8ccb7fc4560 100644
--- a/src/assessments/types/requirement.ts
+++ b/src/assessments/types/requirement.ts
@@ -5,6 +5,7 @@ import { ManualTestStatus } from 'common/types/manual-test-status';
import {
AssessmentNavState,
GeneratedAssessmentInstance,
+ InstanceIdToInstanceDataMap,
} from 'common/types/store-data/assessment-result-data';
import { FeatureFlagStoreData } from 'common/types/store-data/feature-flag-store-data';
import { DetailsViewActionMessageCreator } from 'DetailsView/actions/details-view-action-message-creator';
@@ -39,10 +40,17 @@ export interface Requirement {
addFailureInstruction?: string;
infoAndExamples?: ContentPageComponent;
isManual: boolean;
+ // This is for semi-manual cases where we can't present a list of instances like an assisted
+ // test would, but can infer a PASS or FAIL state. If not specified, acts like () => UNKNOWN.
+ getInitialManualTestStatus?: (instances: InstanceIdToInstanceDataMap) => ManualTestStatus;
guidanceLinks: HyperlinkDefinition[];
columnsConfig?: InstanceTableColumn[];
getAnalyzer?: (provider: AnalyzerProvider) => Analyzer;
getVisualHelperToggle?: (props: VisualHelperToggleConfig) => JSX.Element;
+ // Any results this returns false for will be omitted from visual helper displays, but still
+ // present for the purposes of instance lists or getInitialManualTestStatus. By default, all
+ // results support visualization.
+ isVisualizationSupportedForResult?: (result: DecoratedAxeNodeResult) => boolean;
visualizationInstanceProcessor?: VisualizationInstanceProcessorCallback<
PropertyBags,
PropertyBags
diff --git a/src/background/assessment-data-converter.ts b/src/background/assessment-data-converter.ts
index 0c5c7d24522..edc68817be1 100644
--- a/src/background/assessment-data-converter.ts
+++ b/src/background/assessment-data-converter.ts
@@ -29,6 +29,7 @@ export class AssessmentDataConverter {
stepName: string,
generateInstanceIdentifier: (instance: UniquelyIdentifiableInstances) => string,
getInstanceStatus: (result: DecoratedAxeNodeResult) => ManualTestStatus,
+ isVisualizationSupported: (result: DecoratedAxeNodeResult) => boolean,
): AssessmentInstancesMap {
let instancesMap: AssessmentInstancesMap = {};
@@ -51,6 +52,7 @@ export class AssessmentDataConverter {
stepName,
ruleResult,
getInstanceStatus,
+ isVisualizationSupported,
);
}
});
@@ -98,6 +100,7 @@ export class AssessmentDataConverter {
testStep: string,
ruleResult: DecoratedAxeNodeResult,
getInstanceStatus: (result: DecoratedAxeNodeResult) => ManualTestStatus,
+ isVisualizationSupported: (result: DecoratedAxeNodeResult) => boolean,
): GeneratedAssessmentInstance {
const target: string[] = elementAxeResult.target;
let testStepResults = {};
@@ -114,6 +117,7 @@ export class AssessmentDataConverter {
ruleResult,
elementAxeResult,
getInstanceStatus,
+ isVisualizationSupported,
);
let actualPropertyBag = {
@@ -163,6 +167,7 @@ export class AssessmentDataConverter {
status: ManualTestStatus.UNKNOWN,
isCapturedByUser: false,
failureSummary: null,
+ isVisualizationSupported: true,
isVisualizationEnabled: true,
isVisible: true,
};
@@ -172,12 +177,14 @@ export class AssessmentDataConverter {
ruleResult: DecoratedAxeNodeResult,
elementAxeResult: HtmlElementAxeResults,
getInstanceStatus: (result: DecoratedAxeNodeResult) => ManualTestStatus,
+ isVisualizationSupported: (result: DecoratedAxeNodeResult) => boolean,
): TestStepResult {
return {
id: ruleResult.id,
status: getInstanceStatus(ruleResult),
isCapturedByUser: false,
failureSummary: ruleResult.failureSummary,
+ isVisualizationSupported: isVisualizationSupported(ruleResult),
isVisualizationEnabled: false,
isVisible: true,
};
diff --git a/src/background/stores/assessment-store.ts b/src/background/stores/assessment-store.ts
index e8f9e7d7ce9..a2a5e4108d8 100644
--- a/src/background/stores/assessment-store.ts
+++ b/src/background/stores/assessment-store.ts
@@ -11,6 +11,7 @@ import {
AssessmentData,
AssessmentStoreData,
GeneratedAssessmentInstance,
+ InstanceIdToInstanceDataMap,
TestStepResult,
UserCapturedInstance,
} from 'common/types/store-data/assessment-result-data';
@@ -272,16 +273,17 @@ export class AssessmentStore extends BaseStoreImpl
{
private onChangeAssessmentVisualizationStateForAll = (
payload: ChangeInstanceSelectionPayload,
): void => {
- const config = this.assessmentsProvider
- .forType(payload.test)
- .getVisualizationConfiguration();
+ const { test, requirement } = payload;
+ const config = this.assessmentsProvider.forType(test).getVisualizationConfiguration();
const assessmentDataMap = config.getAssessmentData(this.state)
.generatedAssessmentInstancesMap;
+
forEach(assessmentDataMap, val => {
- const stepResult = val.testStepResults[payload.requirement];
+ const stepResult = val.testStepResults[requirement];
if (stepResult != null) {
- stepResult.isVisualizationEnabled = payload.isVisualizationEnabled;
+ stepResult.isVisualizationEnabled =
+ stepResult.isVisualizationSupported && payload.isVisualizationEnabled;
}
});
@@ -318,15 +320,14 @@ export class AssessmentStore extends BaseStoreImpl {
private onChangeAssessmentVisualizationState = (
payload: ChangeInstanceSelectionPayload,
): void => {
- const config = this.assessmentsProvider
- .forType(payload.test)
- .getVisualizationConfiguration();
+ const { test, requirement } = payload;
+ const config = this.assessmentsProvider.forType(test).getVisualizationConfiguration();
const assessmentData = config.getAssessmentData(this.state);
- const stepResult: TestStepResult =
- assessmentData.generatedAssessmentInstancesMap[payload.selector].testStepResults[
- payload.requirement
- ];
- stepResult.isVisualizationEnabled = payload.isVisualizationEnabled;
+ const instance = assessmentData.generatedAssessmentInstancesMap[payload.selector];
+ const stepResult: TestStepResult = instance.testStepResults[requirement];
+
+ stepResult.isVisualizationEnabled =
+ stepResult.isVisualizationSupported && payload.isVisualizationEnabled;
this.emitChanged();
};
@@ -382,6 +383,7 @@ export class AssessmentStore extends BaseStoreImpl {
step,
config.getInstanceIdentiferGenerator(step),
stepConfig.getInstanceStatus,
+ stepConfig.isVisualizationSupportedForResult,
);
assessmentData.generatedAssessmentInstancesMap = generatedAssessmentInstancesMap;
assessmentData.testStepStatus[step].isStepScanned = true;
@@ -432,12 +434,38 @@ export class AssessmentStore extends BaseStoreImpl {
testStepName: string,
testType: VisualizationType,
): void {
- const isManual = this.assessmentsProvider.getStep(testType, testStepName).isManual;
- if (isManual !== true) {
+ const step = this.assessmentsProvider.getStep(testType, testStepName);
+ const { isManual, getInitialManualTestStatus } = step;
+
+ if (isManual) {
+ this.applyInitialManualTestStatus(
+ assessmentData,
+ testStepName,
+ testType,
+ getInitialManualTestStatus,
+ );
+ } else {
this.updateTestStepStatusForGeneratedInstances(assessmentData, testStepName);
}
}
+ private applyInitialManualTestStatus(
+ assessmentData: AssessmentData,
+ testStepName: string,
+ testType: VisualizationType,
+ getInitialManualTestStatus: (InstanceIdToInstanceDataMap) => ManualTestStatus,
+ ): void {
+ const originalStatus = assessmentData.manualTestStepResultMap[testStepName].status;
+ if (originalStatus !== ManualTestStatus.UNKNOWN) {
+ return; // Never override an explicitly set status
+ }
+
+ const instanceMap = assessmentData.generatedAssessmentInstancesMap;
+ const status = getInitialManualTestStatus(instanceMap);
+ assessmentData.manualTestStepResultMap[testStepName].status = status;
+ this.updateManualTestStepStatus(assessmentData, testStepName, testType);
+ }
+
private getGroupResult(
instanceMap: DictionaryStringTo,
testStepName: string,
diff --git a/src/common/types/store-data/assessment-result-data.ts b/src/common/types/store-data/assessment-result-data.ts
index a44c441affa..f90213f4da2 100644
--- a/src/common/types/store-data/assessment-result-data.ts
+++ b/src/common/types/store-data/assessment-result-data.ts
@@ -61,6 +61,7 @@ export interface TestStepResult {
status: ManualTestStatus;
isCapturedByUser: boolean;
failureSummary: string;
+ isVisualizationSupported: boolean;
isVisualizationEnabled: boolean;
isVisible: boolean;
originalStatus?: ManualTestStatus;
diff --git a/src/scanner/custom-rule-configurations.ts b/src/scanner/custom-rule-configurations.ts
index 4791b40d7c2..481f380563f 100644
--- a/src/scanner/custom-rule-configurations.ts
+++ b/src/scanner/custom-rule-configurations.ts
@@ -10,7 +10,6 @@ import { frameTitleConfiguration } from './custom-rules/frame-title';
import { headerRuleConfiguration } from './custom-rules/header-rule';
import { headingConfiguration } from './custom-rules/heading-rule';
import { imageConfiguration } from './custom-rules/image-rule';
-import { landmarkConfiguration } from './custom-rules/landmark-rule';
import { linkFunctionConfiguration } from './custom-rules/link-function';
import { linkPurposeConfiguration } from './custom-rules/link-purpose';
import { nativeWidgetsDefaultConfiguration } from './custom-rules/native-widgets-default';
@@ -24,7 +23,6 @@ import { RuleConfiguration } from './iruleresults';
export const configuration: RuleConfiguration[] = [
headingConfiguration,
colorConfiguration,
- landmarkConfiguration,
uniqueLandmarkConfiguration,
imageConfiguration,
textAlternativeConfiguration,
diff --git a/src/scanner/custom-rules/landmark-rule.ts b/src/scanner/custom-rules/landmark-rule.ts
deleted file mode 100644
index 778f201e4a1..00000000000
--- a/src/scanner/custom-rules/landmark-rule.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-import { RuleConfiguration } from '../iruleresults';
-
-const landmarkCheckId: string = 'unique-landmark';
-
-export const landmarkConfiguration: RuleConfiguration = {
- checks: [],
- rule: {
- id: 'main-landmark',
- selector: '[role=main], main',
- any: [landmarkCheckId],
- enabled: false,
- },
-};
diff --git a/src/tests/unit/common/visual-helper-toggle-config-builder.ts b/src/tests/unit/common/visual-helper-toggle-config-builder.ts
index 23a86eb2aec..065653bf9b5 100644
--- a/src/tests/unit/common/visual-helper-toggle-config-builder.ts
+++ b/src/tests/unit/common/visual-helper-toggle-config-builder.ts
@@ -52,6 +52,7 @@ export class VisualHelperToggleConfigBuilder extends BaseDataBuilder,
} as GeneratedAssessmentInstance,
@@ -68,7 +70,8 @@ export class VisualHelperToggleConfigBuilder extends BaseDataBuilder,
} as GeneratedAssessmentInstance,
@@ -102,4 +105,29 @@ export class VisualHelperToggleConfigBuilder extends BaseDataBuilder,
+ } as GeneratedAssessmentInstance,
+ 'selector-2': {
+ testStepResults: {
+ [this.stepKey]: {
+ id: 'id1',
+ status: ManualTestStatus.PASS,
+ isVisualizationEnabled: false,
+ isVisualizationSupported: false,
+ } as TestStepResult,
+ } as AssessmentResultType,
+ } as GeneratedAssessmentInstance,
+ };
+ return this;
+ }
}
diff --git a/src/tests/unit/tests/DetailsView/components/assessment-visualization-enabled-toggle.test.tsx b/src/tests/unit/tests/DetailsView/components/assessment-visualization-enabled-toggle.test.tsx
index e9b8e86d8a1..99a457b0984 100644
--- a/src/tests/unit/tests/DetailsView/components/assessment-visualization-enabled-toggle.test.tsx
+++ b/src/tests/unit/tests/DetailsView/components/assessment-visualization-enabled-toggle.test.tsx
@@ -1,200 +1,234 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
-import * as Enzyme from 'enzyme';
-import * as React from 'react';
-import { IMock, Mock, Times } from 'typemoq';
import {
VisualizationToggle,
VisualizationToggleProps,
-} from '../../../../../common/components/visualization-toggle';
-import { DetailsViewActionMessageCreator } from '../../../../../DetailsView/actions/details-view-action-message-creator';
-import { AssessmentVisualizationEnabledToggle } from '../../../../../DetailsView/components/assessment-visualization-enabled-toggle';
-import { visualHelperText } from '../../../../../DetailsView/components/base-visual-helper-toggle';
-import { VisualHelperToggleConfigBuilder } from '../../../common/visual-helper-toggle-config-builder';
-import { VisualizationTogglePropsBuilder } from '../../../common/visualization-toggle-props-builder';
+} from 'common/components/visualization-toggle';
+import { DetailsViewActionMessageCreator } from 'DetailsView/actions/details-view-action-message-creator';
+import { AssessmentVisualizationEnabledToggle } from 'DetailsView/components/assessment-visualization-enabled-toggle';
+import { visualHelperText } from 'DetailsView/components/base-visual-helper-toggle';
+import * as Enzyme from 'enzyme';
+import * as React from 'react';
+import { VisualHelperToggleConfigBuilder } from 'tests/unit/common/visual-helper-toggle-config-builder';
+import { VisualizationTogglePropsBuilder } from 'tests/unit/common/visualization-toggle-props-builder';
+import { IMock, Mock, Times } from 'typemoq';
describe('AssessmentVisualizationEnabledToggle', () => {
const actionMessageCreatorMock: IMock = Mock.ofType(
DetailsViewActionMessageCreator,
);
- it('render with disabled message', () => {
- const props = new VisualHelperToggleConfigBuilder()
- .withToggleStepEnabled(true)
- .withToggleStepScanned(false)
- .withActionMessageCreator(actionMessageCreatorMock.object)
- .withEmptyFilteredMap()
- .build();
+ describe('render', () => {
+ it('is disabled when no instances exist', () => {
+ const props = new VisualHelperToggleConfigBuilder()
+ .withToggleStepEnabled(true)
+ .withToggleStepScanned(false)
+ .withActionMessageCreator(actionMessageCreatorMock.object)
+ .withEmptyFilteredMap()
+ .build();
- const wrapper = Enzyme.shallow();
+ const testSubject = Enzyme.shallow();
- const visualHelperClass = 'visual-helper';
- const toggleDiv = wrapper.find(`.${visualHelperClass}`);
+ expectDisabledTextLayout(testSubject);
- expect(toggleDiv.exists()).toBeTruthy();
+ const expectedToggleProps = getDefaultVisualizationTogglePropsBuilder()
+ .with('checked', false)
+ .with('disabled', true)
+ .build();
- const textDiv = toggleDiv.find(`.${visualHelperClass}-text`);
+ expectChildVisualizationToggleWith(expectedToggleProps, testSubject);
+ });
- expect(textDiv.exists()).toBeTruthy();
- expect(textDiv.childAt(0).text()).toEqual(visualHelperText);
+ it("is disabled when only instances that don't support visualization exist", () => {
+ const props = new VisualHelperToggleConfigBuilder()
+ .withToggleStepEnabled(true)
+ .withToggleStepScanned(false)
+ .withActionMessageCreator(actionMessageCreatorMock.object)
+ .withNonEmptyFilteredMap(false, false)
+ .build();
- const noMatchesWarningClass = 'no-matching-elements';
- expect(wrapper.find(`.${noMatchesWarningClass}`).exists()).toBeTruthy();
+ const testSubject = Enzyme.shallow();
- const toggle = wrapper.find(VisualizationToggle);
+ expectDisabledTextLayout(testSubject);
- const expectedToggleProps = getDefaultVisualizationTogglePropsBuilder()
- .with('checked', false)
- .with('disabled', true)
- .build();
+ const expectedToggleProps = getDefaultVisualizationTogglePropsBuilder()
+ .with('checked', false)
+ .with('disabled', true)
+ .build();
- assertVisualizationToggle(expectedToggleProps, toggle);
- });
+ expectChildVisualizationToggleWith(expectedToggleProps, testSubject);
+ });
- it('render: toggle not disabled', () => {
- const props = new VisualHelperToggleConfigBuilder()
- .withToggleStepEnabled(true)
- .withToggleStepScanned(false)
- .withActionMessageCreator(actionMessageCreatorMock.object)
- .withNonEmptyFilteredMap()
- .build();
+ it('is enabled but unchecked if step is enabled but all instance visualizations are disabled', () => {
+ const props = new VisualHelperToggleConfigBuilder()
+ .withToggleStepEnabled(true)
+ .withToggleStepScanned(false)
+ .withActionMessageCreator(actionMessageCreatorMock.object)
+ .withNonEmptyFilteredMap(false)
+ .build();
- const wrapper = Enzyme.shallow();
+ const testSubject = Enzyme.shallow();
- const visualHelperClass = 'visual-helper';
- const toggleDiv = wrapper.find(`.${visualHelperClass}`);
+ expectEnabledTextLayout(testSubject);
- expect(toggleDiv.exists()).toBeTruthy();
+ const expectedToggleProps = getDefaultVisualizationTogglePropsBuilder()
+ .with('checked', false)
+ .with('disabled', false)
+ .build();
- const textDiv = toggleDiv.find(`.${visualHelperClass}-text`);
+ expectChildVisualizationToggleWith(expectedToggleProps, testSubject);
+ });
- expect(textDiv.exists()).toBeTruthy();
- expect(textDiv.childAt(0).text()).toEqual(visualHelperText);
- expect(wrapper.find('strong').exists()).toBeFalsy();
- const toggle = wrapper.find(VisualizationToggle);
+ it('is enabled and checked if step and instance visualizations are both enabled', () => {
+ const props = new VisualHelperToggleConfigBuilder()
+ .withToggleStepEnabled(false)
+ .withToggleStepScanned(false)
+ .withActionMessageCreator(actionMessageCreatorMock.object)
+ .withNonEmptyFilteredMap(true)
+ .build();
- const expectedToggleProps = getDefaultVisualizationTogglePropsBuilder()
- .with('checked', false)
- .with('disabled', false)
- .build();
+ const testSubject = Enzyme.shallow();
- assertVisualizationToggle(expectedToggleProps, toggle);
- });
+ expectEnabledTextLayout(testSubject);
- it('render: have non empty instance map with a visible instance', () => {
- const props = new VisualHelperToggleConfigBuilder()
- .withToggleStepEnabled(false)
- .withToggleStepScanned(false)
- .withActionMessageCreator(actionMessageCreatorMock.object)
- .withNonEmptyFilteredMap(true)
- .build();
+ const expectedToggleProps = getDefaultVisualizationTogglePropsBuilder()
+ .with('checked', true)
+ .with('disabled', false)
+ .build();
- const wrapper = Enzyme.shallow();
+ expectChildVisualizationToggleWith(expectedToggleProps, testSubject);
+ });
- const visualHelperClass = 'visual-helper';
- const toggleDiv = wrapper.find(`.${visualHelperClass}`);
+ it("is enabled and checked if some instances support visualization and some don't", () => {
+ const props = new VisualHelperToggleConfigBuilder()
+ .withToggleStepEnabled(false)
+ .withToggleStepScanned(false)
+ .withActionMessageCreator(actionMessageCreatorMock.object)
+ .withMixedVisualizationSupportFilteredMap()
+ .build();
- expect(toggleDiv.exists()).toBeTruthy();
+ const testSubject = Enzyme.shallow();
- const textDiv = toggleDiv.find(`.${visualHelperClass}-text`);
+ expectEnabledTextLayout(testSubject);
- expect(textDiv.exists()).toBeTruthy();
- expect(textDiv.childAt(0).text()).toEqual(visualHelperText);
- expect(wrapper.find('strong').exists()).toBeFalsy();
+ const expectedToggleProps = getDefaultVisualizationTogglePropsBuilder()
+ .with('checked', true)
+ .with('disabled', false)
+ .build();
- const toggle = wrapper.find(VisualizationToggle);
+ expectChildVisualizationToggleWith(expectedToggleProps, testSubject);
+ });
- const expectedToggleProps = getDefaultVisualizationTogglePropsBuilder()
- .with('checked', true)
- .with('disabled', false)
- .build();
+ it('is enabled and unchecked if step and instance visualizations are both disabled', () => {
+ const props = new VisualHelperToggleConfigBuilder()
+ .withToggleStepEnabled(false)
+ .withToggleStepScanned(false)
+ .withActionMessageCreator(actionMessageCreatorMock.object)
+ .withNonEmptyFilteredMap(false)
+ .build();
- assertVisualizationToggle(expectedToggleProps, toggle);
- });
+ const testSubject = Enzyme.shallow();
- it('render: have non empty instance map without a visible instance', () => {
- const props = new VisualHelperToggleConfigBuilder()
- .withToggleStepEnabled(false)
- .withToggleStepScanned(false)
- .withActionMessageCreator(actionMessageCreatorMock.object)
- .withNonEmptyFilteredMap()
- .build();
+ expectEnabledTextLayout(testSubject);
- const wrapper = Enzyme.shallow();
+ const expectedToggleProps = getDefaultVisualizationTogglePropsBuilder()
+ .with('checked', false)
+ .with('disabled', false)
+ .build();
- const visualHelperClass = 'visual-helper';
- const toggleDiv = wrapper.find(`.${visualHelperClass}`);
+ expectChildVisualizationToggleWith(expectedToggleProps, testSubject);
+ });
- expect(toggleDiv.exists()).toBeTruthy();
+ function expectEnabledTextLayout(
+ testSubject: Enzyme.ShallowWrapper,
+ ): void {
+ const visualHelperClass = 'visual-helper';
+ const toggleDiv = testSubject.find(`.${visualHelperClass}`);
- const textDiv = toggleDiv.find(`.${visualHelperClass}-text`);
+ expect(toggleDiv.exists()).toBeTruthy();
- expect(textDiv.exists()).toBeTruthy();
- expect(textDiv.childAt(0).text()).toEqual(visualHelperText);
- expect(wrapper.find('strong').exists()).toBeFalsy();
- const toggle = wrapper.find(VisualizationToggle);
+ const textDiv = toggleDiv.find(`.${visualHelperClass}-text`);
- const expectedToggleProps = getDefaultVisualizationTogglePropsBuilder()
- .with('checked', false)
- .with('disabled', false)
- .build();
+ expect(textDiv.exists()).toBeTruthy();
+ expect(textDiv.childAt(0).text()).toEqual(visualHelperText);
+ expect(testSubject.find('strong').exists()).toBeFalsy();
+ }
- assertVisualizationToggle(expectedToggleProps, toggle);
- });
+ function expectDisabledTextLayout(
+ testSubject: Enzyme.ShallowWrapper,
+ ): void {
+ const visualHelperClass = 'visual-helper';
+ const toggleDiv = testSubject.find(`.${visualHelperClass}`);
+
+ expect(toggleDiv.exists()).toBeTruthy();
- it('enables all visualizations when none are shown', () => {
- const props = new VisualHelperToggleConfigBuilder()
- .withToggleStepEnabled(true)
- .withToggleStepScanned(false)
- .withActionMessageCreator(actionMessageCreatorMock.object)
- .build();
-
- const wrapper = Enzyme.shallow();
- actionMessageCreatorMock.reset();
- actionMessageCreatorMock
- .setup(acm =>
- acm.changeAssessmentVisualizationStateForAll(
- true,
- props.assessmentNavState.selectedTestType,
- props.assessmentNavState.selectedTestSubview,
- ),
- )
- .verifiable(Times.once());
-
- wrapper.find(VisualizationToggle).simulate('click');
-
- actionMessageCreatorMock.verifyAll();
+ const textDiv = toggleDiv.find(`.${visualHelperClass}-text`);
+
+ expect(textDiv.exists()).toBeTruthy();
+ expect(textDiv.childAt(0).text()).toEqual(visualHelperText);
+
+ const noMatchesWarningClass = 'no-matching-elements';
+ expect(testSubject.find(`.${noMatchesWarningClass}`).exists()).toBeTruthy();
+ }
});
- it('disables all visualizations when some are shown', () => {
- const props = new VisualHelperToggleConfigBuilder()
- .withToggleStepEnabled(true)
- .withToggleStepScanned(false)
- .withActionMessageCreator(actionMessageCreatorMock.object)
- .withNonEmptyFilteredMap(true)
- .build();
-
- const wrapper = Enzyme.shallow();
- actionMessageCreatorMock.reset();
- actionMessageCreatorMock
- .setup(acm =>
- acm.changeAssessmentVisualizationStateForAll(
- false,
- props.assessmentNavState.selectedTestType,
- props.assessmentNavState.selectedTestSubview,
- ),
- )
- .verifiable(Times.once());
-
- wrapper.find(VisualizationToggle).simulate('click');
-
- actionMessageCreatorMock.verifyAll();
+ describe('toggle behavior', () => {
+ it('enables all visualizations when none are shown', () => {
+ const props = new VisualHelperToggleConfigBuilder()
+ .withToggleStepEnabled(true)
+ .withToggleStepScanned(false)
+ .withActionMessageCreator(actionMessageCreatorMock.object)
+ .build();
+
+ const wrapper = Enzyme.shallow();
+ actionMessageCreatorMock.reset();
+ actionMessageCreatorMock
+ .setup(acm =>
+ acm.changeAssessmentVisualizationStateForAll(
+ true,
+ props.assessmentNavState.selectedTestType,
+ props.assessmentNavState.selectedTestSubview,
+ ),
+ )
+ .verifiable(Times.once());
+
+ wrapper.find(VisualizationToggle).simulate('click');
+
+ actionMessageCreatorMock.verifyAll();
+ });
+
+ it('disables all visualizations when some are shown', () => {
+ const props = new VisualHelperToggleConfigBuilder()
+ .withToggleStepEnabled(true)
+ .withToggleStepScanned(false)
+ .withActionMessageCreator(actionMessageCreatorMock.object)
+ .withNonEmptyFilteredMap(true)
+ .build();
+
+ const wrapper = Enzyme.shallow();
+ actionMessageCreatorMock.reset();
+ actionMessageCreatorMock
+ .setup(acm =>
+ acm.changeAssessmentVisualizationStateForAll(
+ false,
+ props.assessmentNavState.selectedTestType,
+ props.assessmentNavState.selectedTestSubview,
+ ),
+ )
+ .verifiable(Times.once());
+
+ wrapper.find(VisualizationToggle).simulate('click');
+
+ actionMessageCreatorMock.verifyAll();
+ });
});
- function assertVisualizationToggle(
+ function expectChildVisualizationToggleWith(
expectedProps: VisualizationToggleProps,
- visualizationToggle: Enzyme.ShallowWrapper,
+ testSubject: Enzyme.ShallowWrapper,
): void {
+ const visualizationToggle = testSubject.find(VisualizationToggle);
+
expect(visualizationToggle.exists()).toBeTruthy();
const actualProps = visualizationToggle.props();
diff --git a/src/tests/unit/tests/assessments/landmarks/auto-pass-if-no-landmarks.test.ts b/src/tests/unit/tests/assessments/landmarks/auto-pass-if-no-landmarks.test.ts
new file mode 100644
index 00000000000..ece051ee4ac
--- /dev/null
+++ b/src/tests/unit/tests/assessments/landmarks/auto-pass-if-no-landmarks.test.ts
@@ -0,0 +1,40 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+import { autoPassIfNoLandmarks } from 'assessments/landmarks/auto-pass-if-no-landmarks';
+import { ManualTestStatus } from 'common/types/manual-test-status';
+import { InstanceIdToInstanceDataMap } from 'common/types/store-data/assessment-result-data';
+
+describe('autoPassIfNoLandmarks', () => {
+ it('returns PASS for instance data with no landmarks', () => {
+ const input = makeInputDataWithLandmarkRoles([]);
+ expect(autoPassIfNoLandmarks(input)).toBe(ManualTestStatus.PASS);
+ });
+
+ it.each(['main', 'complementary'])(
+ 'returns UNKNOWN for instance data with one %s landmark',
+ (landmarkRole: string) => {
+ const input = makeInputDataWithLandmarkRoles([landmarkRole]);
+ expect(autoPassIfNoLandmarks(input)).toBe(ManualTestStatus.UNKNOWN);
+ },
+ );
+
+ it('returns UNKNOWN for instance data with multiple landmarks', () => {
+ const input = makeInputDataWithLandmarkRoles(['main', 'complementary', 'header']);
+ expect(autoPassIfNoLandmarks(input)).toBe(ManualTestStatus.UNKNOWN);
+ });
+
+ function makeInputDataWithLandmarkRoles(landmarkRoles: string[]): InstanceIdToInstanceDataMap {
+ const data: InstanceIdToInstanceDataMap = {};
+ for (const landmarkRole of landmarkRoles) {
+ data[`#element-with-${landmarkRole}`] = {
+ target: [`#element-with-${landmarkRole}`],
+ html: ``,
+ propertyBag: {
+ role: landmarkRole,
+ },
+ testStepResults: {},
+ };
+ }
+ return data;
+ }
+});
diff --git a/src/tests/unit/tests/assessments/landmarks/does-result-have-main-role.test.ts b/src/tests/unit/tests/assessments/landmarks/does-result-have-main-role.test.ts
new file mode 100644
index 00000000000..83295474935
--- /dev/null
+++ b/src/tests/unit/tests/assessments/landmarks/does-result-have-main-role.test.ts
@@ -0,0 +1,71 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+import { doesResultHaveMainRole } from 'assessments/landmarks/does-result-have-main-role';
+import { DecoratedAxeNodeResult } from 'injected/scanner-utils';
+
+describe('doesResultHaveMainRole', () => {
+ it('returns false for results with no check results', () => {
+ const input = { any: [], all: [] } as DecoratedAxeNodeResult;
+
+ expect(doesResultHaveMainRole(input)).toBe(false);
+ });
+
+ it('returns false for results with check results without role data', () => {
+ const input = {
+ any: [makeCheckResultWithRole(undefined)],
+ all: [makeCheckResultWithRole(undefined)],
+ } as DecoratedAxeNodeResult;
+
+ expect(doesResultHaveMainRole(input)).toBe(false);
+ });
+
+ it('returns false for results with check results with only non-main role data', () => {
+ const input = {
+ any: [makeCheckResultWithRole('complementary')],
+ all: [makeCheckResultWithRole('banner')],
+ } as DecoratedAxeNodeResult;
+
+ expect(doesResultHaveMainRole(input)).toBe(false);
+ });
+
+ it('returns true for results with an "any" check result with "main" role data', () => {
+ const input = {
+ any: [makeCheckResultWithRole('main')],
+ all: [],
+ } as DecoratedAxeNodeResult;
+
+ expect(doesResultHaveMainRole(input)).toBe(true);
+ });
+
+ it('returns true for results with an "all" check result with "main" role data', () => {
+ const input = {
+ any: [],
+ all: [makeCheckResultWithRole('main')],
+ } as DecoratedAxeNodeResult;
+
+ expect(doesResultHaveMainRole(input)).toBe(true);
+ });
+
+ it('returns true for results with mixed check results', () => {
+ const input = {
+ any: [makeCheckResultWithRole('banner'), makeCheckResultWithRole(undefined)],
+ all: [
+ makeCheckResultWithRole('main'),
+ makeCheckResultWithRole('banner'),
+ makeCheckResultWithRole(undefined),
+ ],
+ } as DecoratedAxeNodeResult;
+
+ expect(doesResultHaveMainRole(input)).toBe(true);
+ });
+
+ function makeCheckResultWithRole(role: string): FormattedCheckResult {
+ return {
+ id: 'test-check-id',
+ message: 'test check message',
+ data: {
+ role,
+ },
+ };
+ }
+});
diff --git a/src/tests/unit/tests/background/assessment-data-converter.test.ts b/src/tests/unit/tests/background/assessment-data-converter.test.ts
index c87b86145f7..911c9c97f5f 100644
--- a/src/tests/unit/tests/background/assessment-data-converter.test.ts
+++ b/src/tests/unit/tests/background/assessment-data-converter.test.ts
@@ -13,7 +13,7 @@ import { DecoratedAxeNodeResult, HtmlElementAxeResults } from '../../../../injec
import { TabStopEvent } from '../../../../injected/tab-stops-listener';
import { DictionaryStringTo } from '../../../../types/common-types';
-describe('AssessmentDataConverterTest', () => {
+describe('AssessmentDataConverter', () => {
let testSubject: AssessmentDataConverter;
const uid: string = 'uid123';
let testStep: string;
@@ -22,6 +22,7 @@ describe('AssessmentDataConverterTest', () => {
status: ManualTestStatus.UNKNOWN,
isCapturedByUser: false,
failureSummary: null,
+ isVisualizationSupported: true,
isVisualizationEnabled: true,
isVisible: true,
};
@@ -39,305 +40,285 @@ describe('AssessmentDataConverterTest', () => {
htmlStub = 'some html';
});
- test('generateAssessmentInstancesMap: property bag from any checks', () => {
- const expectedPropertyBag = {
- someProperty: 1,
- };
-
- const selectorMap: DictionaryStringTo = {
- [selectorStub]: {
- ruleResults: {
- rule1: {
- any: [
- {
- id: 'rule1',
- data: expectedPropertyBag,
- },
- ],
- html: htmlStub,
- id: 'id1',
- status: true,
- } as DecoratedAxeNodeResult,
+ describe('generateAssessmentInstancesMap', () => {
+ it('should ignore selectors with no rule results.', () => {
+ const selectorMap: DictionaryStringTo = {
+ [selectorStub]: {
+ ruleResults: {},
+ target: [selectorStub],
},
- target: [selectorStub],
- },
- };
-
- setupGenerateInstanceIdentifierMock(
- { target: [selectorStub], html: htmlStub },
- identifierStub,
- );
- const instanceMap = testSubject.generateAssessmentInstancesMap(
- null,
- selectorMap,
- testStep,
- generateInstanceIdentifierMock.object,
- () => ManualTestStatus.UNKNOWN,
- );
-
- expect(instanceMap[identifierStub].propertyBag).toEqual(expectedPropertyBag);
- });
-
- test(`generateAssessmentInstancesMap: previouslyGeneratedInstances is null,
- new rule result is not false and any data is there.`, () => {
- const selectorMap: DictionaryStringTo = {
- [selectorStub]: {
- ruleResults: {
- rule1: {
- any: [
- {
- id: 'rule1',
- data: { someProperty: 1 },
- },
- ],
- html: htmlStub,
- id: 'id1',
- status: true,
- } as DecoratedAxeNodeResult,
+ };
+ const previouslyGeneratedInstances = {};
+ const instanceMap = testSubject.generateAssessmentInstancesMap(
+ previouslyGeneratedInstances,
+ selectorMap,
+ testStep,
+ undefined,
+ null,
+ null,
+ );
+
+ expect(instanceMap).toEqual(previouslyGeneratedInstances);
+ });
+
+ it('should produce an empty map (not null) if previouslyGeneratedInstances is null and there are no rule results to add', () => {
+ const selectorMap: DictionaryStringTo = {
+ [selectorStub]: {
+ ruleResults: {},
+ target: [selectorStub],
},
- target: [selectorStub],
- },
- };
- const expectedResult = {
- [identifierStub]: {
- html: htmlStub,
- propertyBag: { someProperty: 1 },
- target: [selectorStub],
- testStepResults: {
- [testStep]: {
- id: 'id1',
- status: ManualTestStatus.UNKNOWN,
- isCapturedByUser: false,
- failureSummary: undefined,
- isVisible: true,
- isVisualizationEnabled: false,
+ };
+ const expectedResult = {};
+ const instanceMap = testSubject.generateAssessmentInstancesMap(
+ null,
+ selectorMap,
+ testStep,
+ undefined,
+ null,
+ null,
+ );
+
+ expect(instanceMap).toEqual(expectedResult);
+ });
+
+ it('should create a new instance wrapping the generated result if there is no existing instance matching the selector', () => {
+ const selectorMap: DictionaryStringTo = {
+ [selectorStub]: {
+ ruleResults: {
+ rule1: {
+ html: htmlStub,
+ id: 'id1',
+ status: false,
+ } as DecoratedAxeNodeResult,
},
+ target: [selectorStub],
},
- },
- };
-
- setupGenerateInstanceIdentifierMock(
- { target: [selectorStub], html: htmlStub },
- identifierStub,
- );
- const instanceMap = testSubject.generateAssessmentInstancesMap(
- null,
- selectorMap,
- testStep,
- generateInstanceIdentifierMock.object,
- () => ManualTestStatus.UNKNOWN,
- );
-
- expect(instanceMap).toEqual(expectedResult);
- });
-
- test(`generateAssessmentInstancesMap: previouslyGeneratedInstances is null,
- new rule result is null (shouldn't happen but covered).`, () => {
- const selectorMap: DictionaryStringTo = {
- [selectorStub]: {
- ruleResults: {},
- target: [selectorStub],
- },
- };
- const expectedResult = {};
- const instanceMap = testSubject.generateAssessmentInstancesMap(
- null,
- selectorMap,
- testStep,
- undefined,
- null,
- );
-
- expect(instanceMap).toEqual(expectedResult);
- });
-
- test(`generateAssessmentInstancesMap: previouslyGeneratedInstances is not null,
- new rule result is null (shouldn't happen but covered).`, () => {
- const selectorMap: DictionaryStringTo = {
- [selectorStub]: {
- ruleResults: {},
- target: [selectorStub],
- },
- };
- const previouslyGeneratedInstances = {};
- const instanceMap = testSubject.generateAssessmentInstancesMap(
- previouslyGeneratedInstances,
- selectorMap,
- testStep,
- undefined,
- null,
- );
-
- expect(instanceMap).toEqual(previouslyGeneratedInstances);
- });
-
- test(`generateAssessmentInstancesMap: previouslyGeneratedInstances is
- empty/does not match any new instances and any data is not there`, () => {
- const selectorMap: DictionaryStringTo = {
- [selectorStub]: {
- ruleResults: {
- rule1: {
- html: htmlStub,
- id: 'id1',
- status: false,
- } as DecoratedAxeNodeResult,
+ };
+ const expectedResult = {
+ [identifierStub]: {
+ html: htmlStub,
+ propertyBag: null,
+ target: [selectorStub],
+ testStepResults: {
+ [testStep]: {
+ id: 'id1',
+ status: ManualTestStatus.UNKNOWN,
+ isCapturedByUser: false,
+ failureSummary: undefined,
+ isVisible: true,
+ isVisualizationEnabled: false,
+ isVisualizationSupported: true,
+ },
+ },
},
- target: [selectorStub],
- },
- };
- const expectedResult = {
- [identifierStub]: {
- html: htmlStub,
- propertyBag: null,
- target: [selectorStub],
- testStepResults: {
- [testStep]: {
- id: 'id1',
- status: ManualTestStatus.UNKNOWN,
- isCapturedByUser: false,
- failureSummary: undefined,
- isVisible: true,
- isVisualizationEnabled: false,
+ };
+ setupGenerateInstanceIdentifierMock(
+ { target: [selectorStub], html: htmlStub },
+ identifierStub,
+ );
+ const instanceMap = testSubject.generateAssessmentInstancesMap(
+ {},
+ selectorMap,
+ testStep,
+ generateInstanceIdentifierMock.object,
+ () => ManualTestStatus.UNKNOWN,
+ () => true,
+ );
+
+ expect(instanceMap).toEqual(expectedResult);
+ });
+
+ it("should merge check results' data into the instance's propertyBag", () => {
+ const expectedPropertyBag = {
+ someProperty: 1,
+ };
+
+ const selectorMap: DictionaryStringTo = {
+ [selectorStub]: {
+ ruleResults: {
+ rule1: {
+ any: [
+ {
+ id: 'rule1',
+ data: expectedPropertyBag,
+ },
+ ],
+ html: htmlStub,
+ id: 'id1',
+ status: true,
+ } as DecoratedAxeNodeResult,
},
+ target: [selectorStub],
},
+ };
+
+ setupGenerateInstanceIdentifierMock(
+ { target: [selectorStub], html: htmlStub },
+ identifierStub,
+ );
+ const instanceMap = testSubject.generateAssessmentInstancesMap(
+ null,
+ selectorMap,
+ testStep,
+ generateInstanceIdentifierMock.object,
+ () => ManualTestStatus.UNKNOWN,
+ () => true,
+ );
+
+ expect(instanceMap[identifierStub].propertyBag).toEqual(expectedPropertyBag);
+ });
+
+ it.each([ManualTestStatus.FAIL, ManualTestStatus.UNKNOWN, ManualTestStatus.PASS])(
+ 'should use getInstanceStatus to determine the status of the generated step result',
+ (getInstanceStatusResult: ManualTestStatus) => {
+ const selectorMap: DictionaryStringTo = {
+ [selectorStub]: {
+ ruleResults: {
+ rule1: {
+ html: htmlStub,
+ id: 'id1',
+ status: false,
+ } as DecoratedAxeNodeResult,
+ },
+ target: [selectorStub],
+ },
+ };
+
+ setupGenerateInstanceIdentifierMock(
+ { target: [selectorStub], html: htmlStub },
+ identifierStub,
+ );
+ const instanceMap = testSubject.generateAssessmentInstancesMap(
+ {},
+ selectorMap,
+ testStep,
+ generateInstanceIdentifierMock.object,
+ () => getInstanceStatusResult,
+ () => true,
+ );
+
+ expect(instanceMap[identifierStub].testStepResults[testStep].status).toEqual(
+ getInstanceStatusResult,
+ );
},
- };
- setupGenerateInstanceIdentifierMock(
- { target: [selectorStub], html: htmlStub },
- identifierStub,
- );
- const instanceMap = testSubject.generateAssessmentInstancesMap(
- {},
- selectorMap,
- testStep,
- generateInstanceIdentifierMock.object,
- () => ManualTestStatus.UNKNOWN,
);
- expect(instanceMap).toEqual(expectedResult);
- });
-
- test('generateAssessmentInstancesMap: automated check status should be FAIL', () => {
- const selectorMap: DictionaryStringTo = {
- [selectorStub]: {
- ruleResults: {
- rule1: {
- html: htmlStub,
- id: 'id1',
- status: false,
- } as DecoratedAxeNodeResult,
- },
- target: [selectorStub],
- },
- };
- const expectedResult = {
- [identifierStub]: {
- html: htmlStub,
- propertyBag: null,
- target: [selectorStub],
- testStepResults: {
- [testStep]: {
- id: 'id1',
- status: ManualTestStatus.FAIL,
- isCapturedByUser: false,
- failureSummary: undefined,
- isVisible: true,
- isVisualizationEnabled: false,
+ it.each([true, false])(
+ 'should use isVisualizationSupported to determine the corresponding property of the generated step result',
+ (isVisualizationSupportedResult: boolean) => {
+ const selectorMap: DictionaryStringTo = {
+ [selectorStub]: {
+ ruleResults: {
+ rule1: {
+ html: htmlStub,
+ id: 'id1',
+ status: false,
+ } as DecoratedAxeNodeResult,
+ },
+ target: [selectorStub],
},
- },
+ };
+
+ setupGenerateInstanceIdentifierMock(
+ { target: [selectorStub], html: htmlStub },
+ identifierStub,
+ );
+ const instanceMap = testSubject.generateAssessmentInstancesMap(
+ {},
+ selectorMap,
+ testStep,
+ generateInstanceIdentifierMock.object,
+ () => ManualTestStatus.UNKNOWN,
+ () => isVisualizationSupportedResult,
+ );
+
+ expect(
+ instanceMap[identifierStub].testStepResults[testStep].isVisualizationSupported,
+ ).toEqual(isVisualizationSupportedResult);
},
- };
- setupGenerateInstanceIdentifierMock(
- { target: [selectorStub], html: htmlStub },
- identifierStub,
);
- const instanceMap = testSubject.generateAssessmentInstancesMap(
- {},
- selectorMap,
- testStep,
- generateInstanceIdentifierMock.object,
- () => ManualTestStatus.FAIL,
- );
-
- expect(instanceMap).toEqual(expectedResult);
- });
- test('generateAssessmentInstancesMap: previouslyGeneratedInstances contains matching instance', () => {
- const anotherTestStep = 'another test step';
- const selectorMap: DictionaryStringTo = {
- [selectorStub]: {
- ruleResults: {
- rule1: {
- any: [
- {
- id: 'rule1',
- data: { someProperty: 1 },
- },
- ],
- html: htmlStub,
- id: 'id1',
- status: false,
- } as DecoratedAxeNodeResult,
- },
- target: [selectorStub],
- },
- };
- const previouslyGeneratedInstances: AssessmentInstancesMap = {
- [identifierStub]: {
- html: htmlStub,
- propertyBag: { someProperty: 3 },
- target: [selectorStub],
- testStepResults: {
- [anotherTestStep]: {
- id: 'id2',
- status: ManualTestStatus.UNKNOWN,
- isCapturedByUser: false,
- failureSummary: undefined,
- isVisible: true,
- isVisualizationEnabled: true,
+ it('should merge results for a previously seen selector into the existing instance data', () => {
+ const anotherTestStep = 'another test step';
+ const selectorMap: DictionaryStringTo = {
+ [selectorStub]: {
+ ruleResults: {
+ rule1: {
+ any: [
+ {
+ id: 'rule1',
+ data: { someProperty: 1 },
+ },
+ ],
+ html: htmlStub,
+ id: 'id1',
+ status: false,
+ } as DecoratedAxeNodeResult,
},
+ target: [selectorStub],
},
- },
- };
- const expectedResult = {
- [identifierStub]: {
- html: htmlStub,
- propertyBag: { someProperty: 3 },
- target: [selectorStub],
- testStepResults: {
- [testStep]: {
- id: 'id1',
- status: ManualTestStatus.UNKNOWN,
- isCapturedByUser: false,
- failureSummary: undefined,
- isVisible: true,
- isVisualizationEnabled: false,
+ };
+ const previouslyGeneratedInstances: AssessmentInstancesMap = {
+ [identifierStub]: {
+ html: htmlStub,
+ propertyBag: { someProperty: 3 },
+ target: [selectorStub],
+ testStepResults: {
+ [anotherTestStep]: {
+ id: 'id2',
+ status: ManualTestStatus.UNKNOWN,
+ isCapturedByUser: false,
+ failureSummary: undefined,
+ isVisible: true,
+ isVisualizationEnabled: true,
+ isVisualizationSupported: true,
+ },
},
- [anotherTestStep]: {
- id: 'id2',
- status: ManualTestStatus.UNKNOWN,
- isCapturedByUser: false,
- failureSummary: undefined,
- isVisible: true,
- isVisualizationEnabled: true,
+ },
+ };
+ const expectedResult = {
+ [identifierStub]: {
+ html: htmlStub,
+ propertyBag: { someProperty: 3 },
+ target: [selectorStub],
+ testStepResults: {
+ [testStep]: {
+ id: 'id1',
+ status: ManualTestStatus.UNKNOWN,
+ isCapturedByUser: false,
+ failureSummary: undefined,
+ isVisible: true,
+ isVisualizationEnabled: false,
+ isVisualizationSupported: true,
+ },
+ [anotherTestStep]: {
+ id: 'id2',
+ status: ManualTestStatus.UNKNOWN,
+ isCapturedByUser: false,
+ failureSummary: undefined,
+ isVisible: true,
+ isVisualizationEnabled: true,
+ isVisualizationSupported: true,
+ },
},
},
- },
- };
-
- setupGenerateInstanceIdentifierMock(
- { target: [selectorStub], html: htmlStub },
- identifierStub,
- );
- const instanceMap = testSubject.generateAssessmentInstancesMap(
- previouslyGeneratedInstances,
- selectorMap,
- testStep,
- generateInstanceIdentifierMock.object,
- () => ManualTestStatus.UNKNOWN,
- );
-
- expect(instanceMap).toEqual(expectedResult);
+ };
+
+ setupGenerateInstanceIdentifierMock(
+ { target: [selectorStub], html: htmlStub },
+ identifierStub,
+ );
+ const instanceMap = testSubject.generateAssessmentInstancesMap(
+ previouslyGeneratedInstances,
+ selectorMap,
+ testStep,
+ generateInstanceIdentifierMock.object,
+ () => ManualTestStatus.UNKNOWN,
+ () => true,
+ );
+
+ expect(instanceMap).toEqual(expectedResult);
+ });
});
test('generateAssessmentInstancesMapForEvents: previouslyGeneratedInstances is null', () => {
diff --git a/src/tests/unit/tests/background/stores/__snapshots__/assessment-store.test.ts.snap b/src/tests/unit/tests/background/stores/__snapshots__/assessment-store.test.ts.snap
index 7c92b440b56..217f5139508 100644
--- a/src/tests/unit/tests/background/stores/__snapshots__/assessment-store.test.ts.snap
+++ b/src/tests/unit/tests/background/stores/__snapshots__/assessment-store.test.ts.snap
@@ -1,5 +1,5 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
-exports[`AssessmentStoreTest onResetAllAssessmentsData 1`] = `"tab with Id 1000 not found"`;
+exports[`AssessmentStore onResetAllAssessmentsData 1`] = `"tab with Id 1000 not found"`;
-exports[`AssessmentStoreTest onUpdateTargetTabId 1`] = `"tab with Id 1000 not found"`;
+exports[`AssessmentStore onUpdateTargetTabId 1`] = `"tab with Id 1000 not found"`;
diff --git a/src/tests/unit/tests/background/stores/assessment-store.test.ts b/src/tests/unit/tests/background/stores/assessment-store.test.ts
index f87c17fad8a..39776f31617 100644
--- a/src/tests/unit/tests/background/stores/assessment-store.test.ts
+++ b/src/tests/unit/tests/background/stores/assessment-store.test.ts
@@ -2,6 +2,7 @@
// Licensed under the MIT License.
import { AssessmentsProvider } from 'assessments/types/assessments-provider';
import { Assessment } from 'assessments/types/iassessment';
+import { Requirement } from 'assessments/types/requirement';
import {
AddFailureInstancePayload,
AddResultDescriptionPayload,
@@ -59,7 +60,7 @@ const assessmentKey: string = 'assessment-1';
const requirementKey: string = 'assessment-1-step-1';
const assessmentType = -1 as VisualizationType;
-describe('AssessmentStoreTest', () => {
+describe('AssessmentStore', () => {
let browserMock: IMock;
let assessmentDataConverterMock: IMock;
let assessmentDataRemoverMock: IMock;
@@ -470,7 +471,7 @@ describe('AssessmentStoreTest', () => {
.testListenerToBeCalledOnce(initialState, finalState);
});
- test('onScanCompleted', () => {
+ test('onScanCompleted with an assisted requirement', () => {
const initialAssessmentData = new AssessmentDataBuilder()
.with('testStepStatus', {
['assessment-1-step-1']: getDefaultTestStepData(),
@@ -490,16 +491,121 @@ describe('AssessmentStoreTest', () => {
const expectedInstanceMap = {};
const stepMapStub = assessmentsProvider.getStepMap(assessmentType);
- const stepConfig = assessmentsProvider.getStep(assessmentType, 'assessment-1-step-1');
+ const stepConfig: Readonly = {
+ ...assessmentsProvider.getStep(assessmentType, 'assessment-1-step-1'),
+ isManual: false,
+ };
const assessmentData = new AssessmentDataBuilder()
.with('generatedAssessmentInstancesMap', expectedInstanceMap)
.with('testStepStatus', {
+ // should PASS because it is a non-manual test with no associated instances
['assessment-1-step-1']: generateTestStepData(ManualTestStatus.PASS, true),
+ // should stay unchanged because the event/payload is requirement-specific
+ ['assessment-1-step-2']: getDefaultTestStepData(),
+ ['assessment-1-step-3']: getDefaultTestStepData(),
+ })
+ .with('scanIncompleteWarnings', [])
+ .build();
+
+ const finalState = getStateWithAssessment(assessmentData);
+
+ assessmentsProviderMock
+ .setup(provider => provider.all())
+ .returns(() => assessmentsProvider.all());
+
+ assessmentsProviderMock
+ .setup(provider => provider.getStepMap(assessmentType))
+ .returns(() => stepMapStub);
+
+ assessmentsProviderMock
+ .setup(provider => provider.getStep(assessmentType, 'assessment-1-step-1'))
+ .returns(() => stepConfig);
+
+ assessmentsProviderMock
+ .setup(provider => provider.forType(payload.testType))
+ .returns(() => assessmentMock.object);
+
+ assessmentMock.setup(am => am.getVisualizationConfiguration()).returns(() => configStub);
+
+ getInstanceIdentiferGeneratorMock
+ .setup(idGetter => idGetter(requirementKey))
+ .returns(() => instanceIdentifierGeneratorStub);
+
+ assessmentDataConverterMock
+ .setup(a =>
+ a.generateAssessmentInstancesMap(
+ initialAssessmentData.generatedAssessmentInstancesMap,
+ payload.selectorMap,
+ requirementKey,
+ instanceIdentifierGeneratorStub,
+ stepConfig.getInstanceStatus,
+ stepConfig.isVisualizationSupportedForResult,
+ ),
+ )
+ .returns(() => expectedInstanceMap);
+
+ createStoreTesterForAssessmentActions('scanCompleted')
+ .withActionParam(payload)
+ .testListenerToBeCalledOnce(initialState, finalState);
+ });
+
+ test('onScanCompleted with a manual requirement uses getInitialManualTestStatus to set status', () => {
+ const initialManualTestStepResult = {
+ status: ManualTestStatus.UNKNOWN,
+ id: requirementKey,
+ instances: [
+ {
+ id: '1',
+ description: 'aaa',
+ },
+ ],
+ };
+ const initialAssessmentData = new AssessmentDataBuilder()
+ .with('testStepStatus', {
+ ['assessment-1-step-1']: getDefaultTestStepData(),
+ ['assessment-1-step-2']: getDefaultTestStepData(),
+ ['assessment-1-step-3']: getDefaultTestStepData(),
+ })
+ .with('manualTestStepResultMap', {
+ [requirementKey]: initialManualTestStepResult,
+ })
+ .build();
+ const initialState = getStateWithAssessment(initialAssessmentData);
+
+ const payload: ScanCompletedPayload = {
+ selectorMap: {},
+ scanResult: {} as ScanResults,
+ testType: assessmentType,
+ key: requirementKey,
+ scanIncompleteWarnings: [],
+ };
+
+ const expectedInstanceMap = {};
+ const stepMapStub = assessmentsProvider.getStepMap(assessmentType);
+ const stepConfig: Readonly = {
+ ...assessmentsProvider.getStep(assessmentType, 'assessment-1-step-1'),
+ isManual: true,
+ getInitialManualTestStatus: () => ManualTestStatus.FAIL,
+ };
+
+ const assessmentData = new AssessmentDataBuilder()
+ .with('generatedAssessmentInstancesMap', expectedInstanceMap)
+ .with('testStepStatus', {
+ // should FAIL based on getInitialManualTestStatus
+ ['assessment-1-step-1']: generateTestStepData(ManualTestStatus.FAIL, true),
+ // should stay unchanged because the event/payload is requirement-specific
['assessment-1-step-2']: getDefaultTestStepData(),
['assessment-1-step-3']: getDefaultTestStepData(),
})
.with('scanIncompleteWarnings', [])
+ .with('manualTestStepResultMap', {
+ [requirementKey]: {
+ ...initialManualTestStepResult,
+ // should FAIL based on getInitialManualTestStatus
+ status: ManualTestStatus.FAIL,
+ },
+ })
.build();
const finalState = getStateWithAssessment(assessmentData);
@@ -533,7 +639,108 @@ describe('AssessmentStoreTest', () => {
payload.selectorMap,
requirementKey,
instanceIdentifierGeneratorStub,
- It.isAny(),
+ stepConfig.getInstanceStatus,
+ stepConfig.isVisualizationSupportedForResult,
+ ),
+ )
+ .returns(() => expectedInstanceMap);
+
+ createStoreTesterForAssessmentActions('scanCompleted')
+ .withActionParam(payload)
+ .testListenerToBeCalledOnce(initialState, finalState);
+ });
+
+ test('onScanCompleted with a manual requirement skips getInitialManualTestStatus for requirements that already have a status', () => {
+ const initialManualTestStepResult = {
+ status: ManualTestStatus.PASS,
+ id: requirementKey,
+ instances: [
+ {
+ id: '1',
+ description: 'aaa',
+ },
+ ],
+ };
+ const initialAssessmentData = new AssessmentDataBuilder()
+ .with('testStepStatus', {
+ ['assessment-1-step-1']: generateTestStepData(ManualTestStatus.PASS, true),
+ ['assessment-1-step-2']: getDefaultTestStepData(),
+ ['assessment-1-step-3']: getDefaultTestStepData(),
+ })
+ .with('manualTestStepResultMap', {
+ [requirementKey]: initialManualTestStepResult,
+ })
+ .build();
+ const initialState = getStateWithAssessment(initialAssessmentData);
+
+ const payload: ScanCompletedPayload = {
+ selectorMap: {},
+ scanResult: {} as ScanResults,
+ testType: assessmentType,
+ key: requirementKey,
+ scanIncompleteWarnings: [],
+ };
+
+ const expectedInstanceMap = {};
+ const stepMapStub = assessmentsProvider.getStepMap(assessmentType);
+ const stepConfig: Readonly = {
+ ...assessmentsProvider.getStep(assessmentType, 'assessment-1-step-1'),
+ isManual: true,
+ getInitialManualTestStatus: () => ManualTestStatus.FAIL,
+ };
+
+ const assessmentData = new AssessmentDataBuilder()
+ .with('generatedAssessmentInstancesMap', expectedInstanceMap)
+ .with('testStepStatus', {
+ // should ignore getInitialManualTestStatus because the original state was not UNKNOWN
+ ['assessment-1-step-1']: generateTestStepData(ManualTestStatus.PASS, true),
+ // should stay unchanged because the event/payload is requirement-specific
+ ['assessment-1-step-2']: getDefaultTestStepData(),
+ ['assessment-1-step-3']: getDefaultTestStepData(),
+ })
+ .with('scanIncompleteWarnings', [])
+ .with('manualTestStepResultMap', {
+ [requirementKey]: {
+ ...initialManualTestStepResult,
+ // should ignore getInitialManualTestStatus because the original state was not UNKNOWN
+ status: ManualTestStatus.PASS,
+ },
+ })
+ .build();
+
+ const finalState = getStateWithAssessment(assessmentData);
+
+ assessmentsProviderMock
+ .setup(provider => provider.all())
+ .returns(() => assessmentsProvider.all());
+
+ assessmentsProviderMock
+ .setup(provider => provider.getStepMap(assessmentType))
+ .returns(() => stepMapStub);
+
+ assessmentsProviderMock
+ .setup(provider => provider.getStep(assessmentType, 'assessment-1-step-1'))
+ .returns(() => stepConfig);
+
+ assessmentsProviderMock
+ .setup(provider => provider.forType(payload.testType))
+ .returns(() => assessmentMock.object);
+
+ assessmentMock.setup(am => am.getVisualizationConfiguration()).returns(() => configStub);
+
+ getInstanceIdentiferGeneratorMock
+ .setup(idGetter => idGetter(requirementKey))
+ .returns(() => instanceIdentifierGeneratorStub);
+
+ assessmentDataConverterMock
+ .setup(a =>
+ a.generateAssessmentInstancesMap(
+ initialAssessmentData.generatedAssessmentInstancesMap,
+ payload.selectorMap,
+ requirementKey,
+ instanceIdentifierGeneratorStub,
+ stepConfig.getInstanceStatus,
+ stepConfig.isVisualizationSupportedForResult,
),
)
.returns(() => expectedInstanceMap);
@@ -893,56 +1100,73 @@ describe('AssessmentStoreTest', () => {
.testListenerToBeCalledOnce(initialState, finalState);
});
- test('on changeAssessmentVisualizationState', () => {
- const generatedAssessmentInstancesMap: DictionaryStringTo = {
- selector: {
- testStepResults: {
- [requirementKey]: {
- isVisualizationEnabled: true,
+ test.each`
+ supportsVisualization | startsEnabled | payloadEnabled | expectedFinalEnabled
+ ${false} | ${false} | ${true} | ${false}
+ ${true} | ${false} | ${true} | ${true}
+ ${true} | ${true} | ${false} | ${false}
+ ${true} | ${true} | ${true} | ${true}
+ ${true} | ${false} | ${false} | ${false}
+ `(
+ 'on changeAssessmentVisualizationState: supportsVisualization:$supportsVisualization, ' +
+ 'startsEnabled:$startsEnabled, payloadEnabled:$payloadEnabled -> finalEnabled:$expectedFinalEnabled',
+ ({ supportsVisualization, startsEnabled, payloadEnabled, expectedFinalEnabled }) => {
+ const generatedAssessmentInstancesMap: DictionaryStringTo = {
+ selector: {
+ testStepResults: {
+ [requirementKey]: {
+ isVisualizationEnabled: startsEnabled,
+ isVisualizationSupported: supportsVisualization,
+ },
},
- },
- } as any,
- };
+ } as any,
+ };
- const assessmentData = new AssessmentDataBuilder()
- .with('generatedAssessmentInstancesMap', generatedAssessmentInstancesMap)
- .build();
+ const assessmentData = new AssessmentDataBuilder()
+ .with('generatedAssessmentInstancesMap', generatedAssessmentInstancesMap)
+ .build();
- const initialState = getStateWithAssessment(assessmentData);
+ const initialState = getStateWithAssessment(assessmentData);
- const payload: ChangeInstanceSelectionPayload = {
- test: assessmentType,
- requirement: requirementKey,
- isVisualizationEnabled: true,
- selector: 'selector',
- };
+ const payload: ChangeInstanceSelectionPayload = {
+ test: assessmentType,
+ requirement: requirementKey,
+ isVisualizationEnabled: payloadEnabled,
+ selector: 'selector',
+ };
- assessmentsProviderMock
- .setup(apm => apm.forType(payload.test))
- .returns(() => assessmentMock.object);
+ assessmentsProviderMock
+ .setup(apm => apm.forType(payload.test))
+ .returns(() => assessmentMock.object);
- assessmentMock.setup(am => am.getVisualizationConfiguration()).returns(() => configStub);
+ assessmentMock
+ .setup(am => am.getVisualizationConfiguration())
+ .returns(() => configStub);
- const expectedInstancesMap = cloneDeep(generatedAssessmentInstancesMap);
- expectedInstancesMap.selector.testStepResults[requirementKey].isVisualizationEnabled = true;
+ const expectedInstancesMap = cloneDeep(generatedAssessmentInstancesMap);
+ expectedInstancesMap.selector.testStepResults[
+ requirementKey
+ ].isVisualizationEnabled = expectedFinalEnabled;
- const expectedAssessment = new AssessmentDataBuilder()
- .with('generatedAssessmentInstancesMap', expectedInstancesMap)
- .build();
+ const expectedAssessment = new AssessmentDataBuilder()
+ .with('generatedAssessmentInstancesMap', expectedInstancesMap)
+ .build();
- const finalState = getStateWithAssessment(expectedAssessment);
+ const finalState = getStateWithAssessment(expectedAssessment);
- createStoreTesterForAssessmentActions('changeAssessmentVisualizationState')
- .withActionParam(payload)
- .testListenerToBeCalledOnce(initialState, finalState);
- });
+ createStoreTesterForAssessmentActions('changeAssessmentVisualizationState')
+ .withActionParam(payload)
+ .testListenerToBeCalledOnce(initialState, finalState);
+ },
+ );
- test('on changeAssessmentVisualizationStateForAll', () => {
+ test('changeAssessmentVisualizationStateForAll enables all visualizations that support it', () => {
const generatedAssessmentInstancesMap: DictionaryStringTo = {
selector1: {
testStepResults: {
[requirementKey]: {
isVisualizationEnabled: true,
+ isVisualizationSupported: true,
},
},
} as any,
@@ -950,12 +1174,21 @@ describe('AssessmentStoreTest', () => {
testStepResults: {
[requirementKey]: {
isVisualizationEnabled: false,
+ isVisualizationSupported: false,
},
},
} as any,
selector3: {
testStepResults: {},
} as any,
+ selector4: {
+ testStepResults: {
+ [requirementKey]: {
+ isVisualizationEnabled: false,
+ isVisualizationSupported: true,
+ },
+ },
+ } as any,
};
const assessmentData = new AssessmentDataBuilder()
@@ -978,7 +1211,12 @@ describe('AssessmentStoreTest', () => {
assessmentMock.setup(am => am.getVisualizationConfiguration()).returns(() => configStub);
const expectedInstancesMap = cloneDeep(generatedAssessmentInstancesMap);
- expectedInstancesMap.selector2.testStepResults[
+
+ // Selector 1 shouldn't change because it's already enabled
+ // Selector 2 shouldn't change because it doesn't support visualizations
+ // Selector 3 shouldn't change because it has no test step results
+ // Selector 4 should toggle from disabled to enabled:
+ expectedInstancesMap.selector4.testStepResults[
requirementKey
].isVisualizationEnabled = true;
diff --git a/src/tests/unit/tests/scanner/custom-rules/landmark-role.test.ts b/src/tests/unit/tests/scanner/custom-rules/landmark-role.test.ts
deleted file mode 100644
index 12e0a14e3a7..00000000000
--- a/src/tests/unit/tests/scanner/custom-rules/landmark-role.test.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-import { landmarkConfiguration } from '../../../../../scanner/custom-rules/landmark-rule';
-
-describe('landmarkRule', () => {
- describe('verify landmark configs', () => {
- it('should have correct props', () => {
- expect(landmarkConfiguration.rule.id).toBe('main-landmark');
- expect(landmarkConfiguration.rule.selector).toBe('[role=main], main');
- expect(landmarkConfiguration.rule.any[0]).toBe('unique-landmark');
- expect(landmarkConfiguration.checks.length).toBe(0);
- });
- });
-});
From 335ab1dbe1acbe3be858ecfbfdcf1c509597edb7 Mon Sep 17 00:00:00 2001
From: "dependabot-preview[bot]"
<27856297+dependabot-preview[bot]@users.noreply.github.com>
Date: Thu, 14 May 2020 22:12:54 +0000
Subject: [PATCH 03/15] chore(deps-dev): bump typescript from 3.8.3 to 3.9.2
(#2674)
---
package.json | 2 +-
.../images/test-steps/text-alternative.tsx | 4 +--
.../semantics/test-steps/css-content.tsx | 4 +--
.../test-steps/headers-attribute.tsx | 4 +--
.../semantics/test-steps/table-semantics.tsx | 4 +--
.../sequence/test-steps/css-positioning.tsx | 4 +--
.../sequence/test-steps/layout-tables.tsx | 7 +++--
.../test-steps/high-contrast-mode.tsx | 6 ++--
.../test-steps/resize-text.tsx | 6 ++--
.../details-view-command-bar.test.tsx | 17 ++++++-----
.../left-nav/details-view-left-nav.test.tsx | 12 +++++---
.../DetailsView/details-view-body.test.tsx | 29 ++++++++++++-------
yarn.lock | 8 ++---
13 files changed, 62 insertions(+), 45 deletions(-)
diff --git a/package.json b/package.json
index f3892e53030..836ca9ca459 100644
--- a/package.json
+++ b/package.json
@@ -129,7 +129,7 @@
"tslint-microsoft-contrib": "6.2.0",
"typed-scss-modules": "^1.3.0",
"typemoq": "^2.1.0",
- "typescript": "^3.8.3",
+ "typescript": "^3.9.2",
"webdriverio": "^4.13.0",
"webpack": "^4.43.0",
"webpack-cli": "^3.3.11",
diff --git a/src/assessments/images/test-steps/text-alternative.tsx b/src/assessments/images/test-steps/text-alternative.tsx
index f49f7de0aad..88a0d996c2b 100644
--- a/src/assessments/images/test-steps/text-alternative.tsx
+++ b/src/assessments/images/test-steps/text-alternative.tsx
@@ -76,8 +76,8 @@ const howToTest: JSX.Element = (
If a CSS background image is coded as meaningful:
-
- Use the Web Developer browser extension (CSS >{' '}
- Disable All Styles) to turn off CSS.
+ Use the Web Developer browser extension (CSS{' '}
+ {'>'} Disable All Styles) to turn off CSS.
-
Verify that the information conveyed by the image is visible when CSS is
diff --git a/src/assessments/semantics/test-steps/css-content.tsx b/src/assessments/semantics/test-steps/css-content.tsx
index 42ced03fbb5..22bf2ea54b1 100644
--- a/src/assessments/semantics/test-steps/css-content.tsx
+++ b/src/assessments/semantics/test-steps/css-content.tsx
@@ -70,8 +70,8 @@ const cssContentHowToTest: JSX.Element = (
-
Use the Web Developer browser extension{' '}
- (CSS > Disable All Styles) to turn off
- CSS.
+ (CSS {'>'} Disable All Styles) to turn
+ off CSS.
-
Verify that any information conveyed by the inserted content is
diff --git a/src/assessments/semantics/test-steps/headers-attribute.tsx b/src/assessments/semantics/test-steps/headers-attribute.tsx
index 9c9902f0d2b..95b9ffae4c8 100644
--- a/src/assessments/semantics/test-steps/headers-attribute.tsx
+++ b/src/assessments/semantics/test-steps/headers-attribute.tsx
@@ -29,8 +29,8 @@ const headersAttributeHowToTest: JSX.Element = (
-
Use the Web Developer browser extension (
- Information > Display table information) to reveal any{' '}
- headers attributes on the page. Note: The{' '}
+ Information {'>'} Display table information) to reveal
+ any headers attributes on the page. Note: The{' '}
headers attributes are displayed on the data
cells, and not on the cells they reference.
diff --git a/src/assessments/semantics/test-steps/table-semantics.tsx b/src/assessments/semantics/test-steps/table-semantics.tsx
index f0fcfb0de59..a3d5cea1e37 100644
--- a/src/assessments/semantics/test-steps/table-semantics.tsx
+++ b/src/assessments/semantics/test-steps/table-semantics.tsx
@@ -25,7 +25,7 @@ const tableSemanticsHowToTest: JSX.Element = (
-
Use the Web Developer browser extension (
- Outline > Outline tables) to outline{' '}
+ Outline {'>'} Outline tables) to outline{' '}
elements on the page.
-
@@ -43,7 +43,7 @@ const tableSemanticsHowToTest: JSX.Element = (
-
Use the Web Developer browser extension to reveal elements with ARIA roles (
- Information > Display ARIA Roles).
+ Information {'>'} Display ARIA Roles).
-
Verify that each table is coded correctly for its type:
diff --git a/src/assessments/sequence/test-steps/css-positioning.tsx b/src/assessments/sequence/test-steps/css-positioning.tsx
index b0d9eb0360c..543d992f83a 100644
--- a/src/assessments/sequence/test-steps/css-positioning.tsx
+++ b/src/assessments/sequence/test-steps/css-positioning.tsx
@@ -50,8 +50,8 @@ const howToTest: JSX.Element = (
-
If the page does have meaningful positioned content, use the Web Developer browser
- extension (Miscellaneous > Linearize page) to show the
- page in DOM order.
+ extension (Miscellaneous {'>'} Linearize page) to show
+ the page in DOM order.
-
Verify that the positioned content retains its meaning when the page is linearized.
diff --git a/src/assessments/sequence/test-steps/layout-tables.tsx b/src/assessments/sequence/test-steps/layout-tables.tsx
index a87c5ba0fcc..c0caebb3d74 100644
--- a/src/assessments/sequence/test-steps/layout-tables.tsx
+++ b/src/assessments/sequence/test-steps/layout-tables.tsx
@@ -24,7 +24,8 @@ const howToTest: JSX.Element = (
-
- Use the Web Developer extension (Outline > Outline Tables
+ Use the Web Developer extension (
+ Outline {'>'} Outline Tables
) to identify any elements in the target page.
-
@@ -43,8 +44,8 @@ const howToTest: JSX.Element = (
-
If you find a layout table, use the Web Developer browser extension (
- Miscellaneous > Linearize page) to show the page in DOM
- order.
+ Miscellaneous {'>'} Linearize page) to show the page in
+ DOM order.
-
Verify that content in layout tables still has the correct reading order when the
diff --git a/src/assessments/text-legibility/test-steps/high-contrast-mode.tsx b/src/assessments/text-legibility/test-steps/high-contrast-mode.tsx
index 332e11bd417..0fba224f94c 100644
--- a/src/assessments/text-legibility/test-steps/high-contrast-mode.tsx
+++ b/src/assessments/text-legibility/test-steps/high-contrast-mode.tsx
@@ -18,9 +18,9 @@ const highContrastModeHowToTest: JSX.Element = (
- Open the target page in the new Microsoft Edge or Microsoft Edge Legacy.
-
- Use Windows Settings >{' '}
- Ease of Access > High contrast{' '}
- to apply a high contrast theme.
+ Use Windows Settings {'>'}{' '}
+ Ease of Access {'>'}{' '}
+ High contrast to apply a high contrast theme.
- Verify that the target page adopts the colors specified for the theme.
diff --git a/src/assessments/text-legibility/test-steps/resize-text.tsx b/src/assessments/text-legibility/test-steps/resize-text.tsx
index 69cf604dfac..3501b8aa384 100644
--- a/src/assessments/text-legibility/test-steps/resize-text.tsx
+++ b/src/assessments/text-legibility/test-steps/resize-text.tsx
@@ -28,9 +28,9 @@ const resizeTextHowToTest: JSX.Element = (
-
- Use Windows Settings > System{' '}
- > Display > Scale and layout{' '}
- to
+ Use Windows Settings {'>'}{' '}
+ System {'>'} Display {'>'}{' '}
+ Scale and layout to
- Set the resolution to 1920x1080, and
- Set scaling to 100%.
diff --git a/src/tests/unit/tests/DetailsView/components/details-view-command-bar.test.tsx b/src/tests/unit/tests/DetailsView/components/details-view-command-bar.test.tsx
index 3928b97a231..8f590932b32 100644
--- a/src/tests/unit/tests/DetailsView/components/details-view-command-bar.test.tsx
+++ b/src/tests/unit/tests/DetailsView/components/details-view-command-bar.test.tsx
@@ -3,8 +3,10 @@
import { NamedFC, ReactFCWithDisplayName } from 'common/react/named-fc';
import { ScanMetadata } from 'common/types/store-data/unified-data-interface';
import { DetailsViewActionMessageCreator } from 'DetailsView/actions/details-view-action-message-creator';
-import { DetailsViewSwitcherNavConfiguration } from 'DetailsView/components/details-view-switcher-nav';
-import { DetailsViewBodyProps } from 'DetailsView/details-view-body';
+import {
+ DetailsViewSwitcherNavConfiguration,
+ LeftNavProps,
+} from 'DetailsView/components/details-view-switcher-nav';
import { shallow } from 'enzyme';
import { ActionButton } from 'office-ui-fabric-react';
import * as React from 'react';
@@ -38,12 +40,13 @@ describe('DetailsViewCommandBar', () => {
});
function getProps(): DetailsViewCommandBarProps {
- const CommandBarStub: Readonly> = NamedFC<
- DetailsViewBodyProps
- >('test', _ => null);
- const LeftNavStub: Readonly> = NamedFC<
- DetailsViewBodyProps
+ const CommandBarStub: ReactFCWithDisplayName = NamedFC<
+ DetailsViewCommandBarProps
>('test', _ => null);
+ const LeftNavStub: ReactFCWithDisplayName = NamedFC(
+ 'test',
+ _ => null,
+ );
const switcherNavConfiguration: DetailsViewSwitcherNavConfiguration = {
CommandBar: CommandBarStub,
ReportExportComponentFactory: p => reportExportComponent,
diff --git a/src/tests/unit/tests/DetailsView/components/left-nav/details-view-left-nav.test.tsx b/src/tests/unit/tests/DetailsView/components/left-nav/details-view-left-nav.test.tsx
index 8847dc47128..85bab38586f 100644
--- a/src/tests/unit/tests/DetailsView/components/left-nav/details-view-left-nav.test.tsx
+++ b/src/tests/unit/tests/DetailsView/components/left-nav/details-view-left-nav.test.tsx
@@ -13,7 +13,10 @@ import {
import { FeatureFlagStoreData } from '../../../../../../common/types/store-data/feature-flag-store-data';
import { VisualizationType } from '../../../../../../common/types/visualization-type';
import { DetailsRightPanelConfiguration } from '../../../../../../DetailsView/components/details-view-right-panel';
-import { DetailsViewSwitcherNavConfiguration } from '../../../../../../DetailsView/components/details-view-switcher-nav';
+import {
+ DetailsViewSwitcherNavConfiguration,
+ LeftNavProps,
+} from '../../../../../../DetailsView/components/details-view-switcher-nav';
import {
DetailsViewLeftNav,
DetailsViewLeftNavDeps,
@@ -36,9 +39,10 @@ describe('DetailsViewLeftNav', () => {
(theProps: GetLeftNavSelectedKeyProps) => null,
MockBehavior.Strict,
);
- const LeftNavStub: Readonly> = NamedFC<
- DetailsViewLeftNavProps
- >('test', _ => null);
+ const LeftNavStub: Readonly> = NamedFC(
+ 'test',
+ _ => null,
+ );
const assessmentDataStub: { [key: string]: AssessmentData } = {
x: { testStepStatus: {} } as AssessmentData,
};
diff --git a/src/tests/unit/tests/DetailsView/details-view-body.test.tsx b/src/tests/unit/tests/DetailsView/details-view-body.test.tsx
index 18ab5a78240..9f7ee72b5a3 100644
--- a/src/tests/unit/tests/DetailsView/details-view-body.test.tsx
+++ b/src/tests/unit/tests/DetailsView/details-view-body.test.tsx
@@ -5,7 +5,10 @@ import { IMock, Mock, MockBehavior } from 'typemoq';
import { getDefaultFeatureFlagsWeb } from 'common/feature-flags';
import { ScanMetadata, TargetAppData } from 'common/types/store-data/unified-data-interface';
-import { DetailsViewCommandBarDeps } from 'DetailsView/components/details-view-command-bar';
+import {
+ DetailsViewCommandBarDeps,
+ DetailsViewCommandBarProps,
+} from 'DetailsView/components/details-view-command-bar';
import { VisualizationConfiguration } from '../../../../common/configs/visualization-configuration';
import { VisualizationConfigurationFactory } from '../../../../common/configs/visualization-configuration-factory';
import { NamedFC, ReactFCWithDisplayName } from '../../../../common/react/named-fc';
@@ -22,8 +25,14 @@ import {
} from '../../../../common/types/store-data/visualization-store-data';
import { VisualizationType } from '../../../../common/types/visualization-type';
import { DetailsViewActionMessageCreator } from '../../../../DetailsView/actions/details-view-action-message-creator';
-import { DetailsRightPanelConfiguration } from '../../../../DetailsView/components/details-view-right-panel';
-import { DetailsViewSwitcherNavConfiguration } from '../../../../DetailsView/components/details-view-switcher-nav';
+import {
+ DetailsRightPanelConfiguration,
+ RightPanelProps,
+} from '../../../../DetailsView/components/details-view-right-panel';
+import {
+ DetailsViewSwitcherNavConfiguration,
+ LeftNavProps,
+} from '../../../../DetailsView/components/details-view-switcher-nav';
import { DetailsViewLeftNav } from '../../../../DetailsView/components/left-nav/details-view-left-nav';
import { TargetPageHiddenBar } from '../../../../DetailsView/components/target-page-hidden-bar';
import { DetailsViewBody, DetailsViewBodyProps } from '../../../../DetailsView/details-view-body';
@@ -49,14 +58,14 @@ describe('DetailsViewBody', () => {
describe('render', () => {
beforeEach(() => {
selectedTest = -1;
- const RightPanelStub: Readonly> = NamedFC<
- DetailsViewBodyProps
- >('test', _ => null);
- const CommandBarStub: Readonly> = NamedFC<
- DetailsViewBodyProps
+ const RightPanelStub: Readonly> = NamedFC<
+ RightPanelProps
>('test', _ => null);
- const LeftNavStub: Readonly> = NamedFC<
- DetailsViewBodyProps
+ const CommandBarStub: Readonly> = NamedFC('test', _ => null);
+ const LeftNavStub: Readonly> = NamedFC<
+ LeftNavProps
>('test', _ => null);
rightPanelConfig = {
RightPanel: RightPanelStub,
diff --git a/yarn.lock b/yarn.lock
index 25921a41b45..09b12c33f17 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -10131,10 +10131,10 @@ typemoq@^2.1.0:
lodash "^4.17.4"
postinstall-build "^5.0.1"
-typescript@^3.8.3:
- version "3.8.3"
- resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.8.3.tgz#409eb8544ea0335711205869ec458ab109ee1061"
- integrity sha512-MYlEfn5VrLNsgudQTVJeNaQFUAI7DkhnOjdpAp4T+ku1TfQClewlbSuTVHiA+8skNBgaf02TL/kLOvig4y3G8w==
+typescript@^3.9.2:
+ version "3.9.2"
+ resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.2.tgz#64e9c8e9be6ea583c54607677dd4680a1cf35db9"
+ integrity sha512-q2ktq4n/uLuNNShyayit+DTobV2ApPEo/6so68JaD5ojvc/6GClBipedB9zNWYxRSAlZXAe405Rlijzl6qDiSw==
typeson-registry@^1.0.0-alpha.20:
version "1.0.0-alpha.29"
From b86905208ba3736fff96b730b150654c4bff6e0e Mon Sep 17 00:00:00 2001
From: Liu Haonan
Date: Thu, 14 May 2020 15:21:19 -0700
Subject: [PATCH 04/15] feat(mobile-rules-guidance): add rule link (#2682)
* add rule link
* update test name
* fix a url
* share base url
---
.../android/rule-information-provider.ts | 7 ++++-
.../platform/android/rule-information.ts | 1 +
.../android/scan-results-to-unified-rules.ts | 2 +-
...scan-results-to-unified-rules.test.ts.snap | 10 +++----
.../android/rule-information-provider.test.ts | 2 +-
.../platform/android/rule-information.test.ts | 29 +++++++++++++++++--
.../platform/android/scan-results-helpers.ts | 2 ++
.../scan-results-to-unified-results.test.ts | 7 ++++-
.../scan-results-to-unified-rules.test.ts | 5 +++-
9 files changed, 52 insertions(+), 13 deletions(-)
diff --git a/src/electron/platform/android/rule-information-provider.ts b/src/electron/platform/android/rule-information-provider.ts
index 81236c64b39..2838a19ccbc 100644
--- a/src/electron/platform/android/rule-information-provider.ts
+++ b/src/electron/platform/android/rule-information-provider.ts
@@ -9,11 +9,12 @@ import { RuleInformation } from './rule-information';
export class RuleInformationProvider {
private supportedRules: DictionaryStringTo;
-
+ private readonly ruleLinkBaseUrl = 'https://accessibilityinsights.io/info-examples/android';
constructor() {
this.supportedRules = {
ColorContrast: new RuleInformation(
'ColorContrast',
+ `${this.ruleLinkBaseUrl}/color-contrast/`,
'Text elements must have sufficient contrast against the background.',
[link.WCAG_1_4_3],
this.getColorContrastUnifiedFormattableResolution,
@@ -21,6 +22,7 @@ export class RuleInformationProvider {
),
TouchSizeWcag: new RuleInformation(
'TouchSizeWcag',
+ `${this.ruleLinkBaseUrl}/touch-size-wcag/`,
'Touch inputs must have a sufficient target size.',
[link.WCAG_1_3_1, link.WCAG_3_3_2],
this.getTouchSizeUnifiedFormattableResolution,
@@ -28,6 +30,7 @@ export class RuleInformationProvider {
),
ActiveViewName: new RuleInformation(
'ActiveViewName',
+ `${this.ruleLinkBaseUrl}/active-view-name/`,
"Active views must have a name that's available to assistive technologies.",
[link.WCAG_2_5_5],
() =>
@@ -39,6 +42,7 @@ export class RuleInformationProvider {
),
ImageViewName: new RuleInformation(
'ImageViewName',
+ `${this.ruleLinkBaseUrl}/image-view-name/`,
'Meaningful images must have alternate text.',
[link.WCAG_1_1_1],
() =>
@@ -50,6 +54,7 @@ export class RuleInformationProvider {
),
EditTextValue: new RuleInformation(
'EditTextValue',
+ `${this.ruleLinkBaseUrl}/edit-text-value/`,
'EditText elements must expose their entered text value to assistive technologies',
[link.WCAG_4_1_2],
() =>
diff --git a/src/electron/platform/android/rule-information.ts b/src/electron/platform/android/rule-information.ts
index 2e8827e1610..2082d8c6d21 100644
--- a/src/electron/platform/android/rule-information.ts
+++ b/src/electron/platform/android/rule-information.ts
@@ -14,6 +14,7 @@ export type IncludeThisResultDelegate = (ruleResultsData: RuleResultsData) => bo
export class RuleInformation {
constructor(
readonly ruleId: string,
+ readonly ruleLink: string,
readonly ruleDescription: string,
readonly guidance: GuidanceLink[],
readonly getUnifiedFormattableResolutionDelegate: GetUnifiedFormattableResolutionDelegate,
diff --git a/src/electron/platform/android/scan-results-to-unified-rules.ts b/src/electron/platform/android/scan-results-to-unified-rules.ts
index bdafe26cfa2..4a74b483599 100644
--- a/src/electron/platform/android/scan-results-to-unified-rules.ts
+++ b/src/electron/platform/android/scan-results-to-unified-rules.ts
@@ -48,7 +48,7 @@ function createUnifiedRuleFromRuleResult(
uid: uuidGenerator(),
id: ruleInformation.ruleId,
description: ruleInformation.ruleDescription,
- url: null,
+ url: ruleInformation.ruleLink,
guidance: ruleInformation.guidance,
};
}
diff --git a/src/tests/unit/tests/electron/platform/android/__snapshots__/scan-results-to-unified-rules.test.ts.snap b/src/tests/unit/tests/electron/platform/android/__snapshots__/scan-results-to-unified-rules.test.ts.snap
index fb46dc9fa68..5c7e5bb09a4 100644
--- a/src/tests/unit/tests/electron/platform/android/__snapshots__/scan-results-to-unified-rules.test.ts.snap
+++ b/src/tests/unit/tests/electron/platform/android/__snapshots__/scan-results-to-unified-rules.test.ts.snap
@@ -9,7 +9,7 @@ Array [
"guidance": Array [],
"id": "Rule #1",
"uid": "gguid-mock-stub",
- "url": null,
+ "url": "rule-link",
},
]
`;
@@ -21,7 +21,7 @@ Array [
"guidance": Array [],
"id": "Rule #1",
"uid": "gguid-mock-stub",
- "url": null,
+ "url": "rule-link",
},
]
`;
@@ -39,21 +39,21 @@ Array [
],
"id": "Rule #3",
"uid": "gguid-mock-stub",
- "url": null,
+ "url": "rule-link-3",
},
Object {
"description": "This describes Rule #1",
"guidance": Array [],
"id": "Rule #1",
"uid": "gguid-mock-stub",
- "url": null,
+ "url": "rule-link",
},
Object {
"description": "This describes Rule #2",
"guidance": Array [],
"id": "Rule #2",
"uid": "gguid-mock-stub",
- "url": null,
+ "url": "rule-link",
},
]
`;
diff --git a/src/tests/unit/tests/electron/platform/android/rule-information-provider.test.ts b/src/tests/unit/tests/electron/platform/android/rule-information-provider.test.ts
index 0d03fabca68..e763199a0cf 100644
--- a/src/tests/unit/tests/electron/platform/android/rule-information-provider.test.ts
+++ b/src/tests/unit/tests/electron/platform/android/rule-information-provider.test.ts
@@ -1,10 +1,10 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
-
import { UnifiedFormattableResolution } from 'common/types/store-data/unified-data-interface';
import { RuleResultsData } from 'electron/platform/android/android-scan-results';
import { RuleInformation } from 'electron/platform/android/rule-information';
import { RuleInformationProvider } from 'electron/platform/android/rule-information-provider';
+
import { buildRuleResultObject } from './scan-results-helpers';
describe('RuleInformationProvider', () => {
diff --git a/src/tests/unit/tests/electron/platform/android/rule-information.test.ts b/src/tests/unit/tests/electron/platform/android/rule-information.test.ts
index a1e3cbce780..26f12156181 100644
--- a/src/tests/unit/tests/electron/platform/android/rule-information.test.ts
+++ b/src/tests/unit/tests/electron/platform/android/rule-information.test.ts
@@ -20,7 +20,14 @@ describe('RuleInformation', () => {
test('RuleId works correctly', () => {
for (const ruleId of testInputs) {
- const ruleInformation = new RuleInformation(ruleId, null, null, null, failIfCalled);
+ const ruleInformation = new RuleInformation(
+ ruleId,
+ null,
+ null,
+ null,
+ null,
+ failIfCalled,
+ );
expect(ruleId === ruleInformation.ruleId);
}
});
@@ -28,6 +35,7 @@ describe('RuleInformation', () => {
test('RuleDescription works correctly', () => {
for (const ruleDescription of testInputs) {
const ruleInformation = new RuleInformation(
+ null,
null,
ruleDescription,
null,
@@ -38,12 +46,25 @@ describe('RuleInformation', () => {
}
});
- test('guidance works correctly', () => {
+ test('rule link works correctly', () => {
const guidance = [link.WCAG_1_1_1];
- const ruleInformation = new RuleInformation(null, null, guidance, null, failIfCalled);
+ const ruleInformation = new RuleInformation(null, null, null, guidance, null, failIfCalled);
expect(ruleInformation.guidance).toEqual(guidance);
});
+ test('guidance works correctly', () => {
+ const url = 'rule-link';
+ const ruleInformation = new RuleInformation(
+ null,
+ 'rule-link',
+ null,
+ null,
+ null,
+ failIfCalled,
+ );
+ expect(ruleInformation.ruleLink).toEqual(url);
+ });
+
test('GetUnifiedResolution works correctly', () => {
const testData: RuleResultsData = {
axeViewId: 'test',
@@ -68,6 +89,7 @@ describe('RuleInformation', () => {
null,
null,
null,
+ null,
getUnifiedFormattableResolutionDelegateMock.object,
failIfCalled,
);
@@ -99,6 +121,7 @@ describe('RuleInformation', () => {
null,
null,
null,
+ null,
includeThisResultMock.object,
);
diff --git a/src/tests/unit/tests/electron/platform/android/scan-results-helpers.ts b/src/tests/unit/tests/electron/platform/android/scan-results-helpers.ts
index f39d74f883c..37ba4de2b05 100644
--- a/src/tests/unit/tests/electron/platform/android/scan-results-helpers.ts
+++ b/src/tests/unit/tests/electron/platform/android/scan-results-helpers.ts
@@ -112,12 +112,14 @@ export function buildViewElement(
export function buildRuleInformation(
ruleId: string,
+ ruleLink = 'rule-link',
guidance: GuidanceLink[] = [],
includeResults: boolean = true,
): RuleInformation {
return {
ruleId: ruleId,
ruleDescription: 'This describes ' + ruleId,
+ ruleLink,
guidance,
getUnifiedFormattableResolutionDelegate: r => {
expect('getUnifiedResolution').toBe('This code should never execute');
diff --git a/src/tests/unit/tests/electron/platform/android/scan-results-to-unified-results.test.ts b/src/tests/unit/tests/electron/platform/android/scan-results-to-unified-results.test.ts
index 4ba578dc4f7..f764276aaa3 100644
--- a/src/tests/unit/tests/electron/platform/android/scan-results-to-unified-results.test.ts
+++ b/src/tests/unit/tests/electron/platform/android/scan-results-to-unified-results.test.ts
@@ -36,7 +36,12 @@ describe('ScanResultsToUnifiedResults', () => {
const ruleInformation1: RuleInformation = buildRuleInformation(ruleId1);
const ruleInformation2: RuleInformation = buildRuleInformation(ruleId2);
const ruleInformation3: RuleInformation = buildRuleInformation(ruleId3);
- const ruleInformation4: RuleInformation = buildRuleInformation(ruleId4, [], false);
+ const ruleInformation4: RuleInformation = buildRuleInformation(
+ ruleId4,
+ 'rule-link-4',
+ [],
+ false,
+ );
ruleInformationProviderMock = Mock.ofType();
ruleInformationProviderMock
diff --git a/src/tests/unit/tests/electron/platform/android/scan-results-to-unified-rules.test.ts b/src/tests/unit/tests/electron/platform/android/scan-results-to-unified-rules.test.ts
index d032581d6d9..657f2947589 100644
--- a/src/tests/unit/tests/electron/platform/android/scan-results-to-unified-rules.test.ts
+++ b/src/tests/unit/tests/electron/platform/android/scan-results-to-unified-rules.test.ts
@@ -73,9 +73,12 @@ describe('ScanResultsToUnifiedRules', () => {
const ruleInformation1: RuleInformation = buildRuleInformation(ruleId1);
const ruleInformation2: RuleInformation = buildRuleInformation(ruleId2);
- const ruleInformation3: RuleInformation = buildRuleInformation(ruleId3, [link.WCAG_1_1_1]);
+ const ruleInformation3: RuleInformation = buildRuleInformation(ruleId3, 'rule-link-3', [
+ link.WCAG_1_1_1,
+ ]);
const ruleInformation4: RuleInformation = buildRuleInformation(
ruleId4,
+ 'rule-link-4',
[link.WCAG_1_2_1],
false,
);
From 505427b4b294c4c040121da2d95257b5961c7f2e Mon Sep 17 00:00:00 2001
From: lisli1 <48259897+lisli1@users.noreply.github.com>
Date: Thu, 14 May 2020 16:50:52 -0700
Subject: [PATCH 05/15] feat(nav-bar-content): add visual helper toggle to
requirement view (#2676)
---
.../components/requirement-view.scss | 11 ++++++
.../components/requirement-view.tsx | 37 ++++++++++++++++++-
.../requirement-view.test.tsx.snap | 3 ++
.../components/requirement-view.test.tsx | 29 +++++++++++++++
4 files changed, 78 insertions(+), 2 deletions(-)
diff --git a/src/DetailsView/components/requirement-view.scss b/src/DetailsView/components/requirement-view.scss
index f46a9352d85..60b13c92b13 100644
--- a/src/DetailsView/components/requirement-view.scss
+++ b/src/DetailsView/components/requirement-view.scss
@@ -7,3 +7,14 @@
padding-left: 6px;
padding-top: 1vh;
}
+
+:global(.visual-helper) {
+ display: flex;
+ padding-top: 1.5vh;
+ &-text {
+ padding-right: 0.9vh;
+ font-family: $fontFamily;
+ font-size: 14px;
+ line-height: 20px;
+ }
+}
diff --git a/src/DetailsView/components/requirement-view.tsx b/src/DetailsView/components/requirement-view.tsx
index 355acd5a9bd..077684baa98 100644
--- a/src/DetailsView/components/requirement-view.tsx
+++ b/src/DetailsView/components/requirement-view.tsx
@@ -1,22 +1,54 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
-import { Requirement } from 'assessments/types/requirement';
+import { AssessmentsProvider } from 'assessments/types/assessments-provider';
+import { Requirement, VisualHelperToggleConfig } from 'assessments/types/requirement';
import { NamedFC } from 'common/react/named-fc';
+import {
+ AssessmentNavState,
+ GeneratedAssessmentInstance,
+} from 'common/types/store-data/assessment-result-data';
+import { DetailsViewActionMessageCreator } from 'DetailsView/actions/details-view-action-message-creator';
import { RequirementInstructions } from 'DetailsView/components/requirement-instructions';
import {
RequirementViewTitle,
RequirementViewTitleDeps,
} from 'DetailsView/components/requirement-view-title';
import * as React from 'react';
+import { DictionaryStringTo } from 'types/common-types';
import * as styles from './requirement-view.scss';
-export type RequirementViewDeps = RequirementViewTitleDeps;
+export type RequirementViewDeps = {
+ detailsViewActionMessageCreator: DetailsViewActionMessageCreator;
+} & RequirementViewTitleDeps;
+
export interface RequirementViewProps {
deps: RequirementViewDeps;
requirement: Requirement;
+ assessmentsProvider: AssessmentsProvider;
+ assessmentNavState: AssessmentNavState;
+ instancesMap: DictionaryStringTo;
+ isStepEnabled: boolean;
+ isStepScanned: boolean;
}
export const RequirementView = NamedFC('RequirementView', props => {
+ const requirement: Readonly = props.assessmentsProvider.getStep(
+ props.assessmentNavState.selectedTestType,
+ props.assessmentNavState.selectedTestSubview,
+ );
+
+ const visualHelperToggleConfig: VisualHelperToggleConfig = {
+ deps: props.deps,
+ assessmentNavState: props.assessmentNavState,
+ instancesMap: props.instancesMap,
+ isStepEnabled: props.isStepEnabled,
+ isStepScanned: props.isStepScanned,
+ };
+
+ const visualHelperToggle = requirement.getVisualHelperToggle
+ ? requirement.getVisualHelperToggle(visualHelperToggleConfig)
+ : null;
+
return (
('RequirementView',
infoAndExamples={props.requirement.infoAndExamples}
/>
{props.requirement.description}
+ {visualHelperToggle}
);
diff --git a/src/tests/unit/tests/DetailsView/components/__snapshots__/requirement-view.test.tsx.snap b/src/tests/unit/tests/DetailsView/components/__snapshots__/requirement-view.test.tsx.snap
index 7ad439b8c99..bb6e800d911 100644
--- a/src/tests/unit/tests/DetailsView/components/__snapshots__/requirement-view.test.tsx.snap
+++ b/src/tests/unit/tests/DetailsView/components/__snapshots__/requirement-view.test.tsx.snap
@@ -11,6 +11,9 @@ exports[`RequirementViewTest renders with content from props 1`] = `
test-description
+
+ test-visual-helper-toggle
+
diff --git a/src/tests/unit/tests/DetailsView/components/requirement-view.test.tsx b/src/tests/unit/tests/DetailsView/components/requirement-view.test.tsx
index 7f252622f88..0c8b36b3204 100644
--- a/src/tests/unit/tests/DetailsView/components/requirement-view.test.tsx
+++ b/src/tests/unit/tests/DetailsView/components/requirement-view.test.tsx
@@ -1,6 +1,9 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
+import { AssessmentsProviderImpl } from 'assessments/assessments-provider';
import { Requirement } from 'assessments/types/requirement';
+import { GeneratedAssessmentInstance } from 'common/types/store-data/assessment-result-data';
+import { VisualizationType } from 'common/types/visualization-type';
import {
RequirementView,
RequirementViewDeps,
@@ -8,6 +11,8 @@ import {
} from 'DetailsView/components/requirement-view';
import { shallow } from 'enzyme';
import * as React from 'react';
+import { Mock } from 'typemoq';
+import { DictionaryStringTo } from 'types/common-types';
describe('RequirementViewTest', () => {
it('renders with content from props', () => {
@@ -17,9 +22,33 @@ describe('RequirementViewTest', () => {
howToTest: how-to-test-stub
,
} as Requirement;
+ const assessmentNavState = {
+ selectedTestType: VisualizationType.Headings,
+ selectedTestSubview: 'test-requirement-name',
+ };
+
+ const selectedRequirementStub = {
+ getVisualHelperToggle: ({}) => test-visual-helper-toggle
,
+ } as Readonly;
+
+ const assessmentsProviderMock = Mock.ofType(AssessmentsProviderImpl);
+ assessmentsProviderMock
+ .setup(ap =>
+ ap.getStep(
+ assessmentNavState.selectedTestType,
+ assessmentNavState.selectedTestSubview,
+ ),
+ )
+ .returns(() => selectedRequirementStub);
+
const props: RequirementViewProps = {
deps: {} as RequirementViewDeps,
requirement: requirementStub,
+ assessmentsProvider: assessmentsProviderMock.object,
+ assessmentNavState: assessmentNavState,
+ instancesMap: {} as DictionaryStringTo,
+ isStepEnabled: true,
+ isStepScanned: true,
};
const rendered = shallow();
From 08529b99d0196230f6b18fa9559facabbb3b9383 Mon Sep 17 00:00:00 2001
From: Wahaj <32555133+waabid@users.noreply.github.com>
Date: Thu, 14 May 2020 18:31:11 -0700
Subject: [PATCH 06/15] feat(nav-bar-content): nav link handler uses
requirement key explicitly (#2684)
* feat(nav-bar-content): nav link handler uses requirement key explicitly
* re-added removed line
---
.../left-nav/assessment-left-nav.tsx | 1 +
.../left-nav/left-nav-link-builder.tsx | 1 +
.../components/left-nav/nav-link-handler.ts | 6 ++-
.../left-nav-link-builder.test.tsx.snap | 54 +++++++++++--------
.../left-nav/left-nav-link-builder.test.tsx | 1 +
.../handlers/nav-link-handler.test.ts | 8 ++-
6 files changed, 47 insertions(+), 24 deletions(-)
diff --git a/src/DetailsView/components/left-nav/assessment-left-nav.tsx b/src/DetailsView/components/left-nav/assessment-left-nav.tsx
index 0ed067d4668..2e51322f2c2 100644
--- a/src/DetailsView/components/left-nav/assessment-left-nav.tsx
+++ b/src/DetailsView/components/left-nav/assessment-left-nav.tsx
@@ -41,6 +41,7 @@ export type TestGettingStartedNavLink = {
export type TestRequirementLeftNavLink = {
displayedIndex: string;
testType: VisualizationType;
+ requirementKey: string;
} & AssessmentLeftNavLink;
export type onTestRequirementClick = (
diff --git a/src/DetailsView/components/left-nav/left-nav-link-builder.tsx b/src/DetailsView/components/left-nav/left-nav-link-builder.tsx
index 7a2fbcd28a0..558e2e72795 100644
--- a/src/DetailsView/components/left-nav/left-nav-link-builder.tsx
+++ b/src/DetailsView/components/left-nav/left-nav-link-builder.tsx
@@ -226,6 +226,7 @@ export class LeftNavLinkBuilder {
title: `${displayedIndex}: ${name} (${narratorRequirementStatus})`,
displayedIndex,
testType: test,
+ requirementKey: requirement.key,
};
}
diff --git a/src/DetailsView/components/left-nav/nav-link-handler.ts b/src/DetailsView/components/left-nav/nav-link-handler.ts
index c9505682ca0..27b9ceee676 100644
--- a/src/DetailsView/components/left-nav/nav-link-handler.ts
+++ b/src/DetailsView/components/left-nav/nav-link-handler.ts
@@ -41,7 +41,11 @@ export class NavLinkHandler {
event: React.MouseEvent,
item: TestRequirementLeftNavLink,
) => {
- this.detailsViewActionMessageCreator.selectRequirement(event, item.key, item.testType);
+ this.detailsViewActionMessageCreator.selectRequirement(
+ event,
+ item.requirementKey,
+ item.testType,
+ );
this.detailsViewActionMessageCreator.changeRightContentPanel('TestView');
};
diff --git a/src/tests/unit/tests/DetailsView/components/left-nav/__snapshots__/left-nav-link-builder.test.tsx.snap b/src/tests/unit/tests/DetailsView/components/left-nav/__snapshots__/left-nav-link-builder.test.tsx.snap
index 12051a7943c..0a757a3257a 100644
--- a/src/tests/unit/tests/DetailsView/components/left-nav/__snapshots__/left-nav-link-builder.test.tsx.snap
+++ b/src/tests/unit/tests/DetailsView/components/left-nav/__snapshots__/left-nav-link-builder.test.tsx.snap
@@ -86,6 +86,27 @@ exports[`LeftNavBuilder buildAssessmentTestLinks should build links for assessme
/>
`;
+exports[`LeftNavBuilder buildOverviewLink should build overview link 1`] = `
+
+`;
+
exports[`LeftNavBuilder buildReflowAssessmentTestLinks should build links for assessments: getting started nav link render 1`] = ``;
exports[`LeftNavBuilder buildReflowAssessmentTestLinks should build links for assessments: getting started nav link render 2`] = ``;
@@ -104,6 +125,7 @@ exports[`LeftNavBuilder buildReflowAssessmentTestLinks should build links for as
"name": "requirement-name-1",
"onClickNavLink": [Function],
"onRenderNavLink": [Function],
+ "requirementKey": "requirement-key-1",
"status": -2,
"testType": 1,
"title": "-1.1: requirement-name-1 (passed)",
@@ -128,6 +150,7 @@ exports[`LeftNavBuilder buildReflowAssessmentTestLinks should build links for as
"name": "requirement-name-1",
"onClickNavLink": [Function],
"onRenderNavLink": [Function],
+ "requirementKey": "requirement-key-1",
"status": -2,
"testType": 1,
"title": "0.1: requirement-name-1 (passed)",
@@ -154,6 +177,7 @@ exports[`LeftNavBuilder buildReflowAssessmentTestLinks should build links for as
"name": "requirement-name-1",
"onClickNavLink": [Function],
"onRenderNavLink": [Function],
+ "requirementKey": "requirement-key-1",
"status": -2,
"testType": 1,
"title": "-1.1: requirement-name-1 (passed)",
@@ -182,6 +206,7 @@ exports[`LeftNavBuilder buildReflowAssessmentTestLinks should build links for as
"name": "requirement-name-1",
"onClickNavLink": [Function],
"onRenderNavLink": [Function],
+ "requirementKey": "requirement-key-1",
"status": -2,
"testType": 1,
"title": "0.1: requirement-name-1 (passed)",
@@ -230,6 +255,7 @@ exports[`LeftNavBuilder buildReflowAssessmentTestLinks should build links for as
"name": "requirement-name-1",
"onClickNavLink": [Function],
"onRenderNavLink": [Function],
+ "requirementKey": "requirement-key-1",
"status": -2,
"testType": 1,
"title": "-1.1: requirement-name-1 (passed)",
@@ -246,6 +272,7 @@ exports[`LeftNavBuilder buildReflowAssessmentTestLinks should build links for as
"name": "requirement-name-2",
"onClickNavLink": [Function],
"onRenderNavLink": [Function],
+ "requirementKey": "requirement-key-2",
"status": -2,
"testType": 1,
"title": "-1.2: requirement-name-2 (passed)",
@@ -300,6 +327,7 @@ exports[`LeftNavBuilder buildReflowAssessmentTestLinks should build links for as
"name": "requirement-name-1",
"onClickNavLink": [Function],
"onRenderNavLink": [Function],
+ "requirementKey": "requirement-key-1",
"status": -2,
"testType": 1,
"title": "0.1: requirement-name-1 (passed)",
@@ -316,6 +344,7 @@ exports[`LeftNavBuilder buildReflowAssessmentTestLinks should build links for as
"name": "requirement-name-2",
"onClickNavLink": [Function],
"onRenderNavLink": [Function],
+ "requirementKey": "requirement-key-2",
"status": -2,
"testType": 1,
"title": "0.2: requirement-name-2 (passed)",
@@ -370,6 +399,7 @@ exports[`LeftNavBuilder buildReflowAssessmentTestLinks should build links for as
"name": "requirement-name-1",
"onClickNavLink": [Function],
"onRenderNavLink": [Function],
+ "requirementKey": "requirement-key-1",
"status": -2,
"testType": 1,
"title": "-1.1: requirement-name-1 (passed)",
@@ -386,6 +416,7 @@ exports[`LeftNavBuilder buildReflowAssessmentTestLinks should build links for as
"name": "requirement-name-2",
"onClickNavLink": [Function],
"onRenderNavLink": [Function],
+ "requirementKey": "requirement-key-2",
"status": -2,
"testType": 1,
"title": "-1.2: requirement-name-2 (passed)",
@@ -439,6 +470,7 @@ exports[`LeftNavBuilder buildReflowAssessmentTestLinks should build links for as
"name": "requirement-name-1",
"onClickNavLink": [Function],
"onRenderNavLink": [Function],
+ "requirementKey": "requirement-key-1",
"status": -2,
"testType": 1,
"title": "0.1: requirement-name-1 (passed)",
@@ -455,6 +487,7 @@ exports[`LeftNavBuilder buildReflowAssessmentTestLinks should build links for as
"name": "requirement-name-2",
"onClickNavLink": [Function],
"onRenderNavLink": [Function],
+ "requirementKey": "requirement-key-2",
"status": -2,
"testType": 1,
"title": "0.2: requirement-name-2 (passed)",
@@ -472,27 +505,6 @@ exports[`LeftNavBuilder buildReflowAssessmentTestLinks should build links for as
/>
`;
-exports[`LeftNavBuilder buildOverviewLink should build overview link 1`] = `
-
-`;
-
exports[`LeftNavBuilder buildVisualizationConfigurationLink should build link using configuration 1`] = `
{
},
testType: test,
status,
+ requirementKey: requirement.key,
} as TestRequirementLeftNavLink;
}
});
diff --git a/src/tests/unit/tests/DetailsView/handlers/nav-link-handler.test.ts b/src/tests/unit/tests/DetailsView/handlers/nav-link-handler.test.ts
index d24fb24e579..d6bebe7a516 100644
--- a/src/tests/unit/tests/DetailsView/handlers/nav-link-handler.test.ts
+++ b/src/tests/unit/tests/DetailsView/handlers/nav-link-handler.test.ts
@@ -81,12 +81,16 @@ describe('NavLinkHandler', () => {
describe('onRequirementClick', () => {
it('should call selectRequirement and changeRightContentPanel with appropriate params', () => {
const requirementLink = {
- key: 'some requirement',
+ requirementKey: 'some requirement',
testType: -1,
} as TestRequirementLeftNavLink;
detailsViewActionMessageCreatorMock
.setup(amc =>
- amc.selectRequirement(eventStub, requirementLink.key, requirementLink.testType),
+ amc.selectRequirement(
+ eventStub,
+ requirementLink.requirementKey,
+ requirementLink.testType,
+ ),
)
.verifiable();
From 4c7d0e50eee25a26cd71886b9118b58a8030d165 Mon Sep 17 00:00:00 2001
From: Liu Haonan
Date: Fri, 15 May 2020 08:15:37 -0700
Subject: [PATCH 07/15] feat(mobile-rules-guidance): update common components
to use LinkComponent (#2686)
* using optional link component
* uts
* update all guidance link usage
* fix report-html-generator deps
* revert a change
* update snapshots
---
src/DetailsView/details-view-initializer.ts | 3 +
.../components/cards/rule-resources.tsx | 14 ++-
src/common/components/guidance-links.tsx | 9 +-
src/injected/components/details-dialog.tsx | 5 +-
.../assessment-report-step-header.tsx | 3 +
.../report-sections/full-rule-header.tsx | 5 +-
src/reports/report-html-generator.tsx | 4 +-
.../guidance-links.test.tsx.snap | 16 ++-
.../rule-resources.test.tsx.snap | 111 +++++++++++++-----
.../components/cards/rule-resources.test.tsx | 29 +++--
.../common/components/guidance-links.test.tsx | 20 ++++
...ssessment-report-step-header.test.tsx.snap | 2 +
.../assessment-report-step-header.test.tsx | 9 +-
.../reports/report-html-generator.test.tsx | 3 +
14 files changed, 179 insertions(+), 54 deletions(-)
diff --git a/src/DetailsView/details-view-initializer.ts b/src/DetailsView/details-view-initializer.ts
index 0fe0aba8b54..802774fe5b7 100644
--- a/src/DetailsView/details-view-initializer.ts
+++ b/src/DetailsView/details-view-initializer.ts
@@ -1,5 +1,6 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
+
import { AssessmentDefaultMessageGenerator } from 'assessments/assessment-default-message-generator';
import { Assessments } from 'assessments/assessments';
import { assessmentsProviderWithFeaturesEnabled } from 'assessments/assessments-feature-flag-filter';
@@ -39,6 +40,7 @@ import { ReactStaticRenderer } from 'reports/react-static-renderer';
import { ReportGenerator } from 'reports/report-generator';
import { ReportHtmlGenerator } from 'reports/report-html-generator';
import { WebReportNameGenerator } from 'reports/report-name-generator';
+
import { A11YSelfValidator } from '../common/a11y-self-validator';
import { AutoChecker } from '../common/auto-checker';
import { AxeInfo } from '../common/axe-info';
@@ -310,6 +312,7 @@ if (isNaN(tabId) === false) {
const assessmentReportHtmlGeneratorDeps = {
outcomeTypeSemanticsFromTestStatus,
getGuidanceTagsFromGuidanceLinks: GetGuidanceTagsFromGuidanceLinks,
+ LinkComponent: NewTabLink,
};
const assessmentReportHtmlGenerator = new AssessmentReportHtmlGenerator(
assessmentReportHtmlGeneratorDeps,
diff --git a/src/common/components/cards/rule-resources.tsx b/src/common/components/cards/rule-resources.tsx
index 02a1fbb5258..52c348ad6f5 100644
--- a/src/common/components/cards/rule-resources.tsx
+++ b/src/common/components/cards/rule-resources.tsx
@@ -2,15 +2,17 @@
// Licensed under the MIT License.
import { GuidanceLinks } from 'common/components/guidance-links';
import { GuidanceTags, GuidanceTagsDeps } from 'common/components/guidance-tags';
-import { NewTabLink } from 'common/components/new-tab-link';
import { NamedFC } from 'common/react/named-fc';
+import { LinkComponentType } from 'common/types/link-component-type';
import { UnifiedRule } from 'common/types/store-data/unified-data-interface';
import { isEmpty } from 'lodash';
import * as React from 'react';
import * as styles from './rule-resources.scss';
-export type RuleResourcesDeps = GuidanceTagsDeps;
+export type RuleResourcesDeps = GuidanceTagsDeps & {
+ LinkComponent: LinkComponentType;
+};
export type RuleResourcesProps = {
deps: RuleResourcesDeps;
@@ -35,12 +37,16 @@ export const RuleResources = NamedFC('RuleResources', ({ dep
const ruleUrl = rule.url;
return (
- More information about {ruleId}
+
+ More information about {ruleId}
+
);
};
- const renderGuidanceLinks = () => ;
+ const renderGuidanceLinks = () => (
+
+ );
const renderGuidanceTags = () => ;
return (
diff --git a/src/common/components/guidance-links.tsx b/src/common/components/guidance-links.tsx
index ac28b1f2cbf..fcee38aceb7 100644
--- a/src/common/components/guidance-links.tsx
+++ b/src/common/components/guidance-links.tsx
@@ -1,14 +1,16 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
+import { LinkComponentType } from 'common/types/link-component-type';
import { isEmpty } from 'lodash';
import * as React from 'react';
import { HyperlinkDefinition } from 'views/content/content-page';
+
import { NamedFC } from '../react/named-fc';
-import { NewTabLink } from './new-tab-link';
export interface GuidanceLinksProps {
links: HyperlinkDefinition[];
classNameForDiv?: string;
+ LinkComponent: LinkComponentType;
}
export const GuidanceLinks = NamedFC('GuidanceLinks', (props: GuidanceLinksProps) => {
@@ -27,11 +29,12 @@ export const GuidanceLinks = NamedFC('GuidanceLinks', (props: GuidanceLinksProps
const renderLink = (link: HyperlinkDefinition, index: number, length: number): JSX.Element => {
const addComma: boolean = index !== length - 1;
const comma = addComma ? , : null;
+ const LinkComponent: LinkComponentType = props.LinkComponent;
return (
- event.stopPropagation()}>
+ event.stopPropagation()}>
{link.text.toUpperCase()}
-
+
{comma}
);
diff --git a/src/injected/components/details-dialog.tsx b/src/injected/components/details-dialog.tsx
index 86b7f68bcd8..db8a5594912 100644
--- a/src/injected/components/details-dialog.tsx
+++ b/src/injected/components/details-dialog.tsx
@@ -213,7 +213,10 @@ export class DetailsDialog extends React.Component
{this.renderSectionTitle(sectionTitle, successTitleId)}
-
+
);
diff --git a/src/reports/components/assessment-report-step-header.tsx b/src/reports/components/assessment-report-step-header.tsx
index 5b87003c94c..2c2a57bdea4 100644
--- a/src/reports/components/assessment-report-step-header.tsx
+++ b/src/reports/components/assessment-report-step-header.tsx
@@ -4,6 +4,7 @@ import { DefaultMessageInterface } from 'assessments/assessment-default-message-
import { GuidanceLinks } from 'common/components/guidance-links';
import { GuidanceTags, GuidanceTagsDeps } from 'common/components/guidance-tags';
import { NamedFC } from 'common/react/named-fc';
+import { LinkComponentType } from 'common/types/link-component-type';
import { ManualTestStatus } from 'common/types/manual-test-status';
import * as React from 'react';
@@ -14,6 +15,7 @@ import { allRequirementOutcomeTypes } from './requirement-outcome-type';
export type AssessmentReportStepHeaderDeps = GuidanceTagsDeps & {
outcomeTypeSemanticsFromTestStatus: (testStatus: ManualTestStatus) => OutcomeTypeSemantic;
+ LinkComponent: LinkComponentType;
};
export interface AssessmentReportStepHeaderProps {
@@ -53,6 +55,7 @@ export const AssessmentReportStepHeader = NamedFC
diff --git a/src/reports/components/report-sections/full-rule-header.tsx b/src/reports/components/report-sections/full-rule-header.tsx
index a6c3cfd10a9..77de37345c7 100644
--- a/src/reports/components/report-sections/full-rule-header.tsx
+++ b/src/reports/components/report-sections/full-rule-header.tsx
@@ -5,15 +5,18 @@ import { GuidanceTags } from 'common/components/guidance-tags';
import { NewTabLink } from 'common/components/new-tab-link';
import { GetGuidanceTagsFromGuidanceLinks } from 'common/get-guidance-tags-from-guidance-links';
import { NamedFC } from 'common/react/named-fc';
+import { LinkComponentType } from 'common/types/link-component-type';
import { CardRuleResult } from 'common/types/store-data/card-view-model';
import { isEmpty, kebabCase } from 'lodash';
import * as React from 'react';
+
import { InstanceOutcomeType } from '../instance-outcome-type';
import { OutcomeChip } from '../outcome-chip';
import { outcomeTypeSemantics } from '../outcome-type';
export type FullRuleHeaderDeps = {
getGuidanceTagsFromGuidanceLinks: GetGuidanceTagsFromGuidanceLinks;
+ LinkComponent: LinkComponentType;
};
export type FullRuleHeaderProps = {
@@ -63,7 +66,7 @@ export const FullRuleHeader = NamedFC('FullRuleHeader', pro
}
return (
<>
- ()
+ ()
>
);
};
diff --git a/src/reports/report-html-generator.tsx b/src/reports/report-html-generator.tsx
index 930bdc00ff6..3aaf6661750 100644
--- a/src/reports/report-html-generator.tsx
+++ b/src/reports/report-html-generator.tsx
@@ -2,13 +2,14 @@
// Licensed under the MIT License.
import { noCardInteractionsSupported } from 'common/components/cards/card-interaction-support';
import { FixInstructionProcessor } from 'common/components/fix-instruction-processor';
+import { NewTabLink } from 'common/components/new-tab-link';
import { NullComponent } from 'common/components/null-component';
import { PropertyConfiguration } from 'common/configs/unified-result-property-configurations';
import { GetGuidanceTagsFromGuidanceLinks } from 'common/get-guidance-tags-from-guidance-links';
import { CardsViewModel } from 'common/types/store-data/card-view-model';
+import { ScanMetadata } from 'common/types/store-data/unified-data-interface';
import * as React from 'react';
-import { ScanMetadata } from 'common/types/store-data/unified-data-interface';
import { ReportBody, ReportBodyProps } from './components/report-sections/report-body';
import { ReportCollapsibleContainerControl } from './components/report-sections/report-collapsible-container';
import {
@@ -48,6 +49,7 @@ export class ReportHtmlGenerator {
getPropertyConfigById: this.getPropertyConfiguration,
cardInteractionSupport: noCardInteractionsSupported,
cardsVisualizationModifierButtons: NullComponent,
+ LinkComponent: NewTabLink,
} as SectionDeps,
cardsViewData: cardsViewData,
toUtcString: this.utcDateConverter,
diff --git a/src/tests/unit/tests/common/components/__snapshots__/guidance-links.test.tsx.snap b/src/tests/unit/tests/common/components/__snapshots__/guidance-links.test.tsx.snap
index 4b35414b218..d914e079ab9 100644
--- a/src/tests/unit/tests/common/components/__snapshots__/guidance-links.test.tsx.snap
+++ b/src/tests/unit/tests/common/components/__snapshots__/guidance-links.test.tsx.snap
@@ -1,18 +1,26 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
+exports[`GuidanceLinksTest linkComponentType is defined as ElectronExternalLink 1`] = `
+"
+
+ TEXT1
+
+"
+`;
+
exports[`GuidanceLinksTest links is empty 1`] = `""`;
exports[`GuidanceLinksTest links is not null 1`] = `
"
-
+
TEXT1
-
+
,Â
-
+
TEXT2
-
+
"
`;
diff --git a/src/tests/unit/tests/common/components/cards/__snapshots__/rule-resources.test.tsx.snap b/src/tests/unit/tests/common/components/cards/__snapshots__/rule-resources.test.tsx.snap
index c6a3120627c..1c6d716e43d 100644
--- a/src/tests/unit/tests/common/components/cards/__snapshots__/rule-resources.test.tsx.snap
+++ b/src/tests/unit/tests/common/components/cards/__snapshots__/rule-resources.test.tsx.snap
@@ -2,7 +2,12 @@
exports[`RuleResources renders with {
url: 'test-url',
- guidanceLinks: [ { href: 'test-href' }, [length]: 1 ]
+ guidanceLinks: [ [length]: 0 ],
+ linkComponent: [Function] {
+ [length]: 1,
+ [name]: '',
+ displayName: 'ElectronExternalLink'
+ }
} 1`] = `
-
More information about
some-rule
-
+
`;
-exports[`RuleResources renders with { url: 'test-url', guidanceLinks: [ [length]: 0 ] } 1`] = `
+exports[`RuleResources renders with {
+ url: 'test-url',
+ guidanceLinks: [ { href: 'test-href' }, [length]: 1 ],
+ linkComponent: [Function] {
+ [length]: 1,
+ [name]: '',
+ displayName: 'ElectronExternalLink'
+ }
+} 1`] = `
@@ -58,26 +64,47 @@ exports[`RuleResources renders with { url: 'test-url', guidanceLinks: [ [length]
-
More information about
some-rule
-
+
`;
-exports[`RuleResources renders with { url: 'test-url', guidanceLinks: null } 1`] = `
+exports[`RuleResources renders with {
+ url: 'test-url',
+ guidanceLinks: null,
+ linkComponent: [Function] { [length]: 1, [name]: '', displayName: 'NewTabLink' }
+} 1`] = `
@@ -98,19 +125,36 @@ exports[`RuleResources renders with { url: 'test-url', guidanceLinks: null } 1`]
`;
-exports[`RuleResources renders with { url: null, guidanceLinks: [ [length]: 0 ] } 1`] = `null`;
+exports[`RuleResources renders with {
+ url: null,
+ guidanceLinks: [ [length]: 0 ],
+ linkComponent: [Function] {
+ [length]: 1,
+ [name]: '',
+ displayName: 'ElectronExternalLink'
+ }
+} 1`] = `null`;
-exports[`RuleResources renders with { url: null, guidanceLinks: [ { href: 'test-href' }, [length]: 1 ] } 1`] = `
+exports[`RuleResources renders with {
+ url: null,
+ guidanceLinks: [ { href: 'test-href' }, [length]: 1 ],
+ linkComponent: [Function] { [length]: 1, [name]: '', displayName: 'NewTabLink' }
+} 1`] = `
@@ -121,6 +165,7 @@ exports[`RuleResources renders with { url: null, guidanceLinks: [ { href: 'test-
`;
-exports[`RuleResources renders with { url: null, guidanceLinks: null } 1`] = `null`;
+exports[`RuleResources renders with {
+ url: null,
+ guidanceLinks: null,
+ linkComponent: [Function] { [length]: 1, [name]: '', displayName: 'NewTabLink' }
+} 1`] = `null`;
diff --git a/src/tests/unit/tests/common/components/cards/rule-resources.test.tsx b/src/tests/unit/tests/common/components/cards/rule-resources.test.tsx
index aadf46eaf13..148b456084a 100644
--- a/src/tests/unit/tests/common/components/cards/rule-resources.test.tsx
+++ b/src/tests/unit/tests/common/components/cards/rule-resources.test.tsx
@@ -5,10 +5,14 @@ import {
RuleResourcesDeps,
RuleResourcesProps,
} from 'common/components/cards/rule-resources';
+import { NewTabLink } from 'common/components/new-tab-link';
+import { LinkComponentType } from 'common/types/link-component-type';
+import { ElectronExternalLink } from 'electron/views/device-connect-view/components/electron-external-link';
import { shallow } from 'enzyme';
import { cloneDeep } from 'lodash';
import * as React from 'react';
import { GuidanceLink } from 'scanner/rule-to-links-mappings';
+
import { exampleUnifiedRuleResult } from './sample-view-model-data';
describe('RuleResources', () => {
@@ -16,15 +20,24 @@ describe('RuleResources', () => {
type TestCases = {
url: string;
guidanceLinks: GuidanceLink[];
+ linkComponent: LinkComponentType;
};
const testCases: TestCases[] = [
- { url: 'test-url', guidanceLinks: [{ href: 'test-href' } as GuidanceLink] },
- { url: null, guidanceLinks: [{ href: 'test-href' } as GuidanceLink] },
- { url: 'test-url', guidanceLinks: [] },
- { url: 'test-url', guidanceLinks: null },
- { url: null, guidanceLinks: [] },
- { url: null, guidanceLinks: null },
+ {
+ url: 'test-url',
+ guidanceLinks: [{ href: 'test-href' } as GuidanceLink],
+ linkComponent: ElectronExternalLink,
+ },
+ {
+ url: null,
+ guidanceLinks: [{ href: 'test-href' } as GuidanceLink],
+ linkComponent: NewTabLink,
+ },
+ { url: 'test-url', guidanceLinks: [], linkComponent: ElectronExternalLink },
+ { url: 'test-url', guidanceLinks: null, linkComponent: NewTabLink },
+ { url: null, guidanceLinks: [], linkComponent: ElectronExternalLink },
+ { url: null, guidanceLinks: null, linkComponent: NewTabLink },
];
it.each(testCases)('with %o', testCase => {
@@ -34,7 +47,9 @@ describe('RuleResources', () => {
const props: RuleResourcesProps = {
rule,
- deps: {} as RuleResourcesDeps,
+ deps: {
+ LinkComponent: testCase.linkComponent,
+ } as RuleResourcesDeps,
};
const wrapper = shallow();
diff --git a/src/tests/unit/tests/common/components/guidance-links.test.tsx b/src/tests/unit/tests/common/components/guidance-links.test.tsx
index bbf4c47cfe3..5b03debf9b9 100644
--- a/src/tests/unit/tests/common/components/guidance-links.test.tsx
+++ b/src/tests/unit/tests/common/components/guidance-links.test.tsx
@@ -1,5 +1,6 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
+import { ElectronExternalLink } from 'electron/views/device-connect-view/components/electron-external-link';
import { shallow } from 'enzyme';
import * as React from 'react';
@@ -11,6 +12,7 @@ describe('GuidanceLinksTest', () => {
const props: GuidanceLinksProps = {
links: null,
classNameForDiv: null,
+ LinkComponent: NewTabLink,
};
const rendered = shallow();
@@ -21,6 +23,7 @@ describe('GuidanceLinksTest', () => {
const props: GuidanceLinksProps = {
links: [],
classNameForDiv: null,
+ LinkComponent: NewTabLink,
};
const rendered = shallow();
@@ -40,6 +43,22 @@ describe('GuidanceLinksTest', () => {
},
],
classNameForDiv: 'className',
+ LinkComponent: ElectronExternalLink,
+ };
+
+ const rendered = shallow();
+ expect(rendered.debug()).toMatchSnapshot();
+ });
+
+ test('linkComponentType is defined as ElectronExternalLink', () => {
+ const props: GuidanceLinksProps = {
+ links: [
+ {
+ text: 'text1',
+ href: 'https://url1',
+ },
+ ],
+ LinkComponent: ElectronExternalLink,
};
const rendered = shallow();
@@ -55,6 +74,7 @@ describe('GuidanceLinksTest', () => {
},
],
classNameForDiv: 'className',
+ LinkComponent: NewTabLink,
};
const rendered = shallow();
diff --git a/src/tests/unit/tests/reports/components/__snapshots__/assessment-report-step-header.test.tsx.snap b/src/tests/unit/tests/reports/components/__snapshots__/assessment-report-step-header.test.tsx.snap
index ed588c0f299..e056a0d3cc7 100644
--- a/src/tests/unit/tests/reports/components/__snapshots__/assessment-report-step-header.test.tsx.snap
+++ b/src/tests/unit/tests/reports/components/__snapshots__/assessment-report-step-header.test.tsx.snap
@@ -24,6 +24,7 @@ exports[`AssessmentReportStepHeader matches snapshot 1`] = `
-
{
function genHeader(requirementType: RequirementType): RequirementHeaderReportModel {
@@ -31,6 +31,7 @@ describe('AssessmentReportStepHeader', () => {
return { pastTense: ManualTestStatus[testStatus] + '-tested' };
},
getGuidanceTagsFromGuidanceLinks: Mock.ofInstance(GetGuidanceTagsFromGuidanceLinks).object,
+ LinkComponent: NewTabLink,
};
test('matches snapshot', () => {
diff --git a/src/tests/unit/tests/reports/report-html-generator.test.tsx b/src/tests/unit/tests/reports/report-html-generator.test.tsx
index 833c789d4cd..69deea098e6 100644
--- a/src/tests/unit/tests/reports/report-html-generator.test.tsx
+++ b/src/tests/unit/tests/reports/report-html-generator.test.tsx
@@ -2,6 +2,7 @@
// Licensed under the MIT License.
import { noCardInteractionsSupported } from 'common/components/cards/card-interaction-support';
import { FixInstructionProcessor } from 'common/components/fix-instruction-processor';
+import { NewTabLink } from 'common/components/new-tab-link';
import { NullComponent } from 'common/components/null-component';
import { DateProvider } from 'common/date-provider';
import { GetGuidanceTagsFromGuidanceLinks } from 'common/get-guidance-tags-from-guidance-links';
@@ -20,6 +21,7 @@ import {
import { ReactStaticRenderer } from 'reports/react-static-renderer';
import { ReportHtmlGenerator } from 'reports/report-html-generator';
import { It, Mock, MockBehavior, Times } from 'typemoq';
+
import { exampleUnifiedStatusResults } from '../common/components/cards/sample-view-model-data';
describe('ReportHtmlGenerator', () => {
@@ -69,6 +71,7 @@ describe('ReportHtmlGenerator', () => {
collapsibleControl: ReportCollapsibleContainerControl,
cardInteractionSupport: cardInteractionSupport,
cardsVisualizationModifierButtons: NullComponent,
+ LinkComponent: NewTabLink,
} as SectionDeps,
fixInstructionProcessor: fixInstructionProcessorMock.object,
sectionFactory: sectionFactoryMock.object as ReportBodySectionFactory,
From a6f1985d4e9025a377686fbaba4b8a28ec48a2b1 Mon Sep 17 00:00:00 2001
From: "dependabot-preview[bot]"
<27856297+dependabot-preview[bot]@users.noreply.github.com>
Date: Fri, 15 May 2020 17:41:25 +0000
Subject: [PATCH 08/15] chore(deps-dev): bump @types/lodash from 4.14.150 to
4.14.151 (#2691)
---
package.json | 2 +-
yarn.lock | 8 ++++----
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/package.json b/package.json
index 836ca9ca459..36fbcb4a3c8 100644
--- a/package.json
+++ b/package.json
@@ -65,7 +65,7 @@
"@types/enzyme-adapter-react-16": "^1.0.6",
"@types/jest": "^25.2.2",
"@types/jsdom": "^16.2.1",
- "@types/lodash": "^4.14.150",
+ "@types/lodash": "^4.14.151",
"@types/make-dir": "^2.1.0",
"@types/moment": "^2.13.0",
"@types/puppeteer": "^2.1.0",
diff --git a/yarn.lock b/yarn.lock
index 09b12c33f17..7e021b174bf 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -800,10 +800,10 @@
"@types/parse5" "*"
"@types/tough-cookie" "*"
-"@types/lodash@^4.14.150":
- version "4.14.150"
- resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.150.tgz#649fe44684c3f1fcb6164d943c5a61977e8cf0bd"
- integrity sha512-kMNLM5JBcasgYscD9x/Gvr6lTAv2NVgsKtet/hm93qMyf/D1pt+7jeEZklKJKxMVmXjxbRVQQGfqDSfipYCO6w==
+"@types/lodash@^4.14.151":
+ version "4.14.151"
+ resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.151.tgz#7d58cac32bedb0ec37cb7f99094a167d6176c9d5"
+ integrity sha512-Zst90IcBX5wnwSu7CAS0vvJkTjTELY4ssKbHiTnGcJgi170uiS8yQDdc3v6S77bRqYQIN1App5a1Pc2lceE5/g==
"@types/make-dir@^2.1.0":
version "2.1.0"
From 02f6ae48b4e12ba5a994f3b225abdbb44e2d994f Mon Sep 17 00:00:00 2001
From: "dependabot-preview[bot]"
<27856297+dependabot-preview[bot]@users.noreply.github.com>
Date: Fri, 15 May 2020 17:41:49 +0000
Subject: [PATCH 09/15] chore(deps-dev): bump @types/chrome from 0.0.110 to
0.0.112 (#2694)
---
package.json | 2 +-
yarn.lock | 8 ++++----
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/package.json b/package.json
index 36fbcb4a3c8..24438f3bc49 100644
--- a/package.json
+++ b/package.json
@@ -60,7 +60,7 @@
"7zip-bin": "^5.0.3",
"@electron/get": "^1.12.2",
"@types/applicationinsights-js": "^1.0.7",
- "@types/chrome": "0.0.110",
+ "@types/chrome": "0.0.112",
"@types/enzyme": "^3.10.5",
"@types/enzyme-adapter-react-16": "^1.0.6",
"@types/jest": "^25.2.2",
diff --git a/yarn.lock b/yarn.lock
index 7e021b174bf..3e36158987d 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -672,10 +672,10 @@
dependencies:
"@types/node" "*"
-"@types/chrome@0.0.110":
- version "0.0.110"
- resolved "https://registry.yarnpkg.com/@types/chrome/-/chrome-0.0.110.tgz#e1179fc5e286615308b44ecfc806fe0b81c8708a"
- integrity sha512-oUCGfina2v3eFgCA05vEL6ZlUZcoWaLQCmVRMYeqiDR4RcV9db8WrOQtSypwknathvcdmiatXGK9AiDO9lVDCg==
+"@types/chrome@0.0.112":
+ version "0.0.112"
+ resolved "https://registry.yarnpkg.com/@types/chrome/-/chrome-0.0.112.tgz#fd2a8fd9a410435c79eca2a52ddacddc5bdf9a14"
+ integrity sha512-VJjHiDuF4Xmcn1DuOnGcrMDiGBvoJnaIE6u3ZkhsSz2L16HhnfqIuuM8EAvgQa0ODbNpotHqtPRTKpYoNfpAqQ==
dependencies:
"@types/filesystem" "*"
"@types/har-format" "*"
From a62094f85f5d3f7c7fad852be5af8b6ebefae239 Mon Sep 17 00:00:00 2001
From: "dependabot-preview[bot]"
<27856297+dependabot-preview[bot]@users.noreply.github.com>
Date: Fri, 15 May 2020 17:41:56 +0000
Subject: [PATCH 10/15] chore(deps-dev): bump @types/q from 1.5.2 to 1.5.3
(#2693)
---
package.json | 2 +-
yarn.lock | 8 ++++----
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/package.json b/package.json
index 24438f3bc49..309b21c1e94 100644
--- a/package.json
+++ b/package.json
@@ -69,7 +69,7 @@
"@types/make-dir": "^2.1.0",
"@types/moment": "^2.13.0",
"@types/puppeteer": "^2.1.0",
- "@types/q": "^1.5.2",
+ "@types/q": "^1.5.3",
"@types/react": "^16.9.35",
"@types/react-copy-to-clipboard": "^4.3.0",
"@types/react-dom": "^16.9.8",
diff --git a/yarn.lock b/yarn.lock
index 3e36158987d..93b9d6a3da4 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -866,10 +866,10 @@
dependencies:
"@types/node" "*"
-"@types/q@^1.5.2":
- version "1.5.2"
- resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.2.tgz#690a1475b84f2a884fd07cd797c00f5f31356ea8"
- integrity sha512-ce5d3q03Ex0sy4R14722Rmt6MT07Ua+k4FwDfdcToYJcMKNtRVQvJ6JCAPdAmAnbRb6CsX6aYb9m96NGod9uTw==
+"@types/q@^1.5.3":
+ version "1.5.3"
+ resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.3.tgz#69047ef831f0e5849a3855a25e019850413dc922"
+ integrity sha512-I3wR8FNrk9ny4zJzSB1FBpPHw8kv+eVapS3Hkw+QAF7WCIF7foiEj0GcWFR5mwzw/HUMrLBD+rO/OKJcLf/v+w==
"@types/range-parser@*":
version "1.2.3"
From 89d37c4d5fe3acfd0db52347b7c9eece2b458998 Mon Sep 17 00:00:00 2001
From: AhmedAbdoOrtiga <45858632+AhmedAbdoOrtiga@users.noreply.github.com>
Date: Fri, 15 May 2020 11:17:33 -0700
Subject: [PATCH 11/15] Increase report package version to be published (#2696)
---
src/reports/package/root/package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/reports/package/root/package.json b/src/reports/package/root/package.json
index 2427a74b87b..d82f9063afb 100644
--- a/src/reports/package/root/package.json
+++ b/src/reports/package/root/package.json
@@ -1,6 +1,6 @@
{
"name": "accessibility-insights-report",
- "version": "1.0.2",
+ "version": "1.0.3",
"description": "Accessibility Insights Report",
"license": "MIT",
"repository": {
From bc521a74dddb1d96450268713424f7433559b9ca Mon Sep 17 00:00:00 2001
From: "dependabot-preview[bot]"
<27856297+dependabot-preview[bot]@users.noreply.github.com>
Date: Fri, 15 May 2020 18:21:53 +0000
Subject: [PATCH 12/15] chore(deps-dev): bump @types/jsdom from 16.2.1 to
16.2.2 (#2692)
---
package.json | 2 +-
yarn.lock | 8 ++++----
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/package.json b/package.json
index 309b21c1e94..4940915f41a 100644
--- a/package.json
+++ b/package.json
@@ -64,7 +64,7 @@
"@types/enzyme": "^3.10.5",
"@types/enzyme-adapter-react-16": "^1.0.6",
"@types/jest": "^25.2.2",
- "@types/jsdom": "^16.2.1",
+ "@types/jsdom": "^16.2.2",
"@types/lodash": "^4.14.151",
"@types/make-dir": "^2.1.0",
"@types/moment": "^2.13.0",
diff --git a/yarn.lock b/yarn.lock
index 93b9d6a3da4..f08e3fa1746 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -791,10 +791,10 @@
jest-diff "^25.2.1"
pretty-format "^25.2.1"
-"@types/jsdom@^16.2.1":
- version "16.2.1"
- resolved "https://registry.yarnpkg.com/@types/jsdom/-/jsdom-16.2.1.tgz#9e6eee6a578f74eed5997558ab430dbc11aac753"
- integrity sha512-KCEq427OsWfpX7FRyEMb3i2XIuz8Pt3XPls4nmX0iMTDJWsHD4Kzoa3v4Uv9c9IDf11ALeHUtPcyAjTz/HV03Q==
+"@types/jsdom@^16.2.2":
+ version "16.2.2"
+ resolved "https://registry.yarnpkg.com/@types/jsdom/-/jsdom-16.2.2.tgz#5d820a9578ccb8ac20afecdc141479aa77167dd0"
+ integrity sha512-QP2IQ5d65WtIMfQwttqFVFgMNikqeWO8mwUCfLrHDI4ijwb5qGhzPEm2ajWr2rlcCnjWeoYeb7Jx3+mtZGWMBw==
dependencies:
"@types/node" "*"
"@types/parse5" "*"
From 3acb8abe4acd8dd2a841b3d01583375012f90b33 Mon Sep 17 00:00:00 2001
From: Karan
Date: Fri, 15 May 2020 12:05:48 -0700
Subject: [PATCH 13/15] fix: revert 63145e4 to fix stuck assessment > automated
checks scanning
---
.../components/assessment-test-view.tsx | 1 +
.../assessment-view-update-handler.ts | 8 +-
.../components/assessment-view.tsx | 13 +++-
.../components/reflow-assessment-view.tsx | 15 +++-
src/DetailsView/components/test-step-view.tsx | 47 +----------
.../assessment-test-view.test.tsx.snap | 2 +
.../assessment-view.test.tsx.snap | 2 +-
.../reflow-assessment-view.test.tsx.snap | 8 +-
.../test-step-view.test.tsx.snap | 8 +-
.../assessment-view-update-handler.test.ts | 8 +-
.../components/assessment-view.test.tsx | 21 +++++
.../reflow-assessment-view.test.tsx | 44 ++++++++++-
.../components/test-step-view.test.tsx | 77 +------------------
13 files changed, 115 insertions(+), 139 deletions(-)
diff --git a/src/DetailsView/components/assessment-test-view.tsx b/src/DetailsView/components/assessment-test-view.tsx
index deb01996af2..ae0cb51944e 100644
--- a/src/DetailsView/components/assessment-test-view.tsx
+++ b/src/DetailsView/components/assessment-test-view.tsx
@@ -73,6 +73,7 @@ export const AssessmentTestView = NamedFC(
currentTarget={currentTarget}
prevTarget={prevTarget}
assessmentTestResult={assessmentTestResult}
+ selectedRequirementIsEnabled={selectedRequirementIsEnabled}
/>
);
};
diff --git a/src/DetailsView/components/assessment-view-update-handler.ts b/src/DetailsView/components/assessment-view-update-handler.ts
index 83af945ff5b..4cf0eeb7db6 100644
--- a/src/DetailsView/components/assessment-view-update-handler.ts
+++ b/src/DetailsView/components/assessment-view-update-handler.ts
@@ -26,7 +26,7 @@ export interface AssessmentViewUpdateHandlerProps {
deps: AssessmentViewUpdateHandlerDeps;
assessmentNavState: AssessmentNavState;
assessmentData: AssessmentData;
- isRequirementEnabled: boolean;
+ selectedRequirementIsEnabled: boolean;
currentTarget: Tab;
prevTarget: PersistedTabInfo;
}
@@ -65,12 +65,12 @@ export class AssessmentViewUpdateHandler {
return;
}
- const isRequirementNotScanned = !props.assessmentData.testStepStatus[step].isStepScanned;
- if (props.isRequirementEnabled === false || isRequirementNotScanned) {
+ const isStepNotScanned = !props.assessmentData.testStepStatus[step].isStepScanned;
+ if (props.selectedRequirementIsEnabled === false || isStepNotScanned) {
props.deps.detailsViewActionMessageCreator.enableVisualHelper(
test,
step,
- isRequirementNotScanned,
+ isStepNotScanned,
sendTelemetry,
);
}
diff --git a/src/DetailsView/components/assessment-view.tsx b/src/DetailsView/components/assessment-view.tsx
index 2eb75223b61..aaf9b9bc8eb 100644
--- a/src/DetailsView/components/assessment-view.tsx
+++ b/src/DetailsView/components/assessment-view.tsx
@@ -92,13 +92,23 @@ export class AssessmentView extends React.Component {
);
}
+ public componentDidMount(): void {
+ this.deps.assessmentViewUpdateHandler.onMount(this.props);
+ }
+
public componentDidUpdate(prevProps: AssessmentViewProps): void {
+ this.deps.assessmentViewUpdateHandler.update(prevProps, this.props);
+
const { assessmentTestResult } = this.props;
this.deps.detailsViewExtensionPoint
.apply(assessmentTestResult.definition.extensions)
.onAssessmentViewUpdate(prevProps, this.props);
}
+ public componentWillUnmount(): void {
+ this.deps.assessmentViewUpdateHandler.onUnmount(this.props);
+ }
+
private renderTargetChangeDialog(): JSX.Element {
return (
{
}
featureFlagStoreData={this.props.featureFlagStoreData}
pathSnippetStoreData={this.props.pathSnippetStoreData}
- assessmentData={this.props.assessmentData}
- currentTarget={this.props.currentTarget}
- prevTarget={this.props.prevTarget}
/>
diff --git a/src/DetailsView/components/reflow-assessment-view.tsx b/src/DetailsView/components/reflow-assessment-view.tsx
index a9773f3342b..5d08ef3f14a 100644
--- a/src/DetailsView/components/reflow-assessment-view.tsx
+++ b/src/DetailsView/components/reflow-assessment-view.tsx
@@ -5,6 +5,7 @@ import * as React from 'react';
import {
AssessmentViewUpdateHandler,
AssessmentViewUpdateHandlerDeps,
+ AssessmentViewUpdateHandlerProps,
} from 'DetailsView/components/assessment-view-update-handler';
import { AssessmentTestResult } from '../../common/assessment/assessment-test-result';
import { Tab } from '../../common/itab';
@@ -28,7 +29,7 @@ export type ReflowAssessmentViewProps = {
currentTarget: Tab;
prevTarget: PersistedTabInfo;
assessmentTestResult: AssessmentTestResult;
-};
+} & AssessmentViewUpdateHandlerProps;
export class ReflowAssessmentView extends React.Component {
public render(): JSX.Element {
@@ -46,6 +47,18 @@ export class ReflowAssessmentView extends React.Component {
public render(): JSX.Element {
@@ -90,34 +77,6 @@ export class TestStepView extends React.Component {
);
}
- public componentDidMount(): void {
- this.props.deps.assessmentViewUpdateHandler.onMount(this.getUpdateHandlerProps(this.props));
- }
-
- public componentDidUpdate(prevProps: TestStepViewProps): void {
- this.props.deps.assessmentViewUpdateHandler.update(
- this.getUpdateHandlerProps(prevProps),
- this.getUpdateHandlerProps(this.props),
- );
- }
-
- public componentWillUnmount(): void {
- this.props.deps.assessmentViewUpdateHandler.onUnmount(
- this.getUpdateHandlerProps(this.props),
- );
- }
-
- private getUpdateHandlerProps(props: TestStepViewProps): AssessmentViewUpdateHandlerProps {
- return {
- deps: props.deps,
- isRequirementEnabled: props.isStepEnabled,
- assessmentNavState: props.assessmentNavState,
- assessmentData: props.assessmentData,
- prevTarget: props.prevTarget,
- currentTarget: props.currentTarget,
- };
- }
-
private renderTable(): JSX.Element {
if (this.props.testStep.isManual) {
return (
diff --git a/src/tests/unit/tests/DetailsView/components/__snapshots__/assessment-test-view.test.tsx.snap b/src/tests/unit/tests/DetailsView/components/__snapshots__/assessment-test-view.test.tsx.snap
index 97681ff846c..54f8691ab4f 100644
--- a/src/tests/unit/tests/DetailsView/components/__snapshots__/assessment-test-view.test.tsx.snap
+++ b/src/tests/unit/tests/DetailsView/components/__snapshots__/assessment-test-view.test.tsx.snap
@@ -88,6 +88,7 @@ exports[`AssessmentTestView assessment view, isScanning is false 1`] = `
"detailsViewActionMessageCreator": Object {},
}
}
+ selectedRequirementIsEnabled={false}
/>
}
featureFlag="reflowUI"
@@ -184,6 +185,7 @@ exports[`AssessmentTestView assessment view, isScanning is true 1`] = `
"detailsViewActionMessageCreator": Object {},
}
}
+ selectedRequirementIsEnabled={false}
/>
}
featureFlag="reflowUI"
diff --git a/src/tests/unit/tests/DetailsView/components/__snapshots__/assessment-view.test.tsx.snap b/src/tests/unit/tests/DetailsView/components/__snapshots__/assessment-view.test.tsx.snap
index 77b9fc5f24a..50c6f293a2a 100644
--- a/src/tests/unit/tests/DetailsView/components/__snapshots__/assessment-view.test.tsx.snap
+++ b/src/tests/unit/tests/DetailsView/components/__snapshots__/assessment-view.test.tsx.snap
@@ -22,7 +22,7 @@ exports[`AssessmentViewTest render 1`] = `
-
+
diff --git a/src/tests/unit/tests/DetailsView/components/__snapshots__/reflow-assessment-view.test.tsx.snap b/src/tests/unit/tests/DetailsView/components/__snapshots__/reflow-assessment-view.test.tsx.snap
index f02d039d031..f47530cf044 100644
--- a/src/tests/unit/tests/DetailsView/components/__snapshots__/reflow-assessment-view.test.tsx.snap
+++ b/src/tests/unit/tests/DetailsView/components/__snapshots__/reflow-assessment-view.test.tsx.snap
@@ -3,7 +3,13 @@
exports[`AssessmentViewTest render for gettting started 1`] = `
Test Step Test Name
-
+
-
+
Info & examples
@@ -25,9 +25,9 @@ exports[`TestStepViewTest render, variable part for assisted test 1`] = `
Test Step Test Name
-
+
-
+
Info & examples
diff --git a/src/tests/unit/tests/DetailsView/components/assessment-view-update-handler.test.ts b/src/tests/unit/tests/DetailsView/components/assessment-view-update-handler.test.ts
index 4bd723439c8..abf77fe9bb8 100644
--- a/src/tests/unit/tests/DetailsView/components/assessment-view-update-handler.test.ts
+++ b/src/tests/unit/tests/DetailsView/components/assessment-view-update-handler.test.ts
@@ -18,12 +18,12 @@ describe('AssessmentViewTest', () => {
const firstAssessment = assessmentsProvider.all()[0];
const stepName = firstAssessment.requirements[0].key;
let detailsViewActionMessageCreatorMock: IMock;
- let isRequirementEnabled: boolean;
+ let selectedRequirementIsEnabled: boolean;
let testObject: AssessmentViewUpdateHandler;
beforeEach(() => {
- isRequirementEnabled = false;
+ selectedRequirementIsEnabled = false;
detailsViewActionMessageCreatorMock = Mock.ofType();
testObject = new AssessmentViewUpdateHandler();
});
@@ -71,7 +71,7 @@ describe('AssessmentViewTest', () => {
a.enableVisualHelper(firstAssessment.visualizationType, stepName, false),
)
.verifiable(Times.never());
- isRequirementEnabled = true;
+ selectedRequirementIsEnabled = true;
const props = buildProps({ selector: {} });
testObject.onMount(props);
@@ -218,7 +218,7 @@ describe('AssessmentViewTest', () => {
deps,
prevTarget,
currentTarget: isTargetChanged ? anotherTarget : prevTarget,
- isRequirementEnabled: isRequirementEnabled,
+ selectedRequirementIsEnabled: selectedRequirementIsEnabled,
assessmentNavState,
assessmentData,
};
diff --git a/src/tests/unit/tests/DetailsView/components/assessment-view.test.tsx b/src/tests/unit/tests/DetailsView/components/assessment-view.test.tsx
index f9599aee17f..eb216520c1c 100644
--- a/src/tests/unit/tests/DetailsView/components/assessment-view.test.tsx
+++ b/src/tests/unit/tests/DetailsView/components/assessment-view.test.tsx
@@ -37,6 +37,16 @@ describe('AssessmentViewTest', () => {
expect(rendered.debug()).toMatchSnapshot();
});
+ test('componentDidMount', () => {
+ const props = builder.buildProps();
+ builder.updateHandlerMock.setup(u => u.onMount(props)).verifiable(Times.once());
+
+ const testObject = new AssessmentView(props);
+
+ testObject.componentDidMount();
+ builder.verifyAll();
+ });
+
test('componentDidUpdate', () => {
const prevProps = buildPrevProps();
const props = builder.buildProps();
@@ -44,6 +54,7 @@ describe('AssessmentViewTest', () => {
(previousProps: AssessmentViewProps, currentProps: AssessmentViewProps) => {},
);
+ builder.updateHandlerMock.setup(u => u.update(prevProps, props)).verifiable(Times.once());
builder.detailsViewExtensionPointMock
.setup(d => d.apply(props.assessmentTestResult.definition.extensions))
.returns(() => {
@@ -60,6 +71,16 @@ describe('AssessmentViewTest', () => {
onAssessmentViewUpdateMock.verifyAll();
});
+ test('componentWillUnmount', () => {
+ const props = builder.buildProps();
+ builder.updateHandlerMock.setup(u => u.onUnmount(props)).verifiable(Times.once());
+
+ const testObject = new AssessmentView(props);
+
+ testObject.componentWillUnmount();
+ builder.verifyAll();
+ });
+
function buildPrevProps(): AssessmentViewProps {
const prevStep = 'prevStep';
const prevTest = -100 as VisualizationType;
diff --git a/src/tests/unit/tests/DetailsView/components/reflow-assessment-view.test.tsx b/src/tests/unit/tests/DetailsView/components/reflow-assessment-view.test.tsx
index 46f087b5911..d54c8c89a5b 100644
--- a/src/tests/unit/tests/DetailsView/components/reflow-assessment-view.test.tsx
+++ b/src/tests/unit/tests/DetailsView/components/reflow-assessment-view.test.tsx
@@ -4,8 +4,9 @@ import { AssessmentTestResult } from 'common/assessment/assessment-test-result';
import { AssessmentData } from 'common/types/store-data/assessment-result-data';
import { shallow } from 'enzyme';
import * as React from 'react';
-import { Mock } from 'typemoq';
+import { IMock, Mock, Times } from 'typemoq';
+import { AssessmentViewUpdateHandler } from 'DetailsView/components/assessment-view-update-handler';
import {
ReflowAssessmentView,
ReflowAssessmentViewDeps,
@@ -13,6 +14,12 @@ import {
} from '../../../../../DetailsView/components/reflow-assessment-view';
describe('AssessmentViewTest', () => {
+ let updateHandlerMock: IMock;
+
+ beforeEach(() => {
+ updateHandlerMock = Mock.ofType(AssessmentViewUpdateHandler);
+ });
+
test('render for requirement', () => {
const props = generateProps('requirement');
const rendered = shallow();
@@ -25,6 +32,37 @@ describe('AssessmentViewTest', () => {
expect(rendered.getElement()).toMatchSnapshot();
});
+ test('componentDidMount', () => {
+ const props = generateProps('requirement');
+ updateHandlerMock.setup(u => u.onMount(props)).verifiable(Times.once());
+ const testObject = new ReflowAssessmentView(props);
+
+ testObject.componentDidMount();
+
+ updateHandlerMock.verifyAll();
+ });
+
+ test('componentWillUnmount', () => {
+ const props = generateProps('requirement');
+ updateHandlerMock.setup(u => u.onUnmount(props)).verifiable(Times.once());
+ const testObject = new ReflowAssessmentView(props);
+
+ testObject.componentWillUnmount();
+
+ updateHandlerMock.verifyAll();
+ });
+
+ test('componentDidUpdate', () => {
+ const prevProps = generateProps('requirement1');
+ const props = generateProps('requirement2');
+ updateHandlerMock.setup(u => u.update(prevProps, props)).verifiable(Times.once());
+ const testObject = new ReflowAssessmentView(props);
+
+ testObject.componentDidUpdate(prevProps);
+
+ updateHandlerMock.verifyAll();
+ });
+
function generateProps(subview: string): ReflowAssessmentViewProps {
const assessmentDataMock = Mock.ofType();
@@ -35,7 +73,9 @@ describe('AssessmentViewTest', () => {
} as AssessmentTestResult;
const reflowProps = {
- deps: {} as ReflowAssessmentViewDeps,
+ deps: {
+ assessmentViewUpdateHandler: updateHandlerMock.object,
+ } as ReflowAssessmentViewDeps,
prevTarget: { id: 4 },
currentTarget: { id: 5 },
assessmentNavState: {
diff --git a/src/tests/unit/tests/DetailsView/components/test-step-view.test.tsx b/src/tests/unit/tests/DetailsView/components/test-step-view.test.tsx
index 4fb62edcd41..46b7f927fbe 100644
--- a/src/tests/unit/tests/DetailsView/components/test-step-view.test.tsx
+++ b/src/tests/unit/tests/DetailsView/components/test-step-view.test.tsx
@@ -6,17 +6,9 @@ import { CollapsibleComponent } from 'common/components/collapsible-component';
import { ManualTestStatus } from 'common/types/manual-test-status';
import { VisualizationType } from 'common/types/visualization-type';
import { AssessmentInstanceTable } from 'DetailsView/components/assessment-instance-table';
-import {
- AssessmentViewUpdateHandler,
- AssessmentViewUpdateHandlerProps,
-} from 'DetailsView/components/assessment-view-update-handler';
import { AssessmentVisualizationEnabledToggle } from 'DetailsView/components/assessment-visualization-enabled-toggle';
import { ManualTestStepView } from 'DetailsView/components/manual-test-step-view';
-import {
- TestStepView,
- TestStepViewDeps,
- TestStepViewProps,
-} from 'DetailsView/components/test-step-view';
+import { TestStepView, TestStepViewProps } from 'DetailsView/components/test-step-view';
import * as styles from 'DetailsView/components/test-step-view.scss';
import { AssessmentInstanceTableHandler } from 'DetailsView/handlers/assessment-instance-table-handler';
import * as Enzyme from 'enzyme';
@@ -25,14 +17,12 @@ import { BaseDataBuilder } from 'tests/unit/common/base-data-builder';
import { IMock, It, Mock, MockBehavior, Times } from 'typemoq';
let getVisualHelperToggleMock: IMock<(provider, props) => {}>;
-let updateHandlerMock: IMock;
describe('TestStepViewTest', () => {
beforeEach(() => {
getVisualHelperToggleMock = Mock.ofInstance((provider, props) => {
return null;
});
- updateHandlerMock = Mock.ofType();
});
test('constructor, no side effects', () => {
@@ -145,55 +135,6 @@ describe('TestStepViewTest', () => {
expect(wrapper.debug()).toMatchSnapshot();
});
- test('componentDidUpdate', () => {
- const props = TestStepViewPropsBuilder.defaultProps(
- getVisualHelperToggleMock.object,
- ).build();
- const prevProps = TestStepViewPropsBuilder.defaultProps(
- getVisualHelperToggleMock.object,
- ).build();
- prevProps.assessmentNavState.selectedTestSubview = 'prevTestStep';
- updateHandlerMock
- .setup(u => u.update(getUpdateHandlerProps(prevProps), getUpdateHandlerProps(props)))
- .verifiable(Times.once());
-
- const testObject = new TestStepView(props);
-
- testObject.componentDidUpdate(prevProps);
-
- updateHandlerMock.verifyAll();
- });
-
- test('componentDidMount', () => {
- const props = TestStepViewPropsBuilder.defaultProps(
- getVisualHelperToggleMock.object,
- ).build();
- updateHandlerMock
- .setup(u => u.onMount(getUpdateHandlerProps(props)))
- .verifiable(Times.once());
-
- const testObject = new TestStepView(props);
-
- testObject.componentDidMount();
-
- updateHandlerMock.verifyAll();
- });
-
- test('componentWillUnmount', () => {
- const props = TestStepViewPropsBuilder.defaultProps(
- getVisualHelperToggleMock.object,
- ).build();
- updateHandlerMock
- .setup(u => u.onUnmount(getUpdateHandlerProps(props)))
- .verifiable(Times.once());
-
- const testObject = new TestStepView(props);
-
- testObject.componentWillUnmount();
-
- updateHandlerMock.verifyAll();
- });
-
function validateManualTestStepView(
wrapper: Enzyme.ShallowWrapper,
props: TestStepViewProps,
@@ -208,17 +149,6 @@ describe('TestStepViewTest', () => {
);
expect(props.assessmentsProvider).toEqual(view.prop('assessmentsProvider'));
}
-
- function getUpdateHandlerProps(props: TestStepViewProps): AssessmentViewUpdateHandlerProps {
- return {
- deps: props.deps,
- isRequirementEnabled: props.isStepEnabled,
- assessmentNavState: props.assessmentNavState,
- assessmentData: props.assessmentData,
- prevTarget: props.prevTarget,
- currentTarget: props.currentTarget,
- };
- }
});
class TestStepViewPropsBuilder extends BaseDataBuilder {
@@ -289,10 +219,7 @@ class TestStepViewPropsBuilder extends BaseDataBuilder {
howToTest: Instructions
,
isManual: false,
guidanceLinks: [],
- })
- .with('deps', {
- assessmentViewUpdateHandler: updateHandlerMock.object,
- } as TestStepViewDeps);
+ });
}
public withNoGetToggleConfig(): TestStepViewPropsBuilder {
From 13eb1b56f737867fdd8be3687eaa853c76da738f Mon Sep 17 00:00:00 2001
From: Dan Bjorge
Date: Fri, 15 May 2020 12:19:02 -0700
Subject: [PATCH 14/15] test: add e2e tests for new Landmarks auto-pass
behavior (#2685)
#### Description of changes
Adds new end to end tests that verify the auto-pass-on-no-landmarks behavior introduced in #2644. Updates the product code to add a new data-automation-id, no UI impact.
#### Pull request checklist
- [x] Addresses an existing issue: e2e test for behavior in #2521
- [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
---
.../components/base-visual-helper-toggle.tsx | 2 +
.../components/cards/visual-helper-toggle.tsx | 2 -
.../components/visualization-toggle.tsx | 2 +
src/tests/end-to-end/common/browser.ts | 12 +++++
.../details-view-selectors.ts | 11 +++-
.../page-controllers/details-view-page.ts | 37 ++++++++++++++
.../landmarks/mixed-landmarks.html | 16 ++++++
.../landmarks/no-landmarks.html | 15 ++++++
.../tests/details-view/headings.test.ts | 29 +++--------
.../tests/details-view/landmarks.test.ts | 50 +++++++++++++++++++
...rt-scan-visual-helper-toggle.test.tsx.snap | 3 ++
...-checks-visualization-toggle.test.tsx.snap | 3 ++
.../components/visualization-toggle.test.tsx | 12 +++++
13 files changed, 169 insertions(+), 25 deletions(-)
create mode 100644 src/tests/end-to-end/test-resources/landmarks/mixed-landmarks.html
create mode 100644 src/tests/end-to-end/test-resources/landmarks/no-landmarks.html
create mode 100644 src/tests/end-to-end/tests/details-view/landmarks.test.ts
diff --git a/src/DetailsView/components/base-visual-helper-toggle.tsx b/src/DetailsView/components/base-visual-helper-toggle.tsx
index e2da2b5bc5c..db0580e2fb2 100644
--- a/src/DetailsView/components/base-visual-helper-toggle.tsx
+++ b/src/DetailsView/components/base-visual-helper-toggle.tsx
@@ -7,6 +7,7 @@ import { VisualizationToggle } from '../../common/components/visualization-toggl
import { GeneratedAssessmentInstance } from '../../common/types/store-data/assessment-result-data';
import { DictionaryStringTo } from '../../types/common-types';
+export const visualHelperToggleAutomationId = 'visual-helper-toggle';
export const visualHelperText = 'Visual helper';
export abstract class BaseVisualHelperToggle extends React.Component {
@@ -30,6 +31,7 @@ export abstract class BaseVisualHelperToggle extends React.Component
{disabledMessage}
diff --git a/src/common/components/cards/visual-helper-toggle.tsx b/src/common/components/cards/visual-helper-toggle.tsx
index 374766a56fd..6c534260b96 100644
--- a/src/common/components/cards/visual-helper-toggle.tsx
+++ b/src/common/components/cards/visual-helper-toggle.tsx
@@ -6,8 +6,6 @@ import { css, Toggle } from 'office-ui-fabric-react';
import * as React from 'react';
import * as styles from './visual-helper-toggle.scss';
-export const visualHelperToggleAutomationId = 'visual-helper-toggle';
-
export type VisualHelperToggleDeps = {
cardSelectionMessageCreator: CardSelectionMessageCreator;
};
diff --git a/src/common/components/visualization-toggle.tsx b/src/common/components/visualization-toggle.tsx
index 78ce3eba537..2df34ad0965 100644
--- a/src/common/components/visualization-toggle.tsx
+++ b/src/common/components/visualization-toggle.tsx
@@ -13,6 +13,7 @@ export interface VisualizationToggleProps {
componentRef?: React.RefObject;
onBlur?: (ev) => void;
onFocus?: (ev) => void;
+ 'data-automation-id'?: string;
}
export class VisualizationToggle extends React.Component {
@@ -29,6 +30,7 @@ export class VisualizationToggle extends React.Component;
diff --git a/src/tests/end-to-end/common/browser.ts b/src/tests/end-to-end/common/browser.ts
index fb1bfa1a3e2..c4cf4df4764 100644
--- a/src/tests/end-to-end/common/browser.ts
+++ b/src/tests/end-to-end/common/browser.ts
@@ -83,6 +83,18 @@ export class Browser {
return page;
}
+ public async newAssessment(
+ targetPageUrlOptions?: TargetPageUrlOptions,
+ ): Promise<{ detailsViewPage: DetailsViewPage; targetPage: TargetPage }> {
+ const targetPage = await this.newTargetPage(targetPageUrlOptions);
+ await this.newPopupPage(targetPage); // Required for the details view to register as having permissions/being open
+
+ const detailsViewPage = await this.newDetailsViewPage(targetPage);
+ await detailsViewPage.switchToAssessment();
+
+ return { detailsViewPage, targetPage };
+ }
+
public async waitForDetailsViewPage(targetPage: TargetPage): Promise {
const expectedUrl = await this.getExtensionUrl(detailsViewRelativeUrl(targetPage.tabId));
const underlyingTarget = await this.underlyingBrowser.waitForTarget(
diff --git a/src/tests/end-to-end/common/element-identifiers/details-view-selectors.ts b/src/tests/end-to-end/common/element-identifiers/details-view-selectors.ts
index 1e9b0a6c5b1..935ff28f650 100644
--- a/src/tests/end-to-end/common/element-identifiers/details-view-selectors.ts
+++ b/src/tests/end-to-end/common/element-identifiers/details-view-selectors.ts
@@ -3,6 +3,7 @@
import { resultSectionAutomationId } from 'common/components/cards/result-section';
import { ruleDetailsGroupAutomationId } from 'common/components/cards/rules-with-instances';
import { instanceTableTextContentAutomationId } from 'DetailsView/components/assessment-instance-details-column';
+import { visualHelperToggleAutomationId } from 'DetailsView/components/base-visual-helper-toggle';
import { settingsPanelAutomationId } from 'DetailsView/components/details-view-overlay/settings-panel/settings-panel';
import { IframeWarningContainerAutomationId } from 'DetailsView/components/iframe-warning';
import { overviewHeadingAutomationId } from 'DetailsView/components/overview-content/overview-heading';
@@ -17,7 +18,15 @@ import { getAutomationIdSelector } from 'tests/common/get-automation-id-selector
export const detailsViewSelectors = {
previewFeaturesPanel: '.preview-features-panel',
- testNavLink: (testName: string): string => `nav [name=${testName}] a`,
+ testNavLink: (testName: string): string => `nav [name="${testName}"] a`,
+ requirementNavLink: (requirementName: string): string => `div [name="${requirementName}"] a`,
+
+ visualHelperToggle: getAutomationIdSelector(visualHelperToggleAutomationId),
+
+ requirementWithStatus: (
+ requirementName: string,
+ status: 'Passed' | 'Failed' | 'Incomplete',
+ ): string => `div[name="${requirementName}"][title^="${requirementName}. ${status}."]`,
mainContent: '[role=main]',
instanceTableTextContent: getAutomationIdSelector(instanceTableTextContentAutomationId),
diff --git a/src/tests/end-to-end/common/page-controllers/details-view-page.ts b/src/tests/end-to-end/common/page-controllers/details-view-page.ts
index b785a7cc422..57d22c7979d 100644
--- a/src/tests/end-to-end/common/page-controllers/details-view-page.ts
+++ b/src/tests/end-to-end/common/page-controllers/details-view-page.ts
@@ -31,6 +31,43 @@ export class DetailsViewPage extends Page {
await this.clickSelector('button[title="Assessment"]');
}
+ public async navigateToTest(testName: string): Promise {
+ await this.clickSelector(detailsViewSelectors.testNavLink(testName));
+ await this.waitForSelectorXPath(`//h1[text()="${testName}"]`);
+ }
+
+ public async navigateToRequirement(requirementName: string): Promise {
+ await this.clickSelector(detailsViewSelectors.requirementNavLink(requirementName));
+ await this.waitForSelectorXPath(`//h3[text()="${requirementName}"]`);
+ }
+
+ public async waitForVisualHelperState(
+ state: 'On' | 'Off' | 'disabled',
+ waitOptions?: Puppeteer.WaitForSelectorOptions,
+ ): Promise {
+ const selectorStateSuffix = {
+ On: ':not([disabled])[aria-checked="true"]',
+ Off: ':not([disabled])[aria-checked="false"]',
+ disabled: '[disabled]',
+ }[state];
+
+ await this.waitForSelector(
+ detailsViewSelectors.visualHelperToggle + selectorStateSuffix,
+ waitOptions,
+ );
+ }
+
+ public async waitForRequirementStatus(
+ requirementName: string,
+ status: 'Passed' | 'Failed' | 'Incomplete',
+ waitOptions?: Puppeteer.WaitForSelectorOptions,
+ ): Promise {
+ await this.waitForSelector(
+ detailsViewSelectors.requirementWithStatus(requirementName, status),
+ waitOptions,
+ );
+ }
+
public async openSettingsPanel(): Promise {
await this.ensureNoModals();
diff --git a/src/tests/end-to-end/test-resources/landmarks/mixed-landmarks.html b/src/tests/end-to-end/test-resources/landmarks/mixed-landmarks.html
new file mode 100644
index 00000000000..d45a75ef275
--- /dev/null
+++ b/src/tests/end-to-end/test-resources/landmarks/mixed-landmarks.html
@@ -0,0 +1,16 @@
+
+
+
+
+
+ Landmarks - Mixed
+
+
+
+
+ Main landmark content
+
+
diff --git a/src/tests/end-to-end/test-resources/landmarks/no-landmarks.html b/src/tests/end-to-end/test-resources/landmarks/no-landmarks.html
new file mode 100644
index 00000000000..611259c4d12
--- /dev/null
+++ b/src/tests/end-to-end/test-resources/landmarks/no-landmarks.html
@@ -0,0 +1,15 @@
+
+
+
+
+
+ Landmarks - None
+
+
+
+ No landmarks on this page
+
+
diff --git a/src/tests/end-to-end/tests/details-view/headings.test.ts b/src/tests/end-to-end/tests/details-view/headings.test.ts
index fcbe28a7db2..d36b1d4a7ea 100644
--- a/src/tests/end-to-end/tests/details-view/headings.test.ts
+++ b/src/tests/end-to-end/tests/details-view/headings.test.ts
@@ -4,13 +4,11 @@ import { Browser } from '../../common/browser';
import { launchBrowser } from '../../common/browser-factory';
import { detailsViewSelectors } from '../../common/element-identifiers/details-view-selectors';
import { DetailsViewPage } from '../../common/page-controllers/details-view-page';
-import { TargetPage } from '../../common/page-controllers/target-page';
import { scanForAccessibilityIssues } from '../../common/scan-for-accessibility-issues';
import { DEFAULT_TARGET_PAGE_SCAN_TIMEOUT_MS } from '../../common/timeouts';
describe('Details View -> Assessment -> Headings', () => {
let browser: Browser;
- let targetPage: TargetPage;
let headingsPage: DetailsViewPage;
beforeAll(async () => {
@@ -18,9 +16,13 @@ describe('Details View -> Assessment -> Headings', () => {
suppressFirstTimeDialog: true,
addExtraPermissionsToManifest: 'fake-activeTab',
});
- targetPage = await browser.newTargetPage();
- await browser.newPopupPage(targetPage); // Required for the details view to register as having permissions/being open
- headingsPage = await openHeadingsPage(browser, targetPage);
+
+ headingsPage = (await browser.newAssessment()).detailsViewPage;
+
+ await headingsPage.navigateToTest('Headings');
+ await headingsPage.waitForVisualHelperState('Off', {
+ timeout: DEFAULT_TARGET_PAGE_SCAN_TIMEOUT_MS,
+ });
});
afterAll(async () => {
@@ -44,20 +46,3 @@ describe('Details View -> Assessment -> Headings', () => {
},
);
});
-
-async function openHeadingsPage(
- browser: Browser,
- targetPage: TargetPage,
-): Promise {
- const detailsViewPage = await browser.newDetailsViewPage(targetPage);
- await detailsViewPage.switchToAssessment();
-
- await detailsViewPage.clickSelector(detailsViewSelectors.testNavLink('Headings'));
-
- // Populating the instance table requires scanning the target page
- await detailsViewPage.waitForSelector(detailsViewSelectors.instanceTableTextContent, {
- timeout: DEFAULT_TARGET_PAGE_SCAN_TIMEOUT_MS,
- });
-
- return detailsViewPage;
-}
diff --git a/src/tests/end-to-end/tests/details-view/landmarks.test.ts b/src/tests/end-to-end/tests/details-view/landmarks.test.ts
new file mode 100644
index 00000000000..12175553c23
--- /dev/null
+++ b/src/tests/end-to-end/tests/details-view/landmarks.test.ts
@@ -0,0 +1,50 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+import { Browser } from 'tests/end-to-end/common/browser';
+import { launchBrowser } from 'tests/end-to-end/common/browser-factory';
+import { DEFAULT_TARGET_PAGE_SCAN_TIMEOUT_MS } from 'tests/end-to-end/common/timeouts';
+
+describe('Details View -> Assessment -> Landmarks', () => {
+ let browser: Browser;
+
+ beforeEach(async () => {
+ browser = await launchBrowser({
+ suppressFirstTimeDialog: true,
+ addExtraPermissionsToManifest: 'fake-activeTab',
+ });
+ });
+
+ afterEach(async () => {
+ if (browser) {
+ await browser.close();
+ browser = undefined;
+ }
+ });
+
+ describe('Primary content', () => {
+ it('should automatically pass against a target page with no landmarks', async () => {
+ const { detailsViewPage } = await browser.newAssessment({
+ testResourcePath: 'landmarks/no-landmarks.html',
+ });
+ await detailsViewPage.navigateToTest('Landmarks');
+ await detailsViewPage.navigateToRequirement('Primary content');
+
+ await detailsViewPage.waitForRequirementStatus('Primary content', 'Passed', {
+ timeout: DEFAULT_TARGET_PAGE_SCAN_TIMEOUT_MS,
+ });
+ });
+
+ it('should not automatically pass against a target page with any landmarks', async () => {
+ const { detailsViewPage } = await browser.newAssessment({
+ testResourcePath: 'landmarks/mixed-landmarks.html',
+ });
+ await detailsViewPage.navigateToTest('Landmarks');
+ await detailsViewPage.navigateToRequirement('Primary content');
+
+ await detailsViewPage.waitForVisualHelperState('Off', {
+ timeout: DEFAULT_TARGET_PAGE_SCAN_TIMEOUT_MS,
+ });
+ await detailsViewPage.waitForRequirementStatus('Primary content', 'Incomplete');
+ });
+ });
+});
diff --git a/src/tests/unit/tests/DetailsView/components/__snapshots__/restart-scan-visual-helper-toggle.test.tsx.snap b/src/tests/unit/tests/DetailsView/components/__snapshots__/restart-scan-visual-helper-toggle.test.tsx.snap
index e0cc82c1f75..a2f1aa15eb5 100644
--- a/src/tests/unit/tests/DetailsView/components/__snapshots__/restart-scan-visual-helper-toggle.test.tsx.snap
+++ b/src/tests/unit/tests/DetailsView/components/__snapshots__/restart-scan-visual-helper-toggle.test.tsx.snap
@@ -15,6 +15,7 @@ exports[`RestartScanVisualHelperToggleTest onClick: step enabled = false 1`] = `
{
.setLabel('my test label')
.setClassName('my test class')
.setDisabled(true)
+ .setDataAutomationId('test-automation-id')
.build();
const wrapper = Enzyme.shallow();
@@ -77,6 +78,7 @@ describe('VisualizationToggleTest', () => {
componentRef: props.componentRef,
onFocus: props.onFocus,
onBlur: props.onBlur,
+ 'data-automation-id': props['data-automation-id'],
};
return result;
@@ -89,6 +91,7 @@ class VisualizationTogglePropsBuilder {
private disabled: boolean;
private label: string;
private className: string;
+ private dataAutomationId: string;
private visualizationName: string = 'visualizationName';
private componentRefStub: React.RefObject = {} as React.RefObject;
private onBlurMock: IMock<(event) => void> = Mock.ofInstance(event => {});
@@ -99,6 +102,11 @@ class VisualizationTogglePropsBuilder {
return this;
}
+ public setDataAutomationId(dataAutomationId: string): VisualizationTogglePropsBuilder {
+ this.dataAutomationId = dataAutomationId;
+ return this;
+ }
+
public setLabel(label: string): VisualizationTogglePropsBuilder {
this.label = label;
return this;
@@ -138,6 +146,10 @@ class VisualizationTogglePropsBuilder {
props.className = this.className;
}
+ if (this.dataAutomationId != null) {
+ props['data-automation-id'] = this.dataAutomationId;
+ }
+
return props;
}
}
From 6aaffb3e539e31b38b89b4fe85af9c8e5105ea6b Mon Sep 17 00:00:00 2001
From: AhmedAbdoOrtiga <45858632+AhmedAbdoOrtiga@users.noreply.github.com>
Date: Fri, 15 May 2020 12:32:16 -0700
Subject: [PATCH 15/15] Use toolData instead of enviroment provider for issue
filing (#2689)
---
src/DetailsView/details-view-initializer.ts | 12 +++++++-
src/background/background-init.ts | 12 +++++++-
src/background/global-context-factory.ts | 4 ++-
.../issue-details-text-generator.ts | 6 ++--
src/common/application-properties-provider.ts | 23 +++++++++++++++
.../common/application-properties-provider.ts | 20 +++++--------
src/electron/views/renderer-initializer.ts | 7 ++++-
src/injected/dialog-renderer.tsx | 2 +-
src/injected/main-window-context.ts | 8 +++++
src/injected/main-window-initializer.ts | 11 +++++++
.../common/create-file-issue-handler.ts | 6 ++--
.../common/create-issue-details-builder.ts | 11 ++++---
.../common/issue-details-builder.ts | 7 ++---
.../common/issue-filing-controller-impl.ts | 6 ++--
.../create-azure-boards-issue-filing-url.ts | 6 ++--
.../github/create-github-issue-filing-url.ts | 6 ++--
.../types/issue-filing-service.ts | 6 ++--
.../application-properties-provider.test.ts | 29 +++++++++++++++++++
.../background/global-context-factory.test.ts | 4 +++
.../issue-details-text-generator.test.ts | 27 +++++++++--------
.../application-properties-provider.test.ts | 11 +++----
.../tests/injected/dialog-renderer.test.tsx | 4 +++
.../injected/main-window-context.test.ts | 9 ++++++
.../issue-details-builder.test.ts.snap | 8 ++---
.../common/create-file-issue-handler.test.ts | 22 +++++++++-----
.../common/issue-details-builder.test.ts | 19 ++++++++----
.../issue-filing-controller-impl.test.ts | 20 ++++++++-----
...eate-azure-boards-issue-filing-url.test.ts | 28 +++++++++++-------
.../create-github-issue-filing-url.test.ts | 22 +++++++++-----
29 files changed, 248 insertions(+), 108 deletions(-)
create mode 100644 src/common/application-properties-provider.ts
create mode 100644 src/tests/unit/common/application-properties-provider.test.ts
diff --git a/src/DetailsView/details-view-initializer.ts b/src/DetailsView/details-view-initializer.ts
index 802774fe5b7..48fdea721f1 100644
--- a/src/DetailsView/details-view-initializer.ts
+++ b/src/DetailsView/details-view-initializer.ts
@@ -7,6 +7,7 @@ import { assessmentsProviderWithFeaturesEnabled } from 'assessments/assessments-
import { UserConfigurationActions } from 'background/actions/user-configuration-actions';
import { IssueDetailsTextGenerator } from 'background/issue-details-text-generator';
import { UserConfigurationStore } from 'background/stores/global/user-configuration-store';
+import { createToolData } from 'common/application-properties-provider';
import { ExpandCollapseVisualHelperModifierButtons } from 'common/components/cards/cards-visualization-modifier-buttons';
import { ThemeInnerState } from 'common/components/theme';
import { getCardSelectionViewData } from 'common/get-card-selection-view-data';
@@ -14,6 +15,7 @@ import { isResultHighlightUnavailableWeb } from 'common/is-result-highlight-unav
import { createDefaultLogger } from 'common/logging/default-logger';
import { CardSelectionMessageCreator } from 'common/message-creators/card-selection-message-creator';
import { CardSelectionStoreData } from 'common/types/store-data/card-selection-store-data';
+import { toolName } from 'content/strings/application';
import { textContent } from 'content/strings/text-content';
import { AssessmentViewUpdateHandler } from 'DetailsView/components/assessment-view-update-handler';
import { NoContentAvailableViewDeps } from 'DetailsView/components/no-content-available/no-content-available-view';
@@ -294,6 +296,14 @@ if (isNaN(tabId) === false) {
AxeInfo.Default.version,
);
+ const toolData = createToolData(
+ toolName,
+ browserAdapter.getVersion(),
+ 'axe-core',
+ AxeInfo.Default.version,
+ browserSpec,
+ );
+
const reactStaticRenderer = new ReactStaticRenderer();
const reportNameGenerator = new WebReportNameGenerator();
@@ -343,7 +353,7 @@ if (isNaN(tabId) === false) {
const issueDetailsTextGenerator = new IssueDetailsTextGenerator(
IssueFilingUrlStringUtils,
- environmentInfoProvider,
+ toolData,
createIssueDetailsBuilder(PlainTextFormatter),
);
diff --git a/src/background/background-init.ts b/src/background/background-init.ts
index a96b49e0a71..152099ebe9c 100644
--- a/src/background/background-init.ts
+++ b/src/background/background-init.ts
@@ -4,6 +4,7 @@ import { AppInsights } from 'applicationinsights-js';
import { Assessments } from 'assessments/assessments';
import { ConsoleTelemetryClient } from 'background/telemetry/console-telemetry-client';
import { DebugToolsTelemetryClient } from 'background/telemetry/debug-tools-telemetry-client';
+import { createToolData } from 'common/application-properties-provider';
import { AxeInfo } from '../common/axe-info';
import { ChromeAdapter } from '../common/browser-adapters/chrome-adapter';
import { VisualizationConfigurationFactory } from '../common/configs/visualization-configuration-factory';
@@ -18,7 +19,7 @@ import { NotificationCreator } from '../common/notification-creator';
import { createDefaultPromiseFactory } from '../common/promises/promise-factory';
import { TelemetryDataFactory } from '../common/telemetry-data-factory';
import { UrlValidator } from '../common/url-validator';
-import { title } from '../content/strings/application';
+import { title, toolName } from '../content/strings/application';
import { IssueFilingServiceProviderImpl } from '../issue-filing/issue-filing-service-provider-impl';
import { BrowserMessageBroadcasterFactory } from './browser-message-broadcaster-factory';
import { DevToolsListener } from './dev-tools-listener';
@@ -109,6 +110,14 @@ async function initialize(): Promise {
AxeInfo.Default.version,
);
+ const toolData = createToolData(
+ toolName,
+ browserAdapter.getVersion(),
+ 'axe-core',
+ AxeInfo.Default.version,
+ browserSpec,
+ );
+
const globalContext = await GlobalContextFactory.createContext(
browserAdapter,
telemetryEventHandler,
@@ -119,6 +128,7 @@ async function initialize(): Promise {
persistedData,
IssueFilingServiceProviderImpl,
environmentInfoProvider.getEnvironmentInfo(),
+ toolData,
browserAdapter,
browserAdapter,
logger,
diff --git a/src/background/global-context-factory.ts b/src/background/global-context-factory.ts
index 3d68026ec58..7182e2ba490 100644
--- a/src/background/global-context-factory.ts
+++ b/src/background/global-context-factory.ts
@@ -2,6 +2,7 @@
// Licensed under the MIT License.
import { BrowserPermissionsTracker } from 'background/browser-permissions-tracker';
import { Logger } from 'common/logging/logger';
+import { ToolData } from 'common/types/store-data/unified-data-interface';
import { DebugToolsActionCreator } from 'debug-tools/action-creators/debug-tools-action-creator';
import { DebugToolsController } from 'debug-tools/controllers/debug-tools-controller';
import { BrowserAdapter } from '../common/browser-adapters/browser-adapter';
@@ -45,6 +46,7 @@ export class GlobalContextFactory {
persistedData: PersistedData,
issueFilingServiceProvider: IssueFilingServiceProvider,
environmentInfo: EnvironmentInfo,
+ toolData: ToolData,
storageAdapter: StorageAdapter,
commandsAdapter: CommandsAdapter,
logger: Logger,
@@ -74,7 +76,7 @@ export class GlobalContextFactory {
const issueFilingController = new IssueFilingControllerImpl(
issueFilingServiceProvider,
browserAdapter,
- environmentInfo,
+ toolData,
globalStoreHub.userConfigurationStore,
);
diff --git a/src/background/issue-details-text-generator.ts b/src/background/issue-details-text-generator.ts
index d227fe25aa0..3fdace18a12 100644
--- a/src/background/issue-details-text-generator.ts
+++ b/src/background/issue-details-text-generator.ts
@@ -1,6 +1,6 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
-import { EnvironmentInfoProvider } from '../common/environment-info-provider';
+import { ToolData } from 'common/types/store-data/unified-data-interface';
import { CreateIssueDetailsTextData } from '../common/types/create-issue-details-text-data';
import { IssueDetailsBuilder } from '../issue-filing/common/issue-details-builder';
import { IssueUrlCreationUtils } from '../issue-filing/common/issue-filing-url-string-utils';
@@ -8,7 +8,7 @@ import { IssueUrlCreationUtils } from '../issue-filing/common/issue-filing-url-s
export class IssueDetailsTextGenerator {
constructor(
private issueFilingUrlStringUtils: IssueUrlCreationUtils,
- private environmentInfoProvider: EnvironmentInfoProvider,
+ private toolData: ToolData,
private issueDetailsBuilder: IssueDetailsBuilder,
) {}
@@ -19,7 +19,7 @@ export class IssueDetailsTextGenerator {
`Title: ${this.issueFilingUrlStringUtils.getTitle(data)}`,
`Tags: ${this.buildTags(data, standardTags)}`,
``,
- this.issueDetailsBuilder(this.environmentInfoProvider.getEnvironmentInfo(), data),
+ this.issueDetailsBuilder(this.toolData, data),
].join('\n');
return text;
diff --git a/src/common/application-properties-provider.ts b/src/common/application-properties-provider.ts
new file mode 100644
index 00000000000..c00cffb6d32
--- /dev/null
+++ b/src/common/application-properties-provider.ts
@@ -0,0 +1,23 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+import { ToolData } from './types/store-data/unified-data-interface';
+
+export const createToolData = (
+ toolName: string,
+ toolVersion: string,
+ scanEngineName: string,
+ scanEngineVersion: string,
+ environmentName?: string,
+): ToolData => {
+ return {
+ scanEngineProperties: {
+ name: scanEngineName,
+ version: scanEngineVersion,
+ },
+ applicationProperties: {
+ name: toolName,
+ version: toolVersion,
+ environmentName: environmentName,
+ },
+ };
+};
diff --git a/src/electron/common/application-properties-provider.ts b/src/electron/common/application-properties-provider.ts
index e86ba11c85c..f65a2009dd5 100644
--- a/src/electron/common/application-properties-provider.ts
+++ b/src/electron/common/application-properties-provider.ts
@@ -1,23 +1,17 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
-import { AppDataAdapter } from 'common/browser-adapters/app-data-adapter';
+import { createToolData } from 'common/application-properties-provider';
import { ToolData } from 'common/types/store-data/unified-data-interface';
-import { androidAppTitle } from 'content/strings/application';
import { AndroidScanResults } from 'electron/platform/android/android-scan-results';
export type ToolDataDelegate = (scanResults: AndroidScanResults) => ToolData;
-export const createGetToolDataDelegate = (appDataAdapter: AppDataAdapter): ToolDataDelegate => {
+export const createGetToolDataDelegate = (
+ toolName: string,
+ toolVersion: string,
+ scanEngineName: string,
+): ToolDataDelegate => {
return scanResults => {
- return {
- scanEngineProperties: {
- name: 'axe-android',
- version: scanResults.axeVersion,
- },
- applicationProperties: {
- name: androidAppTitle,
- version: appDataAdapter.getVersion(),
- },
- };
+ return createToolData(toolName, toolVersion, scanEngineName, scanResults.axeVersion);
};
};
diff --git a/src/electron/views/renderer-initializer.ts b/src/electron/views/renderer-initializer.ts
index 72a89447046..38b7ffbd0c1 100644
--- a/src/electron/views/renderer-initializer.ts
+++ b/src/electron/views/renderer-initializer.ts
@@ -303,7 +303,12 @@ getPersistedData(indexedDBInstance, indexedDBDataKeysToFetch).then(
);
windowFrameListener.initialize();
- const getToolData = createGetToolDataDelegate(appDataAdapter);
+ const getToolData = createGetToolDataDelegate(
+ androidAppTitle,
+ appDataAdapter.getVersion(),
+ 'axe-android',
+ );
+
const unifiedResultsBuilder = createDefaultBuilder(getToolData);
const scanController = new ScanController(
scanActions,
diff --git a/src/injected/dialog-renderer.tsx b/src/injected/dialog-renderer.tsx
index 4ce18762bc9..5464ef5ece7 100644
--- a/src/injected/dialog-renderer.tsx
+++ b/src/injected/dialog-renderer.tsx
@@ -83,7 +83,7 @@ export class DialogRenderer {
const issueDetailsTextGenerator = new IssueDetailsTextGenerator(
IssueFilingUrlStringUtils,
- mainWindowContext.getEnvironmentInfoProvider(),
+ mainWindowContext.getToolData(),
createIssueDetailsBuilder(PlainTextFormatter),
);
diff --git a/src/injected/main-window-context.ts b/src/injected/main-window-context.ts
index 33d02892440..01f95df0950 100644
--- a/src/injected/main-window-context.ts
+++ b/src/injected/main-window-context.ts
@@ -1,5 +1,6 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
+import { ToolData } from 'common/types/store-data/unified-data-interface';
import { BaseStore } from '../common/base-store';
import { DevToolActionMessageCreator } from '../common/message-creators/dev-tool-action-message-creator';
import { IssueFilingActionMessageCreator } from '../common/message-creators/issue-filing-action-message-creator';
@@ -19,6 +20,7 @@ export class MainWindowContext {
private issueFilingActionMessageCreator: IssueFilingActionMessageCreator,
private userConfigMessageCreator: UserConfigMessageCreator,
private environmentInfoProvider: EnvironmentInfoProvider,
+ private toolData: ToolData,
private issueFilingServiceProvider: IssueFilingServiceProvider,
) {}
@@ -50,6 +52,10 @@ export class MainWindowContext {
return this.environmentInfoProvider;
}
+ public getToolData(): ToolData {
+ return this.toolData;
+ }
+
public getIssueFilingServiceProvider(): IssueFilingServiceProvider {
return this.issueFilingServiceProvider;
}
@@ -62,6 +68,7 @@ export class MainWindowContext {
issueFilingActionMessageCreator: IssueFilingActionMessageCreator,
userConfigMessageCreator: UserConfigMessageCreator,
environmentInfoProvider: EnvironmentInfoProvider,
+ toolData: ToolData,
issueFilingServiceProvider: IssueFilingServiceProvider,
): void {
window.mainWindowContext = new MainWindowContext(
@@ -72,6 +79,7 @@ export class MainWindowContext {
issueFilingActionMessageCreator,
userConfigMessageCreator,
environmentInfoProvider,
+ toolData,
issueFilingServiceProvider,
);
}
diff --git a/src/injected/main-window-initializer.ts b/src/injected/main-window-initializer.ts
index b7bd994a877..d32d79aa085 100644
--- a/src/injected/main-window-initializer.ts
+++ b/src/injected/main-window-initializer.ts
@@ -21,6 +21,8 @@ import { TargetPageVisualizationUpdater } from 'injected/target-page-visualizati
import { visualizationNeedsUpdate } from 'injected/visualization-needs-update';
import { VisualizationStateChangeHandler } from 'injected/visualization-state-change-handler';
+import { createToolData } from 'common/application-properties-provider';
+import { toolName } from 'content/strings/application';
import { AxeInfo } from '../common/axe-info';
import { InspectConfigurationFactory } from '../common/configs/inspect-configuration-factory';
import { DateProvider } from '../common/date-provider';
@@ -205,6 +207,14 @@ export class MainWindowInitializer extends WindowInitializer {
AxeInfo.Default.version,
);
+ const toolData = createToolData(
+ toolName,
+ this.appDataAdapter.getVersion(),
+ 'axe-core',
+ AxeInfo.Default.version,
+ browserSpec,
+ );
+
MainWindowContext.initialize(
this.devToolStoreProxy,
this.userConfigStoreProxy,
@@ -213,6 +223,7 @@ export class MainWindowInitializer extends WindowInitializer {
issueFilingActionMessageCreator,
userConfigMessageCreator,
environmentInfoProvider,
+ toolData,
IssueFilingServiceProviderImpl,
);
diff --git a/src/issue-filing/common/create-file-issue-handler.ts b/src/issue-filing/common/create-file-issue-handler.ts
index 7522161ca1f..211af036fd6 100644
--- a/src/issue-filing/common/create-file-issue-handler.ts
+++ b/src/issue-filing/common/create-file-issue-handler.ts
@@ -1,10 +1,10 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
import { BrowserAdapter } from 'common/browser-adapters/browser-adapter';
-import { EnvironmentInfo } from 'common/environment-info-provider';
import { CreateIssueDetailsTextData } from 'common/types/create-issue-details-text-data';
import { IssueFilingServicePropertiesMap } from 'common/types/store-data/user-configuration-store';
+import { ToolData } from 'common/types/store-data/unified-data-interface';
import { IssueFilingUrlProvider } from '../types/issue-filing-service';
export const createFileIssueHandler = (
@@ -15,11 +15,11 @@ export const createFileIssueHandler = (
browserAdapter: BrowserAdapter,
servicePropertiesMap: IssueFilingServicePropertiesMap,
issueData: CreateIssueDetailsTextData,
- environmentInfo: EnvironmentInfo,
+ toolData: ToolData,
): Promise => {
const serviceConfig = getSettings(servicePropertiesMap);
- const url = getUrl(serviceConfig, issueData, environmentInfo);
+ const url = getUrl(serviceConfig, issueData, toolData);
await browserAdapter.createActiveTab(url);
};
};
diff --git a/src/issue-filing/common/create-issue-details-builder.ts b/src/issue-filing/common/create-issue-details-builder.ts
index 0b94720d68d..1b346ade8cc 100644
--- a/src/issue-filing/common/create-issue-details-builder.ts
+++ b/src/issue-filing/common/create-issue-details-builder.ts
@@ -1,14 +1,13 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
-import { title } from 'content/strings/application';
+import { ToolData } from 'common/types/store-data/unified-data-interface';
import { compact } from 'lodash';
-import { EnvironmentInfo } from '../../common/environment-info-provider';
import { CreateIssueDetailsTextData } from '../../common/types/create-issue-details-text-data';
import { IssueDetailsBuilder } from './issue-details-builder';
import { MarkupFormatter } from './markup/markup-formatter';
export const createIssueDetailsBuilder = (markup: MarkupFormatter): IssueDetailsBuilder => {
- const getter = (environmentInfo: EnvironmentInfo, data: CreateIssueDetailsTextData): string => {
+ const getter = (toolData: ToolData, data: CreateIssueDetailsTextData): string => {
const {
howToFixSection,
link,
@@ -57,13 +56,13 @@ export const createIssueDetailsBuilder = (markup: MarkupFormatter): IssueDetails
sectionHeader('Environment'),
sectionHeaderSeparator(),
- environmentInfo.browserSpec,
+ toolData.applicationProperties.environmentName,
sectionSeparator(),
footerSeparator(),
- `This accessibility issue was found using ${title} ` +
- `${environmentInfo.extensionVersion} (axe-core ${environmentInfo.axeCoreVersion}), ` +
+ `This accessibility issue was found using ${toolData.applicationProperties.name} ` +
+ `${toolData.applicationProperties.version} (${toolData.scanEngineProperties.name} ${toolData.scanEngineProperties.version}), ` +
'a tool that helps find and fix accessibility issues. Get more information & download ' +
`this tool at ${link('http://aka.ms/AccessibilityInsights')}.`,
];
diff --git a/src/issue-filing/common/issue-details-builder.ts b/src/issue-filing/common/issue-details-builder.ts
index cdbf48d70ad..bb3e075507c 100644
--- a/src/issue-filing/common/issue-details-builder.ts
+++ b/src/issue-filing/common/issue-details-builder.ts
@@ -1,8 +1,5 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
-import { EnvironmentInfo } from '../../common/environment-info-provider';
+import { ToolData } from 'common/types/store-data/unified-data-interface';
import { CreateIssueDetailsTextData } from '../../common/types/create-issue-details-text-data';
-export type IssueDetailsBuilder = (
- environmentInfo: EnvironmentInfo,
- data: CreateIssueDetailsTextData,
-) => string;
+export type IssueDetailsBuilder = (toolData: ToolData, data: CreateIssueDetailsTextData) => string;
diff --git a/src/issue-filing/common/issue-filing-controller-impl.ts b/src/issue-filing/common/issue-filing-controller-impl.ts
index 51fb9203172..e40ff907c03 100644
--- a/src/issue-filing/common/issue-filing-controller-impl.ts
+++ b/src/issue-filing/common/issue-filing-controller-impl.ts
@@ -2,10 +2,10 @@
// Licensed under the MIT License.
import { BaseStore } from 'common/base-store';
import { BrowserAdapter } from 'common/browser-adapters/browser-adapter';
-import { EnvironmentInfo } from 'common/environment-info-provider';
import { CreateIssueDetailsTextData } from 'common/types/create-issue-details-text-data';
import { UserConfigurationStoreData } from 'common/types/store-data/user-configuration-store';
+import { ToolData } from 'common/types/store-data/unified-data-interface';
import { IssueFilingServiceProvider } from '../issue-filing-service-provider';
export type IssueFilingController = {
@@ -16,7 +16,7 @@ export class IssueFilingControllerImpl implements IssueFilingController {
constructor(
private readonly provider: IssueFilingServiceProvider,
private readonly browserAdapter: BrowserAdapter,
- private readonly environmentInfo: EnvironmentInfo,
+ private readonly toolData: ToolData,
private readonly userConfigurationStore: BaseStore,
) {}
@@ -31,7 +31,7 @@ export class IssueFilingControllerImpl implements IssueFilingController {
this.browserAdapter,
userConfigurationStoreData.bugServicePropertiesMap,
issueData,
- this.environmentInfo,
+ this.toolData,
);
};
}
diff --git a/src/issue-filing/services/azure-boards/create-azure-boards-issue-filing-url.ts b/src/issue-filing/services/azure-boards/create-azure-boards-issue-filing-url.ts
index da0af9fc2b1..fb4e67591ed 100644
--- a/src/issue-filing/services/azure-boards/create-azure-boards-issue-filing-url.ts
+++ b/src/issue-filing/services/azure-boards/create-azure-boards-issue-filing-url.ts
@@ -1,7 +1,7 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
+import { ToolData } from 'common/types/store-data/unified-data-interface';
import { title } from 'content/strings/application';
-import { EnvironmentInfo } from '../../../common/environment-info-provider';
import { CreateIssueDetailsTextData } from '../../../common/types/create-issue-details-text-data';
import { createIssueDetailsBuilder } from '../../common/create-issue-details-builder';
import { HTTPQueryBuilder } from '../../common/http-query-builder';
@@ -29,12 +29,12 @@ export const createAzureBoardsIssueFilingUrlProvider = (
return (
settingsData: AzureBoardsIssueFilingSettings,
issueData: CreateIssueDetailsTextData,
- environmentInfo: EnvironmentInfo,
+ toolData: ToolData,
) => {
const titleField = stringUtils.getTitle(issueData);
const standardTags = stringUtils.standardizeTags(issueData);
const tags = buildTags(issueData, standardTags);
- const body = issueDetailsBuilder(environmentInfo, issueData);
+ const body = issueDetailsBuilder(toolData, issueData);
let bodyField: string = '[Microsoft.VSTS.TCM.ReproSteps]';
let workItemType: AzureBoardsWorkItemType = 'Bug';
diff --git a/src/issue-filing/services/github/create-github-issue-filing-url.ts b/src/issue-filing/services/github/create-github-issue-filing-url.ts
index 796aa3a091b..838239ec963 100644
--- a/src/issue-filing/services/github/create-github-issue-filing-url.ts
+++ b/src/issue-filing/services/github/create-github-issue-filing-url.ts
@@ -1,6 +1,6 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
-import { EnvironmentInfo } from '../../../common/environment-info-provider';
+import { ToolData } from 'common/types/store-data/unified-data-interface';
import { CreateIssueDetailsTextData } from '../../../common/types/create-issue-details-text-data';
import { createIssueDetailsBuilder } from '../../common/create-issue-details-builder';
import { HTTPQueryBuilder } from '../../common/http-query-builder';
@@ -22,10 +22,10 @@ export const createGitHubIssueFilingUrlProvider = (
return (
settingsData: GitHubIssueFilingSettings,
issueData: CreateIssueDetailsTextData,
- environmentInfo: EnvironmentInfo,
+ toolData: ToolData,
): string => {
const title = stringUtils.getTitle(issueData);
- const body = issueDetailsBuilder(environmentInfo, issueData);
+ const body = issueDetailsBuilder(toolData, issueData);
const baseUrl = rectifier(settingsData.repository);
diff --git a/src/issue-filing/types/issue-filing-service.ts b/src/issue-filing/types/issue-filing-service.ts
index 34b5eb70c71..f65e5e11527 100644
--- a/src/issue-filing/types/issue-filing-service.ts
+++ b/src/issue-filing/types/issue-filing-service.ts
@@ -1,16 +1,16 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
+import { ToolData } from 'common/types/store-data/unified-data-interface';
import { BrowserAdapter } from '../../common/browser-adapters/browser-adapter';
import { ReactFCWithDisplayName } from '../../common/react/named-fc';
import { IssueFilingServicePropertiesMap } from '../../common/types/store-data/user-configuration-store';
-import { EnvironmentInfo } from './../../common/environment-info-provider';
import { CreateIssueDetailsTextData } from './../../common/types/create-issue-details-text-data';
import { SettingsFormProps } from './settings-form-props';
export type IssueFilingUrlProvider = (
data: Settings,
issueData: CreateIssueDetailsTextData,
- environmentInfo: EnvironmentInfo,
+ toolData: ToolData,
) => string;
export interface IssueFilingService {
@@ -25,7 +25,7 @@ export interface IssueFilingService {
browserAdapter: BrowserAdapter,
servicePropertiesMap: IssueFilingServicePropertiesMap,
issueData: CreateIssueDetailsTextData,
- environmentInfo: EnvironmentInfo,
+ toolData: ToolData,
) => Promise;
}
diff --git a/src/tests/unit/common/application-properties-provider.test.ts b/src/tests/unit/common/application-properties-provider.test.ts
new file mode 100644
index 00000000000..6f764d4a9ed
--- /dev/null
+++ b/src/tests/unit/common/application-properties-provider.test.ts
@@ -0,0 +1,29 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+import { createToolData } from 'common/application-properties-provider';
+
+describe('createToolData', () => {
+ it('returns proper tool data', () => {
+ const result = createToolData(
+ 'test-tool-name',
+ 'test-tool-version',
+ 'test-engine-name',
+ 'test-engine-version',
+ 'test-environment-name',
+ );
+
+ expect(result).toMatchInlineSnapshot(`
+ Object {
+ "applicationProperties": Object {
+ "environmentName": "test-environment-name",
+ "name": "test-tool-name",
+ "version": "test-tool-version",
+ },
+ "scanEngineProperties": Object {
+ "name": "test-engine-name",
+ "version": "test-engine-version",
+ },
+ }
+ `);
+ });
+});
diff --git a/src/tests/unit/tests/background/global-context-factory.test.ts b/src/tests/unit/tests/background/global-context-factory.test.ts
index 96b8ea1b764..000a086dede 100644
--- a/src/tests/unit/tests/background/global-context-factory.test.ts
+++ b/src/tests/unit/tests/background/global-context-factory.test.ts
@@ -10,6 +10,7 @@ import { FeatureFlagStore } from 'background/stores/global/feature-flag-store';
import { LaunchPanelStore } from 'background/stores/global/launch-panel-store';
import { TelemetryEventHandler } from 'background/telemetry/telemetry-event-handler';
import { Logger } from 'common/logging/logger';
+import { ToolData } from 'common/types/store-data/unified-data-interface';
import { IMock, It, Mock } from 'typemoq';
import { BrowserAdapter } from '../../../../common/browser-adapters/browser-adapter';
import { CommandsAdapter } from '../../../../common/browser-adapters/commands-adapter';
@@ -30,6 +31,7 @@ describe('GlobalContextFactoryTest', () => {
let loggerMock: IMock;
let environmentInfoStub: EnvironmentInfo;
+ let toolData: ToolData;
let userDataStub: LocalStorageData;
let idbInstance: IndexedDBAPI;
let persistedDataStub: PersistedData;
@@ -51,6 +53,7 @@ describe('GlobalContextFactoryTest', () => {
userDataStub = {};
environmentInfoStub = {} as EnvironmentInfo;
+ toolData = {} as ToolData;
persistedDataStub = {} as PersistedData;
idbInstance = {} as IndexedDBAPI;
});
@@ -66,6 +69,7 @@ describe('GlobalContextFactoryTest', () => {
persistedDataStub,
issueFilingServiceProviderMock.object,
environmentInfoStub,
+ toolData,
storageAdapterMock.object,
commandsAdapterMock.object,
loggerMock.object,
diff --git a/src/tests/unit/tests/background/issue-details-text-generator.test.ts b/src/tests/unit/tests/background/issue-details-text-generator.test.ts
index 9560c6bd9e7..fd523010e68 100644
--- a/src/tests/unit/tests/background/issue-details-text-generator.test.ts
+++ b/src/tests/unit/tests/background/issue-details-text-generator.test.ts
@@ -1,8 +1,8 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
import { IssueDetailsTextGenerator } from 'background/issue-details-text-generator';
+import { ToolData } from 'common/types/store-data/unified-data-interface';
import { IMock, Mock, MockBehavior } from 'typemoq';
-import { EnvironmentInfoProvider } from '../../../../common/environment-info-provider';
import { CreateIssueDetailsTextData } from '../../../../common/types/create-issue-details-text-data';
import { IssueDetailsBuilder } from '../../../../issue-filing/common/issue-details-builder';
import { IssueUrlCreationUtils } from '../../../../issue-filing/common/issue-filing-url-string-utils';
@@ -11,13 +11,24 @@ describe('Issue details text builder', () => {
let testSubject: IssueDetailsTextGenerator;
let sampleIssueDetailsData: CreateIssueDetailsTextData;
let issueUrlCreationUtilsMock: IMock;
- let envInfoProviderMock: IMock;
let issueDetailsBuilderMock: IMock;
const wcagTags = ['WCAG-1.4.1', 'WCAG-2.8.2'];
const title = `${wcagTags.join(',')}: RR-help (RR-selector)`;
const selector = 'RR-selector';
+ const toolData: ToolData = {
+ scanEngineProperties: {
+ name: 'engine-name',
+ version: 'engine-version',
+ },
+ applicationProperties: {
+ name: 'app-name',
+ version: 'app-version',
+ environmentName: 'environmentName',
+ },
+ };
+
beforeEach(() => {
sampleIssueDetailsData = {
rule: {
@@ -52,22 +63,14 @@ describe('Issue details text builder', () => {
.setup(utils => utils.standardizeTags(sampleIssueDetailsData))
.returns(() => wcagTags);
- const envInfo = {
- axeCoreVersion: 'AXE.CORE.VER',
- browserSpec: 'BROWSER.SPEC',
- extensionVersion: 'MY.EXT.VER',
- };
- envInfoProviderMock = Mock.ofType(undefined, MockBehavior.Strict);
- envInfoProviderMock.setup(provider => provider.getEnvironmentInfo()).returns(() => envInfo);
-
issueDetailsBuilderMock = Mock.ofType(undefined, MockBehavior.Strict);
issueDetailsBuilderMock
- .setup(builder => builder(envInfo, sampleIssueDetailsData))
+ .setup(builder => builder(toolData, sampleIssueDetailsData))
.returns(() => 'test-issue-details-builder');
testSubject = new IssueDetailsTextGenerator(
issueUrlCreationUtilsMock.object,
- envInfoProviderMock.object,
+ toolData,
issueDetailsBuilderMock.object,
);
});
diff --git a/src/tests/unit/tests/electron/common/application-properties-provider.test.ts b/src/tests/unit/tests/electron/common/application-properties-provider.test.ts
index 15a0e6fbb3a..ae8330919ec 100644
--- a/src/tests/unit/tests/electron/common/application-properties-provider.test.ts
+++ b/src/tests/unit/tests/electron/common/application-properties-provider.test.ts
@@ -1,25 +1,26 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
-import { AppDataAdapter } from 'common/browser-adapters/app-data-adapter';
import { createGetToolDataDelegate } from 'electron/common/application-properties-provider';
import { AndroidScanResults } from 'electron/platform/android/android-scan-results';
import { Mock } from 'typemoq';
describe('ToolDataDelegate', () => {
it('returns proper tool data', () => {
- const appDataAdapterMock = Mock.ofType();
- appDataAdapterMock.setup(adapter => adapter.getVersion()).returns(() => 'test-version');
-
const scanResultsMock = Mock.ofType();
scanResultsMock.setup(results => results.axeVersion).returns(() => 'test-axe-version');
- const testSubject = createGetToolDataDelegate(appDataAdapterMock.object);
+ const testSubject = createGetToolDataDelegate(
+ 'Accessibility Insights for Android',
+ 'test-version',
+ 'axe-android',
+ );
const result = testSubject(scanResultsMock.object);
expect(result).toMatchInlineSnapshot(`
Object {
"applicationProperties": Object {
+ "environmentName": undefined,
"name": "Accessibility Insights for Android",
"version": "test-version",
},
diff --git a/src/tests/unit/tests/injected/dialog-renderer.test.tsx b/src/tests/unit/tests/injected/dialog-renderer.test.tsx
index 88eaa06609f..66aa002cadc 100644
--- a/src/tests/unit/tests/injected/dialog-renderer.test.tsx
+++ b/src/tests/unit/tests/injected/dialog-renderer.test.tsx
@@ -16,6 +16,7 @@ import {
import { DevToolStore } from 'background/stores/dev-tools-store';
import { UserConfigurationStore } from 'background/stores/global/user-configuration-store';
import { NavigatorUtils } from 'common/navigator-utils';
+import { ToolData } from 'common/types/store-data/unified-data-interface';
import { BrowserAdapter } from '../../../../common/browser-adapters/browser-adapter';
import { EnvironmentInfoProvider } from '../../../../common/environment-info-provider';
import { FeatureFlags, getDefaultFeatureFlagsWeb } from '../../../../common/feature-flags';
@@ -65,6 +66,8 @@ describe('DialogRendererTests', () => {
let getMainWindoContextMock: IGlobalMock<() => MainWindowContext>;
let rootContainerMock: IMock;
+ const toolData = {} as ToolData;
+
beforeEach(() => {
htmlElementUtilsMock = Mock.ofType(HTMLElementUtils);
windowUtilsMock = Mock.ofType(WindowUtils);
@@ -120,6 +123,7 @@ describe('DialogRendererTests', () => {
issueFilingActionMessageCreatorMock.object,
userConfigMessageCreatorMock.object,
environmentInfoProviderMock.object,
+ toolData,
issueFilingServiceProviderMock.object,
);
});
diff --git a/src/tests/unit/tests/injected/main-window-context.test.ts b/src/tests/unit/tests/injected/main-window-context.test.ts
index f9a9218d06b..cbb03fc4ff6 100644
--- a/src/tests/unit/tests/injected/main-window-context.test.ts
+++ b/src/tests/unit/tests/injected/main-window-context.test.ts
@@ -9,6 +9,7 @@ describe('MainWindowContextTest', () => {
const targetPageActionMessageCreator: any = { name: 'targetPageActionMessageCreator' };
const issueFilingActionMessageCreator: any = { name: 'targetPageActionMessageCreator' };
const environmentInfoProvider: any = { name: 'environmentInfoProvider' };
+ const toolData: any = { name: 'toolData' };
const issueFilingServiceProvider: any = { name: 'issueFilingServiceProvider' };
const userConfigMessageCreator: any = { name: 'userConfigMessageCreator' };
@@ -21,6 +22,7 @@ describe('MainWindowContextTest', () => {
issueFilingActionMessageCreator,
userConfigMessageCreator,
environmentInfoProvider,
+ toolData,
issueFilingServiceProvider,
);
@@ -41,6 +43,7 @@ describe('MainWindowContextTest', () => {
issueFilingActionMessageCreator,
userConfigMessageCreator,
environmentInfoProvider,
+ toolData,
issueFilingServiceProvider,
);
@@ -60,6 +63,7 @@ describe('MainWindowContextTest', () => {
expect(MainWindowContext.getMainWindowContext().getEnvironmentInfoProvider()).toEqual(
environmentInfoProvider,
);
+ expect(MainWindowContext.getMainWindowContext().getToolData()).toEqual(toolData);
expect(MainWindowContext.getMainWindowContext().getIssueFilingServiceProvider()).toEqual(
issueFilingServiceProvider,
);
@@ -74,6 +78,7 @@ describe('MainWindowContextTest', () => {
issueFilingActionMessageCreator,
userConfigMessageCreator,
environmentInfoProvider,
+ toolData,
issueFilingServiceProvider,
);
@@ -81,6 +86,7 @@ describe('MainWindowContextTest', () => {
const userConfigStoreLocal: any = { name: 'userConfigStoreLocal' };
const devToolActionMessageCreatorLocal: any = { name: 'devToolActionMessageCreatorLocal' };
const environmentInfoProviderLocal: any = { name: 'environmentInfoProviderLocal' };
+ const toolDataLocal: any = { name: 'toolDataLocal' };
const issueFilingServiceProviderLocal: any = { name: 'issueFilingServiceProviderLocal' };
const userConfigMessageCreatorLocal: any = { name: 'userConfigMessageCreatorLocal' };
@@ -92,6 +98,7 @@ describe('MainWindowContextTest', () => {
issueFilingActionMessageCreator,
userConfigMessageCreatorLocal,
environmentInfoProviderLocal,
+ toolDataLocal,
issueFilingServiceProviderLocal,
);
@@ -110,6 +117,7 @@ describe('MainWindowContextTest', () => {
expect(mainWindowContextGiven.getEnvironmentInfoProvider()).toEqual(
environmentInfoProviderLocal,
);
+ expect(mainWindowContextGiven.getToolData()).toEqual(toolDataLocal);
expect(mainWindowContextGiven.getIssueFilingServiceProvider()).toEqual(
issueFilingServiceProviderLocal,
);
@@ -129,6 +137,7 @@ describe('MainWindowContextTest', () => {
expect(mainWindowContextNotGiven.getEnvironmentInfoProvider()).toEqual(
environmentInfoProvider,
);
+ expect(mainWindowContextNotGiven.getToolData()).toEqual(toolData);
expect(mainWindowContextNotGiven.getIssueFilingServiceProvider()).toEqual(
issueFilingServiceProvider,
);
diff --git a/src/tests/unit/tests/issue-filing/common/__snapshots__/issue-details-builder.test.ts.snap b/src/tests/unit/tests/issue-filing/common/__snapshots__/issue-details-builder.test.ts.snap
index 030911549dc..e437ec81807 100644
--- a/src/tests/unit/tests/issue-filing/common/__snapshots__/issue-details-builder.test.ts.snap
+++ b/src/tests/unit/tests/issue-filing/common/__snapshots__/issue-details-builder.test.ts.snap
@@ -6,8 +6,8 @@ h-Target application-h--s-h-s--pageTitle
h-Element path-h--s-h-s--RR-selector
h-Snippet-h--s-h-s--s-RR-snippet space-s
h-How to fix-h--s-h-s--h-t--RR-failureSummary--h-t
-h-Environment-h--s-h-s--test spec
---f-s--This accessibility issue was found using Accessibility Insights for Web 1.1.1 (axe-core 2.2.2), a tool that helps find and fix accessibility issues. Get more information & download this tool at l-http://aka.ms/AccessibilityInsights-l."
+h-Environment-h--s-h-s--environmentName
+--f-s--This accessibility issue was found using app-name app-version (engine-name engine-version), a tool that helps find and fix accessibility issues. Get more information & download this tool at l-http://aka.ms/AccessibilityInsights-l."
`;
exports[`Name of the group build issue details when targetApp.url is pageUrl 1`] = `
@@ -16,6 +16,6 @@ h-Target application-h--s-h-s--l-pageUrl-pageTitle-l
h-Element path-h--s-h-s--RR-selector
h-Snippet-h--s-h-s--s-RR-snippet space-s
h-How to fix-h--s-h-s--h-t--RR-failureSummary--h-t
-h-Environment-h--s-h-s--test spec
---f-s--This accessibility issue was found using Accessibility Insights for Web 1.1.1 (axe-core 2.2.2), a tool that helps find and fix accessibility issues. Get more information & download this tool at l-http://aka.ms/AccessibilityInsights-l."
+h-Environment-h--s-h-s--environmentName
+--f-s--This accessibility issue was found using app-name app-version (engine-name engine-version), a tool that helps find and fix accessibility issues. Get more information & download this tool at l-http://aka.ms/AccessibilityInsights-l."
`;
diff --git a/src/tests/unit/tests/issue-filing/common/create-file-issue-handler.test.ts b/src/tests/unit/tests/issue-filing/common/create-file-issue-handler.test.ts
index 7cdfe6d8e71..376416a49ab 100644
--- a/src/tests/unit/tests/issue-filing/common/create-file-issue-handler.test.ts
+++ b/src/tests/unit/tests/issue-filing/common/create-file-issue-handler.test.ts
@@ -1,8 +1,8 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
import { BrowserAdapter } from 'common/browser-adapters/browser-adapter';
-import { EnvironmentInfo } from 'common/environment-info-provider';
import { CreateIssueDetailsTextData } from 'common/types/create-issue-details-text-data';
+import { ToolData } from 'common/types/store-data/unified-data-interface';
import { IssueFilingServicePropertiesMap } from 'common/types/store-data/user-configuration-store';
import { createFileIssueHandler } from 'issue-filing/common/create-file-issue-handler';
import { IssueFilingUrlProvider } from 'issue-filing/types/issue-filing-service';
@@ -16,10 +16,16 @@ describe('createFileIssueHandler', () => {
name: 'pageTitle',
},
} as CreateIssueDetailsTextData;
- const environmentInfoStub: EnvironmentInfo = {
- axeCoreVersion: 'test axe version',
- browserSpec: 'test browser spec',
- extensionVersion: 'test extension version',
+ const toolData: ToolData = {
+ scanEngineProperties: {
+ name: 'engine-name',
+ version: 'engine-version',
+ },
+ applicationProperties: {
+ name: 'app-name',
+ version: 'app-version',
+ environmentName: 'environmentName',
+ },
};
const settingsStub = {
repo: 'test-repo',
@@ -39,7 +45,7 @@ describe('createFileIssueHandler', () => {
urlProviderMock = Mock.ofType>(undefined, MockBehavior.Strict);
urlProviderMock
- .setup(provider => provider(settingsStub, issueData, environmentInfoStub))
+ .setup(provider => provider(settingsStub, issueData, toolData))
.returns(() => urlStub);
browserAdapterMock = Mock.ofType(undefined, MockBehavior.Strict);
@@ -57,7 +63,7 @@ describe('createFileIssueHandler', () => {
);
await expect(
- testSubject(browserAdapterMock.object, serviceMap, issueData, environmentInfoStub),
+ testSubject(browserAdapterMock.object, serviceMap, issueData, toolData),
).resolves.toBe(undefined);
browserAdapterMock.verifyAll();
@@ -76,7 +82,7 @@ describe('createFileIssueHandler', () => {
);
await expect(
- testSubject(browserAdapterMock.object, serviceMap, issueData, environmentInfoStub),
+ testSubject(browserAdapterMock.object, serviceMap, issueData, toolData),
).rejects.toEqual(errorMessage);
});
});
diff --git a/src/tests/unit/tests/issue-filing/common/issue-details-builder.test.ts b/src/tests/unit/tests/issue-filing/common/issue-details-builder.test.ts
index 54cfdf4fbd2..4c4d6153adc 100644
--- a/src/tests/unit/tests/issue-filing/common/issue-details-builder.test.ts
+++ b/src/tests/unit/tests/issue-filing/common/issue-details-builder.test.ts
@@ -1,7 +1,7 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
+import { ToolData } from 'common/types/store-data/unified-data-interface';
import { IMock, It, Mock, MockBehavior } from 'typemoq';
-import { EnvironmentInfo } from '../../../../../common/environment-info-provider';
import { createIssueDetailsBuilder } from '../../../../../issue-filing/common/create-issue-details-builder';
import { MarkupFormatter } from '../../../../../issue-filing/common/markup/markup-formatter';
@@ -24,10 +24,17 @@ describe('Name of the group', () => {
howToFixSummary: 'RR-failureSummary',
snippet: 'RR-snippet space',
};
- const environmentInfo: EnvironmentInfo = {
- extensionVersion: '1.1.1',
- axeCoreVersion: '2.2.2',
- browserSpec: 'test spec',
+
+ const toolData: ToolData = {
+ scanEngineProperties: {
+ name: 'engine-name',
+ version: 'engine-version',
+ },
+ applicationProperties: {
+ name: 'app-name',
+ version: 'app-version',
+ environmentName: 'environmentName',
+ },
};
let markupMock: IMock;
@@ -57,7 +64,7 @@ describe('Name of the group', () => {
sampleIssueDetailsData.targetApp.url = targetAppUrl;
const testSubject = createIssueDetailsBuilder(markupMock.object);
- const result = testSubject(environmentInfo, sampleIssueDetailsData);
+ const result = testSubject(toolData, sampleIssueDetailsData);
expect(result).toMatchSnapshot();
});
diff --git a/src/tests/unit/tests/issue-filing/common/issue-filing-controller-impl.test.ts b/src/tests/unit/tests/issue-filing/common/issue-filing-controller-impl.test.ts
index 49dfc0be99d..b2e275e97e0 100644
--- a/src/tests/unit/tests/issue-filing/common/issue-filing-controller-impl.test.ts
+++ b/src/tests/unit/tests/issue-filing/common/issue-filing-controller-impl.test.ts
@@ -2,8 +2,8 @@
// Licensed under the MIT License.
import { BaseStore } from 'common/base-store';
import { BrowserAdapter } from 'common/browser-adapters/browser-adapter';
-import { EnvironmentInfo } from 'common/environment-info-provider';
import { CreateIssueDetailsTextData } from 'common/types/create-issue-details-text-data';
+import { ToolData } from 'common/types/store-data/unified-data-interface';
import {
IssueFilingServicePropertiesMap,
UserConfigurationStoreData,
@@ -19,10 +19,16 @@ describe('IssueFilingControllerImpl', () => {
const issueData = {
targetApp: {},
} as CreateIssueDetailsTextData;
- const environmentInfoStub: EnvironmentInfo = {
- axeCoreVersion: 'test axe version',
- browserSpec: 'test browser spec',
- extensionVersion: 'test extension version',
+ const toolData: ToolData = {
+ scanEngineProperties: {
+ name: 'engine-name',
+ version: 'engine-version',
+ },
+ applicationProperties: {
+ name: 'app-name',
+ version: 'app-version',
+ environmentName: 'environmentName',
+ },
};
const testUrl = 'test-url';
const map: IssueFilingServicePropertiesMap = {
@@ -36,7 +42,7 @@ describe('IssueFilingControllerImpl', () => {
const issueFilingServiceMock = Mock.ofType();
issueFilingServiceMock
.setup(service =>
- service.fileIssue(browserAdapterMock.object, map, issueData, environmentInfoStub),
+ service.fileIssue(browserAdapterMock.object, map, issueData, toolData),
)
.returns(() => Promise.resolve());
@@ -51,7 +57,7 @@ describe('IssueFilingControllerImpl', () => {
const testSubject = new IssueFilingControllerImpl(
providerMock.object,
browserAdapterMock.object,
- environmentInfoStub,
+ toolData,
storeMock.object,
);
diff --git a/src/tests/unit/tests/issue-filing/services/azure-boards/create-azure-boards-issue-filing-url.test.ts b/src/tests/unit/tests/issue-filing/services/azure-boards/create-azure-boards-issue-filing-url.test.ts
index ac22af7c43f..8e34599985c 100644
--- a/src/tests/unit/tests/issue-filing/services/azure-boards/create-azure-boards-issue-filing-url.test.ts
+++ b/src/tests/unit/tests/issue-filing/services/azure-boards/create-azure-boards-issue-filing-url.test.ts
@@ -2,8 +2,8 @@
// Licensed under the MIT License.
import { IMock, Mock } from 'typemoq';
+import { ToolData } from 'common/types/store-data/unified-data-interface';
import { title } from 'content/strings/application';
-import { EnvironmentInfo } from '../../../../../../common/environment-info-provider';
import { CreateIssueDetailsTextData } from '../../../../../../common/types/create-issue-details-text-data';
import { HTTPQueryBuilder } from '../../../../../../issue-filing/common/http-query-builder';
import { IssueDetailsBuilder } from '../../../../../../issue-filing/common/issue-details-builder';
@@ -16,7 +16,7 @@ describe('createAzureBoardsIssueFilingUrl', () => {
const testIssueDetails = 'html issue details';
let baseTags: string;
- let environmentInfo: EnvironmentInfo;
+ let toolData: ToolData;
let sampleIssueDetailsData: CreateIssueDetailsTextData;
let settingsData: AzureBoardsIssueFilingSettings;
let stringUtilsMock: IMock;
@@ -26,10 +26,16 @@ describe('createAzureBoardsIssueFilingUrl', () => {
let testSubject: IssueFilingUrlProvider;
beforeEach(() => {
- environmentInfo = {
- extensionVersion: '1.1.1',
- axeCoreVersion: '2.2.2',
- browserSpec: 'test spec',
+ toolData = {
+ scanEngineProperties: {
+ name: 'engine-name',
+ version: 'engine-version',
+ },
+ applicationProperties: {
+ name: 'app-name',
+ version: 'app-version',
+ environmentName: 'environmentName',
+ },
};
sampleIssueDetailsData = {
rule: {
@@ -64,7 +70,7 @@ describe('createAzureBoardsIssueFilingUrl', () => {
issueDetailsGetterMock = Mock.ofType();
issueDetailsGetterMock
- .setup(getter => getter(environmentInfo, sampleIssueDetailsData))
+ .setup(getter => getter(toolData, sampleIssueDetailsData))
.returns(() => testIssueDetails);
queryBuilderMock = Mock.ofType();
@@ -104,7 +110,7 @@ describe('createAzureBoardsIssueFilingUrl', () => {
.setup(builder => builder.withParam('[System.Description]', testIssueDetails))
.returns(() => queryBuilderMock.object);
- const result = testSubject(settingsData, sampleIssueDetailsData, environmentInfo);
+ const result = testSubject(settingsData, sampleIssueDetailsData, toolData);
expect(result).toMatchSnapshot();
});
@@ -128,7 +134,7 @@ describe('createAzureBoardsIssueFilingUrl', () => {
.setup(builder => builder.withParam('[System.Description]', testIssueDetails))
.returns(() => queryBuilderMock.object);
- const result = testSubject(settingsData, sampleIssueDetailsData, environmentInfo);
+ const result = testSubject(settingsData, sampleIssueDetailsData, toolData);
expect(result).toMatchSnapshot();
});
@@ -154,7 +160,7 @@ describe('createAzureBoardsIssueFilingUrl', () => {
)
.returns(() => queryBuilderMock.object);
- const result = testSubject(settingsData, sampleIssueDetailsData, environmentInfo);
+ const result = testSubject(settingsData, sampleIssueDetailsData, toolData);
expect(result).toMatchSnapshot();
});
@@ -181,7 +187,7 @@ describe('createAzureBoardsIssueFilingUrl', () => {
)
.returns(() => queryBuilderMock.object);
- const result = testSubject(settingsData, sampleIssueDetailsData, environmentInfo);
+ const result = testSubject(settingsData, sampleIssueDetailsData, toolData);
expect(result).toMatchSnapshot();
});
diff --git a/src/tests/unit/tests/issue-filing/services/github/create-github-issue-filing-url.test.ts b/src/tests/unit/tests/issue-filing/services/github/create-github-issue-filing-url.test.ts
index dfd9ce6cbfc..f4adeffdf20 100644
--- a/src/tests/unit/tests/issue-filing/services/github/create-github-issue-filing-url.test.ts
+++ b/src/tests/unit/tests/issue-filing/services/github/create-github-issue-filing-url.test.ts
@@ -2,7 +2,7 @@
// Licensed under the MIT License.
import { IMock, Mock } from 'typemoq';
-import { EnvironmentInfo } from '../../../../../../common/environment-info-provider';
+import { ToolData } from 'common/types/store-data/unified-data-interface';
import { HTTPQueryBuilder } from '../../../../../../issue-filing/common/http-query-builder';
import { IssueDetailsBuilder } from '../../../../../../issue-filing/common/issue-details-builder';
import { IssueUrlCreationUtils } from '../../../../../../issue-filing/common/issue-filing-url-string-utils';
@@ -13,7 +13,7 @@ import { IssueFilingUrlProvider } from '../../../../../../issue-filing/types/iss
const buildedUrl = 'https://builded-url';
describe('createGitHubIssueFilingUrlTest', () => {
- let environmentInfo: EnvironmentInfo;
+ let toolData: ToolData;
let sampleIssueDetailsData;
let settingsData: GitHubIssueFilingSettings;
let stringUtilsMock: IMock;
@@ -23,10 +23,16 @@ describe('createGitHubIssueFilingUrlTest', () => {
let rectifyMock: IMock;
beforeEach(() => {
- environmentInfo = {
- extensionVersion: '1.1.1',
- axeCoreVersion: '2.2.2',
- browserSpec: 'test spec',
+ toolData = {
+ scanEngineProperties: {
+ name: 'engine-name',
+ version: 'engine-version',
+ },
+ applicationProperties: {
+ name: 'app-name',
+ version: 'app-version',
+ environmentName: 'environmentName',
+ },
};
sampleIssueDetailsData = {
pageTitle: 'pageTitle',
@@ -56,7 +62,7 @@ describe('createGitHubIssueFilingUrlTest', () => {
issueDetailsGetter = Mock.ofType();
const testIssueDetails = 'test issue details';
issueDetailsGetter
- .setup(getter => getter(environmentInfo, sampleIssueDetailsData))
+ .setup(getter => getter(toolData, sampleIssueDetailsData))
.returns(() => testIssueDetails);
const rectifiedUrl = 'rectified-url';
@@ -89,7 +95,7 @@ describe('createGitHubIssueFilingUrlTest', () => {
});
it('creates url', () => {
- const result = testObject(settingsData, sampleIssueDetailsData, environmentInfo);
+ const result = testObject(settingsData, sampleIssueDetailsData, toolData);
expect(result).toEqual(buildedUrl);
});