feat: add allow/block serviceWorkers option (#14714)
Adds cross-browser support for easily allowing/blocking Service Workers via a Context option. Includes plumbing for Playwright Test's `use`. Resolves #14522. Relates #1090. Supercedes #14321.
This commit is contained in:
Родитель
48ab172bda
Коммит
85d03714d9
|
@ -637,10 +637,18 @@ contexts override the proxy, global proxy will be never used and can be any stri
|
|||
## context-option-strict
|
||||
- `strictSelectors` <[boolean]>
|
||||
|
||||
It specified, enables strict selectors mode for this context. In the strict selectors mode all operations
|
||||
If specified, enables strict selectors mode for this context. In the strict selectors mode all operations
|
||||
on selectors that imply single target DOM element will throw when more than one element matches the selector.
|
||||
See [Locator] to learn more about the strict mode.
|
||||
|
||||
## context-option-service-worker-policy
|
||||
- `serviceWorkers` <[ServiceWorkerPolicy]<"allow"|"block">>
|
||||
|
||||
* `"allow"`: [Service Workers](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API) can be registered by sites.
|
||||
* `"block"`: Playwright will block all registration of Service Workers.
|
||||
|
||||
Defaults to `"allow"`.
|
||||
|
||||
## select-options-values
|
||||
* langs: java, js, csharp
|
||||
- `values` <[null]|[string]|[ElementHandle]|[Array]<[string]>|[Object]|[Array]<[ElementHandle]>|[Array]<[Object]>>
|
||||
|
@ -796,6 +804,7 @@ An acceptable perceived color difference in the [YIQ color space](https://en.wik
|
|||
- %%-context-option-recordvideo-dir-%%
|
||||
- %%-context-option-recordvideo-size-%%
|
||||
- %%-context-option-strict-%%
|
||||
- %%-context-option-service-worker-policy-%%
|
||||
|
||||
## browser-option-args
|
||||
- `args` <[Array]<[string]>>
|
||||
|
@ -1020,4 +1029,3 @@ When set to `"hide"`, screenshot will hide text caret. When set to `"initial"`,
|
|||
- %%-screenshot-option-type-%%
|
||||
- %%-screenshot-option-mask-%%
|
||||
- %%-input-timeout-%%
|
||||
|
||||
|
|
|
@ -215,3 +215,4 @@ Learn more about [recording video](../test-configuration.md#record-video).
|
|||
|
||||
## property: TestOptions.viewport = %%-context-option-viewport-%%
|
||||
|
||||
## property: TestOptions.serviceWorkers = %%-context-option-service-worker-policy-%%
|
||||
|
|
|
@ -413,6 +413,7 @@ export async function prepareBrowserContextParams(options: BrowserContextOptions
|
|||
noDefaultViewport: options.viewport === null,
|
||||
extraHTTPHeaders: options.extraHTTPHeaders ? headersObjectToArray(options.extraHTTPHeaders) : undefined,
|
||||
storageState: await prepareStorageState(options),
|
||||
serviceWorkers: options.serviceWorkers,
|
||||
recordHar: prepareRecordHarOptions(options.recordHar),
|
||||
};
|
||||
if (!contextParams.recordVideo && options.videosPath) {
|
||||
|
|
|
@ -747,6 +747,7 @@ export type BrowserTypeLaunchPersistentContextParams = {
|
|||
},
|
||||
recordHar?: RecordHarOptions,
|
||||
strictSelectors?: boolean,
|
||||
serviceWorkers?: 'allow' | 'block',
|
||||
userDataDir: string,
|
||||
slowMo?: number,
|
||||
};
|
||||
|
@ -816,6 +817,7 @@ export type BrowserTypeLaunchPersistentContextOptions = {
|
|||
},
|
||||
recordHar?: RecordHarOptions,
|
||||
strictSelectors?: boolean,
|
||||
serviceWorkers?: 'allow' | 'block',
|
||||
slowMo?: number,
|
||||
};
|
||||
export type BrowserTypeLaunchPersistentContextResult = {
|
||||
|
@ -909,6 +911,7 @@ export type BrowserNewContextParams = {
|
|||
},
|
||||
recordHar?: RecordHarOptions,
|
||||
strictSelectors?: boolean,
|
||||
serviceWorkers?: 'allow' | 'block',
|
||||
proxy?: {
|
||||
server: string,
|
||||
bypass?: string,
|
||||
|
@ -965,6 +968,7 @@ export type BrowserNewContextOptions = {
|
|||
},
|
||||
recordHar?: RecordHarOptions,
|
||||
strictSelectors?: boolean,
|
||||
serviceWorkers?: 'allow' | 'block',
|
||||
proxy?: {
|
||||
server: string,
|
||||
bypass?: string,
|
||||
|
@ -3984,6 +3988,7 @@ export type AndroidDeviceLaunchBrowserParams = {
|
|||
},
|
||||
recordHar?: RecordHarOptions,
|
||||
strictSelectors?: boolean,
|
||||
serviceWorkers?: 'allow' | 'block',
|
||||
pkg?: string,
|
||||
proxy?: {
|
||||
server: string,
|
||||
|
@ -4037,6 +4042,7 @@ export type AndroidDeviceLaunchBrowserOptions = {
|
|||
},
|
||||
recordHar?: RecordHarOptions,
|
||||
strictSelectors?: boolean,
|
||||
serviceWorkers?: 'allow' | 'block',
|
||||
pkg?: string,
|
||||
proxy?: {
|
||||
server: string,
|
||||
|
|
|
@ -455,6 +455,11 @@ ContextOptions:
|
|||
height: number
|
||||
recordHar: RecordHarOptions?
|
||||
strictSelectors: boolean?
|
||||
serviceWorkers:
|
||||
type: enum?
|
||||
literals:
|
||||
- allow
|
||||
- block
|
||||
|
||||
LocalUtils:
|
||||
type: interface
|
||||
|
|
|
@ -354,6 +354,7 @@ export function createScheme(tChannel: (name: string) => Validator): Scheme {
|
|||
})),
|
||||
recordHar: tOptional(tType('RecordHarOptions')),
|
||||
strictSelectors: tOptional(tBoolean),
|
||||
serviceWorkers: tOptional(tEnum(['allow', 'block'])),
|
||||
userDataDir: tString,
|
||||
slowMo: tOptional(tNumber),
|
||||
});
|
||||
|
@ -410,6 +411,7 @@ export function createScheme(tChannel: (name: string) => Validator): Scheme {
|
|||
})),
|
||||
recordHar: tOptional(tType('RecordHarOptions')),
|
||||
strictSelectors: tOptional(tBoolean),
|
||||
serviceWorkers: tOptional(tEnum(['allow', 'block'])),
|
||||
proxy: tOptional(tObject({
|
||||
server: tString,
|
||||
bypass: tOptional(tString),
|
||||
|
@ -1441,6 +1443,7 @@ export function createScheme(tChannel: (name: string) => Validator): Scheme {
|
|||
})),
|
||||
recordHar: tOptional(tType('RecordHarOptions')),
|
||||
strictSelectors: tOptional(tBoolean),
|
||||
serviceWorkers: tOptional(tEnum(['allow', 'block'])),
|
||||
pkg: tOptional(tString),
|
||||
proxy: tOptional(tObject({
|
||||
server: tString,
|
||||
|
|
|
@ -122,6 +122,8 @@ export abstract class BrowserContext extends SdkObject {
|
|||
|
||||
if (debugMode() === 'console')
|
||||
await this.extendInjectedScript(consoleApiSource.source);
|
||||
if (this._options.serviceWorkers === 'block')
|
||||
await this.addInitScript(`\nnavigator.serviceWorker.register = () => { console.warn('Service Worker registration blocked by Playwright'); };\n`);
|
||||
}
|
||||
|
||||
async _ensureVideosPath() {
|
||||
|
|
|
@ -266,6 +266,7 @@ export type BrowserContextOptions = {
|
|||
strictSelectors?: boolean,
|
||||
proxy?: ProxySettings,
|
||||
baseURL?: string,
|
||||
serviceWorkers?: 'allow' | 'block',
|
||||
};
|
||||
|
||||
export type EnvArray = { name: string, value: string }[];
|
||||
|
|
|
@ -10371,13 +10371,22 @@ export interface BrowserType<Unused = {}> {
|
|||
height: number;
|
||||
};
|
||||
|
||||
/**
|
||||
* - `"allow"`: [Service Workers](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API) can be registered
|
||||
* by sites.
|
||||
* - `"block"`: Playwright will block all registration of Service Workers.
|
||||
*
|
||||
* Defaults to `"allow"`.
|
||||
*/
|
||||
serviceWorkers?: "allow"|"block";
|
||||
|
||||
/**
|
||||
* Slows down Playwright operations by the specified amount of milliseconds. Useful so that you can see what is going on.
|
||||
*/
|
||||
slowMo?: number;
|
||||
|
||||
/**
|
||||
* It specified, enables strict selectors mode for this context. In the strict selectors mode all operations on selectors
|
||||
* If specified, enables strict selectors mode for this context. In the strict selectors mode all operations on selectors
|
||||
* that imply single target DOM element will throw when more than one element matches the selector. See [Locator] to learn
|
||||
* more about the strict mode.
|
||||
*/
|
||||
|
@ -11528,7 +11537,16 @@ export interface AndroidDevice {
|
|||
};
|
||||
|
||||
/**
|
||||
* It specified, enables strict selectors mode for this context. In the strict selectors mode all operations on selectors
|
||||
* - `"allow"`: [Service Workers](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API) can be registered
|
||||
* by sites.
|
||||
* - `"block"`: Playwright will block all registration of Service Workers.
|
||||
*
|
||||
* Defaults to `"allow"`.
|
||||
*/
|
||||
serviceWorkers?: "allow"|"block";
|
||||
|
||||
/**
|
||||
* If specified, enables strict selectors mode for this context. In the strict selectors mode all operations on selectors
|
||||
* that imply single target DOM element will throw when more than one element matches the selector. See [Locator] to learn
|
||||
* more about the strict mode.
|
||||
*/
|
||||
|
@ -13060,6 +13078,15 @@ export interface Browser extends EventEmitter {
|
|||
height: number;
|
||||
};
|
||||
|
||||
/**
|
||||
* - `"allow"`: [Service Workers](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API) can be registered
|
||||
* by sites.
|
||||
* - `"block"`: Playwright will block all registration of Service Workers.
|
||||
*
|
||||
* Defaults to `"allow"`.
|
||||
*/
|
||||
serviceWorkers?: "allow"|"block";
|
||||
|
||||
/**
|
||||
* Populates context with given storage state. This option can be used to initialize context with logged-in information
|
||||
* obtained via
|
||||
|
@ -13115,7 +13142,7 @@ export interface Browser extends EventEmitter {
|
|||
};
|
||||
|
||||
/**
|
||||
* It specified, enables strict selectors mode for this context. In the strict selectors mode all operations on selectors
|
||||
* If specified, enables strict selectors mode for this context. In the strict selectors mode all operations on selectors
|
||||
* that imply single target DOM element will throw when more than one element matches the selector. See [Locator] to learn
|
||||
* more about the strict mode.
|
||||
*/
|
||||
|
@ -15521,6 +15548,15 @@ export interface BrowserContextOptions {
|
|||
height: number;
|
||||
};
|
||||
|
||||
/**
|
||||
* - `"allow"`: [Service Workers](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API) can be registered
|
||||
* by sites.
|
||||
* - `"block"`: Playwright will block all registration of Service Workers.
|
||||
*
|
||||
* Defaults to `"allow"`.
|
||||
*/
|
||||
serviceWorkers?: "allow"|"block";
|
||||
|
||||
/**
|
||||
* Populates context with given storage state. This option can be used to initialize context with logged-in information
|
||||
* obtained via
|
||||
|
@ -15576,7 +15612,7 @@ export interface BrowserContextOptions {
|
|||
};
|
||||
|
||||
/**
|
||||
* It specified, enables strict selectors mode for this context. In the strict selectors mode all operations on selectors
|
||||
* If specified, enables strict selectors mode for this context. In the strict selectors mode all operations on selectors
|
||||
* that imply single target DOM element will throw when more than one element matches the selector. See [Locator] to learn
|
||||
* more about the strict mode.
|
||||
*/
|
||||
|
|
|
@ -159,6 +159,7 @@ export const test = _baseTest.extend<TestFixtures, WorkerFixtures>({
|
|||
baseURL: [ async ({ }, use) => {
|
||||
await use(process.env.PLAYWRIGHT_TEST_BASE_URL);
|
||||
}, { option: true } ],
|
||||
serviceWorkers: [ 'allow', { option: true } ],
|
||||
contextOptions: [ {}, { option: true } ],
|
||||
|
||||
_combinedContextOptions: async ({
|
||||
|
@ -183,6 +184,7 @@ export const test = _baseTest.extend<TestFixtures, WorkerFixtures>({
|
|||
userAgent,
|
||||
baseURL,
|
||||
contextOptions,
|
||||
serviceWorkers,
|
||||
}, use) => {
|
||||
const options: BrowserContextOptions = {};
|
||||
if (acceptDownloads !== undefined)
|
||||
|
@ -225,6 +227,8 @@ export const test = _baseTest.extend<TestFixtures, WorkerFixtures>({
|
|||
options.viewport = viewport;
|
||||
if (baseURL !== undefined)
|
||||
options.baseURL = baseURL;
|
||||
if (serviceWorkers !== undefined)
|
||||
options.serviceWorkers = serviceWorkers;
|
||||
await use({
|
||||
...contextOptions,
|
||||
...options,
|
||||
|
|
|
@ -152,6 +152,7 @@ function contextHash(context: BrowserContextOptions): string {
|
|||
timezoneId: context.timezoneId,
|
||||
userAgent: context.userAgent,
|
||||
deviceScaleFactor: context.deviceScaleFactor,
|
||||
serviceWorkers: context.serviceWorkers,
|
||||
};
|
||||
return JSON.stringify(hash);
|
||||
}
|
||||
|
|
|
@ -2494,6 +2494,7 @@ type ColorScheme = Exclude<BrowserContextOptions['colorScheme'], undefined>;
|
|||
type ExtraHTTPHeaders = Exclude<BrowserContextOptions['extraHTTPHeaders'], undefined>;
|
||||
type Proxy = Exclude<BrowserContextOptions['proxy'], undefined>;
|
||||
type StorageState = Exclude<BrowserContextOptions['storageState'], undefined>;
|
||||
type ServiceWorkerPolicy = Exclude<BrowserContextOptions['serviceWorkers'], undefined>;
|
||||
type ConnectOptions = {
|
||||
/**
|
||||
* A browser websocket endpoint to connect to.
|
||||
|
@ -2798,6 +2799,14 @@ export interface PlaywrightTestOptions {
|
|||
* Learn more about [various timeouts](https://playwright.dev/docs/test-timeouts).
|
||||
*/
|
||||
navigationTimeout: number | undefined;
|
||||
/**
|
||||
* - `"allow"`: [Service Workers](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API) can be registered
|
||||
* by sites.
|
||||
* - `"block"`: Playwright will block all registration of Service Workers.
|
||||
*
|
||||
* Defaults to `"allow"`.
|
||||
*/
|
||||
serviceWorkers: ServiceWorkerPolicy | undefined;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { browserTest as it, expect } from '../config/browserTest';
|
||||
|
||||
it('should allow service workers by default', async ({ page, server }) => {
|
||||
await page.goto(server.PREFIX + '/serviceworkers/empty/sw.html');
|
||||
await expect(page.evaluate(() => window['registrationPromise'])).resolves.toBeTruthy();
|
||||
});
|
||||
|
||||
it.describe('block', () => {
|
||||
it.use({ serviceWorkers: 'block' });
|
||||
|
||||
it('blocks service worker registration', async ({ page, server }) => {
|
||||
await Promise.all([
|
||||
page.waitForEvent('console', evt => evt.text() === 'Service Worker registration blocked by Playwright'),
|
||||
page.goto(server.PREFIX + '/serviceworkers/empty/sw.html'),
|
||||
]);
|
||||
});
|
||||
});
|
|
@ -175,6 +175,7 @@ type ColorScheme = Exclude<BrowserContextOptions['colorScheme'], undefined>;
|
|||
type ExtraHTTPHeaders = Exclude<BrowserContextOptions['extraHTTPHeaders'], undefined>;
|
||||
type Proxy = Exclude<BrowserContextOptions['proxy'], undefined>;
|
||||
type StorageState = Exclude<BrowserContextOptions['storageState'], undefined>;
|
||||
type ServiceWorkerPolicy = Exclude<BrowserContextOptions['serviceWorkers'], undefined>;
|
||||
type ConnectOptions = {
|
||||
/**
|
||||
* A browser websocket endpoint to connect to.
|
||||
|
@ -231,6 +232,7 @@ export interface PlaywrightTestOptions {
|
|||
contextOptions: BrowserContextOptions;
|
||||
actionTimeout: number | undefined;
|
||||
navigationTimeout: number | undefined;
|
||||
serviceWorkers: ServiceWorkerPolicy | undefined;
|
||||
}
|
||||
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче