210 lines
5.0 KiB
TypeScript
210 lines
5.0 KiB
TypeScript
/* tslint:disable no-string-literal no-console */
|
|
|
|
import * as fs from 'fs';
|
|
import * as path from 'path';
|
|
import * as puppeteer from 'puppeteer';
|
|
import { expect } from 'chai';
|
|
import { Suite } from 'mocha';
|
|
import {
|
|
EventType,
|
|
eventWithTime,
|
|
IncrementalSource,
|
|
MouseInteractions,
|
|
} from '../src/types';
|
|
import { Replayer } from '../src';
|
|
|
|
const now = Date.now();
|
|
|
|
const events: eventWithTime[] = [
|
|
{
|
|
type: EventType.DomContentLoaded,
|
|
data: {},
|
|
timestamp: now,
|
|
},
|
|
{
|
|
type: EventType.Load,
|
|
data: {},
|
|
timestamp: now + 1000,
|
|
},
|
|
{
|
|
type: EventType.Meta,
|
|
data: {
|
|
href: 'http://localhost',
|
|
width: 1000,
|
|
height: 800,
|
|
},
|
|
timestamp: now + 1000,
|
|
},
|
|
{
|
|
type: EventType.FullSnapshot,
|
|
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: [],
|
|
id: 4,
|
|
},
|
|
],
|
|
id: 2,
|
|
},
|
|
],
|
|
id: 1,
|
|
},
|
|
initialOffset: {
|
|
top: 0,
|
|
left: 0,
|
|
},
|
|
},
|
|
timestamp: now + 1000,
|
|
},
|
|
{
|
|
type: EventType.IncrementalSnapshot,
|
|
data: {
|
|
source: IncrementalSource.MouseInteraction,
|
|
type: MouseInteractions.Click,
|
|
id: 1,
|
|
x: 0,
|
|
y: 0,
|
|
},
|
|
timestamp: now + 2000,
|
|
},
|
|
{
|
|
type: EventType.IncrementalSnapshot,
|
|
data: {
|
|
source: IncrementalSource.MouseInteraction,
|
|
type: MouseInteractions.Click,
|
|
id: 1,
|
|
x: 0,
|
|
y: 0,
|
|
},
|
|
timestamp: now + 3000,
|
|
},
|
|
{
|
|
type: EventType.IncrementalSnapshot,
|
|
data: {
|
|
source: IncrementalSource.MouseInteraction,
|
|
type: MouseInteractions.Click,
|
|
id: 1,
|
|
x: 0,
|
|
y: 0,
|
|
},
|
|
timestamp: now + 4000,
|
|
},
|
|
];
|
|
|
|
interface IWindow extends Window {
|
|
rrweb: {
|
|
Replayer: typeof Replayer;
|
|
};
|
|
}
|
|
|
|
interface ISuite extends Suite {
|
|
code: string;
|
|
browser: puppeteer.Browser;
|
|
page: puppeteer.Page;
|
|
}
|
|
|
|
describe('replayer', function(this: ISuite) {
|
|
before(async () => {
|
|
this.browser = await puppeteer.launch({
|
|
headless: false,
|
|
args: ['--no-sandbox'],
|
|
});
|
|
|
|
const bundlePath = path.resolve(__dirname, '../dist/rrweb.min.js');
|
|
this.code = fs.readFileSync(bundlePath, 'utf8');
|
|
});
|
|
|
|
beforeEach(async () => {
|
|
const page: puppeteer.Page = await this.browser.newPage();
|
|
await page.goto('about:blank');
|
|
await page.evaluate(this.code);
|
|
await page.evaluate(`const events = ${JSON.stringify(events)}`);
|
|
this.page = page;
|
|
|
|
page.on('console', msg => console.log('PAGE LOG:', msg.text()));
|
|
});
|
|
|
|
afterEach(async () => {
|
|
await this.page.close();
|
|
});
|
|
|
|
after(async () => {
|
|
await this.browser.close();
|
|
});
|
|
|
|
it('can get meta data', async () => {
|
|
const meta = await this.page.evaluate(() => {
|
|
const { Replayer } = ((window as unknown) as IWindow).rrweb;
|
|
const replayer = new Replayer(events);
|
|
return replayer.getMetaData();
|
|
});
|
|
expect(meta).to.deep.equal({
|
|
totalTime: events[events.length - 1].timestamp - events[0].timestamp,
|
|
});
|
|
});
|
|
|
|
it('will start actions when play', async () => {
|
|
const actionLength = await this.page.evaluate(() => {
|
|
const { Replayer } = ((window as unknown) as IWindow).rrweb;
|
|
const replayer = new Replayer(events);
|
|
replayer.play();
|
|
return replayer['timer']['actions'].length;
|
|
});
|
|
expect(actionLength).to.equal(events.length);
|
|
});
|
|
|
|
it('will clean actions when pause', async () => {
|
|
const actionLength = await this.page.evaluate(() => {
|
|
const { Replayer } = ((window as unknown) as IWindow).rrweb;
|
|
const replayer = new Replayer(events);
|
|
replayer.play();
|
|
replayer.pause();
|
|
return replayer['timer']['actions'].length;
|
|
});
|
|
expect(actionLength).to.equal(0);
|
|
});
|
|
|
|
it('can play at any time offset', async () => {
|
|
const actionLength = await this.page.evaluate(() => {
|
|
const { Replayer } = ((window as unknown) as IWindow).rrweb;
|
|
const replayer = new Replayer(events);
|
|
replayer.play(1500);
|
|
return replayer['timer']['actions'].length;
|
|
});
|
|
expect(actionLength).to.equal(
|
|
events.filter(e => e.timestamp - events[0].timestamp >= 1500).length,
|
|
);
|
|
});
|
|
|
|
it('can resume at any time offset', async () => {
|
|
const actionLength = await this.page.evaluate(() => {
|
|
const { Replayer } = ((window as unknown) as IWindow).rrweb;
|
|
const replayer = new Replayer(events);
|
|
replayer.play(1500);
|
|
replayer.pause();
|
|
replayer.resume(1500);
|
|
return replayer['timer']['actions'].length;
|
|
});
|
|
expect(actionLength).to.equal(
|
|
events.filter(e => e.timestamp - events[0].timestamp >= 1500).length,
|
|
);
|
|
});
|
|
});
|