mirror of
https://github.com/microsoft/playwright.git
synced 2024-11-28 09:23:42 +03:00
cherry-pick(#31914): chore: various roll fixes for .NET
This commit is contained in:
parent
468b9b1e7a
commit
dfecfa5be1
@ -503,6 +503,12 @@ If set changes the request URL. New URL must have same protocol as original one.
|
||||
Maximum number of request redirects that will be followed automatically. An error will be thrown if the number is exceeded.
|
||||
Defaults to `20`. Pass `0` to not follow redirects.
|
||||
|
||||
### option: Route.fetch.maxRetries
|
||||
* since: v1.46
|
||||
- `maxRetries` <[int]>
|
||||
|
||||
Maximum number of times network errors should be retried. Currently only `ECONNRESET` error is retried. Does not retry based on HTTP response codes. An error will be thrown if the limit is exceeded. Defaults to `0` - no retries.
|
||||
|
||||
### option: Route.fetch.timeout
|
||||
* since: v1.33
|
||||
- `timeout` <[float]>
|
||||
|
@ -524,9 +524,9 @@ Does not enforce fixed viewport, allows resizing window in the headed mode.
|
||||
## context-option-clientCertificates
|
||||
- `clientCertificates` <[Array]<[Object]>>
|
||||
- `origin` <[string]> Exact origin that the certificate is valid for. Origin includes `https` protocol, a hostname and optionally a port.
|
||||
- `certPath` ?<[string]> Path to the file with the certificate in PEM format.
|
||||
- `keyPath` ?<[string]> Path to the file with the private key in PEM format.
|
||||
- `pfxPath` ?<[string]> Path to the PFX or PKCS12 encoded private key and certificate chain.
|
||||
- `certPath` ?<[path]> Path to the file with the certificate in PEM format.
|
||||
- `keyPath` ?<[path]> Path to the file with the private key in PEM format.
|
||||
- `pfxPath` ?<[path]> Path to the PFX or PKCS12 encoded private key and certificate chain.
|
||||
- `passphrase` ?<[string]> Passphrase for the private key (PEM or PFX).
|
||||
|
||||
TLS Client Authentication allows the server to request a client certificate and verify it.
|
||||
|
6
packages/playwright-core/types/types.d.ts
vendored
6
packages/playwright-core/types/types.d.ts
vendored
@ -19570,6 +19570,12 @@ export interface Route {
|
||||
*/
|
||||
maxRedirects?: number;
|
||||
|
||||
/**
|
||||
* Maximum number of times network errors should be retried. Currently only `ECONNRESET` error is retried. Does not
|
||||
* retry based on HTTP response codes. An error will be thrown if the limit is exceeded. Defaults to `0` - no retries.
|
||||
*/
|
||||
maxRetries?: number;
|
||||
|
||||
/**
|
||||
* If set changes the request method (e.g. GET or POST).
|
||||
*/
|
||||
|
@ -17,9 +17,15 @@
|
||||
import os from 'os';
|
||||
import * as util from 'util';
|
||||
import { getPlaywrightVersion } from '../../packages/playwright-core/lib/utils/userAgent';
|
||||
import { expect, playwrightTest as it } from '../config/browserTest';
|
||||
import { expect, playwrightTest as base } from '../config/browserTest';
|
||||
import { kTargetClosedErrorMessage } from 'tests/config/errors';
|
||||
|
||||
const it = base.extend({
|
||||
context: async () => {
|
||||
throw new Error('global fetch tests should not use context');
|
||||
}
|
||||
});
|
||||
|
||||
it.skip(({ mode }) => mode !== 'default');
|
||||
|
||||
for (const method of ['fetch', 'delete', 'get', 'head', 'patch', 'post', 'put'] as const) {
|
||||
@ -33,9 +39,11 @@ for (const method of ['fetch', 'delete', 'get', 'head', 'patch', 'post', 'put']
|
||||
expect(response.headers()['content-type']).toBe('application/json; charset=utf-8');
|
||||
expect(response.headersArray()).toContainEqual({ name: 'Content-Type', value: 'application/json; charset=utf-8' });
|
||||
expect(await response.text()).toBe('head' === method ? '' : '{"foo": "bar"}\n');
|
||||
await request.dispose();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
it(`should dispose global request`, async function({ playwright, server }) {
|
||||
const request = await playwright.request.newContext();
|
||||
const response = await request.get(server.PREFIX + '/simple.json');
|
||||
@ -43,6 +51,7 @@ it(`should dispose global request`, async function({ playwright, server }) {
|
||||
await request.dispose();
|
||||
const error = await response.body().catch(e => e);
|
||||
expect(error.message).toContain('Response has been disposed');
|
||||
await request.dispose();
|
||||
});
|
||||
|
||||
it('should support global userAgent option', async ({ playwright, server }) => {
|
||||
@ -54,6 +63,7 @@ it('should support global userAgent option', async ({ playwright, server }) => {
|
||||
expect(response.ok()).toBeTruthy();
|
||||
expect(response.url()).toBe(server.EMPTY_PAGE);
|
||||
expect(serverRequest.headers['user-agent']).toBe('My Agent');
|
||||
await request.dispose();
|
||||
});
|
||||
|
||||
it('should support global timeout option', async ({ playwright, server }) => {
|
||||
@ -61,6 +71,7 @@ it('should support global timeout option', async ({ playwright, server }) => {
|
||||
server.setRoute('/empty.html', (req, res) => {});
|
||||
const error = await request.get(server.EMPTY_PAGE).catch(e => e);
|
||||
expect(error.message).toContain('Request timed out after 100ms');
|
||||
await request.dispose();
|
||||
});
|
||||
|
||||
it('should propagate extra http headers with redirects', async ({ playwright, server }) => {
|
||||
@ -76,6 +87,7 @@ it('should propagate extra http headers with redirects', async ({ playwright, se
|
||||
expect(req1.headers['my-secret']).toBe('Value');
|
||||
expect(req2.headers['my-secret']).toBe('Value');
|
||||
expect(req3.headers['my-secret']).toBe('Value');
|
||||
await request.dispose();
|
||||
});
|
||||
|
||||
it('should support global httpCredentials option', async ({ playwright, server }) => {
|
||||
@ -96,6 +108,7 @@ it('should return error with wrong credentials', async ({ playwright, server })
|
||||
const request = await playwright.request.newContext({ httpCredentials: { username: 'user', password: 'wrong' } });
|
||||
const response = await request.get(server.EMPTY_PAGE);
|
||||
expect(response.status()).toBe(401);
|
||||
await request.dispose();
|
||||
});
|
||||
|
||||
it('should work with correct credentials and matching origin', async ({ playwright, server }) => {
|
||||
@ -103,6 +116,7 @@ it('should work with correct credentials and matching origin', async ({ playwrig
|
||||
const request = await playwright.request.newContext({ httpCredentials: { username: 'user', password: 'pass', origin: server.PREFIX } });
|
||||
const response = await request.get(server.EMPTY_PAGE);
|
||||
expect(response.status()).toBe(200);
|
||||
await request.dispose();
|
||||
});
|
||||
|
||||
it('should work with correct credentials and matching origin case insensitive', async ({ playwright, server }) => {
|
||||
@ -110,6 +124,7 @@ it('should work with correct credentials and matching origin case insensitive',
|
||||
const request = await playwright.request.newContext({ httpCredentials: { username: 'user', password: 'pass', origin: server.PREFIX.toUpperCase() } });
|
||||
const response = await request.get(server.EMPTY_PAGE);
|
||||
expect(response.status()).toBe(200);
|
||||
await request.dispose();
|
||||
});
|
||||
|
||||
it('should return error with correct credentials and mismatching scheme', async ({ playwright, server }) => {
|
||||
@ -117,6 +132,7 @@ it('should return error with correct credentials and mismatching scheme', async
|
||||
const request = await playwright.request.newContext({ httpCredentials: { username: 'user', password: 'pass', origin: server.PREFIX.replace('http://', 'https://') } });
|
||||
const response = await request.get(server.EMPTY_PAGE);
|
||||
expect(response.status()).toBe(401);
|
||||
await request.dispose();
|
||||
});
|
||||
|
||||
it('should return error with correct credentials and mismatching hostname', async ({ playwright, server }) => {
|
||||
@ -126,6 +142,7 @@ it('should return error with correct credentials and mismatching hostname', asyn
|
||||
const request = await playwright.request.newContext({ httpCredentials: { username: 'user', password: 'pass', origin: origin } });
|
||||
const response = await request.get(server.EMPTY_PAGE);
|
||||
expect(response.status()).toBe(401);
|
||||
await request.dispose();
|
||||
});
|
||||
|
||||
it('should return error with correct credentials and mismatching port', async ({ playwright, server }) => {
|
||||
@ -134,6 +151,7 @@ it('should return error with correct credentials and mismatching port', async ({
|
||||
const request = await playwright.request.newContext({ httpCredentials: { username: 'user', password: 'pass', origin: origin } });
|
||||
const response = await request.get(server.EMPTY_PAGE);
|
||||
expect(response.status()).toBe(401);
|
||||
await request.dispose();
|
||||
});
|
||||
|
||||
it('should support WWW-Authenticate: Basic', async ({ playwright, server }) => {
|
||||
@ -152,6 +170,7 @@ it('should support WWW-Authenticate: Basic', async ({ playwright, server }) => {
|
||||
const response = await request.get(server.EMPTY_PAGE);
|
||||
expect(response.status()).toBe(200);
|
||||
expect(credentials).toBe('user:pass');
|
||||
await request.dispose();
|
||||
});
|
||||
|
||||
it('should support HTTPCredentials.send', async ({ playwright, server }) => {
|
||||
@ -176,12 +195,14 @@ it('should support HTTPCredentials.send', async ({ playwright, server }) => {
|
||||
expect(serverRequest.headers.authorization).toBe(undefined);
|
||||
expect(response.status()).toBe(200);
|
||||
}
|
||||
await request.dispose();
|
||||
});
|
||||
|
||||
it('should support global ignoreHTTPSErrors option', async ({ playwright, httpsServer }) => {
|
||||
const request = await playwright.request.newContext({ ignoreHTTPSErrors: true });
|
||||
const response = await request.get(httpsServer.EMPTY_PAGE);
|
||||
expect(response.status()).toBe(200);
|
||||
await request.dispose();
|
||||
});
|
||||
|
||||
it('should propagate ignoreHTTPSErrors on redirects', async ({ playwright, httpsServer }) => {
|
||||
@ -189,12 +210,14 @@ it('should propagate ignoreHTTPSErrors on redirects', async ({ playwright, https
|
||||
const request = await playwright.request.newContext();
|
||||
const response = await request.get(httpsServer.PREFIX + '/redir', { ignoreHTTPSErrors: true });
|
||||
expect(response.status()).toBe(200);
|
||||
await request.dispose();
|
||||
});
|
||||
|
||||
it('should resolve url relative to global baseURL option', async ({ playwright, server }) => {
|
||||
const request = await playwright.request.newContext({ baseURL: server.PREFIX });
|
||||
const response = await request.get('/empty.html');
|
||||
expect(response.url()).toBe(server.EMPTY_PAGE);
|
||||
await request.dispose();
|
||||
});
|
||||
|
||||
it('should set playwright as user-agent', async ({ playwright, server, isWindows, isLinux, isMac }) => {
|
||||
@ -221,12 +244,14 @@ it('should set playwright as user-agent', async ({ playwright, server, isWindows
|
||||
expect(userAgentMasked.replace(/<ARCH>; \w+ [^)]+/, '<ARCH>; distro version')).toBe('Playwright/X.X.X (<ARCH>; distro version) node/X.X' + suffix);
|
||||
else if (isMac)
|
||||
expect(userAgentMasked).toBe('Playwright/X.X.X (<ARCH>; macOS X.X) node/X.X' + suffix);
|
||||
await request.dispose();
|
||||
});
|
||||
|
||||
it('should be able to construct with context options', async ({ playwright, browserType, server }) => {
|
||||
const request = await playwright.request.newContext((browserType as any)._defaultContextOptions);
|
||||
const response = await request.get(server.EMPTY_PAGE);
|
||||
expect(response.ok()).toBeTruthy();
|
||||
await request.dispose();
|
||||
});
|
||||
|
||||
it('should return empty body', async ({ playwright, server }) => {
|
||||
@ -254,6 +279,7 @@ it('should abort requests when context is disposed', async ({ playwright, server
|
||||
expect(result.message).toContain(kTargetClosedErrorMessage);
|
||||
}
|
||||
await connectionClosed;
|
||||
await request.dispose();
|
||||
});
|
||||
|
||||
it('should abort redirected requests when context is disposed', async ({ playwright, server }) => {
|
||||
@ -269,6 +295,7 @@ it('should abort redirected requests when context is disposed', async ({ playwri
|
||||
expect(result instanceof Error).toBeTruthy();
|
||||
expect(result.message).toContain(kTargetClosedErrorMessage);
|
||||
await connectionClosed;
|
||||
await request.dispose();
|
||||
});
|
||||
|
||||
it('should remove content-length from redirected post requests', async ({ playwright, server }) => {
|
||||
@ -473,7 +500,6 @@ it('should serialize post data on the client', async ({ playwright, server }) =>
|
||||
await postReq;
|
||||
const body = await (await serverReq).postBody;
|
||||
expect(body.toString()).toBe('{"foo":"bar"}');
|
||||
// expect(serverRequest.rawHeaders).toContain('vaLUE');
|
||||
await request.dispose();
|
||||
});
|
||||
|
||||
@ -486,7 +512,8 @@ it('should throw after dispose', async ({ playwright, server }) => {
|
||||
|
||||
it('should retry ECONNRESET', {
|
||||
annotation: { type: 'issue', description: 'https://github.com/microsoft/playwright/issues/30978' }
|
||||
}, async ({ context, server }) => {
|
||||
}, async ({ playwright, server }) => {
|
||||
const request = await playwright.request.newContext();
|
||||
let requestCount = 0;
|
||||
server.setRoute('/test', (req, res) => {
|
||||
if (requestCount++ < 3) {
|
||||
@ -496,8 +523,9 @@ it('should retry ECONNRESET', {
|
||||
res.writeHead(200, { 'content-type': 'text/plain' });
|
||||
res.end('Hello!');
|
||||
});
|
||||
const response = await context.request.fetch(server.PREFIX + '/test', { maxRetries: 3 });
|
||||
const response = await request.fetch(server.PREFIX + '/test', { maxRetries: 3 });
|
||||
expect(response.status()).toBe(200);
|
||||
expect(await response.text()).toBe('Hello!');
|
||||
expect(requestCount).toBe(4);
|
||||
await request.dispose();
|
||||
});
|
||||
|
@ -400,10 +400,18 @@ function generateNameDefault(member, name, t, parent) {
|
||||
if (names[2] === names[1])
|
||||
names.pop(); // get rid of duplicates, cheaply
|
||||
let attemptedName = names.pop();
|
||||
const typesDiffer = function(left, right) {
|
||||
const typesDiffer = function(/** @type {Documentation.Type} */ left, /** @type {Documentation.Type} */ right) {
|
||||
if (left.expression && right.expression)
|
||||
return left.expression !== right.expression;
|
||||
return JSON.stringify(right.properties) !== JSON.stringify(left.properties);
|
||||
const toExpression = (/** @type {Documentation.Member} */ t) => t.name + t.type?.expression;
|
||||
const leftOverRightProperties = new Set(left.properties?.map(toExpression) ?? []);
|
||||
for (const prop of right.properties ?? []) {
|
||||
const expression = toExpression(prop);
|
||||
if (!leftOverRightProperties.has(expression))
|
||||
return true;
|
||||
leftOverRightProperties.delete(expression);
|
||||
}
|
||||
return leftOverRightProperties.size > 0;
|
||||
};
|
||||
while (true) {
|
||||
// crude attempt at removing plurality
|
||||
|
Loading…
Reference in New Issue
Block a user