Enforce anon/pseudo-anon via types

pull/21833/head
James Salter 2021-07-21 08:23:42 +01:00
parent 3135e42586
commit 74b0e52f9a
2 changed files with 54 additions and 19 deletions

View File

@ -1,11 +1,28 @@
import posthog from 'posthog-js';
import SdkConfig from './SdkConfig';
export interface IEvent {
key: string;
interface IEvent {
// The event name that will be used by PostHog.
// TODO: standard format (camel case? snake? UpperCase?)
eventName: string;
// The properties of the event that will be stored in PostHog.
properties: {}
}
// If an event extends IPseudonymousEvent, the event contains pseudonymous data
// that won't be sent unless the user has explicitly consented to pseudonymous tracking.
// For example, hashed user IDs or room IDs.
export interface IPseudonymousEvent extends IEvent {}
// If an event extends IAnonymousEvent, the event strictly contains *only* anonymous data which
// may be sent without explicit user consent.
export interface IAnonymousEvent extends IEvent {}
export interface IRoomEvent extends IPseudonymousEvent {
hashedRoomId: string
}
export interface IOnboardingLoginBegin extends IEvent {
key: "onboarding_login_begin",
}
@ -55,27 +72,32 @@ export class PosthogAnalytics {
this.onlyTrackAnonymousEvents = enabled;
}
public track<E extends IEvent>(
key: E["key"],
public trackPseudonymousEvent<E extends IPseudonymousEvent>(
eventName: E["eventName"],
properties: E["properties"],
anonymous = false,
) {
if (!this.initialised) return;
if (this.onlyTrackAnonymousEvents && !anonymous) return;
this.posthog.capture(key, properties);
if (this.onlyTrackAnonymousEvents) return;
this.posthog.capture(eventName, properties);
}
public async trackRoomEvent<E extends IEvent>(
key: E["key"],
roomId: string,
public trackAnonymousEvent<E extends IAnonymousEvent>(
eventName: E["eventName"],
properties: E["properties"],
...args
) {
if (!this.initialised) return;
this.posthog.capture(eventName, properties);
}
public async trackRoomEvent<E extends IRoomEvent>(
eventName: E["eventName"],
roomId: string,
properties: Omit<E["properties"], "roomId">,
) {
const updatedProperties = {
...properties,
hashedRoomId: roomId ? await hashHex(roomId) : null,
};
this.track(key, updatedProperties, ...args);
this.trackPseudonymousEvent(eventName, updatedProperties);
}
}

View File

@ -1,4 +1,4 @@
import { IEvent, PosthogAnalytics } from '../src/PosthogAnalytics';
import { IAnonymousEvent, IRoomEvent, PosthogAnalytics } from '../src/PosthogAnalytics';
import SdkConfig from '../src/SdkConfig';
const crypto = require('crypto');
@ -12,13 +12,20 @@ class FakePosthog {
}
}
export interface ITestEvent extends IEvent {
export interface ITestEvent extends IAnonymousEvent {
key: "jest_test_event",
properties: {
foo: string
}
}
export interface ITestRoomEvent extends IRoomEvent {
key: "jest_test_room_event",
properties: {
foo: string
}
}
describe("PosthogAnalytics", () => {
let analytics: PosthogAnalytics;
let fakePosthog: FakePosthog;
@ -61,7 +68,7 @@ describe("PosthogAnalytics", () => {
it("Should pass track() to posthog", () => {
analytics.init(false);
analytics.track<ITestEvent>("jest_test_event", {
analytics.trackAnonymousEvent<ITestEvent>("jest_test_event", {
foo: "bar",
});
expect(fakePosthog.capture.mock.calls[0][0]).toBe("jest_test_event");
@ -71,7 +78,7 @@ describe("PosthogAnalytics", () => {
it("Should pass trackRoomEvent to posthog", () => {
analytics.init(false);
const roomId = "42";
return analytics.trackRoomEvent<ITestEvent>("jest_test_event", roomId, {
return analytics.trackRoomEvent<IRoomEvent>("jest_test_event", roomId, {
foo: "bar",
}).then(() => {
expect(fakePosthog.capture.mock.calls[0][0]).toBe("jest_test_event");
@ -82,11 +89,17 @@ describe("PosthogAnalytics", () => {
});
});
it("Should silently not send messages if not inititalised", () => {
analytics.track<ITestEvent>("jest_test_event", {
it("Should silently not track if not inititalised", () => {
analytics.trackAnonymousEvent<ITestEvent>("jest_test_event", {
foo: "bar",
});
expect(fakePosthog.capture.mock.calls.length).toBe(0);
});
it("Should not track non-anonymous messages if onlyTrackAnonymousEvents is true", () => {
analytics.trackAnonymousEvent<ITestEvent>("jest_test_event", {
foo: "bar",
});
});
});