diff --git a/src/assessments/assessment-default-message-generator.tsx b/src/assessments/assessment-default-message-generator.tsx index 0b89c88358d..ad90f978474 100644 --- a/src/assessments/assessment-default-message-generator.tsx +++ b/src/assessments/assessment-default-message-generator.tsx @@ -17,10 +17,10 @@ export type IMessageGenerator = ( export type IGetMessageGenerator = ( generator: AssessmentDefaultMessageGenerator, ) => IMessageGenerator; -export interface DefaultMessageInterface { +export type DefaultMessageInterface = { message: JSX.Element; instanceCount: number; -} +} | null; function failingInstances(result: TestStepResult): boolean { return result.status !== ManualTestStatus.PASS; diff --git a/src/common/components/flagged-component.tsx b/src/common/components/flagged-component.tsx index 08110cc8c3e..031b5adcdbe 100644 --- a/src/common/components/flagged-component.tsx +++ b/src/common/components/flagged-component.tsx @@ -12,7 +12,7 @@ export interface FlaggedComponentProps { } export class FlaggedComponent extends React.Component { - public render(): JSX.Element { + public render(): JSX.Element | null { const flagName = this.props.featureFlag; if (this.props.featureFlagStoreData != null && this.props.featureFlagStoreData[flagName]) { diff --git a/src/common/components/with-store-subscription.tsx b/src/common/components/with-store-subscription.tsx index e508ff19fc8..033affaa4fe 100644 --- a/src/common/components/with-store-subscription.tsx +++ b/src/common/components/with-store-subscription.tsx @@ -26,7 +26,7 @@ export function withStoreSubscription

, S constructor(props: P) { super(props); if (this.hasStores()) { - this.state = this.props.deps.storesHub.getAllStoreData(); + this.state = this.props.deps.storesHub.getAllStoreData()!; } else { this.state = {} as S; } diff --git a/src/common/store-proxy.ts b/src/common/store-proxy.ts index 333ddc43856..50ca09faa6f 100644 --- a/src/common/store-proxy.ts +++ b/src/common/store-proxy.ts @@ -12,10 +12,10 @@ import { StoreUpdateMessage } from './types/store-update-message'; export class StoreProxy extends Store implements BaseStore { private state: TState; private storeId: string; - private tabId: number; + private tabId?: number; private browserAdapter: BrowserAdapter; - constructor(storeId: string, browserAdapter: BrowserAdapter, tabId: number = null) { + constructor(storeId: string, browserAdapter: BrowserAdapter, tabId?: number) { super(); this.storeId = storeId; this.browserAdapter = browserAdapter; diff --git a/src/common/stores/base-client-stores-hub.ts b/src/common/stores/base-client-stores-hub.ts index 641d5a6332b..5ab850718f8 100644 --- a/src/common/stores/base-client-stores-hub.ts +++ b/src/common/stores/base-client-stores-hub.ts @@ -46,7 +46,7 @@ export class BaseClientStoresHub implements ClientStoresHub { }); } - public getAllStoreData(): T { + public getAllStoreData(): T | null { if (!this.hasStores()) { return null; } diff --git a/src/common/stores/client-stores-hub.ts b/src/common/stores/client-stores-hub.ts index 0e2e5fc3226..fdc9ab4a692 100644 --- a/src/common/stores/client-stores-hub.ts +++ b/src/common/stores/client-stores-hub.ts @@ -8,5 +8,5 @@ export interface ClientStoresHub { removeChangedListenerFromAllStores(listener: () => void): void; hasStores(): boolean; hasStoreData(): boolean; - getAllStoreData(): T; + getAllStoreData(): T | null; } diff --git a/src/tests/end-to-end/common/browser.ts b/src/tests/end-to-end/common/browser.ts index cc6731db47b..486621ce004 100644 --- a/src/tests/end-to-end/common/browser.ts +++ b/src/tests/end-to-end/common/browser.ts @@ -136,7 +136,7 @@ export class Browser { resolve(tabs[0].id), ); }); - }); + }, null); } private async waitForBackgroundPageMatching( diff --git a/src/tests/end-to-end/common/page-controllers/page.ts b/src/tests/end-to-end/common/page-controllers/page.ts index 128388498b5..b93c0444bdf 100644 --- a/src/tests/end-to-end/common/page-controllers/page.ts +++ b/src/tests/end-to-end/common/page-controllers/page.ts @@ -50,11 +50,12 @@ export class Page { forceEventFailure(`'pageerror' (console.error): ${serializeError(error)}`); }); underlyingPage.on('requestfailed', request => { + const failure = request.failure()!; const url = request.url(); // Checking for 'fonts' and 'icons' in url as a workaround for #923 if (!includes(url, 'fonts') && !includes(url, 'icons')) { forceEventFailure( - `'requestfailed' from '${url}' with errorText: ${request.failure().errorText}`, + `'requestfailed' from '${url}' with errorText: ${failure.errorText}`, ); } }); @@ -100,7 +101,7 @@ export class Page { await this.screenshotOnError(async () => await this.underlyingPage.close()); } - public async evaluate(fn: PageFunction, arg?: Arg): Promise { + public async evaluate(fn: PageFunction, arg: Arg): Promise { const timeout = DEFAULT_PAGE_ELEMENT_WAIT_TIMEOUT_MS; // We don't wrap this in screenshotOnError because Playwright serializes evaluate() and // screenshot() such that screenshot() will always time out if evaluate is still running. @@ -111,7 +112,7 @@ export class Page { public async waitForSelector( selector: string, options?: WaitForSelectorOptions, - ): Promise> { + ): Promise | null> { return await this.screenshotOnError( async () => await this.underlyingPage.waitForSelector(selector, { @@ -134,7 +135,9 @@ export class Page { }); } - public async getSelectorElement(selector: string): Promise> { + public async getSelectorElement( + selector: string, + ): Promise | null> { return await this.screenshotOnError(async () => { return await this.underlyingPage.$(selector); }); @@ -167,12 +170,17 @@ export class Page { selector: string, options?: WaitForSelectorOptions, ): Promise { + if (options?.state === 'hidden' || options?.state === 'detached') { + throw new Error("Cannot get properties about selectors that shouldn't be there"); + } return await this.screenshotOnError(async () => { const element = await this.underlyingPage.waitForSelector(selector, { timeout: DEFAULT_PAGE_ELEMENT_WAIT_TIMEOUT_MS, ...options, }); - return await this.underlyingPage.evaluate(el => el.outerHTML, element); + // element! is safe because we verified that options.state is not one of the options + // that can result in waitForSelector returning null + return await this.underlyingPage.evaluate(el => el.outerHTML, element!); }); } diff --git a/src/tests/end-to-end/common/scan-for-accessibility-issues.ts b/src/tests/end-to-end/common/scan-for-accessibility-issues.ts index e6dc7c5f76d..b807dcfc3be 100644 --- a/src/tests/end-to-end/common/scan-for-accessibility-issues.ts +++ b/src/tests/end-to-end/common/scan-for-accessibility-issues.ts @@ -30,7 +30,7 @@ export async function scanForAccessibilityIssues( async function injectAxeIfUndefined(page: Page): Promise { const axeIsUndefined = await page.evaluate(() => { return (window as any).axe === undefined; - }); + }, null); if (axeIsUndefined) { await page.injectScriptFile( diff --git a/tsconfig.strictNullChecks.json b/tsconfig.strictNullChecks.json index b8ceaf21dcc..ad6eebf70ef 100644 --- a/tsconfig.strictNullChecks.json +++ b/tsconfig.strictNullChecks.json @@ -29,10 +29,9 @@ "./src/DetailsView/components/switcher-style-names.ts", "./src/DetailsView/components/target-page-hidden-bar.tsx", "./src/DetailsView/components/test-status-choice-group.tsx", - "./src/Devtools/inspect-handler.ts", - "./src/Devtools/target-page-inspector.ts", "./src/ad-hoc-visualizations/issues/get-notification-message.ts", "./src/assessments/adaptable-content/test-steps/test-step.ts", + "./src/assessments/assessment-default-message-generator.tsx", "./src/assessments/audio-video-only/test-steps/test-steps.ts", "./src/assessments/auto-pass-if-no-results.ts", "./src/assessments/color/test-steps/test-steps.tsx", @@ -112,6 +111,7 @@ "./src/common/components/expand-collapse-left-nav-hamburger-button.tsx", "./src/common/components/external-link.tsx", "./src/common/components/fix-instruction-processor.tsx", + "./src/common/components/flagged-component.tsx", "./src/common/components/header-icon.tsx", "./src/common/components/header.tsx", "./src/common/components/issue-filing-needs-settings-help-text.tsx", @@ -150,8 +150,7 @@ "./src/common/navigator-utils.ts", "./src/common/platform.ts", "./src/common/state-dispatcher.ts", - "./src/common/stores/client-stores-hub.ts", - "./src/common/stores/store-names.ts", + "./src/common/store-proxy.ts", "./src/common/tabbable-elements-helper.ts", "./src/common/types/deep-partial.ts", "./src/common/types/details-view-pivot-type.ts", @@ -329,6 +328,9 @@ "./src/tests/end-to-end/common/element-identifiers/target-page-selectors.ts", "./src/tests/end-to-end/common/force-test-failure.ts", "./src/tests/end-to-end/common/manifest-overide.ts", + "./src/tests/end-to-end/common/page-controllers/content-page.ts", + "./src/tests/end-to-end/common/page-controllers/page.ts", + "./src/tests/end-to-end/common/page-controllers/popup-page.ts", "./src/tests/end-to-end/common/playwright-option-types.ts", "./src/tests/end-to-end/common/prepare-test-result-file-path.ts", "./src/tests/end-to-end/common/pretty-print-axe-violations.ts", @@ -361,6 +363,7 @@ "./src/views/content/guidance-title.tsx" ], "include": [ + "src/Devtools/**/*", "src/assessments/language/common/**/*", "src/background/injector/**/*", "src/common/action/**/*", @@ -373,6 +376,7 @@ "src/common/message-creators/types/**/*", "src/common/promises/**/*", "src/common/react/**/*", + "src/common/stores/**/*", "src/common/styles/**/*", "src/common/types/property-bag/**/*", "src/content/settings/**/*",