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 { mirror } from './utils';
|
||||
|
||||
export { EventType, IncrementalSource, MouseInteractions, ReplayerEvents } from './types'
|
||||
export { record, Replayer, mirror };
|
||||
export {
|
||||
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 {
|
||||
const {
|
||||
emit,
|
||||
@@ -34,7 +51,7 @@ function record(options: recordOptions = {}): listenerHandler | undefined {
|
||||
|
||||
let lastFullSnapshotEvent: eventWithTime;
|
||||
let incrementalSnapshotCount = 0;
|
||||
const wrappedEmit = (e: eventWithTime, isCheckout?: boolean) => {
|
||||
wrappedEmit = (e: eventWithTime, isCheckout?: boolean) => {
|
||||
emit(e, isCheckout);
|
||||
if (e.type === EventType.FullSnapshot) {
|
||||
lastFullSnapshotEvent = e;
|
||||
|
||||
12
src/types.ts
12
src/types.ts
@@ -6,6 +6,7 @@ export enum EventType {
|
||||
FullSnapshot,
|
||||
IncrementalSnapshot,
|
||||
Meta,
|
||||
Custom,
|
||||
}
|
||||
|
||||
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 {
|
||||
Mutation,
|
||||
MouseMove,
|
||||
@@ -91,7 +100,8 @@ export type event =
|
||||
| loadedEvent
|
||||
| fullSnapshotEvent
|
||||
| incrementalSnapshotEvent
|
||||
| metaEvent;
|
||||
| metaEvent
|
||||
| customEvent;
|
||||
|
||||
export type eventWithTime = event & {
|
||||
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 {
|
||||
rrweb: {
|
||||
record: (options: recordOptions) => listenerHandler | undefined;
|
||||
addCustomEvent<T>(tag: string, payload: T): void;
|
||||
};
|
||||
emit: (e: eventWithTime) => undefined;
|
||||
}
|
||||
@@ -180,4 +181,19 @@ describe('record', function(this: ISuite) {
|
||||
await this.page.waitFor(50);
|
||||
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