fix the skip event calculation (#242)
This commit is contained in:
@@ -216,10 +216,10 @@ export class Replayer {
|
|||||||
* @param timeOffset number
|
* @param timeOffset number
|
||||||
*/
|
*/
|
||||||
public play(timeOffset = 0) {
|
public play(timeOffset = 0) {
|
||||||
if (this.service.state.value == 'ended') {
|
if (this.service.state.value === 'ended') {
|
||||||
this.service.send({ type: 'REPLAY'});
|
this.service.send({ type: 'REPLAY' });
|
||||||
}
|
}
|
||||||
if (this.service.state.value == 'paused') {
|
if (this.service.state.value === 'paused') {
|
||||||
this.service.send({ type: 'RESUME', payload: { timeOffset } });
|
this.service.send({ type: 'RESUME', payload: { timeOffset } });
|
||||||
} else {
|
} else {
|
||||||
this.service.send({ type: 'PLAY', payload: { timeOffset } });
|
this.service.send({ type: 'PLAY', payload: { timeOffset } });
|
||||||
|
|||||||
@@ -79,27 +79,37 @@ export type PlayerState =
|
|||||||
* If the array have multiple meta and fullsnapshot events,
|
* If the array have multiple meta and fullsnapshot events,
|
||||||
* return the events from last meta to the end.
|
* return the events from last meta to the end.
|
||||||
*/
|
*/
|
||||||
export function getLastSession(events: eventWithTime[]): eventWithTime[] {
|
export function getLastSession(
|
||||||
const lastSession: eventWithTime[] = [];
|
events: eventWithTime[],
|
||||||
|
baselineTime: number,
|
||||||
let hasFullSnapshot = false;
|
): eventWithTime[] {
|
||||||
let hasMeta = false;
|
let startMetaIdx: number | null = null;
|
||||||
|
let endMetaIdx: number | null = null;
|
||||||
|
|
||||||
for (let idx = events.length - 1; idx >= 0; idx--) {
|
for (let idx = events.length - 1; idx >= 0; idx--) {
|
||||||
const event = events[idx];
|
const event = events[idx];
|
||||||
lastSession.unshift(event);
|
|
||||||
if (event.type === EventType.FullSnapshot) {
|
|
||||||
hasFullSnapshot = true;
|
|
||||||
}
|
|
||||||
if (event.type === EventType.Meta) {
|
if (event.type === EventType.Meta) {
|
||||||
hasMeta = true;
|
if (event.timestamp > baselineTime) {
|
||||||
|
endMetaIdx = idx;
|
||||||
|
} else {
|
||||||
|
startMetaIdx = idx;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (hasFullSnapshot && hasMeta) {
|
if (startMetaIdx !== null) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return lastSession;
|
// baseline time is less than first meta event
|
||||||
|
if (startMetaIdx === null && endMetaIdx !== null) {
|
||||||
|
startMetaIdx = endMetaIdx;
|
||||||
|
endMetaIdx = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return events.slice(
|
||||||
|
startMetaIdx ?? 0,
|
||||||
|
endMetaIdx === null ? events.length : endMetaIdx + 1,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
type PlayerAssets = {
|
type PlayerAssets = {
|
||||||
@@ -198,12 +208,13 @@ export function createPlayerService(
|
|||||||
play(ctx) {
|
play(ctx) {
|
||||||
const { timer, events, baselineTime, lastPlayedEvent } = ctx;
|
const { timer, events, baselineTime, lastPlayedEvent } = ctx;
|
||||||
timer.clear();
|
timer.clear();
|
||||||
const neededEvents = getLastSession(events);
|
const neededEvents = getLastSession(events, baselineTime);
|
||||||
|
|
||||||
const actions = new Array<actionWithDelay>();
|
const actions = new Array<actionWithDelay>();
|
||||||
for (const event of neededEvents) {
|
for (const event of neededEvents) {
|
||||||
if (
|
if (
|
||||||
lastPlayedEvent &&
|
lastPlayedEvent &&
|
||||||
|
lastPlayedEvent.timestamp > baselineTime &&
|
||||||
(event.timestamp <= lastPlayedEvent.timestamp ||
|
(event.timestamp <= lastPlayedEvent.timestamp ||
|
||||||
event === lastPlayedEvent)
|
event === lastPlayedEvent)
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -336,6 +336,8 @@ export type playerConfig = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export type playerMetaData = {
|
export type playerMetaData = {
|
||||||
|
startTime: number;
|
||||||
|
endTime: number;
|
||||||
totalTime: number;
|
totalTime: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -6,14 +6,43 @@ import { EventType } from '../src/types';
|
|||||||
const events = sampleEvents.filter(
|
const events = sampleEvents.filter(
|
||||||
(e) => ![EventType.DomContentLoaded, EventType.Load].includes(e.type),
|
(e) => ![EventType.DomContentLoaded, EventType.Load].includes(e.type),
|
||||||
);
|
);
|
||||||
|
const nextEvents = events.map((e) => ({
|
||||||
|
...e,
|
||||||
|
timestamp: e.timestamp + 1000,
|
||||||
|
}));
|
||||||
|
const nextNextEvents = nextEvents.map((e) => ({
|
||||||
|
...e,
|
||||||
|
timestamp: e.timestamp + 1000,
|
||||||
|
}));
|
||||||
|
|
||||||
describe('get last session', () => {
|
describe('get last session', () => {
|
||||||
it('will return all the events when there is only one session', () => {
|
it('will return all the events when there is only one session', () => {
|
||||||
expect(getLastSession(events)).to.deep.equal(events);
|
expect(getLastSession(events, events[0].timestamp)).to.deep.equal(events);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('will return last session when there is more than one in the events', () => {
|
it('will return last session when there is more than one in the events', () => {
|
||||||
const multiple = events.concat(events).concat(events);
|
const multiple = events.concat(nextEvents).concat(nextNextEvents);
|
||||||
expect(getLastSession(multiple)).to.deep.equal(events);
|
expect(
|
||||||
|
getLastSession(
|
||||||
|
multiple,
|
||||||
|
nextNextEvents[nextNextEvents.length - 1].timestamp,
|
||||||
|
),
|
||||||
|
).to.deep.equal(nextNextEvents);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('will return last session when baseline time is future time', () => {
|
||||||
|
const multiple = events.concat(nextEvents).concat(nextNextEvents);
|
||||||
|
expect(
|
||||||
|
getLastSession(
|
||||||
|
multiple,
|
||||||
|
nextNextEvents[nextNextEvents.length - 1].timestamp + 1000,
|
||||||
|
),
|
||||||
|
).to.deep.equal(nextNextEvents);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('will return first session when baseline time is previous time', () => {
|
||||||
|
expect(getLastSession(events, events[0].timestamp - 1000)).to.deep.equal(
|
||||||
|
events,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import * as puppeteer from 'puppeteer';
|
|||||||
import { expect } from 'chai';
|
import { expect } from 'chai';
|
||||||
import { Suite } from 'mocha';
|
import { Suite } from 'mocha';
|
||||||
import { launchPuppeteer, sampleEvents as events } from './utils';
|
import { launchPuppeteer, sampleEvents as events } from './utils';
|
||||||
|
import { EventType } from '../src/types';
|
||||||
|
|
||||||
interface ISuite extends Suite {
|
interface ISuite extends Suite {
|
||||||
code: string;
|
code: string;
|
||||||
@@ -59,7 +60,11 @@ describe('replayer', function (this: ISuite) {
|
|||||||
replayer.play();
|
replayer.play();
|
||||||
replayer['timer']['actions'].length;
|
replayer['timer']['actions'].length;
|
||||||
`);
|
`);
|
||||||
expect(actionLength).to.equal(events.length);
|
expect(actionLength).to.equal(
|
||||||
|
events.filter(
|
||||||
|
(e) => ![EventType.DomContentLoaded, EventType.Load].includes(e.type),
|
||||||
|
).length,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('will clean actions when pause', async () => {
|
it('will clean actions when pause', async () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user