test(har): add more har tests (#14997)
This commit is contained in:
parent
aaafb77036
commit
883e4d449a
|
|
@ -194,44 +194,34 @@ class HarBackend {
|
||||||
const harLog = this._harFile.log;
|
const harLog = this._harFile.log;
|
||||||
const visited = new Set<HAREntry>();
|
const visited = new Set<HAREntry>();
|
||||||
while (true) {
|
while (true) {
|
||||||
const entries = harLog.entries.filter(entry => entry.request.url === url && entry.request.method === method);
|
const entries: HAREntry[] = [];
|
||||||
|
for (const candidate of harLog.entries) {
|
||||||
|
if (candidate.request.url !== url || candidate.request.method !== method)
|
||||||
|
continue;
|
||||||
|
if (method === 'POST' && postData && candidate.request.postData) {
|
||||||
|
const buffer = await this._loadContent(candidate.request.postData);
|
||||||
|
if (!buffer.equals(postData))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
entries.push(candidate);
|
||||||
|
}
|
||||||
|
|
||||||
if (!entries.length)
|
if (!entries.length)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
let entry: HAREntry | undefined;
|
let entry = entries[0];
|
||||||
|
|
||||||
|
// Disambiguate using headers - then one with most matching headers wins.
|
||||||
if (entries.length > 1) {
|
if (entries.length > 1) {
|
||||||
// Disambiguating requests
|
const list: { candidate: HAREntry, matchingHeaders: number }[] = [];
|
||||||
|
for (const candidate of entries) {
|
||||||
// 1. Disambiguate using postData - this covers GraphQL
|
const matchingHeaders = countMatchingHeaders(candidate.request.headers, headers);
|
||||||
if (!entry && postData) {
|
list.push({ candidate, matchingHeaders });
|
||||||
for (const candidate of entries) {
|
|
||||||
if (!candidate.request.postData)
|
|
||||||
continue;
|
|
||||||
const buffer = await this._loadContent(candidate.request.postData);
|
|
||||||
if (buffer.equals(postData)) {
|
|
||||||
entry = candidate;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
list.sort((a, b) => b.matchingHeaders - a.matchingHeaders);
|
||||||
// Last. Disambiguate using headers - then one with most matching headers wins.
|
entry = list[0].candidate;
|
||||||
if (!entry) {
|
|
||||||
const list: { candidate: HAREntry, matchingHeaders: number }[] = [];
|
|
||||||
for (const candidate of entries) {
|
|
||||||
const matchingHeaders = countMatchingHeaders(candidate.request.headers, headers);
|
|
||||||
list.push({ candidate, matchingHeaders });
|
|
||||||
}
|
|
||||||
list.sort((a, b) => b.matchingHeaders - a.matchingHeaders);
|
|
||||||
entry = list[0].candidate;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
entry = entries[0];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (visited.has(entry))
|
if (visited.has(entry))
|
||||||
throw new Error(`Found redirect cycle for ${url}`);
|
throw new Error(`Found redirect cycle for ${url}`);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,8 @@
|
||||||
|
|
||||||
import { browserTest as it, expect } from '../config/browserTest';
|
import { browserTest as it, expect } from '../config/browserTest';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
|
import path from 'path';
|
||||||
|
import extractZip from '../../packages/playwright-core/bundles/zip/node_modules/extract-zip';
|
||||||
|
|
||||||
it('should fulfill from har, matching the method and following redirects', async ({ contextFactory, isAndroid, asset }) => {
|
it('should fulfill from har, matching the method and following redirects', async ({ contextFactory, isAndroid, asset }) => {
|
||||||
it.fixme(isAndroid);
|
it.fixme(isAndroid);
|
||||||
|
|
@ -192,3 +194,91 @@ it('should round-trip har.zip', async ({ contextFactory, isAndroid, server }, te
|
||||||
expect(await page2.content()).toContain('hello, world!');
|
expect(await page2.content()).toContain('hello, world!');
|
||||||
await expect(page2.locator('body')).toHaveCSS('background-color', 'rgb(255, 192, 203)');
|
await expect(page2.locator('body')).toHaveCSS('background-color', 'rgb(255, 192, 203)');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should round-trip extracted har.zip', async ({ contextFactory, isAndroid, server }, testInfo) => {
|
||||||
|
it.fixme(isAndroid);
|
||||||
|
|
||||||
|
const harPath = testInfo.outputPath('har.zip');
|
||||||
|
const context1 = await contextFactory({ recordHar: { path: harPath } });
|
||||||
|
const page1 = await context1.newPage();
|
||||||
|
await page1.goto(server.PREFIX + '/one-style.html');
|
||||||
|
await context1.close();
|
||||||
|
|
||||||
|
const harDir = testInfo.outputPath('hardir');
|
||||||
|
await extractZip(harPath, { dir: harDir });
|
||||||
|
|
||||||
|
const context2 = await contextFactory({ har: { path: path.join(harDir, 'har.har') } });
|
||||||
|
const page2 = await context2.newPage();
|
||||||
|
await page2.goto(server.PREFIX + '/one-style.html');
|
||||||
|
expect(await page2.content()).toContain('hello, world!');
|
||||||
|
await expect(page2.locator('body')).toHaveCSS('background-color', 'rgb(255, 192, 203)');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should round-trip har with postData', async ({ contextFactory, isAndroid, server }, testInfo) => {
|
||||||
|
it.fixme(isAndroid);
|
||||||
|
server.setRoute('/echo', async (req, res) => {
|
||||||
|
const body = await req.postBody;
|
||||||
|
res.end(body.toString());
|
||||||
|
});
|
||||||
|
|
||||||
|
const harPath = testInfo.outputPath('har.zip');
|
||||||
|
const context1 = await contextFactory({ recordHar: { path: harPath } });
|
||||||
|
const page1 = await context1.newPage();
|
||||||
|
await page1.goto(server.EMPTY_PAGE);
|
||||||
|
const fetchFunction = async (body: string) => {
|
||||||
|
const response = await fetch('/echo', { method: 'POST', body });
|
||||||
|
return await response.text();
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(await page1.evaluate(fetchFunction, '1')).toBe('1');
|
||||||
|
expect(await page1.evaluate(fetchFunction, '2')).toBe('2');
|
||||||
|
expect(await page1.evaluate(fetchFunction, '3')).toBe('3');
|
||||||
|
await context1.close();
|
||||||
|
|
||||||
|
const context2 = await contextFactory({ har: { path: harPath } });
|
||||||
|
const page2 = await context2.newPage();
|
||||||
|
await page2.goto(server.EMPTY_PAGE);
|
||||||
|
expect(await page2.evaluate(fetchFunction, '1')).toBe('1');
|
||||||
|
expect(await page2.evaluate(fetchFunction, '2')).toBe('2');
|
||||||
|
expect(await page2.evaluate(fetchFunction, '3')).toBe('3');
|
||||||
|
expect(await page2.evaluate(fetchFunction, '4').catch(e => e)).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should disambiguate by header', async ({ contextFactory, isAndroid, server }, testInfo) => {
|
||||||
|
it.fixme(isAndroid);
|
||||||
|
|
||||||
|
server.setRoute('/echo', async (req, res) => {
|
||||||
|
res.end(req.headers['baz']);
|
||||||
|
});
|
||||||
|
|
||||||
|
const harPath = testInfo.outputPath('har.zip');
|
||||||
|
const context1 = await contextFactory({ recordHar: { path: harPath } });
|
||||||
|
const page1 = await context1.newPage();
|
||||||
|
await page1.goto(server.EMPTY_PAGE);
|
||||||
|
|
||||||
|
const fetchFunction = async (bazValue: string) => {
|
||||||
|
const response = await fetch('/echo', {
|
||||||
|
method: 'POST',
|
||||||
|
body: '',
|
||||||
|
headers: {
|
||||||
|
foo: 'foo-value',
|
||||||
|
bar: 'bar-value',
|
||||||
|
baz: bazValue,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return await response.text();
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(await page1.evaluate(fetchFunction, 'baz1')).toBe('baz1');
|
||||||
|
expect(await page1.evaluate(fetchFunction, 'baz2')).toBe('baz2');
|
||||||
|
expect(await page1.evaluate(fetchFunction, 'baz3')).toBe('baz3');
|
||||||
|
await context1.close();
|
||||||
|
|
||||||
|
const context2 = await contextFactory({ har: { path: harPath } });
|
||||||
|
const page2 = await context2.newPage();
|
||||||
|
await page2.goto(server.EMPTY_PAGE);
|
||||||
|
expect(await page2.evaluate(fetchFunction, 'baz1')).toBe('baz1');
|
||||||
|
expect(await page2.evaluate(fetchFunction, 'baz2')).toBe('baz2');
|
||||||
|
expect(await page2.evaluate(fetchFunction, 'baz3')).toBe('baz3');
|
||||||
|
expect(await page2.evaluate(fetchFunction, 'baz4')).toBe('baz1');
|
||||||
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue