impl #81 custom event
This is the record side impl of custom event, according to the issue, we may also add first-class support for the custom event tag like display color labels in the replayer-ui.
This commit is contained in:
11
src/index.ts
11
src/index.ts
@@ -1,6 +1,11 @@
|
|||||||
import record from './record';
|
import record, { addCustomEvent } from './record';
|
||||||
import { Replayer } from './replay';
|
import { Replayer } from './replay';
|
||||||
import { mirror } from './utils';
|
import { mirror } from './utils';
|
||||||
|
|
||||||
export { EventType, IncrementalSource, MouseInteractions, ReplayerEvents } from './types'
|
export {
|
||||||
export { record, Replayer, mirror };
|
EventType,
|
||||||
|
IncrementalSource,
|
||||||
|
MouseInteractions,
|
||||||
|
ReplayerEvents,
|
||||||
|
} from './types';
|
||||||
|
export { record, addCustomEvent, Replayer, mirror };
|
||||||
|
|||||||
@@ -17,6 +17,23 @@ function wrapEvent(e: event): eventWithTime {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let wrappedEmit!: (e: eventWithTime, isCheckout?: boolean) => void;
|
||||||
|
|
||||||
|
export function addCustomEvent<T>(tag: string, payload: T) {
|
||||||
|
if (!wrappedEmit) {
|
||||||
|
throw new Error('please add custom event after start recording');
|
||||||
|
}
|
||||||
|
wrappedEmit(
|
||||||
|
wrapEvent({
|
||||||
|
type: EventType.Custom,
|
||||||
|
data: {
|
||||||
|
tag,
|
||||||
|
payload,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
function record(options: recordOptions = {}): listenerHandler | undefined {
|
function record(options: recordOptions = {}): listenerHandler | undefined {
|
||||||
const {
|
const {
|
||||||
emit,
|
emit,
|
||||||
@@ -34,7 +51,7 @@ function record(options: recordOptions = {}): listenerHandler | undefined {
|
|||||||
|
|
||||||
let lastFullSnapshotEvent: eventWithTime;
|
let lastFullSnapshotEvent: eventWithTime;
|
||||||
let incrementalSnapshotCount = 0;
|
let incrementalSnapshotCount = 0;
|
||||||
const wrappedEmit = (e: eventWithTime, isCheckout?: boolean) => {
|
wrappedEmit = (e: eventWithTime, isCheckout?: boolean) => {
|
||||||
emit(e, isCheckout);
|
emit(e, isCheckout);
|
||||||
if (e.type === EventType.FullSnapshot) {
|
if (e.type === EventType.FullSnapshot) {
|
||||||
lastFullSnapshotEvent = e;
|
lastFullSnapshotEvent = e;
|
||||||
|
|||||||
12
src/types.ts
12
src/types.ts
@@ -6,6 +6,7 @@ export enum EventType {
|
|||||||
FullSnapshot,
|
FullSnapshot,
|
||||||
IncrementalSnapshot,
|
IncrementalSnapshot,
|
||||||
Meta,
|
Meta,
|
||||||
|
Custom,
|
||||||
}
|
}
|
||||||
|
|
||||||
export type domContentLoadedEvent = {
|
export type domContentLoadedEvent = {
|
||||||
@@ -43,6 +44,14 @@ export type metaEvent = {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type customEvent<T = unknown> = {
|
||||||
|
type: EventType.Custom;
|
||||||
|
data: {
|
||||||
|
tag: string;
|
||||||
|
payload: T;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
export enum IncrementalSource {
|
export enum IncrementalSource {
|
||||||
Mutation,
|
Mutation,
|
||||||
MouseMove,
|
MouseMove,
|
||||||
@@ -91,7 +100,8 @@ export type event =
|
|||||||
| loadedEvent
|
| loadedEvent
|
||||||
| fullSnapshotEvent
|
| fullSnapshotEvent
|
||||||
| incrementalSnapshotEvent
|
| incrementalSnapshotEvent
|
||||||
| metaEvent;
|
| metaEvent
|
||||||
|
| customEvent;
|
||||||
|
|
||||||
export type eventWithTime = event & {
|
export type eventWithTime = event & {
|
||||||
timestamp: number;
|
timestamp: number;
|
||||||
|
|||||||
@@ -245,3 +245,89 @@ exports[`async-checkout 1`] = `
|
|||||||
}
|
}
|
||||||
]"
|
]"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`custom-event 1`] = `
|
||||||
|
"[
|
||||||
|
{
|
||||||
|
\\"type\\": 4,
|
||||||
|
\\"data\\": {
|
||||||
|
\\"href\\": \\"about:blank\\",
|
||||||
|
\\"width\\": 800,
|
||||||
|
\\"height\\": 600
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"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\\": \\"input\\",
|
||||||
|
\\"attributes\\": {
|
||||||
|
\\"type\\": \\"text\\"
|
||||||
|
},
|
||||||
|
\\"childNodes\\": [],
|
||||||
|
\\"id\\": 6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"\\\\n \\\\n \\\\n \\",
|
||||||
|
\\"id\\": 7
|
||||||
|
}
|
||||||
|
],
|
||||||
|
\\"id\\": 4
|
||||||
|
}
|
||||||
|
],
|
||||||
|
\\"id\\": 2
|
||||||
|
}
|
||||||
|
],
|
||||||
|
\\"id\\": 1
|
||||||
|
},
|
||||||
|
\\"initialOffset\\": {
|
||||||
|
\\"left\\": 0,
|
||||||
|
\\"top\\": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 5,
|
||||||
|
\\"data\\": {
|
||||||
|
\\"tag\\": \\"tag1\\",
|
||||||
|
\\"payload\\": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 5,
|
||||||
|
\\"data\\": {
|
||||||
|
\\"tag\\": \\"tag2\\",
|
||||||
|
\\"payload\\": {
|
||||||
|
\\"a\\": \\"b\\"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]"
|
||||||
|
`;
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ interface ISuite extends Suite {
|
|||||||
interface IWindow extends Window {
|
interface IWindow extends Window {
|
||||||
rrweb: {
|
rrweb: {
|
||||||
record: (options: recordOptions) => listenerHandler | undefined;
|
record: (options: recordOptions) => listenerHandler | undefined;
|
||||||
|
addCustomEvent<T>(tag: string, payload: T): void;
|
||||||
};
|
};
|
||||||
emit: (e: eventWithTime) => undefined;
|
emit: (e: eventWithTime) => undefined;
|
||||||
}
|
}
|
||||||
@@ -180,4 +181,19 @@ describe('record', function(this: ISuite) {
|
|||||||
await this.page.waitFor(50);
|
await this.page.waitFor(50);
|
||||||
assertSnapshot(this.events, __filename, 'async-checkout');
|
assertSnapshot(this.events, __filename, 'async-checkout');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('can add custom event', async () => {
|
||||||
|
await this.page.evaluate(() => {
|
||||||
|
const { record, addCustomEvent } = (window as IWindow).rrweb;
|
||||||
|
record({
|
||||||
|
emit: (window as IWindow).emit,
|
||||||
|
});
|
||||||
|
addCustomEvent<number>('tag1', 1);
|
||||||
|
addCustomEvent<{ a: string }>('tag2', {
|
||||||
|
a: 'b',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
await this.page.waitFor(50);
|
||||||
|
assertSnapshot(this.events, __filename, 'custom-event');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user