diff --git a/.eslintrc.js b/.eslintrc.js
index 5ecf3f5e98..1b2476bf3d 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -14,6 +14,9 @@ module.exports = {
settings: {
react: { version: "18" }
},
+ ignorePatterns: [
+ '/packages/playwright/bundles/expect/third_party/**/*'
+ ],
overrides: [
{
files: ['./examples/**/*'],
@@ -34,7 +37,7 @@ module.exports = {
rules: {
"@typescript-eslint/no-unused-vars": [2, {args: "none"}],
"@typescript-eslint/consistent-type-imports": [2, {disallowTypeAnnotations: false}],
- // "@typescript-eslint/no-unnecessary-condition": [2],
+ "@typescript-eslint/no-unnecessary-condition": [2],
/**
* Enforced rules
diff --git a/packages/html-reporter/src/reportView.tsx b/packages/html-reporter/src/reportView.tsx
index db95dd412c..1b37aea0ca 100644
--- a/packages/html-reporter/src/reportView.tsx
+++ b/packages/html-reporter/src/reportView.tsx
@@ -78,7 +78,7 @@ export const ReportView: React.FC<{
return
{report?.json() && }
- {report?.json().metadata && }
+ {report?.json().metadata && }
{
- return test?.annotations?.filter(annotation => !annotation.type.startsWith('_')) || [];
+ return test?.annotations.filter(annotation => !annotation.type.startsWith('_')) || [];
}, [test?.annotations]);
return
@@ -58,10 +58,10 @@ export const TestCaseView: React.FC<{
next »
}
- {test && {test?.title}
}
+ {test && {test.title}
}
{test &&
-
+
{test.location.file}:{test.location.line}
@@ -69,7 +69,7 @@ export const TestCaseView: React.FC<{
{msToString(test.duration)}
}
{test && (!!test.projectName || labels) &&
- {test && !!test.projectName &&
}
+ {!!test.projectName &&
}
{labels &&
}
}
{!!visibleAnnotations.length &&
@@ -80,7 +80,7 @@ export const TestCaseView: React.FC<{
id: String(index),
title: {statusIcon(result.status)} {retryLabel(index)}
,
render: () =>
- })) || []} selectedTab={String(selectedResultIndex)} setSelectedTab={id => setSelectedResultIndex(+id)} />}
+ }))} selectedTab={String(selectedResultIndex)} setSelectedTab={id => setSelectedResultIndex(+id)} />}
;
};
diff --git a/packages/html-reporter/src/testFileView.tsx b/packages/html-reporter/src/testFileView.tsx
index 2113c008ff..b6689c14c7 100644
--- a/packages/html-reporter/src/testFileView.tsx
+++ b/packages/html-reporter/src/testFileView.tsx
@@ -86,9 +86,9 @@ function videoBadge(test: TestCaseSummary): JSX.Element | undefined {
return resultWithVideo ? {video()} : undefined;
}
-function traceBadge(test: TestCaseSummary): JSX.Element | undefined {
+function traceBadge(test: TestCaseSummary): JSX.Element {
const firstTraces = test.results.map(result => result.attachments.filter(attachment => attachment.name === 'trace')).filter(traces => traces.length > 0)[0];
- return firstTraces ? {trace()} : undefined;
+ return {trace()};
}
const LabelsClickView: React.FCProject: {report.projectNames[0]}}
{filteredStats && Filtered: {filteredStats.total} {!!filteredStats.total && ('(' + msToString(filteredStats.duration) + ')')}
}
- {report ? new Date(report.startTime).toLocaleString() : ''}
- Total time: {msToString(report.duration ?? 0)}
+ {new Date(report.startTime).toLocaleString()}
+ Total time: {msToString(report.duration)}
{!!report.errors.length &&
{report.errors.map((error, index) => )}
diff --git a/packages/html-reporter/src/testResultView.tsx b/packages/html-reporter/src/testResultView.tsx
index bdaec18d24..8b95c02bdf 100644
--- a/packages/html-reporter/src/testResultView.tsx
+++ b/packages/html-reporter/src/testResultView.tsx
@@ -77,7 +77,7 @@ export const TestResultView: React.FC<{
result: TestResult,
}> = ({ test, result }) => {
const { screenshots, videos, traces, otherAttachments, diffs, errors, otherAttachmentAnchors, screenshotAnchors } = React.useMemo(() => {
- const attachments = result?.attachments || [];
+ const attachments = result.attachments;
const screenshots = new Set(attachments.filter(a => a.contentType.startsWith('image/')));
const screenshotAnchors = [...screenshots].map(a => `attachment-${a.name}`);
const videos = attachments.filter(a => a.contentType.startsWith('video/'));
diff --git a/packages/playwright-core/src/browserServerImpl.ts b/packages/playwright-core/src/browserServerImpl.ts
index 73455aa5c0..80053db7a0 100644
--- a/packages/playwright-core/src/browserServerImpl.ts
+++ b/packages/playwright-core/src/browserServerImpl.ts
@@ -38,6 +38,7 @@ export class BrowserServerLauncherImpl implements BrowserServerLauncher {
async launchServer(options: LaunchServerOptions = {}): Promise {
const playwright = createPlaywright({ sdkLanguage: 'javascript', isServer: true });
// TODO: enable socks proxy once ipv6 is supported.
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
const socksProxy = false ? new SocksProxy() : undefined;
playwright.options.socksProxyPort = await socksProxy?.listen(0);
diff --git a/packages/playwright-core/src/client/browserContext.ts b/packages/playwright-core/src/client/browserContext.ts
index 28afee001e..e30461464e 100644
--- a/packages/playwright-core/src/client/browserContext.ts
+++ b/packages/playwright-core/src/client/browserContext.ts
@@ -116,9 +116,7 @@ export class BrowserContext extends ChannelOwner
const pageObject = Page.from(page);
const parsedError = parseError(error);
this.emit(Events.BrowserContext.WebError, new WebError(pageObject, parsedError));
- if (pageObject) {
- pageObject.emit(Events.Page.PageError, parsedError);
- }
+ pageObject.emit(Events.Page.PageError, parsedError);
});
this._channel.on('dialog', ({ dialog }) => {
const dialogObject = Dialog.from(dialog);
diff --git a/packages/playwright-core/src/client/browserType.ts b/packages/playwright-core/src/client/browserType.ts
index d4eb59ff5a..a7ef63f855 100644
--- a/packages/playwright-core/src/client/browserType.ts
+++ b/packages/playwright-core/src/client/browserType.ts
@@ -150,7 +150,7 @@ export class BrowserType extends ChannelOwner imple
let closeError: string | undefined;
const onPipeClosed = (reason?: string) => {
// Emulate all pages, contexts and the browser closing upon disconnect.
- for (const context of browser.contexts() || []) {
+ for (const context of browser.contexts()) {
for (const page of context.pages()) {
page._onClose();
}
diff --git a/packages/playwright-core/src/client/connection.ts b/packages/playwright-core/src/client/connection.ts
index dba0cdd303..51394e6066 100644
--- a/packages/playwright-core/src/client/connection.ts
+++ b/packages/playwright-core/src/client/connection.ts
@@ -137,7 +137,7 @@ export class Connection extends EventEmitter {
}
const location = frames[0] ? { file: frames[0].file, line: frames[0].line, column: frames[0].column } : undefined;
const metadata: channels.Metadata = { apiName, location, internal: !apiName, stepId };
- if (this._tracingCount && frames && type !== 'LocalUtils') {
+ if (this._tracingCount && type !== 'LocalUtils') {
this._localUtils?._channel.addStackToTracingNoReply({ callData: { stack: frames, id } }).catch(() => {});
}
// We need to exit zones before calling into the server, otherwise
@@ -217,7 +217,7 @@ export class Connection extends EventEmitter {
private _tChannelImplFromWire(names: '*' | string[], arg: any, path: string, context: ValidatorContext) {
if (arg && typeof arg === 'object' && typeof arg.guid === 'string') {
- const object = this._objects.get(arg.guid)!;
+ const object = this._objects.get(arg.guid);
if (!object) {
throw new Error(`Object with guid ${arg.guid} was not bound in the connection`);
}
diff --git a/packages/playwright-core/src/client/consoleMessage.ts b/packages/playwright-core/src/client/consoleMessage.ts
index fcdc3fd149..f880ff47a4 100644
--- a/packages/playwright-core/src/client/consoleMessage.ts
+++ b/packages/playwright-core/src/client/consoleMessage.ts
@@ -28,7 +28,7 @@ export class ConsoleMessage implements api.ConsoleMessage {
private _event: channels.BrowserContextConsoleEvent | channels.ElectronApplicationConsoleEvent;
constructor(event: channels.BrowserContextConsoleEvent | channels.ElectronApplicationConsoleEvent) {
- this._page = ('page' in event && event.page) ? Page.from(event.page) : null;
+ this._page = 'page' in event ? Page.from(event.page) : null;
this._event = event;
}
diff --git a/packages/playwright-core/src/client/elementHandle.ts b/packages/playwright-core/src/client/elementHandle.ts
index c731781ffb..30387fb7c1 100644
--- a/packages/playwright-core/src/client/elementHandle.ts
+++ b/packages/playwright-core/src/client/elementHandle.ts
@@ -248,6 +248,7 @@ export function convertSelectOptionValues(values: string | api.ElementHandle | S
return {};
}
for (let i = 0; i < values.length; i++) {
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
assert(values[i] !== null, `options[${i}]: expected object, got null`);
}
if (values[0] instanceof ElementHandle) {
@@ -262,6 +263,7 @@ export function convertSelectOptionValues(values: string | api.ElementHandle | S
type SetInputFilesFiles = Pick;
function filePayloadExceedsSizeLimit(payloads: FilePayload[]) {
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
return payloads.reduce((size, item) => size + (item.buffer ? item.buffer.byteLength : 0), 0) >= fileUploadSizeLimit;
}
diff --git a/packages/playwright-core/src/client/eventEmitter.ts b/packages/playwright-core/src/client/eventEmitter.ts
index 01d620225d..1bf502a15b 100644
--- a/packages/playwright-core/src/client/eventEmitter.ts
+++ b/packages/playwright-core/src/client/eventEmitter.ts
@@ -66,6 +66,7 @@ export class EventEmitter implements EventEmitterType {
}
const handler = events[type];
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
if (handler === undefined) {
return false;
}
@@ -120,6 +121,7 @@ export class EventEmitter implements EventEmitterType {
} else {
// To avoid recursion in the case that type === "newListener"! Before
// adding it to the listeners, first emit "newListener".
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
if (events.newListener !== undefined) {
this.emit('newListener', type, unwrapListener(listener));
@@ -194,6 +196,7 @@ export class EventEmitter implements EventEmitterType {
}
const list = events[type];
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
if (list === undefined) {
return this;
}
@@ -203,6 +206,7 @@ export class EventEmitter implements EventEmitterType {
this._events = Object.create(null);
} else {
delete events[type];
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
if (events.removeListener) {
this.emit('removeListener', type, (list as any).listener ?? listener);
}
@@ -233,6 +237,7 @@ export class EventEmitter implements EventEmitterType {
events[type] = list[0];
}
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
if (events.removeListener !== undefined) {
this.emit('removeListener', type, originalListener || listener);
}
@@ -280,10 +285,12 @@ export class EventEmitter implements EventEmitterType {
}
// not listening for removeListener, no need to emit
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
if (!events.removeListener) {
if (type === undefined) {
this._events = Object.create(null);
this._eventsCount = 0;
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
} else if (events[type] !== undefined) {
if (--this._eventsCount === 0) {
this._events = Object.create(null);
@@ -315,6 +322,7 @@ export class EventEmitter implements EventEmitterType {
if (typeof listeners === 'function') {
this.removeListener(type, listeners);
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
} else if (listeners !== undefined) {
// LIFO order
for (let i = listeners.length - 1; i >= 0; i--) {
@@ -338,6 +346,7 @@ export class EventEmitter implements EventEmitterType {
if (typeof listener === 'function') {
return 1;
}
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
if (listener !== undefined) {
return listener.length;
}
@@ -370,6 +379,7 @@ export class EventEmitter implements EventEmitterType {
}
const listener = events[type];
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
if (listener === undefined) {
return [];
}
@@ -421,6 +431,6 @@ function unwrapListeners(arr: Listener[]): Listener[] {
return arr.map(l => wrappedListener(l) ?? l);
}
-function wrappedListener(l: Listener): Listener {
+function wrappedListener(l: Listener): Listener | undefined {
return (l as any).listener;
}
diff --git a/packages/playwright-core/src/client/fetch.ts b/packages/playwright-core/src/client/fetch.ts
index d508b6fd3a..2e60fd9933 100644
--- a/packages/playwright-core/src/client/fetch.ts
+++ b/packages/playwright-core/src/client/fetch.ts
@@ -206,6 +206,7 @@ export class APIRequestContext extends ChannelOwner implements api.Fr
async waitForFunction(pageFunction: structs.PageFunction, arg?: Arg, options: WaitForFunctionOptions = {}): Promise> {
if (typeof options.polling === 'string') {
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
assert(options.polling === 'raf', 'Unknown polling option: ' + options.polling);
}
const result = await this._channel.waitForFunction({
diff --git a/packages/playwright-core/src/client/network.ts b/packages/playwright-core/src/client/network.ts
index 56e5e879bb..958ed06d9f 100644
--- a/packages/playwright-core/src/client/network.ts
+++ b/packages/playwright-core/src/client/network.ts
@@ -945,6 +945,7 @@ export class RawHeaders {
static _fromHeadersObjectLossy(headers: Headers): RawHeaders {
const headersArray: HeadersArray = Object.entries(headers).map(([name, value]) => ({
name, value
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
})).filter(header => header.value !== undefined);
return new RawHeaders(headersArray);
}
@@ -958,7 +959,7 @@ export class RawHeaders {
get(name: string): string | null {
const values = this.getAll(name);
- if (!values || !values.length) {
+ if (!values.length) {
return null;
}
return values.join(name.toLowerCase() === 'set-cookie' ? '\n' : ', ');
diff --git a/packages/playwright-core/src/client/playwright.ts b/packages/playwright-core/src/client/playwright.ts
index 7221a04115..2590a5beb1 100644
--- a/packages/playwright-core/src/client/playwright.ts
+++ b/packages/playwright-core/src/client/playwright.ts
@@ -51,7 +51,7 @@ export class Playwright extends ChannelOwner {
this._bidiChromium._playwright = this;
this._bidiFirefox = BrowserType.from(initializer.bidiFirefox);
this._bidiFirefox._playwright = this;
- this.devices = this._connection.localUtils().devices ?? {};
+ this.devices = this._connection.localUtils().devices;
this.selectors = new Selectors();
this.errors = { TimeoutError };
diff --git a/packages/playwright-core/src/common/socksProxy.ts b/packages/playwright-core/src/common/socksProxy.ts
index 615d47eb11..7c3c0286af 100644
--- a/packages/playwright-core/src/common/socksProxy.ts
+++ b/packages/playwright-core/src/common/socksProxy.ts
@@ -200,7 +200,7 @@ class SocksConnection {
private async _readBytes(length: number): Promise {
this._fence = this._offset + length;
- if (!this._buffer || this._buffer.length < this._fence) {
+ if (this._buffer.length < this._fence) {
await new Promise(f => this._fenceCallback = f);
}
this._offset += length;
diff --git a/packages/playwright-core/src/common/types.ts b/packages/playwright-core/src/common/types.ts
index 55145b5565..da62f3298c 100644
--- a/packages/playwright-core/src/common/types.ts
+++ b/packages/playwright-core/src/common/types.ts
@@ -20,4 +20,10 @@ export type Rect = Size & Point;
export type Quad = [ Point, Point, Point, Point ];
export type TimeoutOptions = { timeout?: number };
export type NameValue = { name: string, value: string };
-export type HeadersArray = NameValue[];
\ No newline at end of file
+export type HeadersArray = NameValue[];
+
+export const assertUnreachable = (x: never): never => assertUnreachableWithError(x, new Error('Unreachable variant'));
+
+export const assertUnreachableWithError = (x: never, error: Error): never => {
+ throw error;
+};
\ No newline at end of file
diff --git a/packages/playwright-core/src/protocol/serializers.ts b/packages/playwright-core/src/protocol/serializers.ts
index 6794d20797..78f47dfdf3 100644
--- a/packages/playwright-core/src/protocol/serializers.ts
+++ b/packages/playwright-core/src/protocol/serializers.ts
@@ -15,6 +15,7 @@
*/
import type { SerializedValue } from '@protocol/channels';
+import { assertUnreachable } from '../common/types';
export function parseSerializedValue(value: SerializedValue, handles: any[] | undefined): any {
return innerParseSerializedValue(value, handles, new Map());
@@ -34,23 +35,28 @@ function innerParseSerializedValue(value: SerializedValue, handles: any[] | unde
return value.b;
}
if (value.v !== undefined) {
- if (value.v === 'undefined') {
- return undefined;
- }
- if (value.v === 'null') {
- return null;
- }
- if (value.v === 'NaN') {
- return NaN;
- }
- if (value.v === 'Infinity') {
- return Infinity;
- }
- if (value.v === '-Infinity') {
- return -Infinity;
- }
- if (value.v === '-0') {
- return -0;
+ switch (value.v) {
+ case 'undefined': {
+ return undefined;
+ }
+ case 'null': {
+ return null;
+ }
+ case 'NaN': {
+ return NaN;
+ }
+ case 'Infinity': {
+ return Infinity;
+ }
+ case '-Infinity': {
+ return -Infinity;
+ }
+ case '-0': {
+ return -0;
+ }
+ default: {
+ return assertUnreachable(value.v);
+ }
}
}
if (value.d !== undefined) {
diff --git a/packages/playwright-core/src/protocol/transport.ts b/packages/playwright-core/src/protocol/transport.ts
index ad8fdd29d0..e5c0913b30 100644
--- a/packages/playwright-core/src/protocol/transport.ts
+++ b/packages/playwright-core/src/protocol/transport.ts
@@ -79,6 +79,7 @@ export class PipeTransport {
_dispatch(buffer: Buffer) {
this._data = Buffer.concat([this._data, buffer]);
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
while (true) {
if (!this._bytesLeft && this._data.length < 4) {
// Need more data.
diff --git a/packages/playwright-core/src/protocol/validatorPrimitives.ts b/packages/playwright-core/src/protocol/validatorPrimitives.ts
index 6c66e153d4..32fcb58046 100644
--- a/packages/playwright-core/src/protocol/validatorPrimitives.ts
+++ b/packages/playwright-core/src/protocol/validatorPrimitives.ts
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+import { assertUnreachableWithError } from '../common/types';
import { isUnderTest } from '../utils';
export class ValidationError extends Error {}
@@ -67,28 +68,32 @@ export const tString: Validator = (arg: any, path: string, context: ValidatorCon
throw new ValidationError(`${path}: expected string, got ${typeof arg}`);
};
export const tBinary: Validator = (arg: any, path: string, context: ValidatorContext) => {
- if (context.binary === 'fromBase64') {
- if (arg instanceof String) {
- return Buffer.from(arg.valueOf(), 'base64');
+ switch (context.binary) {
+ case 'fromBase64': {
+ if (arg instanceof String) {
+ return Buffer.from(arg.valueOf(), 'base64');
+ }
+ if (typeof arg === 'string') {
+ return Buffer.from(arg, 'base64');
+ }
+ throw new ValidationError(`${path}: expected base64-encoded buffer, got ${typeof arg}`);
}
- if (typeof arg === 'string') {
- return Buffer.from(arg, 'base64');
+ case 'toBase64': {
+ if (!(arg instanceof Buffer)) {
+ throw new ValidationError(`${path}: expected Buffer, got ${typeof arg}`);
+ }
+ return (arg as Buffer).toString('base64');
+ }
+ case 'buffer': {
+ if (!(arg instanceof Buffer)) {
+ throw new ValidationError(`${path}: expected Buffer, got ${typeof arg}`);
+ }
+ return arg;
+ }
+ default: {
+ return assertUnreachableWithError(context.binary, new ValidationError(`Unsupported binary behavior "${context.binary}"`));
}
- throw new ValidationError(`${path}: expected base64-encoded buffer, got ${typeof arg}`);
}
- if (context.binary === 'toBase64') {
- if (!(arg instanceof Buffer)) {
- throw new ValidationError(`${path}: expected Buffer, got ${typeof arg}`);
- }
- return (arg as Buffer).toString('base64');
- }
- if (context.binary === 'buffer') {
- if (!(arg instanceof Buffer)) {
- throw new ValidationError(`${path}: expected Buffer, got ${typeof arg}`);
- }
- return arg;
- }
- throw new ValidationError(`Unsupported binary behavior "${context.binary}"`);
};
export const tUndefined: Validator = (arg: any, path: string, context: ValidatorContext) => {
if (Object.is(arg, undefined)) {
@@ -156,6 +161,7 @@ export const tChannel = (names: '*' | string[]): Validator => {
export const tType = (name: string): Validator => {
return (arg: any, path: string, context: ValidatorContext) => {
const v = scheme[name];
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
if (!v) {
throw new ValidationError(path + ': unknown type "' + name + '"');
}
diff --git a/packages/playwright-core/src/remote/playwrightConnection.ts b/packages/playwright-core/src/remote/playwrightConnection.ts
index 3b10592d9d..0a6f8c1cc4 100644
--- a/packages/playwright-core/src/remote/playwrightConnection.ts
+++ b/packages/playwright-core/src/remote/playwrightConnection.ts
@@ -28,6 +28,7 @@ import { DebugControllerDispatcher } from '../server/dispatchers/debugController
import { startProfiling, stopProfiling } from '../utils';
import { monotonicTime } from '../utils';
import { debugLogger } from '../utils/debugLogger';
+import { assertUnreachableWithError } from '../common/types';
export type ClientType = 'controller' | 'launch-browser' | 'reuse-browser' | 'pre-launched-browser-or-android';
@@ -108,16 +109,20 @@ export class PlaywrightConnection {
this._root = new RootDispatcher(this._dispatcherConnection, async (scope, options) => {
await startProfiling();
- if (clientType === 'reuse-browser') {
- return await this._initReuseBrowsersMode(scope);
+ switch (clientType) {
+ case 'reuse-browser': {
+ return await this._initReuseBrowsersMode(scope);
+ }
+ case 'pre-launched-browser-or-android': {
+ return this._preLaunched.browser ? await this._initPreLaunchedBrowserMode(scope) : await this._initPreLaunchedAndroidMode(scope);
+ }
+ case 'launch-browser': {
+ return await this._initLaunchBrowserMode(scope, options);
+ }
+ default: {
+ return assertUnreachableWithError(clientType, new Error('Unsupported client type: ' + clientType));
+ }
}
- if (clientType === 'pre-launched-browser-or-android') {
- return this._preLaunched.browser ? await this._initPreLaunchedBrowserMode(scope) : await this._initPreLaunchedAndroidMode(scope);
- }
- if (clientType === 'launch-browser') {
- return await this._initLaunchBrowserMode(scope, options);
- }
- throw new Error('Unsupported client type: ' + clientType);
});
}
@@ -233,9 +238,6 @@ export class PlaywrightConnection {
await context.stopPendingOperations('Connection closed');
}
}
- if (!browser.contexts()) {
- await browser.close({ reason: 'Connection terminated' });
- }
}
});
diff --git a/packages/playwright-core/src/server/android/android.ts b/packages/playwright-core/src/server/android/android.ts
index e0e437ab26..9c7035d7da 100644
--- a/packages/playwright-core/src/server/android/android.ts
+++ b/packages/playwright-core/src/server/android/android.ts
@@ -334,7 +334,7 @@ export class AndroidDevice extends SdkObject {
const artifactsDir = await fs.promises.mkdtemp(ARTIFACTS_FOLDER);
const cleanupArtifactsDir = async () => {
const errors = await removeFolders([artifactsDir]);
- for (let i = 0; i < (errors || []).length; ++i) {
+ for (let i = 0; i < errors.length; ++i) {
debug('pw:android')(`exception while removing ${artifactsDir}: ${errors[i]}`);
}
};
@@ -438,6 +438,7 @@ export class AndroidDevice extends SdkObject {
}
const pkg = await this._extractPkg(pid);
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
if (this._isClosed) {
return;
}
diff --git a/packages/playwright-core/src/server/bidi/bidiBrowser.ts b/packages/playwright-core/src/server/bidi/bidiBrowser.ts
index 569998b115..a314127510 100644
--- a/packages/playwright-core/src/server/bidi/bidiBrowser.ts
+++ b/packages/playwright-core/src/server/bidi/bidiBrowser.ts
@@ -159,9 +159,9 @@ export class BidiBrowser extends Browser {
}
return;
}
- let context = this._contexts.get(event.userContext);
+ let context: BidiBrowserContext | undefined | null = this._contexts.get(event.userContext);
if (!context) {
- context = this._defaultContext as BidiBrowserContext;
+ context = this._defaultContext as BidiBrowserContext | null;
}
if (!context) {
return;
@@ -240,6 +240,7 @@ export class BidiBrowserContext extends BrowserContext {
httpOnly: c.httpOnly,
secure: c.secure,
expires: c.expiry ?? -1,
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
sameSite: c.sameSite ? fromBidiSameSite(c.sameSite) : 'None',
};
return copy;
diff --git a/packages/playwright-core/src/server/bidi/bidiExecutionContext.ts b/packages/playwright-core/src/server/bidi/bidiExecutionContext.ts
index cfc691f52e..1d063f6e6e 100644
--- a/packages/playwright-core/src/server/bidi/bidiExecutionContext.ts
+++ b/packages/playwright-core/src/server/bidi/bidiExecutionContext.ts
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+import { assertUnreachableWithError } from 'playwright-core/lib/common/types';
import { parseEvaluationResultValue } from '../isomorphic/utilityScriptSerializers';
import * as js from '../javascript';
import type { BidiSession } from './bidiConnection';
@@ -51,13 +52,17 @@ export class BidiExecutionContext implements js.ExecutionContextDelegate {
awaitPromise: true,
userActivation: true,
});
- if (response.type === 'success') {
- return BidiDeserializer.deserialize(response.result);
+ switch (response.type) {
+ case 'success': {
+ return BidiDeserializer.deserialize(response.result);
+ }
+ case 'exception': {
+ throw new js.JavaScriptErrorInEvaluate(response.exceptionDetails.text + '\nFull val: ' + JSON.stringify(response.exceptionDetails));
+ }
+ default: {
+ return assertUnreachableWithError(response, new js.JavaScriptErrorInEvaluate('Unexpected response type: ' + JSON.stringify(response)));
+ }
}
- if (response.type === 'exception') {
- throw new js.JavaScriptErrorInEvaluate(response.exceptionDetails.text + '\nFull val: ' + JSON.stringify(response.exceptionDetails));
- }
- throw new js.JavaScriptErrorInEvaluate('Unexpected response type: ' + JSON.stringify(response));
}
async rawEvaluateHandle(expression: string): Promise {
@@ -69,16 +74,20 @@ export class BidiExecutionContext implements js.ExecutionContextDelegate {
awaitPromise: true,
userActivation: true,
});
- if (response.type === 'success') {
- if ('handle' in response.result) {
- return response.result.handle!;
+ switch (response.type) {
+ case 'success': {
+ if ('handle' in response.result) {
+ return response.result.handle!;
+ }
+ throw new js.JavaScriptErrorInEvaluate('Cannot get handle: ' + JSON.stringify(response.result));
+ }
+ case 'exception': {
+ throw new js.JavaScriptErrorInEvaluate(response.exceptionDetails.text + '\nFull val: ' + JSON.stringify(response.exceptionDetails));
+ }
+ default: {
+ return assertUnreachableWithError(response, new js.JavaScriptErrorInEvaluate('Unexpected response type: ' + JSON.stringify(response)));
}
- throw new js.JavaScriptErrorInEvaluate('Cannot get handle: ' + JSON.stringify(response.result));
}
- if (response.type === 'exception') {
- throw new js.JavaScriptErrorInEvaluate(response.exceptionDetails.text + '\nFull val: ' + JSON.stringify(response.exceptionDetails));
- }
- throw new js.JavaScriptErrorInEvaluate('Unexpected response type: ' + JSON.stringify(response));
}
async evaluateWithArguments(functionDeclaration: string, returnByValue: boolean, utilityScript: js.JSHandle, values: any[], objectIds: string[]): Promise {
@@ -95,17 +104,21 @@ export class BidiExecutionContext implements js.ExecutionContextDelegate {
awaitPromise: true,
userActivation: true,
});
- if (response.type === 'exception') {
- throw new js.JavaScriptErrorInEvaluate(response.exceptionDetails.text + '\nFull val: ' + JSON.stringify(response.exceptionDetails));
- }
- if (response.type === 'success') {
- if (returnByValue) {
- return parseEvaluationResultValue(BidiDeserializer.deserialize(response.result));
+ switch (response.type) {
+ case 'success': {
+ if (returnByValue) {
+ return parseEvaluationResultValue(BidiDeserializer.deserialize(response.result));
+ }
+ const objectId = 'handle' in response.result ? response.result.handle : undefined ;
+ return utilityScript._context.createHandle({ objectId, ...response.result });
+ }
+ case 'exception': {
+ throw new js.JavaScriptErrorInEvaluate(response.exceptionDetails.text + '\nFull val: ' + JSON.stringify(response.exceptionDetails));
+ }
+ default: {
+ return assertUnreachableWithError(response, new js.JavaScriptErrorInEvaluate('Unexpected response type: ' + JSON.stringify(response)));
}
- const objectId = 'handle' in response.result ? response.result.handle : undefined ;
- return utilityScript._context.createHandle({ objectId, ...response.result });
}
- throw new js.JavaScriptErrorInEvaluate('Unexpected response type: ' + JSON.stringify(response));
}
async getProperties(context: js.ExecutionContext, objectId: js.ObjectId): Promise