mirror of
https://github.com/vector-im/element-call.git
synced 2026-05-01 09:54:37 +00:00
163 lines
4.7 KiB
TypeScript
163 lines
4.7 KiB
TypeScript
/*
|
|
Copyright 2025 New Vector Ltd.
|
|
|
|
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
|
Please see LICENSE in the repository root for full details.
|
|
*/
|
|
|
|
import {
|
|
expect,
|
|
describe,
|
|
it,
|
|
vi,
|
|
beforeEach,
|
|
beforeAll,
|
|
afterAll,
|
|
} from "vitest";
|
|
import { logger } from "matrix-js-sdk/lib/logger";
|
|
import { type MatrixRTCSession } from "matrix-js-sdk/lib/matrixrtc";
|
|
|
|
import { PosthogAnalytics } from "./PosthogAnalytics";
|
|
import { CallEndedTracker } from "./PosthogEvents";
|
|
import { mockConfig } from "../utils/test";
|
|
|
|
const defaultCounters = {
|
|
roomEventEncryptionKeysSent: 10,
|
|
roomEventEncryptionKeysReceived: 5,
|
|
};
|
|
|
|
const defaultTotals = {
|
|
roomEventEncryptionKeysReceivedTotalAge: 500,
|
|
};
|
|
|
|
function createMockRtcSession(overrides?: {
|
|
counters?: Partial<typeof defaultCounters>;
|
|
totals?: Partial<typeof defaultTotals>;
|
|
}): MatrixRTCSession {
|
|
return {
|
|
statistics: {
|
|
counters: { ...defaultCounters, ...overrides?.counters },
|
|
totals: { ...defaultTotals, ...overrides?.totals },
|
|
},
|
|
} as unknown as MatrixRTCSession;
|
|
}
|
|
|
|
describe("CallEnded", () => {
|
|
beforeAll(() => {
|
|
mockConfig();
|
|
});
|
|
|
|
beforeEach(() => {
|
|
vi.restoreAllMocks();
|
|
vi.spyOn(PosthogAnalytics.instance, "trackEvent").mockImplementation(
|
|
() => {},
|
|
);
|
|
});
|
|
|
|
afterAll(() => {
|
|
PosthogAnalytics.resetInstance();
|
|
});
|
|
|
|
it("warns if startTime is missing when track is called", () => {
|
|
const warnSpy = vi.spyOn(logger, "warn");
|
|
const tracker = new CallEndedTracker();
|
|
const mockSession = createMockRtcSession();
|
|
|
|
tracker.track("test-call-id", 2, false, mockSession);
|
|
|
|
expect(warnSpy).toHaveBeenCalledWith(
|
|
"[PosthogEvents] Failed to send posthog callEnded event due to missing startTime",
|
|
);
|
|
expect(PosthogAnalytics.instance.trackEvent).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it("tracks event with correct properties when startTime is set", () => {
|
|
const tracker = new CallEndedTracker();
|
|
const mockSession = createMockRtcSession();
|
|
|
|
tracker.cacheStartCall(new Date(Date.now() - 60000));
|
|
tracker.cacheParticipantCountChanged(5);
|
|
tracker.track("test-call-id", 3, true, mockSession);
|
|
|
|
expect(PosthogAnalytics.instance.trackEvent).toHaveBeenCalledWith(
|
|
{
|
|
eventName: "CallEnded",
|
|
callId: "test-call-id",
|
|
callParticipantsMax: 5,
|
|
callParticipantsOnLeave: 3,
|
|
callDuration: expect.closeTo(60, 1),
|
|
roomEventEncryptionKeysSent: 10,
|
|
roomEventEncryptionKeysReceived: 5,
|
|
roomEventEncryptionKeysReceivedAverageAge: 100,
|
|
},
|
|
{ send_instantly: true },
|
|
);
|
|
});
|
|
|
|
it("tracks maxParticipantsCount correctly across multiple changes", () => {
|
|
const tracker = new CallEndedTracker();
|
|
const mockSession = createMockRtcSession();
|
|
|
|
tracker.cacheStartCall(new Date());
|
|
tracker.cacheParticipantCountChanged(3);
|
|
tracker.cacheParticipantCountChanged(7);
|
|
tracker.cacheParticipantCountChanged(2);
|
|
tracker.track("test-call-id", 1, false, mockSession);
|
|
|
|
expect(PosthogAnalytics.instance.trackEvent).toHaveBeenCalledWith(
|
|
expect.objectContaining({
|
|
callParticipantsMax: 7,
|
|
}),
|
|
expect.anything(),
|
|
);
|
|
});
|
|
|
|
it("computes roomEventEncryptionKeysReceivedAverageAge as 0 when no keys received", () => {
|
|
const tracker = new CallEndedTracker();
|
|
const mockSession = createMockRtcSession({
|
|
counters: { roomEventEncryptionKeysReceived: 0 },
|
|
});
|
|
|
|
tracker.cacheStartCall(new Date());
|
|
tracker.track("test-call-id", 1, false, mockSession);
|
|
|
|
expect(PosthogAnalytics.instance.trackEvent).toHaveBeenCalledWith(
|
|
expect.objectContaining({
|
|
roomEventEncryptionKeysReceivedAverageAge: 0,
|
|
}),
|
|
expect.anything(),
|
|
);
|
|
});
|
|
|
|
it("computes roomEventEncryptionKeysReceivedAverageAge correctly when keys are received", () => {
|
|
const tracker = new CallEndedTracker();
|
|
const mockSession = createMockRtcSession({
|
|
counters: { roomEventEncryptionKeysReceived: 4 },
|
|
totals: { roomEventEncryptionKeysReceivedTotalAge: 200 },
|
|
});
|
|
|
|
tracker.cacheStartCall(new Date());
|
|
tracker.track("test-call-id", 1, false, mockSession);
|
|
|
|
expect(PosthogAnalytics.instance.trackEvent).toHaveBeenCalledWith(
|
|
expect.objectContaining({
|
|
roomEventEncryptionKeysReceivedAverageAge: 50,
|
|
}),
|
|
expect.anything(),
|
|
);
|
|
});
|
|
|
|
it("passes send_instantly option correctly", () => {
|
|
const tracker = new CallEndedTracker();
|
|
const mockSession = createMockRtcSession();
|
|
|
|
tracker.cacheStartCall(new Date());
|
|
tracker.track("test-call-id", 1, false, mockSession);
|
|
|
|
expect(PosthogAnalytics.instance.trackEvent).toHaveBeenCalledWith(
|
|
expect.anything(),
|
|
{ send_instantly: false },
|
|
);
|
|
});
|
|
});
|