refactor the test infra: use puppeteer instead of jsdom to get rid of some hack implementations
This commit is contained in:
6
index.d.ts
vendored
6
index.d.ts
vendored
@@ -1,4 +1,4 @@
|
|||||||
declare module 'mocha-jsdom' {
|
declare module 'rollup-plugin-typescript' {
|
||||||
function mochaDom(options: any): void;
|
function typescript(): any;
|
||||||
export = mochaDom;
|
export = typescript;
|
||||||
}
|
}
|
||||||
|
|||||||
11
package.json
11
package.json
@@ -4,7 +4,8 @@
|
|||||||
"description": "rrweb's component to take a snapshot of DOM, aka DOM serializer",
|
"description": "rrweb's component to take a snapshot of DOM, aka DOM serializer",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "TS_NODE_FILES=true mocha -r ts-node/register test/**/*.ts"
|
"test": "TS_NODE_FILES=true mocha -r ts-node/register test/**/*.ts",
|
||||||
|
"compile": "rollup --config"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
@@ -23,14 +24,16 @@
|
|||||||
"homepage": "https://github.com/rrweb-io/rrweb-snapshot#readme",
|
"homepage": "https://github.com/rrweb-io/rrweb-snapshot#readme",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/chai": "^4.1.4",
|
"@types/chai": "^4.1.4",
|
||||||
"@types/jsdom": "^11.12.0",
|
|
||||||
"@types/mocha": "^5.2.5",
|
"@types/mocha": "^5.2.5",
|
||||||
"@types/node": "^10.11.3",
|
"@types/node": "^10.11.3",
|
||||||
|
"@types/puppeteer": "^1.8.0",
|
||||||
"chai": "^4.1.2",
|
"chai": "^4.1.2",
|
||||||
"jsdom": "^12.1.0",
|
|
||||||
"mocha": "^5.2.0",
|
"mocha": "^5.2.0",
|
||||||
"mocha-jsdom": "^2.0.0",
|
"puppeteer": "^1.9.0",
|
||||||
|
"rollup": "^0.66.4",
|
||||||
|
"rollup-plugin-typescript": "^1.0.0",
|
||||||
"ts-node": "^7.0.1",
|
"ts-node": "^7.0.1",
|
||||||
|
"tslib": "^1.9.3",
|
||||||
"tslint": "^4.5.1",
|
"tslint": "^4.5.1",
|
||||||
"typescript": "^3.0.3"
|
"typescript": "^3.0.3"
|
||||||
}
|
}
|
||||||
|
|||||||
10
rollup.config.js
Normal file
10
rollup.config.js
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
import typescript from 'rollup-plugin-typescript';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
input: './src/index.ts',
|
||||||
|
plugins: [typescript()],
|
||||||
|
output: {
|
||||||
|
name: 'rrweb',
|
||||||
|
format: 'iife',
|
||||||
|
},
|
||||||
|
};
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<script src="a.js"></script>
|
<script src="http://localhost:3030/js/a.js"></script>
|
||||||
<script>
|
<script>
|
||||||
var a = 1 + 1;
|
var a = 1 + 1;
|
||||||
</script>
|
</script>
|
||||||
@@ -30,7 +30,7 @@
|
|||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<noscript src="a.js"></noscript>
|
<noscript src="http://localhost:3030/js/a.js"></noscript>
|
||||||
<noscript></noscript>
|
<noscript></noscript>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
|
|||||||
16
test/html/with-style-sheet.html
Normal file
16
test/html/with-style-sheet.html
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
||||||
|
<title>with style sheet</title>
|
||||||
|
<link rel="stylesheet" href="http://localhost:3030/css/style.css">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
@@ -1,10 +1,12 @@
|
|||||||
import 'mocha';
|
|
||||||
import mochaDom = require('mocha-jsdom');
|
|
||||||
import { expect } from 'chai';
|
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import { JSDOM } from 'jsdom';
|
import * as http from 'http';
|
||||||
import { snapshot, rebuild } from '../src';
|
import * as url from 'url';
|
||||||
|
import 'mocha';
|
||||||
|
import * as puppeteer from 'puppeteer';
|
||||||
|
import * as rollup from 'rollup';
|
||||||
|
import typescript = require('rollup-plugin-typescript');
|
||||||
|
import { expect } from 'chai';
|
||||||
|
|
||||||
const htmlFolder = path.join(__dirname, 'html');
|
const htmlFolder = path.join(__dirname, 'html');
|
||||||
const htmls = fs.readdirSync(htmlFolder).map(filePath => {
|
const htmls = fs.readdirSync(htmlFolder).map(filePath => {
|
||||||
@@ -24,65 +26,86 @@ const htmls = fs.readdirSync(htmlFolder).map(filePath => {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
interface IMimeType {
|
||||||
|
[key: string]: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const server = () =>
|
||||||
|
new Promise(resolve => {
|
||||||
|
const mimeType: IMimeType = {
|
||||||
|
'.html': 'text/html',
|
||||||
|
'.js': 'text/javascript',
|
||||||
|
'.css': 'text/css',
|
||||||
|
};
|
||||||
|
const s = http.createServer((req, res) => {
|
||||||
|
const parsedUrl = url.parse(req.url);
|
||||||
|
const sanitizePath = path
|
||||||
|
.normalize(parsedUrl.pathname)
|
||||||
|
.replace(/^(\.\.[\/\\])+/, '');
|
||||||
|
let pathname = path.join(__dirname, sanitizePath);
|
||||||
|
try {
|
||||||
|
const data = fs.readFileSync(pathname);
|
||||||
|
const ext = path.parse(pathname).ext;
|
||||||
|
res.setHeader('Content-type', mimeType[ext] || 'text/plain');
|
||||||
|
res.setHeader('Access-Control-Allow-Origin', '*');
|
||||||
|
res.setHeader('Access-Control-Allow-Methods', 'GET');
|
||||||
|
res.setHeader('Access-Control-Allow-Headers', 'Content-type');
|
||||||
|
res.end(data);
|
||||||
|
} catch (error) {
|
||||||
|
res.end();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
s.listen(3030).on('listening', () => {
|
||||||
|
resolve(s);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('integration tests', () => {
|
describe('integration tests', () => {
|
||||||
mochaDom({ url: 'http://localhost' });
|
before(async () => {
|
||||||
|
this.server = await server();
|
||||||
|
this.browser = await puppeteer.launch({
|
||||||
|
headless: false,
|
||||||
|
executablePath: '/home/yanzhen/Desktop/chrome-linux/chrome',
|
||||||
|
});
|
||||||
|
|
||||||
|
const bundle = await rollup.rollup({
|
||||||
|
input: path.resolve(__dirname, '../src/index.ts'),
|
||||||
|
plugins: [typescript()],
|
||||||
|
});
|
||||||
|
const { code } = await bundle.generate({
|
||||||
|
name: 'rrweb',
|
||||||
|
format: 'iife',
|
||||||
|
});
|
||||||
|
this.code = code;
|
||||||
|
});
|
||||||
|
|
||||||
|
after(() => {
|
||||||
|
this.browser.close();
|
||||||
|
this.server.close();
|
||||||
|
});
|
||||||
|
|
||||||
for (const html of htmls) {
|
for (const html of htmls) {
|
||||||
it('[html file]: ' + html.filePath, done => {
|
it('[html file]: ' + html.filePath, async () => {
|
||||||
const srcDom = new JSDOM(html.src, { runScripts: 'dangerously' });
|
const page: puppeteer.Page = await this.browser.newPage();
|
||||||
const destDom = new JSDOM(html.dest);
|
await page.goto(`http://localhost:3030/html/${html.filePath}`);
|
||||||
srcDom.window.document.addEventListener('DOMContentLoaded', () => {
|
await page.setContent(html.src);
|
||||||
const snap = snapshot(srcDom.window.document);
|
page.once('load', async () => {
|
||||||
const rebuildDom = rebuild(snap);
|
await page.evaluate(() => {
|
||||||
const htmlStr = destDom.window.document.documentElement.outerHTML.replace(
|
const x = new XMLSerializer();
|
||||||
/\n\n/g,
|
return x.serializeToString(document);
|
||||||
'',
|
});
|
||||||
);
|
const rebuildHtml = (await page.evaluate(`${this.code}
|
||||||
const rebuildStr = (rebuildDom as Document).documentElement.outerHTML.replace(
|
const x = new XMLSerializer();
|
||||||
/\n\n/g,
|
const snap = rrweb.snapshot(document);
|
||||||
'',
|
x.serializeToString(rrweb.rebuild(snap));
|
||||||
);
|
`)).replace(/\n\n/g, '');
|
||||||
try {
|
await page.goto(`data:text/html,${html.dest}`);
|
||||||
expect(rebuildStr).to.equal(htmlStr);
|
const destHtml = (await page.evaluate(() => {
|
||||||
done();
|
const x = new XMLSerializer();
|
||||||
} catch (error) {
|
return x.serializeToString(document);
|
||||||
done(error);
|
})).replace(/\n\n/g, '');
|
||||||
|
expect(rebuildHtml).to.equal(destHtml);
|
||||||
|
});
|
||||||
|
}).timeout(5000);
|
||||||
}
|
}
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
it('will snapshot document type', () => {
|
|
||||||
const raw = '<html></html>';
|
|
||||||
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,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|||||||
1
test/js/a.js
Normal file
1
test/js/a.js
Normal file
@@ -0,0 +1 @@
|
|||||||
|
var a = 1 + 1;
|
||||||
0
test/server.ts
Normal file
0
test/server.ts
Normal file
@@ -11,5 +11,5 @@
|
|||||||
},
|
},
|
||||||
"compileOnSave": true,
|
"compileOnSave": true,
|
||||||
"exclude": ["test"],
|
"exclude": ["test"],
|
||||||
"include": ["index.d.ts"]
|
"include": ["src", "index.d.ts"]
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user