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(
|
this.newDocumentQueue = this.newDocumentQueue.filter(
|
||||||
(m) => m !== mutationInQueue,
|
(m) => m !== mutationInQueue,
|
||||||
);
|
);
|
||||||
if (builtNode.contentDocument) {
|
|
||||||
const { documentElement, head } = builtNode.contentDocument;
|
|
||||||
this.insertStyleRules(documentElement, head);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
const { documentElement, head } = this.iframe.contentDocument;
|
const { documentElement, head } = this.iframe.contentDocument;
|
||||||
this.insertStyleRules(documentElement, head);
|
this.insertStyleRules(documentElement, head);
|
||||||
@@ -726,6 +722,13 @@ export class Replayer {
|
|||||||
skipChild: false,
|
skipChild: false,
|
||||||
afterAppend: (builtNode) => {
|
afterAppend: (builtNode) => {
|
||||||
this.collectIframeAndAttachDocument(collected, 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,
|
cache: this.cache,
|
||||||
});
|
});
|
||||||
@@ -734,10 +737,6 @@ export class Replayer {
|
|||||||
this.newDocumentQueue = this.newDocumentQueue.filter(
|
this.newDocumentQueue = this.newDocumentQueue.filter(
|
||||||
(m) => m !== mutationInQueue,
|
(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,
|
(m) => m !== mutationInQueue,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (target.contentDocument) {
|
|
||||||
const { documentElement, head } = target.contentDocument;
|
|
||||||
this.insertStyleRules(documentElement, head);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mutation.previousId || mutation.nextId) {
|
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';
|
} from './utils';
|
||||||
import styleSheetRuleEvents from './events/style-sheet-rule-events';
|
import styleSheetRuleEvents from './events/style-sheet-rule-events';
|
||||||
import orderingEvents from './events/ordering';
|
import orderingEvents from './events/ordering';
|
||||||
|
import iframeEvents from './events/iframe';
|
||||||
|
|
||||||
interface ISuite {
|
interface ISuite {
|
||||||
code: string;
|
code: string;
|
||||||
@@ -222,6 +223,115 @@ describe('replayer', function () {
|
|||||||
expect(result).toEqual(false);
|
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 () => {
|
it('can stream events in live mode', async () => {
|
||||||
const status = await page.evaluate(`
|
const status = await page.evaluate(`
|
||||||
const { Replayer } = rrweb;
|
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 { serializedNodeWithId, idNodeMap, INode, MaskInputOptions, SlimDOMOptions, MaskInputFn, MaskTextFn } from 'rrweb-snapshot';
|
||||||
import { PackFn, UnpackFn } from './packer/base';
|
import { PackFn, UnpackFn } from './packer/base';
|
||||||
import { IframeManager } from './record/iframe-manager';
|
import { IframeManager } from './record/iframe-manager';
|
||||||
|
|||||||
Reference in New Issue
Block a user