diff --git a/package.json b/package.json index 9775ce78..c7846fa8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "rrweb", - "version": "0.4.1", + "version": "0.4.2", "description": "record and replay the web", "main": "dist/index.js", "module": "dist/module.js", @@ -15,6 +15,11 @@ "keywords": [ "rrweb" ], + "files": [ + "dist", + "index.d.ts", + "src/types.ts" + ], "author": "yanzhen@smartx.com", "license": "MIT", "bugs": { @@ -26,10 +31,12 @@ "@types/mocha": "^5.2.5", "@types/node": "^10.11.7", "@types/puppeteer": "^1.9.0", + "@types/rewire": "^2.5.28", "chai": "^4.2.0", "jest-snapshot": "^23.6.0", "mocha": "^5.2.0", "puppeteer": "^1.9.0", + "rewire": "^4.0.1", "rollup": "^0.66.6", "rollup-plugin-node-resolve": "^3.4.0", "rollup-plugin-typescript": "^1.0.0", diff --git a/src/record/observer.ts b/src/record/observer.ts index 6b3186e9..3e9ad9a8 100644 --- a/src/record/observer.ts +++ b/src/record/observer.ts @@ -47,7 +47,7 @@ function initMutationObserver(cb: mutationCallBack): MutationObserver { const observer = new MutationObserver(mutations => { const texts: textCursor[] = []; const attributes: attributeCursor[] = []; - const removes: removedNodeMutation[] = []; + let removes: removedNodeMutation[] = []; const adds: addedNodeMutation[] = []; const dropped: Node[] = []; @@ -123,8 +123,21 @@ function initMutationObserver(cb: mutationCallBack): MutationObserver { } }); + removes = removes.map(remove => { + if (remove.parentNode) { + remove.parentId = mirror.getId(remove.parentNode as INode); + delete remove.parentNode; + } + return remove; + }); + Array.from(addsSet).forEach(n => { - if (n.parentNode && dropped.indexOf(n.parentNode) < 0) { + const parentId = mirror.getId(n.parentNode as INode); + if ( + parentId && + !dropped.some(d => d === n.parentNode) && + !removes.some(r => r.id === parentId) + ) { adds.push({ parentId: mirror.getId(n.parentNode as INode), previousId: !n.previousSibling @@ -149,13 +162,7 @@ function initMutationObserver(cb: mutationCallBack): MutationObserver { id: mirror.getId(attribute.node as INode), attributes: attribute.attributes, })), - removes: removes.map(remove => { - if (remove.parentNode) { - remove.parentId = mirror.getId(remove.parentNode as INode); - delete remove.parentNode; - } - return remove; - }), + removes, adds, }); }); diff --git a/test/__snapshots__/integration.ts.snap b/test/__snapshots__/integration.ts.snap index 25e1e926..4cde8b9f 100644 --- a/test/__snapshots__/integration.ts.snap +++ b/test/__snapshots__/integration.ts.snap @@ -1,3 +1,884 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`form 1`] = `"[{\\"type\\":0,\\"data\\":{\\"href\\":\\"about:blank\\"},\\"timestamp\\":1542268800000},{\\"type\\":1,\\"data\\":{\\"width\\":800,\\"height\\":600},\\"timestamp\\":1542268800000},{\\"type\\":2,\\"data\\":{\\"node\\":{\\"type\\":0,\\"childNodes\\":[{\\"type\\":1,\\"name\\":\\"html\\",\\"publicId\\":\\"\\",\\"systemId\\":\\"\\",\\"id\\":2},{\\"type\\":2,\\"tagName\\":\\"html\\",\\"attributes\\":{\\"lang\\":\\"en\\"},\\"childNodes\\":[{\\"type\\":2,\\"tagName\\":\\"head\\",\\"attributes\\":{},\\"childNodes\\":[{\\"type\\":3,\\"textContent\\":\\"\\\\n \\",\\"id\\":5},{\\"type\\":2,\\"tagName\\":\\"meta\\",\\"attributes\\":{\\"charset\\":\\"UTF-8\\"},\\"childNodes\\":[],\\"id\\":6},{\\"type\\":3,\\"textContent\\":\\"\\\\n \\",\\"id\\":7},{\\"type\\":2,\\"tagName\\":\\"meta\\",\\"attributes\\":{\\"name\\":\\"viewport\\",\\"content\\":\\"width=device-width, initial-scale=1.0\\"},\\"childNodes\\":[],\\"id\\":8},{\\"type\\":3,\\"textContent\\":\\"\\\\n \\",\\"id\\":9},{\\"type\\":2,\\"tagName\\":\\"meta\\",\\"attributes\\":{\\"http-equiv\\":\\"X-UA-Compatible\\",\\"content\\":\\"ie=edge\\"},\\"childNodes\\":[],\\"id\\":10},{\\"type\\":3,\\"textContent\\":\\"\\\\n \\",\\"id\\":11},{\\"type\\":2,\\"tagName\\":\\"title\\",\\"attributes\\":{},\\"childNodes\\":[{\\"type\\":3,\\"textContent\\":\\"form fields\\",\\"id\\":13}],\\"id\\":12},{\\"type\\":3,\\"textContent\\":\\"\\\\n\\",\\"id\\":14}],\\"id\\":4},{\\"type\\":3,\\"textContent\\":\\"\\\\n\\\\n\\",\\"id\\":15},{\\"type\\":2,\\"tagName\\":\\"body\\",\\"attributes\\":{},\\"childNodes\\":[{\\"type\\":3,\\"textContent\\":\\"\\\\n \\",\\"id\\":17},{\\"type\\":2,\\"tagName\\":\\"form\\",\\"attributes\\":{},\\"childNodes\\":[{\\"type\\":3,\\"textContent\\":\\"\\\\n \\",\\"id\\":19},{\\"type\\":2,\\"tagName\\":\\"label\\",\\"attributes\\":{\\"for\\":\\"text\\"},\\"childNodes\\":[{\\"type\\":3,\\"textContent\\":\\"\\\\n \\",\\"id\\":21},{\\"type\\":2,\\"tagName\\":\\"input\\",\\"attributes\\":{\\"type\\":\\"text\\"},\\"childNodes\\":[],\\"id\\":22},{\\"type\\":3,\\"textContent\\":\\"\\\\n \\",\\"id\\":23}],\\"id\\":20},{\\"type\\":3,\\"textContent\\":\\"\\\\n \\",\\"id\\":24},{\\"type\\":2,\\"tagName\\":\\"label\\",\\"attributes\\":{\\"for\\":\\"radio\\"},\\"childNodes\\":[{\\"type\\":3,\\"textContent\\":\\"\\\\n \\",\\"id\\":26},{\\"type\\":2,\\"tagName\\":\\"input\\",\\"attributes\\":{\\"type\\":\\"radio\\"},\\"childNodes\\":[],\\"id\\":27},{\\"type\\":3,\\"textContent\\":\\"\\\\n \\",\\"id\\":28}],\\"id\\":25},{\\"type\\":3,\\"textContent\\":\\"\\\\n \\",\\"id\\":29},{\\"type\\":2,\\"tagName\\":\\"label\\",\\"attributes\\":{\\"for\\":\\"checkbox\\"},\\"childNodes\\":[{\\"type\\":3,\\"textContent\\":\\"\\\\n \\",\\"id\\":31},{\\"type\\":2,\\"tagName\\":\\"input\\",\\"attributes\\":{\\"type\\":\\"checkbox\\"},\\"childNodes\\":[],\\"id\\":32},{\\"type\\":3,\\"textContent\\":\\"\\\\n \\",\\"id\\":33}],\\"id\\":30},{\\"type\\":3,\\"textContent\\":\\"\\\\n \\",\\"id\\":34},{\\"type\\":2,\\"tagName\\":\\"label\\",\\"attributes\\":{\\"for\\":\\"textarea\\"},\\"childNodes\\":[{\\"type\\":3,\\"textContent\\":\\"\\\\n \\",\\"id\\":36},{\\"type\\":2,\\"tagName\\":\\"textarea\\",\\"attributes\\":{\\"name\\":\\"\\",\\"id\\":\\"\\",\\"cols\\":\\"30\\",\\"rows\\":\\"10\\"},\\"childNodes\\":[],\\"id\\":37},{\\"type\\":3,\\"textContent\\":\\"\\\\n \\",\\"id\\":38}],\\"id\\":35},{\\"type\\":3,\\"textContent\\":\\"\\\\n \\",\\"id\\":39},{\\"type\\":2,\\"tagName\\":\\"label\\",\\"attributes\\":{\\"for\\":\\"select\\"},\\"childNodes\\":[{\\"type\\":3,\\"textContent\\":\\"\\\\n \\",\\"id\\":41},{\\"type\\":2,\\"tagName\\":\\"select\\",\\"attributes\\":{\\"name\\":\\"\\",\\"id\\":\\"\\",\\"value\\":\\"1\\"},\\"childNodes\\":[{\\"type\\":3,\\"textContent\\":\\"\\\\n \\",\\"id\\":43},{\\"type\\":2,\\"tagName\\":\\"option\\",\\"attributes\\":{\\"value\\":\\"1\\",\\"selected\\":true},\\"childNodes\\":[{\\"type\\":3,\\"textContent\\":\\"1\\",\\"id\\":45}],\\"id\\":44},{\\"type\\":3,\\"textContent\\":\\"\\\\n \\",\\"id\\":46},{\\"type\\":2,\\"tagName\\":\\"option\\",\\"attributes\\":{\\"value\\":\\"2\\"},\\"childNodes\\":[{\\"type\\":3,\\"textContent\\":\\"2\\",\\"id\\":48}],\\"id\\":47},{\\"type\\":3,\\"textContent\\":\\"\\\\n \\",\\"id\\":49}],\\"id\\":42},{\\"type\\":3,\\"textContent\\":\\"\\\\n \\",\\"id\\":50}],\\"id\\":40},{\\"type\\":3,\\"textContent\\":\\"\\\\n \\",\\"id\\":51}],\\"id\\":18},{\\"type\\":3,\\"textContent\\":\\"\\\\n\\\\n \\",\\"id\\":52},{\\"type\\":2,\\"tagName\\":\\"script\\",\\"attributes\\":{},\\"childNodes\\":[{\\"type\\":3,\\"textContent\\":\\"SCRIPT_PLACEHOLDER\\",\\"id\\":54}],\\"id\\":53},{\\"type\\":3,\\"textContent\\":\\"\\\\n \\\\n \\\\n\\\\n\\\\n\\",\\"id\\":55}],\\"id\\":16}],\\"id\\":3}],\\"id\\":1},\\"initialOffset\\":{\\"left\\":0,\\"top\\":0}},\\"timestamp\\":1542268800000},{\\"type\\":3,\\"data\\":{\\"source\\":2,\\"type\\":5,\\"id\\":22},\\"timestamp\\":1542268800000},{\\"type\\":3,\\"data\\":{\\"source\\":5,\\"text\\":\\"t\\",\\"isChecked\\":false,\\"id\\":22},\\"timestamp\\":1542268800000},{\\"type\\":3,\\"data\\":{\\"source\\":5,\\"text\\":\\"te\\",\\"isChecked\\":false,\\"id\\":22},\\"timestamp\\":1542268800000},{\\"type\\":3,\\"data\\":{\\"source\\":5,\\"text\\":\\"tes\\",\\"isChecked\\":false,\\"id\\":22},\\"timestamp\\":1542268800000},{\\"type\\":3,\\"data\\":{\\"source\\":5,\\"text\\":\\"test\\",\\"isChecked\\":false,\\"id\\":22},\\"timestamp\\":1542268800000},{\\"type\\":3,\\"data\\":{\\"source\\":1,\\"positions\\":[{\\"x\\":204,\\"y\\":117,\\"timeOffset\\":0}]},\\"timestamp\\":1542268800000},{\\"type\\":3,\\"data\\":{\\"source\\":2,\\"type\\":1,\\"id\\":27,\\"x\\":204,\\"y\\":117},\\"timestamp\\":1542268800000},{\\"type\\":3,\\"data\\":{\\"source\\":2,\\"type\\":6,\\"id\\":22},\\"timestamp\\":1542268800000},{\\"type\\":3,\\"data\\":{\\"source\\":2,\\"type\\":5,\\"id\\":27},\\"timestamp\\":1542268800000},{\\"type\\":3,\\"data\\":{\\"source\\":2,\\"type\\":0,\\"id\\":27,\\"x\\":204,\\"y\\":117},\\"timestamp\\":1542268800000},{\\"type\\":3,\\"data\\":{\\"source\\":2,\\"type\\":2,\\"id\\":27,\\"x\\":204,\\"y\\":117},\\"timestamp\\":1542268800000},{\\"type\\":3,\\"data\\":{\\"source\\":5,\\"text\\":\\"on\\",\\"isChecked\\":true,\\"id\\":27},\\"timestamp\\":1542268800000},{\\"type\\":3,\\"data\\":{\\"source\\":2,\\"type\\":1,\\"id\\":32,\\"x\\":228,\\"y\\":117},\\"timestamp\\":1542268800000},{\\"type\\":3,\\"data\\":{\\"source\\":2,\\"type\\":6,\\"id\\":27},\\"timestamp\\":1542268800000},{\\"type\\":3,\\"data\\":{\\"source\\":2,\\"type\\":5,\\"id\\":32},\\"timestamp\\":1542268800000},{\\"type\\":3,\\"data\\":{\\"source\\":2,\\"type\\":0,\\"id\\":32,\\"x\\":228,\\"y\\":117},\\"timestamp\\":1542268800000},{\\"type\\":3,\\"data\\":{\\"source\\":2,\\"type\\":2,\\"id\\":32,\\"x\\":228,\\"y\\":117},\\"timestamp\\":1542268800000},{\\"type\\":3,\\"data\\":{\\"source\\":5,\\"text\\":\\"on\\",\\"isChecked\\":true,\\"id\\":32},\\"timestamp\\":1542268800000},{\\"type\\":3,\\"data\\":{\\"source\\":2,\\"type\\":6,\\"id\\":32},\\"timestamp\\":1542268800000},{\\"type\\":3,\\"data\\":{\\"source\\":2,\\"type\\":5,\\"id\\":37},\\"timestamp\\":1542268800000},{\\"type\\":3,\\"data\\":{\\"source\\":5,\\"text\\":\\"t\\",\\"isChecked\\":false,\\"id\\":37},\\"timestamp\\":1542268800000},{\\"type\\":3,\\"data\\":{\\"source\\":5,\\"text\\":\\"te\\",\\"isChecked\\":false,\\"id\\":37},\\"timestamp\\":1542268800000},{\\"type\\":3,\\"data\\":{\\"source\\":5,\\"text\\":\\"tex\\",\\"isChecked\\":false,\\"id\\":37},\\"timestamp\\":1542268800000},{\\"type\\":3,\\"data\\":{\\"source\\":5,\\"text\\":\\"text\\",\\"isChecked\\":false,\\"id\\":37},\\"timestamp\\":1542268800000},{\\"type\\":3,\\"data\\":{\\"source\\":5,\\"text\\":\\"texta\\",\\"isChecked\\":false,\\"id\\":37},\\"timestamp\\":1542268800000},{\\"type\\":3,\\"data\\":{\\"source\\":5,\\"text\\":\\"textar\\",\\"isChecked\\":false,\\"id\\":37},\\"timestamp\\":1542268800000},{\\"type\\":3,\\"data\\":{\\"source\\":5,\\"text\\":\\"textare\\",\\"isChecked\\":false,\\"id\\":37},\\"timestamp\\":1542268800000},{\\"type\\":3,\\"data\\":{\\"source\\":5,\\"text\\":\\"textarea\\",\\"isChecked\\":false,\\"id\\":37},\\"timestamp\\":1542268800000},{\\"type\\":3,\\"data\\":{\\"source\\":5,\\"text\\":\\"textarea \\",\\"isChecked\\":false,\\"id\\":37},\\"timestamp\\":1542268800000},{\\"type\\":3,\\"data\\":{\\"source\\":5,\\"text\\":\\"textarea t\\",\\"isChecked\\":false,\\"id\\":37},\\"timestamp\\":1542268800000},{\\"type\\":3,\\"data\\":{\\"source\\":5,\\"text\\":\\"textarea te\\",\\"isChecked\\":false,\\"id\\":37},\\"timestamp\\":1542268800000},{\\"type\\":3,\\"data\\":{\\"source\\":5,\\"text\\":\\"textarea tes\\",\\"isChecked\\":false,\\"id\\":37},\\"timestamp\\":1542268800000},{\\"type\\":3,\\"data\\":{\\"source\\":5,\\"text\\":\\"textarea test\\",\\"isChecked\\":false,\\"id\\":37},\\"timestamp\\":1542268800000},{\\"type\\":3,\\"data\\":{\\"source\\":5,\\"text\\":\\"1\\",\\"isChecked\\":false,\\"id\\":42},\\"timestamp\\":1542268800000}]"`; +exports[`child-list 1`] = ` +"[ + { + \\"type\\": 0, + \\"data\\": {}, + \\"timestamp\\": 1542268800000 + }, + { + \\"type\\": 1, + \\"data\\": {}, + \\"timestamp\\": 1542268800000 + }, + { + \\"type\\": 4, + \\"data\\": { + \\"href\\": \\"about:blank\\", + \\"width\\": 800, + \\"height\\": 600 + }, + \\"timestamp\\": 1542268800000 + }, + { + \\"type\\": 2, + \\"data\\": { + \\"node\\": { + \\"type\\": 0, + \\"childNodes\\": [ + { + \\"type\\": 2, + \\"tagName\\": \\"html\\", + \\"attributes\\": {}, + \\"childNodes\\": [ + { + \\"type\\": 2, + \\"tagName\\": \\"head\\", + \\"attributes\\": {}, + \\"childNodes\\": [], + \\"id\\": 3 + }, + { + \\"type\\": 2, + \\"tagName\\": \\"body\\", + \\"attributes\\": {}, + \\"childNodes\\": [ + { + \\"type\\": 3, + \\"textContent\\": \\"\\\\n \\", + \\"id\\": 5 + }, + { + \\"type\\": 2, + \\"tagName\\": \\"ul\\", + \\"attributes\\": {}, + \\"childNodes\\": [ + { + \\"type\\": 3, + \\"textContent\\": \\"\\\\n \\", + \\"id\\": 7 + }, + { + \\"type\\": 2, + \\"tagName\\": \\"li\\", + \\"attributes\\": {}, + \\"childNodes\\": [], + \\"id\\": 8 + }, + { + \\"type\\": 3, + \\"textContent\\": \\"\\\\n \\", + \\"id\\": 9 + } + ], + \\"id\\": 6 + }, + { + \\"type\\": 3, + \\"textContent\\": \\"\\\\n\\\\n \\", + \\"id\\": 10 + }, + { + \\"type\\": 2, + \\"tagName\\": \\"script\\", + \\"attributes\\": {}, + \\"childNodes\\": [ + { + \\"type\\": 3, + \\"textContent\\": \\"SCRIPT_PLACEHOLDER\\", + \\"id\\": 12 + } + ], + \\"id\\": 11 + }, + { + \\"type\\": 3, + \\"textContent\\": \\"\\\\n \\\\n \\", + \\"id\\": 13 + } + ], + \\"id\\": 4 + } + ], + \\"id\\": 2 + } + ], + \\"id\\": 1 + }, + \\"initialOffset\\": { + \\"left\\": 0, + \\"top\\": 0 + } + }, + \\"timestamp\\": 1542268800000 + }, + { + \\"type\\": 3, + \\"data\\": { + \\"source\\": 0, + \\"texts\\": [], + \\"attributes\\": [], + \\"removes\\": [ + { + \\"parentId\\": 4, + \\"id\\": 6 + } + ], + \\"adds\\": [] + }, + \\"timestamp\\": 1542268800000 + } +]" +`; + +exports[`form 1`] = ` +"[ + { + \\"type\\": 0, + \\"data\\": {}, + \\"timestamp\\": 1542268800000 + }, + { + \\"type\\": 1, + \\"data\\": {}, + \\"timestamp\\": 1542268800000 + }, + { + \\"type\\": 4, + \\"data\\": { + \\"href\\": \\"about:blank\\", + \\"width\\": 800, + \\"height\\": 600 + }, + \\"timestamp\\": 1542268800000 + }, + { + \\"type\\": 2, + \\"data\\": { + \\"node\\": { + \\"type\\": 0, + \\"childNodes\\": [ + { + \\"type\\": 1, + \\"name\\": \\"html\\", + \\"publicId\\": \\"\\", + \\"systemId\\": \\"\\", + \\"id\\": 2 + }, + { + \\"type\\": 2, + \\"tagName\\": \\"html\\", + \\"attributes\\": { + \\"lang\\": \\"en\\" + }, + \\"childNodes\\": [ + { + \\"type\\": 2, + \\"tagName\\": \\"head\\", + \\"attributes\\": {}, + \\"childNodes\\": [ + { + \\"type\\": 3, + \\"textContent\\": \\"\\\\n \\", + \\"id\\": 5 + }, + { + \\"type\\": 2, + \\"tagName\\": \\"meta\\", + \\"attributes\\": { + \\"charset\\": \\"UTF-8\\" + }, + \\"childNodes\\": [], + \\"id\\": 6 + }, + { + \\"type\\": 3, + \\"textContent\\": \\"\\\\n \\", + \\"id\\": 7 + }, + { + \\"type\\": 2, + \\"tagName\\": \\"meta\\", + \\"attributes\\": { + \\"name\\": \\"viewport\\", + \\"content\\": \\"width=device-width, initial-scale=1.0\\" + }, + \\"childNodes\\": [], + \\"id\\": 8 + }, + { + \\"type\\": 3, + \\"textContent\\": \\"\\\\n \\", + \\"id\\": 9 + }, + { + \\"type\\": 2, + \\"tagName\\": \\"meta\\", + \\"attributes\\": { + \\"http-equiv\\": \\"X-UA-Compatible\\", + \\"content\\": \\"ie=edge\\" + }, + \\"childNodes\\": [], + \\"id\\": 10 + }, + { + \\"type\\": 3, + \\"textContent\\": \\"\\\\n \\", + \\"id\\": 11 + }, + { + \\"type\\": 2, + \\"tagName\\": \\"title\\", + \\"attributes\\": {}, + \\"childNodes\\": [ + { + \\"type\\": 3, + \\"textContent\\": \\"form fields\\", + \\"id\\": 13 + } + ], + \\"id\\": 12 + }, + { + \\"type\\": 3, + \\"textContent\\": \\"\\\\n\\", + \\"id\\": 14 + } + ], + \\"id\\": 4 + }, + { + \\"type\\": 3, + \\"textContent\\": \\"\\\\n\\\\n\\", + \\"id\\": 15 + }, + { + \\"type\\": 2, + \\"tagName\\": \\"body\\", + \\"attributes\\": {}, + \\"childNodes\\": [ + { + \\"type\\": 3, + \\"textContent\\": \\"\\\\n \\", + \\"id\\": 17 + }, + { + \\"type\\": 2, + \\"tagName\\": \\"form\\", + \\"attributes\\": {}, + \\"childNodes\\": [ + { + \\"type\\": 3, + \\"textContent\\": \\"\\\\n \\", + \\"id\\": 19 + }, + { + \\"type\\": 2, + \\"tagName\\": \\"label\\", + \\"attributes\\": { + \\"for\\": \\"text\\" + }, + \\"childNodes\\": [ + { + \\"type\\": 3, + \\"textContent\\": \\"\\\\n \\", + \\"id\\": 21 + }, + { + \\"type\\": 2, + \\"tagName\\": \\"input\\", + \\"attributes\\": { + \\"type\\": \\"text\\" + }, + \\"childNodes\\": [], + \\"id\\": 22 + }, + { + \\"type\\": 3, + \\"textContent\\": \\"\\\\n \\", + \\"id\\": 23 + } + ], + \\"id\\": 20 + }, + { + \\"type\\": 3, + \\"textContent\\": \\"\\\\n \\", + \\"id\\": 24 + }, + { + \\"type\\": 2, + \\"tagName\\": \\"label\\", + \\"attributes\\": { + \\"for\\": \\"radio\\" + }, + \\"childNodes\\": [ + { + \\"type\\": 3, + \\"textContent\\": \\"\\\\n \\", + \\"id\\": 26 + }, + { + \\"type\\": 2, + \\"tagName\\": \\"input\\", + \\"attributes\\": { + \\"type\\": \\"radio\\" + }, + \\"childNodes\\": [], + \\"id\\": 27 + }, + { + \\"type\\": 3, + \\"textContent\\": \\"\\\\n \\", + \\"id\\": 28 + } + ], + \\"id\\": 25 + }, + { + \\"type\\": 3, + \\"textContent\\": \\"\\\\n \\", + \\"id\\": 29 + }, + { + \\"type\\": 2, + \\"tagName\\": \\"label\\", + \\"attributes\\": { + \\"for\\": \\"checkbox\\" + }, + \\"childNodes\\": [ + { + \\"type\\": 3, + \\"textContent\\": \\"\\\\n \\", + \\"id\\": 31 + }, + { + \\"type\\": 2, + \\"tagName\\": \\"input\\", + \\"attributes\\": { + \\"type\\": \\"checkbox\\" + }, + \\"childNodes\\": [], + \\"id\\": 32 + }, + { + \\"type\\": 3, + \\"textContent\\": \\"\\\\n \\", + \\"id\\": 33 + } + ], + \\"id\\": 30 + }, + { + \\"type\\": 3, + \\"textContent\\": \\"\\\\n \\", + \\"id\\": 34 + }, + { + \\"type\\": 2, + \\"tagName\\": \\"label\\", + \\"attributes\\": { + \\"for\\": \\"textarea\\" + }, + \\"childNodes\\": [ + { + \\"type\\": 3, + \\"textContent\\": \\"\\\\n \\", + \\"id\\": 36 + }, + { + \\"type\\": 2, + \\"tagName\\": \\"textarea\\", + \\"attributes\\": { + \\"name\\": \\"\\", + \\"id\\": \\"\\", + \\"cols\\": \\"30\\", + \\"rows\\": \\"10\\" + }, + \\"childNodes\\": [], + \\"id\\": 37 + }, + { + \\"type\\": 3, + \\"textContent\\": \\"\\\\n \\", + \\"id\\": 38 + } + ], + \\"id\\": 35 + }, + { + \\"type\\": 3, + \\"textContent\\": \\"\\\\n \\", + \\"id\\": 39 + }, + { + \\"type\\": 2, + \\"tagName\\": \\"label\\", + \\"attributes\\": { + \\"for\\": \\"select\\" + }, + \\"childNodes\\": [ + { + \\"type\\": 3, + \\"textContent\\": \\"\\\\n \\", + \\"id\\": 41 + }, + { + \\"type\\": 2, + \\"tagName\\": \\"select\\", + \\"attributes\\": { + \\"name\\": \\"\\", + \\"id\\": \\"\\", + \\"value\\": \\"1\\" + }, + \\"childNodes\\": [ + { + \\"type\\": 3, + \\"textContent\\": \\"\\\\n \\", + \\"id\\": 43 + }, + { + \\"type\\": 2, + \\"tagName\\": \\"option\\", + \\"attributes\\": { + \\"value\\": \\"1\\", + \\"selected\\": true + }, + \\"childNodes\\": [ + { + \\"type\\": 3, + \\"textContent\\": \\"1\\", + \\"id\\": 45 + } + ], + \\"id\\": 44 + }, + { + \\"type\\": 3, + \\"textContent\\": \\"\\\\n \\", + \\"id\\": 46 + }, + { + \\"type\\": 2, + \\"tagName\\": \\"option\\", + \\"attributes\\": { + \\"value\\": \\"2\\" + }, + \\"childNodes\\": [ + { + \\"type\\": 3, + \\"textContent\\": \\"2\\", + \\"id\\": 48 + } + ], + \\"id\\": 47 + }, + { + \\"type\\": 3, + \\"textContent\\": \\"\\\\n \\", + \\"id\\": 49 + } + ], + \\"id\\": 42 + }, + { + \\"type\\": 3, + \\"textContent\\": \\"\\\\n \\", + \\"id\\": 50 + } + ], + \\"id\\": 40 + }, + { + \\"type\\": 3, + \\"textContent\\": \\"\\\\n \\", + \\"id\\": 51 + } + ], + \\"id\\": 18 + }, + { + \\"type\\": 3, + \\"textContent\\": \\"\\\\n\\\\n \\", + \\"id\\": 52 + }, + { + \\"type\\": 2, + \\"tagName\\": \\"script\\", + \\"attributes\\": {}, + \\"childNodes\\": [ + { + \\"type\\": 3, + \\"textContent\\": \\"SCRIPT_PLACEHOLDER\\", + \\"id\\": 54 + } + ], + \\"id\\": 53 + }, + { + \\"type\\": 3, + \\"textContent\\": \\"\\\\n \\\\n \\\\n\\\\n\\\\n\\", + \\"id\\": 55 + } + ], + \\"id\\": 16 + } + ], + \\"id\\": 3 + } + ], + \\"id\\": 1 + }, + \\"initialOffset\\": { + \\"left\\": 0, + \\"top\\": 0 + } + }, + \\"timestamp\\": 1542268800000 + }, + { + \\"type\\": 3, + \\"data\\": { + \\"source\\": 2, + \\"type\\": 5, + \\"id\\": 22 + }, + \\"timestamp\\": 1542268800000 + }, + { + \\"type\\": 3, + \\"data\\": { + \\"source\\": 5, + \\"text\\": \\"t\\", + \\"isChecked\\": false, + \\"id\\": 22 + }, + \\"timestamp\\": 1542268800000 + }, + { + \\"type\\": 3, + \\"data\\": { + \\"source\\": 5, + \\"text\\": \\"te\\", + \\"isChecked\\": false, + \\"id\\": 22 + }, + \\"timestamp\\": 1542268800000 + }, + { + \\"type\\": 3, + \\"data\\": { + \\"source\\": 5, + \\"text\\": \\"tes\\", + \\"isChecked\\": false, + \\"id\\": 22 + }, + \\"timestamp\\": 1542268800000 + }, + { + \\"type\\": 3, + \\"data\\": { + \\"source\\": 5, + \\"text\\": \\"test\\", + \\"isChecked\\": false, + \\"id\\": 22 + }, + \\"timestamp\\": 1542268800000 + }, + { + \\"type\\": 3, + \\"data\\": { + \\"source\\": 1, + \\"positions\\": [ + { + \\"x\\": 204, + \\"y\\": 117, + \\"timeOffset\\": 0 + } + ] + }, + \\"timestamp\\": 1542268800000 + }, + { + \\"type\\": 3, + \\"data\\": { + \\"source\\": 2, + \\"type\\": 1, + \\"id\\": 27, + \\"x\\": 204, + \\"y\\": 117 + }, + \\"timestamp\\": 1542268800000 + }, + { + \\"type\\": 3, + \\"data\\": { + \\"source\\": 2, + \\"type\\": 6, + \\"id\\": 22 + }, + \\"timestamp\\": 1542268800000 + }, + { + \\"type\\": 3, + \\"data\\": { + \\"source\\": 2, + \\"type\\": 5, + \\"id\\": 27 + }, + \\"timestamp\\": 1542268800000 + }, + { + \\"type\\": 3, + \\"data\\": { + \\"source\\": 2, + \\"type\\": 0, + \\"id\\": 27, + \\"x\\": 204, + \\"y\\": 117 + }, + \\"timestamp\\": 1542268800000 + }, + { + \\"type\\": 3, + \\"data\\": { + \\"source\\": 2, + \\"type\\": 2, + \\"id\\": 27, + \\"x\\": 204, + \\"y\\": 117 + }, + \\"timestamp\\": 1542268800000 + }, + { + \\"type\\": 3, + \\"data\\": { + \\"source\\": 5, + \\"text\\": \\"on\\", + \\"isChecked\\": true, + \\"id\\": 27 + }, + \\"timestamp\\": 1542268800000 + }, + { + \\"type\\": 3, + \\"data\\": { + \\"source\\": 2, + \\"type\\": 1, + \\"id\\": 32, + \\"x\\": 228, + \\"y\\": 117 + }, + \\"timestamp\\": 1542268800000 + }, + { + \\"type\\": 3, + \\"data\\": { + \\"source\\": 2, + \\"type\\": 6, + \\"id\\": 27 + }, + \\"timestamp\\": 1542268800000 + }, + { + \\"type\\": 3, + \\"data\\": { + \\"source\\": 2, + \\"type\\": 5, + \\"id\\": 32 + }, + \\"timestamp\\": 1542268800000 + }, + { + \\"type\\": 3, + \\"data\\": { + \\"source\\": 2, + \\"type\\": 0, + \\"id\\": 32, + \\"x\\": 228, + \\"y\\": 117 + }, + \\"timestamp\\": 1542268800000 + }, + { + \\"type\\": 3, + \\"data\\": { + \\"source\\": 2, + \\"type\\": 2, + \\"id\\": 32, + \\"x\\": 228, + \\"y\\": 117 + }, + \\"timestamp\\": 1542268800000 + }, + { + \\"type\\": 3, + \\"data\\": { + \\"source\\": 5, + \\"text\\": \\"on\\", + \\"isChecked\\": true, + \\"id\\": 32 + }, + \\"timestamp\\": 1542268800000 + }, + { + \\"type\\": 3, + \\"data\\": { + \\"source\\": 2, + \\"type\\": 6, + \\"id\\": 32 + }, + \\"timestamp\\": 1542268800000 + }, + { + \\"type\\": 3, + \\"data\\": { + \\"source\\": 2, + \\"type\\": 5, + \\"id\\": 37 + }, + \\"timestamp\\": 1542268800000 + }, + { + \\"type\\": 3, + \\"data\\": { + \\"source\\": 5, + \\"text\\": \\"t\\", + \\"isChecked\\": false, + \\"id\\": 37 + }, + \\"timestamp\\": 1542268800000 + }, + { + \\"type\\": 3, + \\"data\\": { + \\"source\\": 5, + \\"text\\": \\"te\\", + \\"isChecked\\": false, + \\"id\\": 37 + }, + \\"timestamp\\": 1542268800000 + }, + { + \\"type\\": 3, + \\"data\\": { + \\"source\\": 5, + \\"text\\": \\"tex\\", + \\"isChecked\\": false, + \\"id\\": 37 + }, + \\"timestamp\\": 1542268800000 + }, + { + \\"type\\": 3, + \\"data\\": { + \\"source\\": 5, + \\"text\\": \\"text\\", + \\"isChecked\\": false, + \\"id\\": 37 + }, + \\"timestamp\\": 1542268800000 + }, + { + \\"type\\": 3, + \\"data\\": { + \\"source\\": 5, + \\"text\\": \\"texta\\", + \\"isChecked\\": false, + \\"id\\": 37 + }, + \\"timestamp\\": 1542268800000 + }, + { + \\"type\\": 3, + \\"data\\": { + \\"source\\": 5, + \\"text\\": \\"textar\\", + \\"isChecked\\": false, + \\"id\\": 37 + }, + \\"timestamp\\": 1542268800000 + }, + { + \\"type\\": 3, + \\"data\\": { + \\"source\\": 5, + \\"text\\": \\"textare\\", + \\"isChecked\\": false, + \\"id\\": 37 + }, + \\"timestamp\\": 1542268800000 + }, + { + \\"type\\": 3, + \\"data\\": { + \\"source\\": 5, + \\"text\\": \\"textarea\\", + \\"isChecked\\": false, + \\"id\\": 37 + }, + \\"timestamp\\": 1542268800000 + }, + { + \\"type\\": 3, + \\"data\\": { + \\"source\\": 5, + \\"text\\": \\"textarea \\", + \\"isChecked\\": false, + \\"id\\": 37 + }, + \\"timestamp\\": 1542268800000 + }, + { + \\"type\\": 3, + \\"data\\": { + \\"source\\": 5, + \\"text\\": \\"textarea t\\", + \\"isChecked\\": false, + \\"id\\": 37 + }, + \\"timestamp\\": 1542268800000 + }, + { + \\"type\\": 3, + \\"data\\": { + \\"source\\": 5, + \\"text\\": \\"textarea te\\", + \\"isChecked\\": false, + \\"id\\": 37 + }, + \\"timestamp\\": 1542268800000 + }, + { + \\"type\\": 3, + \\"data\\": { + \\"source\\": 5, + \\"text\\": \\"textarea tes\\", + \\"isChecked\\": false, + \\"id\\": 37 + }, + \\"timestamp\\": 1542268800000 + }, + { + \\"type\\": 3, + \\"data\\": { + \\"source\\": 5, + \\"text\\": \\"textarea test\\", + \\"isChecked\\": false, + \\"id\\": 37 + }, + \\"timestamp\\": 1542268800000 + }, + { + \\"type\\": 3, + \\"data\\": { + \\"source\\": 5, + \\"text\\": \\"1\\", + \\"isChecked\\": false, + \\"id\\": 42 + }, + \\"timestamp\\": 1542268800000 + } +]" +`; diff --git a/test/html/child-list.html b/test/html/child-list.html new file mode 100644 index 00000000..45dee83a --- /dev/null +++ b/test/html/child-list.html @@ -0,0 +1,5 @@ + + + \ No newline at end of file diff --git a/test/integration.ts b/test/integration.ts index ed799b39..9c65f69c 100644 --- a/test/integration.ts +++ b/test/integration.ts @@ -77,7 +77,32 @@ describe('record integration tests', () => { await page.select('select', '1'); const snapshots = await page.evaluate('window.snapshots'); - const result = matchSnapshot(JSON.stringify(snapshots), __filename, 'form'); + const result = matchSnapshot( + JSON.stringify(snapshots, null, 2), + __filename, + 'form', + ); + assert(result.pass, result.pass ? '' : result.report()); + }).timeout(5000); + + it('can record childList mutations', async () => { + const page: puppeteer.Page = await this.browser.newPage(); + await page.goto('about:blank'); + await page.setContent(getHtml.call(this, 'child-list.html')); + + await page.evaluate(() => { + const li = document.createElement('li'); + const ul = document.querySelector('ul') as HTMLUListElement; + ul.appendChild(li); + document.body.removeChild(ul); + }); + + const snapshots = await page.evaluate('window.snapshots'); + const result = matchSnapshot( + JSON.stringify(snapshots, null, 2), + __filename, + 'child-list', + ); assert(result.pass, result.pass ? '' : result.report()); }).timeout(5000); });