Fix cross origin iframe bugs (#1093)
* fix: error data while recording some websites are integrated with stripe These websites will usually have an iframe with src "https://js.stripe.com/v3/m-outer-xxx.html" * add test case for the bug * fix: recordCrossOriginIframes: true does not work with pack/unpack fn 1. bugfix 2. add test case 3. add rrweb-all.js to the result of command: bundle:browser 4. make puppeteer headless in CI by default to increase the speed and stability
This commit is contained in:
2
.github/workflows/ci-cd.yml
vendored
2
.github/workflows/ci-cd.yml
vendored
@@ -30,7 +30,7 @@ jobs:
|
||||
run: yarn turbo run check-types
|
||||
|
||||
- name: Run tests
|
||||
run: xvfb-run --server-args="-screen 0 1920x1080x24" yarn test
|
||||
run: PUPPETEER_HEADLESS=true xvfb-run --server-args="-screen 0 1920x1080x24" yarn test
|
||||
|
||||
- name: Upload diff images to GitHub
|
||||
uses: actions/upload-artifact@v3
|
||||
|
||||
@@ -214,6 +214,11 @@ if (process.env.BROWSER_ONLY) {
|
||||
name: 'rrweb',
|
||||
pathFn: (p) => p,
|
||||
},
|
||||
{
|
||||
input: './src/entries/all.ts',
|
||||
name: 'rrweb',
|
||||
pathFn: toAllPath,
|
||||
},
|
||||
{
|
||||
input: './src/plugins/console/record/index.ts',
|
||||
name: 'rrwebConsoleRecord',
|
||||
|
||||
@@ -83,24 +83,30 @@ export class IframeManager {
|
||||
);
|
||||
}
|
||||
private handleMessage(message: MessageEvent | CrossOriginIframeMessageEvent) {
|
||||
if ((message as CrossOriginIframeMessageEvent).data.type === 'rrweb') {
|
||||
const iframeSourceWindow = message.source;
|
||||
if (!iframeSourceWindow) return;
|
||||
const crossOriginMessageEvent = message as CrossOriginIframeMessageEvent;
|
||||
if (
|
||||
crossOriginMessageEvent.data.type !== 'rrweb' ||
|
||||
// To filter out the rrweb messages which are forwarded by some sites.
|
||||
crossOriginMessageEvent.origin !== crossOriginMessageEvent.data.origin
|
||||
)
|
||||
return;
|
||||
|
||||
const iframeEl = this.crossOriginIframeMap.get(message.source);
|
||||
if (!iframeEl) return;
|
||||
const iframeSourceWindow = message.source;
|
||||
if (!iframeSourceWindow) return;
|
||||
|
||||
const transformedEvent = this.transformCrossOriginEvent(
|
||||
iframeEl,
|
||||
(message as CrossOriginIframeMessageEvent).data.event,
|
||||
const iframeEl = this.crossOriginIframeMap.get(message.source);
|
||||
if (!iframeEl) return;
|
||||
|
||||
const transformedEvent = this.transformCrossOriginEvent(
|
||||
iframeEl,
|
||||
crossOriginMessageEvent.data.event,
|
||||
);
|
||||
|
||||
if (transformedEvent)
|
||||
this.wrappedEmit(
|
||||
transformedEvent,
|
||||
crossOriginMessageEvent.data.isCheckout,
|
||||
);
|
||||
|
||||
if (transformedEvent)
|
||||
this.wrappedEmit(
|
||||
transformedEvent,
|
||||
(message as CrossOriginIframeMessageEvent).data.isCheckout,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private transformCrossOriginEvent(
|
||||
|
||||
@@ -165,7 +165,11 @@ function record<T = eventWithTime>(
|
||||
e = plugin.eventProcessor(e);
|
||||
}
|
||||
}
|
||||
if (packFn) {
|
||||
if (
|
||||
packFn &&
|
||||
// Disable packing events which will be emitted to parent frames.
|
||||
!passEmitsToParent
|
||||
) {
|
||||
e = (packFn(e) as unknown) as eventWithTime;
|
||||
}
|
||||
return (e as unknown) as T;
|
||||
@@ -190,6 +194,7 @@ function record<T = eventWithTime>(
|
||||
const message: CrossOriginIframeMessageEventContent<T> = {
|
||||
type: 'rrweb',
|
||||
event: eventProcessor(e),
|
||||
origin: window.location.origin,
|
||||
isCheckout,
|
||||
};
|
||||
window.parent.postMessage(message, '*');
|
||||
|
||||
@@ -200,6 +200,8 @@ declare global {
|
||||
export type CrossOriginIframeMessageEventContent<T = eventWithTime> = {
|
||||
type: 'rrweb';
|
||||
event: T;
|
||||
// The origin of the iframe which originally emits this message. It is used to check the integrity of message and to filter out the rrweb messages which are forwarded by some sites.
|
||||
origin: string;
|
||||
isCheckout?: boolean;
|
||||
};
|
||||
export type CrossOriginIframeMessageEvent = MessageEvent<CrossOriginIframeMessageEventContent>;
|
||||
|
||||
@@ -307,6 +307,418 @@ exports[`cross origin iframes audio.html should emit contents of iframe once 1`]
|
||||
]"
|
||||
`;
|
||||
|
||||
exports[`cross origin iframes blank.html should filter out forwarded cross origin rrweb messages 1`] = `
|
||||
"[
|
||||
{
|
||||
\\"type\\": 4,
|
||||
\\"data\\": {
|
||||
\\"href\\": \\"about:blank\\",
|
||||
\\"width\\": 1920,
|
||||
\\"height\\": 1080
|
||||
}
|
||||
},
|
||||
{
|
||||
\\"type\\": 2,
|
||||
\\"data\\": {
|
||||
\\"node\\": {
|
||||
\\"type\\": 0,
|
||||
\\"childNodes\\": [
|
||||
{
|
||||
\\"type\\": 1,
|
||||
\\"name\\": \\"html\\",
|
||||
\\"publicId\\": \\"\\",
|
||||
\\"systemId\\": \\"\\",
|
||||
\\"id\\": 2
|
||||
},
|
||||
{
|
||||
\\"type\\": 2,
|
||||
\\"tagName\\": \\"html\\",
|
||||
\\"attributes\\": {},
|
||||
\\"childNodes\\": [
|
||||
{
|
||||
\\"type\\": 2,
|
||||
\\"tagName\\": \\"head\\",
|
||||
\\"attributes\\": {},
|
||||
\\"childNodes\\": [
|
||||
{
|
||||
\\"type\\": 2,
|
||||
\\"tagName\\": \\"script\\",
|
||||
\\"attributes\\": {
|
||||
\\"type\\": \\"\\"
|
||||
},
|
||||
\\"childNodes\\": [
|
||||
{
|
||||
\\"type\\": 3,
|
||||
\\"textContent\\": \\"SCRIPT_PLACEHOLDER\\",
|
||||
\\"id\\": 6
|
||||
}
|
||||
],
|
||||
\\"id\\": 5
|
||||
}
|
||||
],
|
||||
\\"id\\": 4
|
||||
},
|
||||
{
|
||||
\\"type\\": 2,
|
||||
\\"tagName\\": \\"body\\",
|
||||
\\"attributes\\": {},
|
||||
\\"childNodes\\": [
|
||||
{
|
||||
\\"type\\": 3,
|
||||
\\"textContent\\": \\"\\\\n \\",
|
||||
\\"id\\": 8
|
||||
},
|
||||
{
|
||||
\\"type\\": 2,
|
||||
\\"tagName\\": \\"iframe\\",
|
||||
\\"attributes\\": {
|
||||
\\"rr_src\\": \\"http://localhost:3030/html/blank.html\\"
|
||||
},
|
||||
\\"childNodes\\": [],
|
||||
\\"id\\": 9
|
||||
},
|
||||
{
|
||||
\\"type\\": 3,
|
||||
\\"textContent\\": \\"\\\\n \\\\n \\\\n \\",
|
||||
\\"id\\": 10
|
||||
}
|
||||
],
|
||||
\\"id\\": 7
|
||||
}
|
||||
],
|
||||
\\"id\\": 3
|
||||
}
|
||||
],
|
||||
\\"id\\": 1
|
||||
},
|
||||
\\"initialOffset\\": {
|
||||
\\"left\\": 0,
|
||||
\\"top\\": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
\\"type\\": 3,
|
||||
\\"data\\": {
|
||||
\\"source\\": 0,
|
||||
\\"adds\\": [
|
||||
{
|
||||
\\"parentId\\": 9,
|
||||
\\"nextId\\": null,
|
||||
\\"node\\": {
|
||||
\\"type\\": 0,
|
||||
\\"childNodes\\": [
|
||||
{
|
||||
\\"type\\": 2,
|
||||
\\"tagName\\": \\"html\\",
|
||||
\\"attributes\\": {},
|
||||
\\"childNodes\\": [
|
||||
{
|
||||
\\"type\\": 2,
|
||||
\\"tagName\\": \\"head\\",
|
||||
\\"attributes\\": {},
|
||||
\\"childNodes\\": [
|
||||
{
|
||||
\\"type\\": 2,
|
||||
\\"tagName\\": \\"script\\",
|
||||
\\"attributes\\": {
|
||||
\\"type\\": \\"\\"
|
||||
},
|
||||
\\"childNodes\\": [
|
||||
{
|
||||
\\"type\\": 3,
|
||||
\\"textContent\\": \\"SCRIPT_PLACEHOLDER\\",
|
||||
\\"id\\": 15
|
||||
}
|
||||
],
|
||||
\\"id\\": 14
|
||||
}
|
||||
],
|
||||
\\"id\\": 13
|
||||
},
|
||||
{
|
||||
\\"type\\": 2,
|
||||
\\"tagName\\": \\"body\\",
|
||||
\\"attributes\\": {},
|
||||
\\"childNodes\\": [
|
||||
{
|
||||
\\"type\\": 3,
|
||||
\\"textContent\\": \\"\\\\n\\\\n\\",
|
||||
\\"id\\": 17
|
||||
}
|
||||
],
|
||||
\\"id\\": 16
|
||||
}
|
||||
],
|
||||
\\"id\\": 12
|
||||
}
|
||||
],
|
||||
\\"compatMode\\": \\"BackCompat\\",
|
||||
\\"id\\": 11
|
||||
}
|
||||
}
|
||||
],
|
||||
\\"removes\\": [],
|
||||
\\"texts\\": [],
|
||||
\\"attributes\\": [],
|
||||
\\"isAttachIframe\\": true
|
||||
}
|
||||
},
|
||||
{
|
||||
\\"type\\": 3,
|
||||
\\"data\\": {
|
||||
\\"source\\": 0,
|
||||
\\"texts\\": [],
|
||||
\\"attributes\\": [],
|
||||
\\"removes\\": [],
|
||||
\\"adds\\": [
|
||||
{
|
||||
\\"parentId\\": 16,
|
||||
\\"nextId\\": null,
|
||||
\\"node\\": {
|
||||
\\"type\\": 2,
|
||||
\\"tagName\\": \\"iframe\\",
|
||||
\\"attributes\\": {},
|
||||
\\"childNodes\\": [],
|
||||
\\"id\\": 18
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
\\"type\\": 3,
|
||||
\\"data\\": {
|
||||
\\"source\\": 0,
|
||||
\\"adds\\": [
|
||||
{
|
||||
\\"parentId\\": 18,
|
||||
\\"nextId\\": null,
|
||||
\\"node\\": {
|
||||
\\"type\\": 0,
|
||||
\\"childNodes\\": [
|
||||
{
|
||||
\\"type\\": 2,
|
||||
\\"tagName\\": \\"html\\",
|
||||
\\"attributes\\": {},
|
||||
\\"childNodes\\": [
|
||||
{
|
||||
\\"type\\": 2,
|
||||
\\"tagName\\": \\"head\\",
|
||||
\\"attributes\\": {},
|
||||
\\"childNodes\\": [
|
||||
{
|
||||
\\"type\\": 2,
|
||||
\\"tagName\\": \\"script\\",
|
||||
\\"attributes\\": {
|
||||
\\"type\\": \\"\\"
|
||||
},
|
||||
\\"childNodes\\": [
|
||||
{
|
||||
\\"type\\": 3,
|
||||
\\"textContent\\": \\"SCRIPT_PLACEHOLDER\\",
|
||||
\\"id\\": 23
|
||||
}
|
||||
],
|
||||
\\"id\\": 22
|
||||
}
|
||||
],
|
||||
\\"id\\": 21
|
||||
},
|
||||
{
|
||||
\\"type\\": 2,
|
||||
\\"tagName\\": \\"body\\",
|
||||
\\"attributes\\": {},
|
||||
\\"childNodes\\": [
|
||||
{
|
||||
\\"type\\": 3,
|
||||
\\"textContent\\": \\"\\\\n\\\\n\\",
|
||||
\\"id\\": 25
|
||||
}
|
||||
],
|
||||
\\"id\\": 24
|
||||
}
|
||||
],
|
||||
\\"id\\": 20
|
||||
}
|
||||
],
|
||||
\\"compatMode\\": \\"BackCompat\\",
|
||||
\\"id\\": 19
|
||||
}
|
||||
}
|
||||
],
|
||||
\\"removes\\": [],
|
||||
\\"texts\\": [],
|
||||
\\"attributes\\": [],
|
||||
\\"isAttachIframe\\": true
|
||||
}
|
||||
}
|
||||
]"
|
||||
`;
|
||||
|
||||
exports[`cross origin iframes blank.html should support packFn option in record() 1`] = `
|
||||
"[
|
||||
{
|
||||
\\"type\\": 4,
|
||||
\\"data\\": {
|
||||
\\"href\\": \\"about:blank\\",
|
||||
\\"width\\": 1920,
|
||||
\\"height\\": 1080
|
||||
},
|
||||
\\"v\\": \\"v1\\"
|
||||
},
|
||||
{
|
||||
\\"type\\": 2,
|
||||
\\"data\\": {
|
||||
\\"node\\": {
|
||||
\\"type\\": 0,
|
||||
\\"childNodes\\": [
|
||||
{
|
||||
\\"type\\": 1,
|
||||
\\"name\\": \\"html\\",
|
||||
\\"publicId\\": \\"\\",
|
||||
\\"systemId\\": \\"\\",
|
||||
\\"id\\": 2
|
||||
},
|
||||
{
|
||||
\\"type\\": 2,
|
||||
\\"tagName\\": \\"html\\",
|
||||
\\"attributes\\": {},
|
||||
\\"childNodes\\": [
|
||||
{
|
||||
\\"type\\": 2,
|
||||
\\"tagName\\": \\"head\\",
|
||||
\\"attributes\\": {},
|
||||
\\"childNodes\\": [
|
||||
{
|
||||
\\"type\\": 2,
|
||||
\\"tagName\\": \\"script\\",
|
||||
\\"attributes\\": {
|
||||
\\"type\\": \\"\\"
|
||||
},
|
||||
\\"childNodes\\": [
|
||||
{
|
||||
\\"type\\": 3,
|
||||
\\"textContent\\": \\"SCRIPT_PLACEHOLDER\\",
|
||||
\\"id\\": 6
|
||||
}
|
||||
],
|
||||
\\"id\\": 5
|
||||
}
|
||||
],
|
||||
\\"id\\": 4
|
||||
},
|
||||
{
|
||||
\\"type\\": 2,
|
||||
\\"tagName\\": \\"body\\",
|
||||
\\"attributes\\": {},
|
||||
\\"childNodes\\": [
|
||||
{
|
||||
\\"type\\": 3,
|
||||
\\"textContent\\": \\"\\\\n \\",
|
||||
\\"id\\": 8
|
||||
},
|
||||
{
|
||||
\\"type\\": 2,
|
||||
\\"tagName\\": \\"iframe\\",
|
||||
\\"attributes\\": {
|
||||
\\"rr_src\\": \\"http://localhost:3030/html/blank.html\\"
|
||||
},
|
||||
\\"childNodes\\": [],
|
||||
\\"id\\": 9
|
||||
},
|
||||
{
|
||||
\\"type\\": 3,
|
||||
\\"textContent\\": \\"\\\\n \\\\n \\\\n \\",
|
||||
\\"id\\": 10
|
||||
}
|
||||
],
|
||||
\\"id\\": 7
|
||||
}
|
||||
],
|
||||
\\"id\\": 3
|
||||
}
|
||||
],
|
||||
\\"id\\": 1
|
||||
},
|
||||
\\"initialOffset\\": {
|
||||
\\"left\\": 0,
|
||||
\\"top\\": 0
|
||||
}
|
||||
},
|
||||
\\"v\\": \\"v1\\"
|
||||
},
|
||||
{
|
||||
\\"type\\": 3,
|
||||
\\"data\\": {
|
||||
\\"source\\": 0,
|
||||
\\"adds\\": [
|
||||
{
|
||||
\\"parentId\\": 9,
|
||||
\\"nextId\\": null,
|
||||
\\"node\\": {
|
||||
\\"type\\": 0,
|
||||
\\"childNodes\\": [
|
||||
{
|
||||
\\"type\\": 2,
|
||||
\\"tagName\\": \\"html\\",
|
||||
\\"attributes\\": {},
|
||||
\\"childNodes\\": [
|
||||
{
|
||||
\\"type\\": 2,
|
||||
\\"tagName\\": \\"head\\",
|
||||
\\"attributes\\": {},
|
||||
\\"childNodes\\": [
|
||||
{
|
||||
\\"type\\": 2,
|
||||
\\"tagName\\": \\"script\\",
|
||||
\\"attributes\\": {
|
||||
\\"type\\": \\"\\"
|
||||
},
|
||||
\\"childNodes\\": [
|
||||
{
|
||||
\\"type\\": 3,
|
||||
\\"textContent\\": \\"SCRIPT_PLACEHOLDER\\",
|
||||
\\"id\\": 15
|
||||
}
|
||||
],
|
||||
\\"id\\": 14
|
||||
}
|
||||
],
|
||||
\\"id\\": 13
|
||||
},
|
||||
{
|
||||
\\"type\\": 2,
|
||||
\\"tagName\\": \\"body\\",
|
||||
\\"attributes\\": {},
|
||||
\\"childNodes\\": [
|
||||
{
|
||||
\\"type\\": 3,
|
||||
\\"textContent\\": \\"\\\\n\\\\n\\",
|
||||
\\"id\\": 17
|
||||
}
|
||||
],
|
||||
\\"id\\": 16
|
||||
}
|
||||
],
|
||||
\\"id\\": 12
|
||||
}
|
||||
],
|
||||
\\"compatMode\\": \\"BackCompat\\",
|
||||
\\"id\\": 11
|
||||
}
|
||||
}
|
||||
],
|
||||
\\"removes\\": [],
|
||||
\\"texts\\": [],
|
||||
\\"attributes\\": [],
|
||||
\\"isAttachIframe\\": true
|
||||
},
|
||||
\\"v\\": \\"v1\\"
|
||||
}
|
||||
]"
|
||||
`;
|
||||
|
||||
exports[`cross origin iframes form.html should map input events correctly 1`] = `
|
||||
"[
|
||||
{
|
||||
|
||||
@@ -13,9 +13,9 @@ import {
|
||||
getServerURL,
|
||||
launchPuppeteer,
|
||||
startServer,
|
||||
stripBase64,
|
||||
waitForRAF,
|
||||
} from '../utils';
|
||||
import { unpack } from '../../src/packer/unpack';
|
||||
import type * as http from 'http';
|
||||
|
||||
interface ISuite {
|
||||
@@ -33,42 +33,61 @@ interface IWindow extends Window {
|
||||
options: recordOptions<eventWithTime>,
|
||||
) => listenerHandler | undefined;
|
||||
addCustomEvent<T>(tag: string, payload: T): void;
|
||||
pack: (e: eventWithTime) => string;
|
||||
};
|
||||
emit: (e: eventWithTime) => undefined;
|
||||
snapshots: eventWithTime[];
|
||||
}
|
||||
type ExtraOptions = {
|
||||
usePackFn?: boolean;
|
||||
};
|
||||
|
||||
async function injectRecordScript(frame: puppeteer.Frame) {
|
||||
async function injectRecordScript(
|
||||
frame: puppeteer.Frame,
|
||||
options?: ExtraOptions,
|
||||
) {
|
||||
await frame.addScriptTag({
|
||||
path: path.resolve(__dirname, '../../dist/rrweb.js'),
|
||||
path: path.resolve(__dirname, '../../dist/rrweb-all.js'),
|
||||
});
|
||||
await frame.evaluate(() => {
|
||||
options = options || {};
|
||||
await frame.evaluate((options) => {
|
||||
((window as unknown) as IWindow).snapshots = [];
|
||||
const { record } = ((window as unknown) as IWindow).rrweb;
|
||||
record({
|
||||
const { record, pack } = ((window as unknown) as IWindow).rrweb;
|
||||
const config: recordOptions<eventWithTime> = {
|
||||
recordCrossOriginIframes: true,
|
||||
recordCanvas: true,
|
||||
emit(event) {
|
||||
((window as unknown) as IWindow).snapshots.push(event);
|
||||
((window as unknown) as IWindow).emit(event);
|
||||
},
|
||||
});
|
||||
});
|
||||
};
|
||||
if (options.usePackFn) {
|
||||
config.packFn = pack;
|
||||
}
|
||||
record(config);
|
||||
}, options);
|
||||
|
||||
for (const child of frame.childFrames()) {
|
||||
await injectRecordScript(child);
|
||||
await injectRecordScript(child, options);
|
||||
}
|
||||
}
|
||||
|
||||
const setup = function (this: ISuite, content: string): ISuite {
|
||||
const ctx = {} as ISuite;
|
||||
const setup = function (
|
||||
this: ISuite,
|
||||
content: string,
|
||||
options?: ExtraOptions,
|
||||
): ISuite {
|
||||
const ctx = {} as ISuite & {
|
||||
serverB: http.Server;
|
||||
serverBURL: string;
|
||||
};
|
||||
|
||||
beforeAll(async () => {
|
||||
ctx.browser = await launchPuppeteer();
|
||||
ctx.server = await startServer();
|
||||
ctx.serverURL = getServerURL(ctx.server);
|
||||
// ctx.serverB = await startServer();
|
||||
// ctx.serverBURL = getServerURL(ctx.serverB);
|
||||
ctx.serverB = await startServer();
|
||||
ctx.serverBURL = getServerURL(ctx.serverB);
|
||||
|
||||
const bundlePath = path.resolve(__dirname, '../../dist/rrweb.js');
|
||||
ctx.code = fs.readFileSync(bundlePath, 'utf8');
|
||||
@@ -90,7 +109,7 @@ const setup = function (this: ISuite, content: string): ISuite {
|
||||
});
|
||||
|
||||
ctx.page.on('console', (msg) => console.log('PAGE LOG:', msg.text()));
|
||||
await injectRecordScript(ctx.page.mainFrame());
|
||||
await injectRecordScript(ctx.page.mainFrame(), options);
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
@@ -100,7 +119,7 @@ const setup = function (this: ISuite, content: string): ISuite {
|
||||
afterAll(async () => {
|
||||
await ctx.browser.close();
|
||||
ctx.server.close();
|
||||
// ctx.serverB.close();
|
||||
ctx.serverB.close();
|
||||
});
|
||||
|
||||
return ctx;
|
||||
@@ -484,6 +503,61 @@ describe('cross origin iframes', function (this: ISuite) {
|
||||
assertSnapshot(snapshots);
|
||||
});
|
||||
});
|
||||
|
||||
describe('blank.html', function (this: ISuite) {
|
||||
const content = `
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body>
|
||||
<iframe src="{SERVER_URL}/html/blank.html"></iframe>
|
||||
</body>
|
||||
</html>
|
||||
`;
|
||||
const ctx = setup.call(this, content) as ISuite & {
|
||||
serverBURL: string;
|
||||
};
|
||||
|
||||
it('should filter out forwarded cross origin rrweb messages', async () => {
|
||||
const frame = ctx.page.mainFrame().childFrames()[0];
|
||||
const iframe2URL = `${ctx.serverBURL}/html/blank.html`;
|
||||
await frame.evaluate((iframe2URL) => {
|
||||
// Add a message proxy to forward messages from child frames to its parent frame.
|
||||
window.addEventListener('message', (event) => {
|
||||
if (event.source !== window)
|
||||
window.parent.postMessage(event.data, '*');
|
||||
});
|
||||
const iframe2 = document.createElement('iframe');
|
||||
iframe2.src = iframe2URL;
|
||||
document.body.appendChild(iframe2);
|
||||
}, iframe2URL);
|
||||
|
||||
// Wait for iframe2 to load
|
||||
await ctx.page.waitForFrame(iframe2URL);
|
||||
// Record iframe2
|
||||
await injectRecordScript(frame.childFrames()[0]);
|
||||
|
||||
await waitForRAF(frame.childFrames()[0]);
|
||||
const snapshots = (await ctx.page.evaluate(
|
||||
'window.snapshots',
|
||||
)) as eventWithTime[];
|
||||
assertSnapshot(snapshots);
|
||||
});
|
||||
|
||||
describe('should support packFn option in record()', () => {
|
||||
const ctx = setup.call(this, content, { usePackFn: true });
|
||||
it('', async () => {
|
||||
const frame = ctx.page.mainFrame().childFrames()[0];
|
||||
await waitForRAF(frame);
|
||||
const packedSnapshots = (await ctx.page.evaluate(
|
||||
'window.snapshots',
|
||||
)) as string[];
|
||||
const unpackedSnapshots = packedSnapshots.map((packed) =>
|
||||
unpack(packed),
|
||||
) as eventWithTime[];
|
||||
assertSnapshot(unpackedSnapshots);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('same origin iframes', function (this: ISuite) {
|
||||
|
||||
@@ -576,8 +576,10 @@ export const polyfillWebGLGlobals = () => {
|
||||
global.WebGL2RenderingContext = WebGL2RenderingContext as any;
|
||||
};
|
||||
|
||||
export async function waitForRAF(page: puppeteer.Page) {
|
||||
return await page.evaluate(() => {
|
||||
export async function waitForRAF(
|
||||
pageOrFrame: puppeteer.Page | puppeteer.Frame,
|
||||
) {
|
||||
return await pageOrFrame.evaluate(() => {
|
||||
return new Promise((resolve) => {
|
||||
requestAnimationFrame(() => {
|
||||
requestAnimationFrame(resolve);
|
||||
|
||||
Reference in New Issue
Block a user