File size: 2,354 Bytes
fd2c364
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
import { beforeEach, describe, expect, it, vi } from "vitest";

const mocks = vi.hoisted(() => ({
  trackEvent: vi.fn(),
}));

vi.mock("#/services/telemetry", () => ({
  trackEvent: mocks.trackEvent,
}));

import {
  trackCloudConversationReady,
  trackCloudDeviceAuthorizationStarted,
  trackCloudDeviceAuthorizationSucceeded,
} from "#/services/cloud-funnel-analytics";

describe("cloud funnel analytics", () => {
  beforeEach(() => {
    mocks.trackEvent.mockReset();
  });

  it("emits the device authorization milestones with coarse attribution", () => {
    trackCloudDeviceAuthorizationStarted(
      "https://app.all-hands.dev",
      "onboarding",
    );
    trackCloudDeviceAuthorizationSucceeded(
      "https://app.all-hands.dev",
      "onboarding",
    );

    expect(mocks.trackEvent).toHaveBeenNthCalledWith(
      1,
      "cloud_device_authorization_started",
      expect.objectContaining({
        backend_kind: "cloud",
        connection_method: "cloud_login",
        agent_server_version: "unknown",
        automation_sdk_version: "unknown",
        backend_version: "unknown",
        source: "onboarding",
      }),
    );
    expect(mocks.trackEvent).toHaveBeenNthCalledWith(
      2,
      "cloud_device_authorization_succeeded",
      expect.objectContaining({ source: "onboarding" }),
    );
  });

  it("emits the ready milestone without conversation content", () => {
    trackCloudConversationReady("task-id", "conversation-id");

    expect(mocks.trackEvent).toHaveBeenNthCalledWith(
      1,
      "cloud_conversation_ready",
      expect.objectContaining({
        task_id: "task-id",
        conversation_id: "conversation-id",
        backend_kind: "cloud",
        agent_server_version: "unknown",
        automation_sdk_version: "unknown",
        backend_version: "unknown",
      }),
    );
  });

  it("uses a stable insert ID to deduplicate polling consumers at ingestion", () => {
    trackCloudConversationReady("task-dedupe", "conversation-dedupe");
    trackCloudConversationReady("task-dedupe", "conversation-dedupe");

    expect(mocks.trackEvent).toHaveBeenCalledTimes(2);
    expect(mocks.trackEvent).toHaveBeenNthCalledWith(
      2,
      "cloud_conversation_ready",
      expect.objectContaining({
        $insert_id: "agent_canvas:cloud_conversation_ready:task-dedupe",
      }),
    );
  });
});