fix: custom style rules don't get inserted into some iframe elements (#823)
* fix: custom style rules don't get inserted into some iframe elements * code style tweak
This commit is contained in:
@@ -660,10 +660,6 @@ export class Replayer {
|
||||
this.newDocumentQueue = this.newDocumentQueue.filter(
|
||||
(m) => m !== mutationInQueue,
|
||||
);
|
||||
if (builtNode.contentDocument) {
|
||||
const { documentElement, head } = builtNode.contentDocument;
|
||||
this.insertStyleRules(documentElement, head);
|
||||
}
|
||||
}
|
||||
const { documentElement, head } = this.iframe.contentDocument;
|
||||
this.insertStyleRules(documentElement, head);
|
||||
@@ -726,6 +722,13 @@ export class Replayer {
|
||||
skipChild: false,
|
||||
afterAppend: (builtNode) => {
|
||||
this.collectIframeAndAttachDocument(collected, builtNode);
|
||||
if (
|
||||
builtNode.__sn.type === NodeType.Element &&
|
||||
builtNode.__sn.tagName.toUpperCase() === 'HTML'
|
||||
) {
|
||||
const { documentElement, head } = iframeEl.contentDocument!;
|
||||
this.insertStyleRules(documentElement, head);
|
||||
}
|
||||
},
|
||||
cache: this.cache,
|
||||
});
|
||||
@@ -734,10 +737,6 @@ export class Replayer {
|
||||
this.newDocumentQueue = this.newDocumentQueue.filter(
|
||||
(m) => m !== mutationInQueue,
|
||||
);
|
||||
if (builtNode.contentDocument) {
|
||||
const { documentElement, head } = builtNode.contentDocument;
|
||||
this.insertStyleRules(documentElement, head);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1482,10 +1481,6 @@ export class Replayer {
|
||||
(m) => m !== mutationInQueue,
|
||||
);
|
||||
}
|
||||
if (target.contentDocument) {
|
||||
const { documentElement, head } = target.contentDocument;
|
||||
this.insertStyleRules(documentElement, head);
|
||||
}
|
||||
}
|
||||
|
||||
if (mutation.previousId || mutation.nextId) {
|
||||
|
||||
591
packages/rrweb/test/events/iframe.ts
Normal file
591
packages/rrweb/test/events/iframe.ts
Normal file
@@ -0,0 +1,591 @@
|
||||
import { EventType, eventWithTime, IncrementalSource } from '../../src/types';
|
||||
|
||||
const now = Date.now();
|
||||
|
||||
const events: eventWithTime[] = [
|
||||
{
|
||||
type: EventType.DomContentLoaded,
|
||||
data: {},
|
||||
timestamp: now,
|
||||
},
|
||||
{
|
||||
type: EventType.Load,
|
||||
data: {},
|
||||
timestamp: now + 100,
|
||||
},
|
||||
{
|
||||
type: EventType.Meta,
|
||||
data: {
|
||||
href: 'http://localhost',
|
||||
width: 1200,
|
||||
height: 500,
|
||||
},
|
||||
timestamp: now + 100,
|
||||
},
|
||||
{
|
||||
type: EventType.FullSnapshot,
|
||||
data: {
|
||||
node: {
|
||||
id: 1,
|
||||
type: 0,
|
||||
childNodes: [
|
||||
{ id: 2, name: 'html', type: 1, publicId: '', systemId: '' },
|
||||
{
|
||||
id: 3,
|
||||
type: 2,
|
||||
tagName: 'html',
|
||||
attributes: { lang: 'en' },
|
||||
childNodes: [
|
||||
{
|
||||
id: 4,
|
||||
type: 2,
|
||||
tagName: 'head',
|
||||
attributes: {},
|
||||
childNodes: [],
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
type: 2,
|
||||
tagName: 'body',
|
||||
attributes: {},
|
||||
childNodes: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
initialOffset: { top: 0, left: 0 },
|
||||
},
|
||||
timestamp: now + 200,
|
||||
},
|
||||
{
|
||||
type: EventType.IncrementalSnapshot,
|
||||
data: {
|
||||
source: IncrementalSource.Mutation,
|
||||
texts: [],
|
||||
attributes: [],
|
||||
removes: [],
|
||||
adds: [
|
||||
{
|
||||
parentId: 5,
|
||||
nextId: null,
|
||||
node: {
|
||||
type: 2,
|
||||
tagName: 'iframe',
|
||||
attributes: { id: 'one' },
|
||||
childNodes: [],
|
||||
id: 6,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
timestamp: now + 500,
|
||||
},
|
||||
// add iframe one
|
||||
{
|
||||
type: EventType.IncrementalSnapshot,
|
||||
data: {
|
||||
source: IncrementalSource.Mutation,
|
||||
adds: [
|
||||
{
|
||||
parentId: 6,
|
||||
nextId: null,
|
||||
node: {
|
||||
type: 0,
|
||||
childNodes: [
|
||||
{
|
||||
type: 1,
|
||||
name: 'html',
|
||||
publicId: '',
|
||||
systemId: '',
|
||||
rootId: 7,
|
||||
id: 8,
|
||||
},
|
||||
{
|
||||
type: 2,
|
||||
tagName: 'html',
|
||||
attributes: { lang: 'en' },
|
||||
childNodes: [
|
||||
{
|
||||
type: 2,
|
||||
tagName: 'head',
|
||||
attributes: {},
|
||||
childNodes: [],
|
||||
rootId: 7,
|
||||
id: 10,
|
||||
},
|
||||
{
|
||||
type: 2,
|
||||
tagName: 'body',
|
||||
attributes: {},
|
||||
childNodes: [
|
||||
{
|
||||
type: 2,
|
||||
tagName: 'div',
|
||||
attributes: {},
|
||||
childNodes: [
|
||||
{
|
||||
type: 3,
|
||||
textContent: '\n\t\tiframe 1\n\t',
|
||||
rootId: 7,
|
||||
id: 13,
|
||||
},
|
||||
],
|
||||
rootId: 7,
|
||||
id: 12,
|
||||
},
|
||||
{ type: 3, textContent: '\n\t', rootId: 7, id: 14 },
|
||||
{
|
||||
type: 2,
|
||||
tagName: 'script',
|
||||
attributes: {},
|
||||
childNodes: [
|
||||
{
|
||||
type: 3,
|
||||
textContent: 'SCRIPT_PLACEHOLDER',
|
||||
rootId: 7,
|
||||
id: 16,
|
||||
},
|
||||
],
|
||||
rootId: 7,
|
||||
id: 15,
|
||||
},
|
||||
{ type: 3, textContent: '\t\n', rootId: 7, id: 17 },
|
||||
],
|
||||
rootId: 7,
|
||||
id: 11,
|
||||
},
|
||||
],
|
||||
rootId: 7,
|
||||
id: 9,
|
||||
},
|
||||
],
|
||||
id: 7,
|
||||
},
|
||||
},
|
||||
],
|
||||
removes: [],
|
||||
texts: [],
|
||||
attributes: [],
|
||||
isAttachIframe: true,
|
||||
},
|
||||
timestamp: now + 500,
|
||||
},
|
||||
{
|
||||
type: EventType.IncrementalSnapshot,
|
||||
data: {
|
||||
source: IncrementalSource.Mutation,
|
||||
texts: [],
|
||||
attributes: [],
|
||||
removes: [],
|
||||
adds: [
|
||||
{
|
||||
parentId: 5,
|
||||
nextId: null,
|
||||
node: {
|
||||
type: 2,
|
||||
tagName: 'iframe',
|
||||
attributes: { id: 'two' },
|
||||
childNodes: [],
|
||||
id: 38,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
timestamp: now + 1000,
|
||||
},
|
||||
// add iframe two
|
||||
{
|
||||
type: EventType.IncrementalSnapshot,
|
||||
data: {
|
||||
source: IncrementalSource.Mutation,
|
||||
adds: [
|
||||
{
|
||||
parentId: 38,
|
||||
nextId: null,
|
||||
node: {
|
||||
type: 0,
|
||||
childNodes: [
|
||||
{
|
||||
type: 1,
|
||||
name: 'html',
|
||||
publicId: '',
|
||||
systemId: '',
|
||||
rootId: 39,
|
||||
id: 40,
|
||||
},
|
||||
{
|
||||
type: 2,
|
||||
tagName: 'html',
|
||||
attributes: { lang: 'en' },
|
||||
childNodes: [
|
||||
{
|
||||
type: 2,
|
||||
tagName: 'head',
|
||||
attributes: {},
|
||||
childNodes: [
|
||||
{ type: 3, textContent: '\n ', rootId: 39, id: 43 },
|
||||
{
|
||||
type: 2,
|
||||
tagName: 'meta',
|
||||
attributes: { charset: 'UTF-8' },
|
||||
childNodes: [],
|
||||
rootId: 39,
|
||||
id: 44,
|
||||
},
|
||||
{ type: 3, textContent: '\n ', rootId: 39, id: 45 },
|
||||
{
|
||||
type: 2,
|
||||
tagName: 'meta',
|
||||
attributes: {
|
||||
name: 'viewport',
|
||||
content: 'width=device-width, initial-scale=1.0',
|
||||
},
|
||||
childNodes: [],
|
||||
rootId: 39,
|
||||
id: 46,
|
||||
},
|
||||
{ type: 3, textContent: '\n ', rootId: 39, id: 47 },
|
||||
{
|
||||
type: 2,
|
||||
tagName: 'title',
|
||||
attributes: {},
|
||||
childNodes: [
|
||||
{
|
||||
type: 3,
|
||||
textContent: 'iframe 2',
|
||||
rootId: 39,
|
||||
id: 49,
|
||||
},
|
||||
],
|
||||
rootId: 39,
|
||||
id: 48,
|
||||
},
|
||||
{ type: 3, textContent: '\n ', rootId: 39, id: 50 },
|
||||
],
|
||||
rootId: 39,
|
||||
id: 42,
|
||||
},
|
||||
{ type: 3, textContent: '\n ', rootId: 39, id: 51 },
|
||||
{
|
||||
type: 2,
|
||||
tagName: 'body',
|
||||
attributes: {},
|
||||
childNodes: [
|
||||
{
|
||||
type: 3,
|
||||
textContent: '\n iframe 2\n ',
|
||||
rootId: 39,
|
||||
id: 53,
|
||||
},
|
||||
{
|
||||
type: 2,
|
||||
tagName: 'iframe',
|
||||
attributes: { id: 'three', frameborder: '0' },
|
||||
childNodes: [],
|
||||
rootId: 39,
|
||||
id: 54,
|
||||
},
|
||||
{ type: 3, textContent: '\n ', rootId: 39, id: 55 },
|
||||
{
|
||||
type: 2,
|
||||
tagName: 'iframe',
|
||||
attributes: { id: 'four', frameborder: '0' },
|
||||
childNodes: [],
|
||||
rootId: 39,
|
||||
id: 56,
|
||||
},
|
||||
{ type: 3, textContent: '\n \n\n', rootId: 39, id: 57 },
|
||||
],
|
||||
rootId: 39,
|
||||
id: 52,
|
||||
},
|
||||
],
|
||||
rootId: 39,
|
||||
id: 41,
|
||||
},
|
||||
],
|
||||
id: 39,
|
||||
},
|
||||
},
|
||||
],
|
||||
removes: [],
|
||||
texts: [],
|
||||
attributes: [],
|
||||
isAttachIframe: true,
|
||||
},
|
||||
timestamp: now + 1000,
|
||||
},
|
||||
// add iframe three
|
||||
{
|
||||
type: EventType.IncrementalSnapshot,
|
||||
data: {
|
||||
source: IncrementalSource.Mutation,
|
||||
adds: [
|
||||
{
|
||||
parentId: 54,
|
||||
nextId: null,
|
||||
node: {
|
||||
type: 0,
|
||||
childNodes: [
|
||||
{
|
||||
type: 2,
|
||||
tagName: 'html',
|
||||
attributes: {},
|
||||
childNodes: [
|
||||
{
|
||||
type: 2,
|
||||
tagName: 'head',
|
||||
attributes: {},
|
||||
childNodes: [],
|
||||
rootId: 58,
|
||||
id: 60,
|
||||
},
|
||||
{
|
||||
type: 2,
|
||||
tagName: 'body',
|
||||
attributes: {},
|
||||
childNodes: [],
|
||||
rootId: 58,
|
||||
id: 61,
|
||||
},
|
||||
],
|
||||
rootId: 58,
|
||||
id: 59,
|
||||
},
|
||||
],
|
||||
id: 58,
|
||||
},
|
||||
},
|
||||
],
|
||||
removes: [],
|
||||
texts: [],
|
||||
attributes: [],
|
||||
isAttachIframe: true,
|
||||
},
|
||||
timestamp: now + 1000,
|
||||
},
|
||||
// add iframe four
|
||||
{
|
||||
type: EventType.IncrementalSnapshot,
|
||||
data: {
|
||||
source: IncrementalSource.Mutation,
|
||||
adds: [
|
||||
{
|
||||
parentId: 56,
|
||||
nextId: null,
|
||||
node: {
|
||||
type: 0,
|
||||
childNodes: [
|
||||
{
|
||||
type: 1,
|
||||
name: 'html',
|
||||
publicId: '',
|
||||
systemId: '',
|
||||
rootId: 62,
|
||||
id: 63,
|
||||
},
|
||||
{
|
||||
type: 2,
|
||||
tagName: 'html',
|
||||
attributes: { lang: 'en' },
|
||||
childNodes: [
|
||||
{
|
||||
type: 2,
|
||||
tagName: 'head',
|
||||
attributes: {},
|
||||
childNodes: [
|
||||
{ type: 3, textContent: '\n ', rootId: 62, id: 66 },
|
||||
{
|
||||
type: 2,
|
||||
tagName: 'meta',
|
||||
attributes: { charset: 'UTF-8' },
|
||||
childNodes: [],
|
||||
rootId: 62,
|
||||
id: 67,
|
||||
},
|
||||
{ type: 3, textContent: '\n ', rootId: 62, id: 68 },
|
||||
{
|
||||
type: 2,
|
||||
tagName: 'meta',
|
||||
attributes: {
|
||||
name: 'viewport',
|
||||
content: 'width=device-width, initial-scale=1.0',
|
||||
},
|
||||
childNodes: [],
|
||||
rootId: 62,
|
||||
id: 69,
|
||||
},
|
||||
{ type: 3, textContent: '\n ', rootId: 62, id: 70 },
|
||||
{
|
||||
type: 2,
|
||||
tagName: 'title',
|
||||
attributes: {},
|
||||
childNodes: [
|
||||
{
|
||||
type: 3,
|
||||
textContent: 'iframe 4',
|
||||
rootId: 62,
|
||||
id: 72,
|
||||
},
|
||||
],
|
||||
rootId: 62,
|
||||
id: 71,
|
||||
},
|
||||
{ type: 3, textContent: '\n ', rootId: 62, id: 73 },
|
||||
],
|
||||
rootId: 62,
|
||||
id: 65,
|
||||
},
|
||||
{ type: 3, textContent: '\n ', rootId: 62, id: 74 },
|
||||
{
|
||||
type: 2,
|
||||
tagName: 'body',
|
||||
attributes: {},
|
||||
childNodes: [
|
||||
{
|
||||
type: 3,
|
||||
textContent: '\n iframe 4\n \n ',
|
||||
rootId: 62,
|
||||
id: 76,
|
||||
},
|
||||
{
|
||||
type: 2,
|
||||
tagName: 'script',
|
||||
attributes: {},
|
||||
childNodes: [
|
||||
{
|
||||
type: 3,
|
||||
textContent: 'SCRIPT_PLACEHOLDER',
|
||||
rootId: 62,
|
||||
id: 78,
|
||||
},
|
||||
],
|
||||
rootId: 62,
|
||||
id: 77,
|
||||
},
|
||||
{ type: 3, textContent: '\n\n', rootId: 62, id: 79 },
|
||||
],
|
||||
rootId: 62,
|
||||
id: 75,
|
||||
},
|
||||
],
|
||||
rootId: 62,
|
||||
id: 64,
|
||||
},
|
||||
],
|
||||
id: 62,
|
||||
},
|
||||
},
|
||||
],
|
||||
removes: [],
|
||||
texts: [],
|
||||
attributes: [],
|
||||
isAttachIframe: true,
|
||||
},
|
||||
timestamp: now + 1500,
|
||||
},
|
||||
// add iframe five
|
||||
{
|
||||
type: EventType.IncrementalSnapshot,
|
||||
data: {
|
||||
source: IncrementalSource.Mutation,
|
||||
adds: [
|
||||
{
|
||||
parentId: 80,
|
||||
nextId: null,
|
||||
node: {
|
||||
type: 0,
|
||||
childNodes: [
|
||||
{
|
||||
type: 2,
|
||||
tagName: 'html',
|
||||
attributes: {},
|
||||
childNodes: [
|
||||
{
|
||||
type: 2,
|
||||
tagName: 'head',
|
||||
attributes: {},
|
||||
childNodes: [],
|
||||
rootId: 81,
|
||||
id: 83,
|
||||
},
|
||||
{
|
||||
type: 2,
|
||||
tagName: 'body',
|
||||
attributes: {},
|
||||
childNodes: [
|
||||
{
|
||||
type: 2,
|
||||
tagName: 'script',
|
||||
attributes: {},
|
||||
childNodes: [
|
||||
{
|
||||
type: 3,
|
||||
textContent: 'SCRIPT_PLACEHOLDER',
|
||||
rootId: 81,
|
||||
id: 86,
|
||||
},
|
||||
],
|
||||
rootId: 81,
|
||||
id: 85,
|
||||
},
|
||||
],
|
||||
rootId: 81,
|
||||
id: 84,
|
||||
},
|
||||
],
|
||||
rootId: 81,
|
||||
id: 82,
|
||||
},
|
||||
],
|
||||
id: 81,
|
||||
},
|
||||
},
|
||||
],
|
||||
removes: [],
|
||||
texts: [],
|
||||
attributes: [],
|
||||
isAttachIframe: true,
|
||||
},
|
||||
timestamp: now + 2000,
|
||||
},
|
||||
{
|
||||
type: EventType.IncrementalSnapshot,
|
||||
data: {
|
||||
source: IncrementalSource.Mutation,
|
||||
texts: [],
|
||||
attributes: [],
|
||||
removes: [],
|
||||
adds: [
|
||||
{
|
||||
parentId: 75,
|
||||
nextId: null,
|
||||
node: {
|
||||
type: 2,
|
||||
tagName: 'iframe',
|
||||
attributes: { id: 'five' },
|
||||
childNodes: [],
|
||||
rootId: 62,
|
||||
id: 80,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
timestamp: now + 2000,
|
||||
},
|
||||
// remove the html element of iframe four
|
||||
{
|
||||
type: EventType.IncrementalSnapshot,
|
||||
data: {
|
||||
source: IncrementalSource.Mutation,
|
||||
texts: [],
|
||||
attributes: [],
|
||||
removes: [{ parentId: 62, id: 64 }],
|
||||
adds: [],
|
||||
},
|
||||
timestamp: now + 2500,
|
||||
},
|
||||
];
|
||||
|
||||
export default events;
|
||||
@@ -11,6 +11,7 @@ import {
|
||||
} from './utils';
|
||||
import styleSheetRuleEvents from './events/style-sheet-rule-events';
|
||||
import orderingEvents from './events/ordering';
|
||||
import iframeEvents from './events/iframe';
|
||||
|
||||
interface ISuite {
|
||||
code: string;
|
||||
@@ -222,6 +223,115 @@ describe('replayer', function () {
|
||||
expect(result).toEqual(false);
|
||||
});
|
||||
|
||||
it('can fast-forward mutation events containing nested iframe elements', async () => {
|
||||
await page.evaluate(`
|
||||
events = ${JSON.stringify(iframeEvents)};
|
||||
const { Replayer } = rrweb;
|
||||
var replayer = new Replayer(events,{showDebug:true});
|
||||
replayer.pause(250);
|
||||
`);
|
||||
const iframe = await page.$('iframe');
|
||||
const contentDocument = await iframe!.contentFrame()!;
|
||||
expect(await contentDocument!.$('iframe')).toBeNull();
|
||||
|
||||
const delay = 50;
|
||||
// restart the replayer
|
||||
await page.evaluate('replayer.play(0);');
|
||||
await page.waitForTimeout(delay);
|
||||
await page.evaluate('replayer.pause(550);'); // add 'iframe one' at 500
|
||||
expect(await contentDocument!.$('iframe')).not.toBeNull();
|
||||
const iframeOneDocument = await (await contentDocument!.$(
|
||||
'iframe',
|
||||
))!.contentFrame();
|
||||
expect(iframeOneDocument).not.toBeNull();
|
||||
expect(await iframeOneDocument!.$('noscript')).not.toBeNull();
|
||||
// make sure custom style rules are inserted rules
|
||||
expect((await iframeOneDocument!.$$('style')).length).toBe(1);
|
||||
expect(
|
||||
await iframeOneDocument!.$eval(
|
||||
'noscript',
|
||||
(element) => window.getComputedStyle(element).display,
|
||||
),
|
||||
).toEqual('none');
|
||||
|
||||
// add 'iframe two' and 'iframe three' at 1000
|
||||
await page.evaluate('replayer.play(0);');
|
||||
await page.waitForTimeout(delay);
|
||||
await page.evaluate('replayer.pause(1050);');
|
||||
expect((await contentDocument!.$$('iframe')).length).toEqual(2);
|
||||
let iframeTwoDocument = await (
|
||||
await contentDocument!.$$('iframe')
|
||||
)[1]!.contentFrame();
|
||||
expect(iframeTwoDocument).not.toBeNull();
|
||||
expect((await iframeTwoDocument!.$$('iframe')).length).toEqual(2);
|
||||
let iframeThreeDocument = await (
|
||||
await iframeTwoDocument!.$$('iframe')
|
||||
)[0]!.contentFrame();
|
||||
let iframeFourDocument = await (
|
||||
await iframeTwoDocument!.$$('iframe')
|
||||
)[1]!.contentFrame();
|
||||
expect(iframeThreeDocument).not.toBeNull();
|
||||
expect(iframeFourDocument).not.toBeNull();
|
||||
|
||||
// add 'iframe four' at 1500
|
||||
await page.evaluate('replayer.play(0);');
|
||||
await page.waitForTimeout(delay);
|
||||
await page.evaluate('replayer.pause(1550);');
|
||||
iframeTwoDocument = await (
|
||||
await contentDocument!.$$('iframe')
|
||||
)[1]!.contentFrame();
|
||||
iframeFourDocument = await (
|
||||
await iframeTwoDocument!.$$('iframe')
|
||||
)[1]!.contentFrame();
|
||||
expect(await iframeFourDocument!.$('iframe')).toBeNull();
|
||||
expect(await iframeFourDocument!.$('style')).not.toBeNull();
|
||||
expect(await iframeFourDocument!.title()).toEqual('iframe 4');
|
||||
|
||||
// add 'iframe five' at 2000
|
||||
await page.evaluate('replayer.play(0);');
|
||||
await page.waitForTimeout(delay);
|
||||
await page.evaluate('replayer.pause(2050);');
|
||||
iframeTwoDocument = await (
|
||||
await contentDocument!.$$('iframe')
|
||||
)[1]!.contentFrame();
|
||||
iframeFourDocument = await (
|
||||
await iframeTwoDocument!.$$('iframe')
|
||||
)[1]!.contentFrame();
|
||||
expect(await iframeFourDocument!.$('iframe')).not.toBeNull();
|
||||
const iframeFiveDocument = await (await iframeFourDocument!.$(
|
||||
'iframe',
|
||||
))!.contentFrame();
|
||||
expect(iframeFiveDocument).not.toBeNull();
|
||||
expect((await iframeFiveDocument!.$$('style')).length).toBe(1);
|
||||
expect(await iframeFiveDocument!.$('noscript')).not.toBeNull();
|
||||
expect(
|
||||
await iframeFiveDocument!.$eval(
|
||||
'noscript',
|
||||
(element) => window.getComputedStyle(element).display,
|
||||
),
|
||||
).toEqual('none');
|
||||
|
||||
// remove the html element of 'iframe four' at 2500
|
||||
await page.evaluate('replayer.play(0);');
|
||||
await page.waitForTimeout(delay);
|
||||
await page.evaluate('replayer.pause(2550);');
|
||||
iframeTwoDocument = await (
|
||||
await contentDocument!.$$('iframe')
|
||||
)[1]!.contentFrame();
|
||||
iframeFourDocument = await (
|
||||
await iframeTwoDocument!.$$('iframe')
|
||||
)[1]!.contentFrame();
|
||||
// the html element should be removed
|
||||
expect(await iframeFourDocument!.$('html')).toBeNull();
|
||||
// the doctype should still exist
|
||||
expect(
|
||||
await iframeTwoDocument!.evaluate(
|
||||
(iframe) => (iframe as HTMLIFrameElement)!.contentDocument!.doctype,
|
||||
(await iframeTwoDocument!.$$('iframe'))[1],
|
||||
),
|
||||
).not.toBeNull();
|
||||
});
|
||||
|
||||
it('can stream events in live mode', async () => {
|
||||
const status = await page.evaluate(`
|
||||
const { Replayer } = rrweb;
|
||||
|
||||
1
packages/rrweb/typings/types.d.ts
vendored
1
packages/rrweb/typings/types.d.ts
vendored
@@ -1,3 +1,4 @@
|
||||
/// <reference types="css-font-loading-module" />
|
||||
import { serializedNodeWithId, idNodeMap, INode, MaskInputOptions, SlimDOMOptions, MaskInputFn, MaskTextFn } from 'rrweb-snapshot';
|
||||
import { PackFn, UnpackFn } from './packer/base';
|
||||
import { IframeManager } from './record/iframe-manager';
|
||||
|
||||
Reference in New Issue
Block a user