diff --git a/.prettierrc b/.prettierrc
index 1502887d..a20502b7 100644
--- a/.prettierrc
+++ b/.prettierrc
@@ -1,4 +1,4 @@
{
"singleQuote": true,
- "trailingComma": "es5"
-}
\ No newline at end of file
+ "trailingComma": "all"
+}
diff --git a/index.d.ts b/index.d.ts
new file mode 100644
index 00000000..f7f2dbfa
--- /dev/null
+++ b/index.d.ts
@@ -0,0 +1,4 @@
+declare module 'mocha-jsdom' {
+ function mochaDom(options: any): void;
+ export = mochaDom;
+}
diff --git a/package.json b/package.json
index c8c0d7d1..2c62a4c9 100644
--- a/package.json
+++ b/package.json
@@ -4,7 +4,7 @@
"description": "rrweb's component to take a snapshot of DOM, aka DOM serializer",
"main": "index.js",
"scripts": {
- "test": "mocha -r ts-node/register src/**/*.test.ts"
+ "test": "TS_NODE_FILES=true mocha -r ts-node/register test/**/*.ts"
},
"repository": {
"type": "git",
@@ -23,9 +23,13 @@
"homepage": "https://github.com/rrweb-io/rrweb-snapshot#readme",
"devDependencies": {
"@types/chai": "^4.1.4",
+ "@types/jsdom": "^11.12.0",
"@types/mocha": "^5.2.5",
+ "@types/node": "^10.11.3",
"chai": "^4.1.2",
+ "jsdom": "^12.1.0",
"mocha": "^5.2.0",
+ "mocha-jsdom": "^2.0.0",
"ts-node": "^7.0.1",
"tslint": "^4.5.1",
"typescript": "^3.0.3"
diff --git a/src/rebuild.ts b/src/rebuild.ts
index 1d581e45..3dee6026 100644
--- a/src/rebuild.ts
+++ b/src/rebuild.ts
@@ -14,7 +14,11 @@ function buildNode(n: serializedNodeWithId): Node | null {
const node = document.createElement(n.tagName);
for (const name in n.attributes) {
if (n.attributes.hasOwnProperty(name)) {
- node.setAttribute(name, n.attributes[name]);
+ try {
+ node.setAttribute(name, n.attributes[name]);
+ } catch (error) {
+ // skip invalid attribute
+ }
}
}
return node;
diff --git a/test/html/about-mozilla.html b/test/html/about-mozilla.html
new file mode 100644
index 00000000..f353c482
--- /dev/null
+++ b/test/html/about-mozilla.html
@@ -0,0 +1,57 @@
+
+
+
+
+ The Book of Mozilla, 11:9
+
+
+
+
+
+
+ Mammon slept. And the beast reborn spread over the earth and its numbers
+ grew legion. And they proclaimed the times and sacrificed crops unto the
+ fire, with the cunning of foxes. And they built a new world in their own
+ image as promised by the
+ sacred words, and spoke
+ of the beast with their children. Mammon awoke, and lo! it was
+ naught but a follower.
+
+
+
+ from The Book of Mozilla, 11:9
(10th Edition)
+
+
+
+
+
\ No newline at end of file
diff --git a/test/html/basic.html b/test/html/basic.html
new file mode 100644
index 00000000..95fac2be
--- /dev/null
+++ b/test/html/basic.html
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+ Document
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/test/index.ts b/test/index.ts
new file mode 100644
index 00000000..a9fba369
--- /dev/null
+++ b/test/index.ts
@@ -0,0 +1,70 @@
+import 'mocha';
+import mochaDom = require('mocha-jsdom');
+import { expect } from 'chai';
+import * as fs from 'fs';
+import * as path from 'path';
+import { JSDOM } from 'jsdom';
+import { snapshot, rebuild } from '../src';
+
+const htmlFolder = path.join(__dirname, 'html');
+const htmls = fs.readdirSync(htmlFolder).map(filePath => {
+ return {
+ filePath,
+ content: fs.readFileSync(path.resolve(htmlFolder, filePath), 'utf-8'),
+ };
+});
+
+describe('integration tests', () => {
+ mochaDom({ url: 'http://localhost' });
+
+ it('will snapshot document type', () => {
+ const raw = '';
+ const dom = new JSDOM(raw);
+ const snap = snapshot(dom.window.document);
+ expect(snap).to.deep.equal({
+ type: 0,
+ childNodes: [
+ {
+ type: 2,
+ tagName: 'html',
+ attributes: {},
+ childNodes: [
+ {
+ type: 2,
+ tagName: 'head',
+ attributes: {},
+ childNodes: [],
+ id: 3,
+ },
+ {
+ type: 2,
+ tagName: 'body',
+ attributes: {},
+ childNodes: [],
+ id: 4,
+ },
+ ],
+ id: 2,
+ },
+ ],
+ id: 1,
+ });
+ });
+
+ it('will not throw error with invalid attribute', () => {
+ const raw = ``;
+ const dom = new JSDOM(raw);
+ expect(() => rebuild(snapshot(dom.window.document))).not.to.throw();
+ });
+
+ for (const html of htmls) {
+ it('[html file]:' + html.filePath, () => {
+ const dom = new JSDOM(html.content);
+ const snap = snapshot(dom.window.document);
+ const rebuildDom = rebuild(snap);
+ expect((rebuildDom as Document).documentElement.outerHTML).to.equal(
+ dom.window.document.documentElement.outerHTML,
+ );
+ });
+ }
+});
diff --git a/tsconfig.json b/tsconfig.json
index ce1b7e3c..06b323aa 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -9,5 +9,7 @@
"outDir": "build",
"lib": ["es6", "dom"]
},
- "compileOnSave": true
+ "compileOnSave": true,
+ "exclude": ["test"],
+ "include": ["index.d.ts"]
}
diff --git a/tslint.json b/tslint.json
index 3a0c0801..a153081c 100644
--- a/tslint.json
+++ b/tslint.json
@@ -9,7 +9,13 @@
"object-literal-sort-keys": false,
"no-unused-variable": true,
"object-literal-key-quotes": false,
- "variable-name": [true, "ban-keywords", "check-format", "allow-leading-underscore"]
+ "variable-name": [
+ true,
+ "ban-keywords",
+ "check-format",
+ "allow-leading-underscore"
+ ],
+ "arrow-parens": false
},
"rulesDirectory": []
-}
\ No newline at end of file
+}