Skip to content
Source
Sign inSign up

liveActivityPreferences.test.ts

161 lines5.4 KB

1import { beforeEach, vi } from "vite-plus/test";
2import { describe, expect, it } from "@effect/vitest";
3import * as Effect from "effect/Effect";
4import type { EnvironmentId } from "@t3tools/contracts";
5import { ManagedRelay } from "@t3tools/client-runtime/relay";
6import * as Layer from "effect/Layer";
7import { HttpClient } from "effect/http";
8​
9import type { SavedRemoteConnection } from "../../lib/connection";
10import * as MobileStorage from "../../persistence/mobile-storage";
11import {
12 CloudEnvironmentLinkError,
13 linkEnvironmentToCloudWithPreference,
14} from "../cloud/linkEnvironment";
15import { setLiveActivityUpdatesEnabled } from "./liveActivityPreferences";
16import { updateAgentAwarenessRegistrationPreferences } from "./remoteRegistration";
17​
18vi.mock("expo-secure-store", () => ({
19 deleteItemAsync: vi.fn(),
20 getItemAsync: vi.fn(),
21 setItemAsync: vi.fn(),
22}));
23​
24vi.mock("react-native", () => ({
25 Platform: { OS: "ios" },
26}));
27​
28vi.mock("expo-constants", () => ({
29 default: { expoConfig: {} },
30}));
31​
32vi.mock("expo-device", () => ({}));
33​
34vi.mock("../cloud/linkEnvironment", async (importOriginal) => ({
35 ...(await importOriginal<typeof import("../cloud/linkEnvironment")>()),
36 linkEnvironmentToCloudWithPreference: vi.fn(() => Effect.void),
37}));
38​
39vi.mock("./remoteRegistration", () => ({
40 updateAgentAwarenessRegistrationPreferences: vi.fn(() => Effect.void),
41}));
42​
43const connection: SavedRemoteConnection = {
44 environmentId: "env-1" as EnvironmentId,
45 environmentLabel: "Desktop",
46 pairingUrl: "https://desktop.example.test/",
47 displayUrl: "https://desktop.example.test/",
48 httpBaseUrl: "https://desktop.example.test/",
49 wsBaseUrl: "wss://desktop.example.test/ws",
50 bearerToken: "local-bearer",
51};
52​
53const layerTest = Layer.mergeAll(
54 Layer.succeed(ManagedRelay.ManagedRelayClient, null as never),
55 Layer.succeed(
56 HttpClient.HttpClient,
57 HttpClient.make(() => Effect.die("unexpected HTTP request")),
58 ),
59 Layer.succeed(
60 MobileStorage.MobileStorage,
61 MobileStorage.MobileStorage.of({
62 loadOrCreateAgentAwarenessDeviceId: Effect.succeed("device-1"),
63 loadAgentAwarenessDeviceId: Effect.succeed("device-1"),
64 loadAgentAwarenessRegistrationRecord: Effect.succeed(null),
65 saveAgentAwarenessRegistrationRecord: () => Effect.void,
66 clearAgentAwarenessRegistrationRecord: Effect.void,
67 loadRecentThreadShortcuts: Effect.succeed([]),
68 saveRecentThreadShortcuts: () => Effect.void,
69 }),
70 ),
71);
72​
73describe("liveActivityPreferences", () => {
74 beforeEach(() => {
75 vi.clearAllMocks();
76 });
77​
78 it.effect("restores relay preferences when an environment update fails", () => {
79 vi.mocked(linkEnvironmentToCloudWithPreference).mockImplementationOnce(() =>
80 Effect.fail(new CloudEnvironmentLinkError({ message: "environment update failed" })),
81 );
82​
83 return Effect.gen(function* () {
84 const exit = yield* Effect.exit(
85 setLiveActivityUpdatesEnabled({
86 enabled: false,
87 previousEnabled: true,
88 clerkToken: "clerk-token",
89 connections: [connection],
90 canConfigureEnvironment: () => true,
91 }),
92 );
93​
94 expect(exit._tag).toBe("Failure");
95 expect(updateAgentAwarenessRegistrationPreferences).toHaveBeenNthCalledWith(1, {
96 liveActivitiesEnabled: false,
97 });
98 expect(updateAgentAwarenessRegistrationPreferences).toHaveBeenNthCalledWith(2, {
99 liveActivitiesEnabled: true,
100 });
101 expect(linkEnvironmentToCloudWithPreference).toHaveBeenNthCalledWith(1, {
102 clerkToken: "clerk-token",
103 connection,
104 liveActivitiesEnabled: false,
105 });
106 expect(linkEnvironmentToCloudWithPreference).toHaveBeenNthCalledWith(2, {
107 clerkToken: "clerk-token",
108 connection,
109 liveActivitiesEnabled: true,
110 });
111 }).pipe(Effect.provide(layerTest));
112 });
113​
114 it.effect("only re-links environments with relay access when enabling updates", () => {
115 const readOnlyConnection: SavedRemoteConnection = {
116 ...connection,
117 environmentId: "read-only" as EnvironmentId,
118 };
119​
120 return Effect.gen(function* () {
121 yield* setLiveActivityUpdatesEnabled({
122 enabled: true,
123 previousEnabled: false,
124 clerkToken: "clerk-token",
125 connections: [readOnlyConnection, connection],
126 canConfigureEnvironment: (environmentId) => environmentId === connection.environmentId,
127 });
128​
129 expect(updateAgentAwarenessRegistrationPreferences).toHaveBeenCalledWith({
130 liveActivitiesEnabled: true,
131 });
132 expect(linkEnvironmentToCloudWithPreference).toHaveBeenCalledExactlyOnceWith({
133 clerkToken: "clerk-token",
134 connection,
135 liveActivitiesEnabled: true,
136 });
137 }).pipe(Effect.provide(layerTest));
138 });
139​
140 it.effect("checks current relay access after updating the device registration", () => {
141 let canConfigureEnvironment = true;
142 vi.mocked(updateAgentAwarenessRegistrationPreferences).mockImplementationOnce(() =>
143 Effect.sync(() => {
144 canConfigureEnvironment = false;
145 }),
146 );
147​
148 return Effect.gen(function* () {
149 yield* setLiveActivityUpdatesEnabled({
150 enabled: false,
151 previousEnabled: true,
152 clerkToken: "clerk-token",
153 connections: [connection],
154 canConfigureEnvironment: () => canConfigureEnvironment,
155 });
156​
157 expect(linkEnvironmentToCloudWithPreference).not.toHaveBeenCalled();
158 expect(updateAgentAwarenessRegistrationPreferences).toHaveBeenCalledTimes(1);
159 }).pipe(Effect.provide(layerTest));
160 });
161});