@q9labsai/chalk-react-native 4.1.11 → 4.1.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/android.js +4 -2
- package/dist/{chunk-MMBE2BVK.js → chunk-4NLA35HE.js} +649 -407
- package/dist/{chunk-LZ67SXGB.js → chunk-MK6OO4V7.js} +6 -0
- package/dist/client.js +1 -1
- package/dist/components/Entrance.d.ts.map +1 -1
- package/dist/components/logo/Logo.d.ts +11 -0
- package/dist/components/logo/Logo.d.ts.map +1 -0
- package/dist/components/native-space-view/SpaceTopBar.android.d.ts.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -2
- package/dist/ios-pad.js +4 -2
- package/dist/ios-phone.js +4 -2
- package/dist/ios.js +4 -2
- package/dist/macos.js +4 -2
- package/package.json +4 -4
- package/src/callkit/callkit.test.ts +12 -10
- package/src/components/Entrance.tsx +2 -1
- package/src/components/logo/Logo.tsx +309 -0
- package/src/components/native-space-view/SpaceTopBar.android.tsx +2 -1
- package/src/index.ts +2 -0
- package/src/space-client/create-native-space-client.ts +8 -0
- package/dist/components/LogoElements.d.ts +0 -6
- package/dist/components/LogoElements.d.ts.map +0 -1
- package/dist/test-support/test-renderer.d.ts +0 -20
- package/dist/test-support/test-renderer.d.ts.map +0 -1
- package/src/android/connection-service.test.ts +0 -114
- package/src/callkit/resolve-space-callkit-options.test.ts +0 -68
- package/src/client.test.ts +0 -12
- package/src/clipboard.test.ts +0 -79
- package/src/components/Chalk.test.tsx +0 -223
- package/src/components/EmbeddedWhiteboard.test.tsx +0 -92
- package/src/components/Entrance.test.tsx +0 -19
- package/src/components/EntranceView.android.test.tsx +0 -100
- package/src/components/EntranceView.ios-pad.test.tsx +0 -160
- package/src/components/EntranceView.ios-phone.test.tsx +0 -137
- package/src/components/EntranceView.test.tsx +0 -15
- package/src/components/LogoElements.test.tsx +0 -60
- package/src/components/LogoElements.tsx +0 -119
- package/src/components/ReactionPicker.test.tsx +0 -19
- package/src/components/RtcVideoView.test.tsx +0 -12
- package/src/components/SpaceView.android.test.tsx +0 -11
- package/src/components/SpaceView.ios-pad.test.tsx +0 -11
- package/src/components/SpaceView.ios-phone.test.tsx +0 -11
- package/src/components/SpaceView.macos.test.tsx +0 -11
- package/src/components/SpaceView.shared.test.tsx +0 -116
- package/src/components/SpaceView.test.tsx +0 -15
- package/src/components/android-connection-service-controller.test.ts +0 -80
- package/src/components/episode-diagnostic-render-observer.test.ts +0 -24
- package/src/components/native-animation-controller.test.ts +0 -47
- package/src/components/native-chat.test.ts +0 -22
- package/src/components/native-entrance/entrance-controller-store.test.ts +0 -75
- package/src/components/native-media-visibility.test.ts +0 -77
- package/src/components/native-space-callkit-controller.test.ts +0 -62
- package/src/components/native-space-view/AppearanceSettings.test.tsx +0 -56
- package/src/components/native-space-view/ParticipantActionSheet.test.tsx +0 -18
- package/src/components/native-space-view/SettingsSheet.test.tsx +0 -17
- package/src/components/native-space-view/SpaceActionMenu.test.tsx +0 -126
- package/src/components/native-space-view/SpaceBottomDock.android.test.tsx +0 -61
- package/src/components/native-space-view/SpaceChatSheet.test.tsx +0 -18
- package/src/components/native-space-view/SpaceMoreSheet.test.tsx +0 -15
- package/src/components/native-space-view/SpacePanelSheet.test.tsx +0 -15
- package/src/components/native-space-view/SpacePeopleSheet.test.tsx +0 -13
- package/src/components/native-space-view/SpaceSurfacePrimitives.test.tsx +0 -12
- package/src/components/native-space-view/SpaceTopBar.android.test.tsx +0 -43
- package/src/components/native-space-view/SpaceWhiteboardSurface.test.tsx +0 -85
- package/src/components/native-space-view/diagnostics.test.ts +0 -31
- package/src/components/native-space-view/format-space-duration.test.ts +0 -13
- package/src/components/native-space-view/native-space-grid-keys.test.ts +0 -11
- package/src/components/native-space-view/native-space-page-store.test.ts +0 -23
- package/src/components/native-space-view/space-chat-attachments.test.ts +0 -33
- package/src/components/native-space-view/space-progressive-surface-helpers.test.ts +0 -24
- package/src/components/native-space-view/useSpaceViewController.contract.test.ts +0 -10
- package/src/components/native-space-view/useSpaceViewController.test.ts +0 -106
- package/src/components/native-space-view/useSpaceViewDerived.test.ts +0 -58
- package/src/components/native-space-view/useSpaceViewPanels.controlled.test.ts +0 -40
- package/src/components/native-space-view/useSpaceViewPanels.test.ts +0 -73
- package/src/components/space-lifecycle.test.ts +0 -19
- package/src/context/space-client-context.test.tsx +0 -10
- package/src/diagnostics.test.ts +0 -29
- package/src/hooks/entrance-preview-store.test.ts +0 -79
- package/src/hooks/space-hooks.test.ts +0 -76
- package/src/hooks/useLayout.test.ts +0 -16
- package/src/invites.test.ts +0 -51
- package/src/public-surface.test.ts +0 -26
- package/src/runtime.test.ts +0 -83
- package/src/space-client/cloudflare-rtk-native.test.ts +0 -118
- package/src/space-client/create-native-space-client.test.ts +0 -300
- package/src/telemetry.test.ts +0 -143
- package/src/test-support/test-renderer.test.ts +0 -9
- package/src/test-support/test-renderer.ts +0 -28
- package/src/ui/appearance.test.ts +0 -61
- package/src/ui/native-appearance-context.controlled.test.tsx +0 -41
- package/src/ui/native-appearance-context.test.tsx +0 -14
- package/src/ui/native-theme.test.ts +0 -34
- package/src/ui/native-theme.test.tsx +0 -14
- package/src/ui/participant-avatar.test.ts +0 -29
- package/src/ui/theme-tokens.test.ts +0 -14
- package/src/ui/theme.test.ts +0 -36
- package/src/utils/build-chalk-invite-link.test.ts +0 -12
- package/src/utils/ios-simulator.test.ts +0 -96
- package/src/utils/native-space-layout.test.ts +0 -170
- package/src/whiteboard/embedded-whiteboard-assets.test.ts +0 -31
|
@@ -3,6 +3,7 @@ import { HugeiconsIcon } from "@hugeicons/react-native";
|
|
|
3
3
|
import { Image, Platform, StyleSheet, Text, View } from "react-native";
|
|
4
4
|
import { Theme } from "../../ui/theme";
|
|
5
5
|
import { useNativeTheme } from "../../ui/native-theme";
|
|
6
|
+
import { Logo } from "../logo/Logo";
|
|
6
7
|
|
|
7
8
|
export interface SpaceTopBarProps {
|
|
8
9
|
spaceName: string;
|
|
@@ -16,7 +17,7 @@ export function SpaceTopBarAndroid({ spaceName, participantCount, formattedDurat
|
|
|
16
17
|
return (
|
|
17
18
|
<View style={[styles.topBar, { backgroundColor: theme.colors.darkCanvas, borderColor: theme.colors.border }]}>
|
|
18
19
|
<View style={styles.topBarLeft}>
|
|
19
|
-
{logoUrl ? <Image accessibilityLabel="Chalk" source={{ uri: logoUrl }} style={styles.logo} /> :
|
|
20
|
+
{logoUrl ? <Image accessibilityLabel="Chalk" source={{ uri: logoUrl }} style={styles.logo} /> : <Logo height={24} variant="mark" />}
|
|
20
21
|
<View style={[styles.connectionDot, { backgroundColor: theme.colors.success }]} />
|
|
21
22
|
<Text style={[styles.topBarSpaceName, { color: theme.colors.foreground }]} numberOfLines={1}>
|
|
22
23
|
{spaceName}
|
package/src/index.ts
CHANGED
|
@@ -2,6 +2,8 @@ export { Chalk } from "./components/Chalk";
|
|
|
2
2
|
export type { ChalkFeatures, ChalkProps, ChalkTheme, ChalkThemeTokens, SpaceLayout } from "./components/Chalk";
|
|
3
3
|
export { Entrance } from "./components/Entrance";
|
|
4
4
|
export type { EntranceProps, EntranceSettings } from "./components/Entrance";
|
|
5
|
+
export { Logo } from "./components/logo/Logo";
|
|
6
|
+
export type { LogoMotion, LogoProps, LogoVariant } from "./components/logo/Logo";
|
|
5
7
|
export { ChalkProvider, useSpaceClient } from "./context/space-client-context";
|
|
6
8
|
export type { ChalkProviderProps } from "./context/space-client-context";
|
|
7
9
|
export { useCan, useChat, useConnection, useMedia, useParticipants, useReactions, useSelf, useWhiteboard } from "./hooks/space-hooks";
|
|
@@ -144,6 +144,7 @@ function createMediaClient(apiBaseURL: string, input: MediaFactoryInput, fetch:
|
|
|
144
144
|
});
|
|
145
145
|
return createRTKConnectionMediaClient(client);
|
|
146
146
|
}
|
|
147
|
+
const replaceMediaConnection = input.replaceMediaConnection;
|
|
147
148
|
const client = new CloudflareSFUClient({
|
|
148
149
|
bootstrap: input.access.media.clientPayload,
|
|
149
150
|
participantId: subject.participantId,
|
|
@@ -156,6 +157,13 @@ function createMediaClient(apiBaseURL: string, input: MediaFactoryInput, fetch:
|
|
|
156
157
|
participantId: subject.participantId,
|
|
157
158
|
fetch,
|
|
158
159
|
}),
|
|
160
|
+
replaceMediaConnection: replaceMediaConnection
|
|
161
|
+
? async () => {
|
|
162
|
+
const replacement = await replaceMediaConnection();
|
|
163
|
+
if (replacement.provider !== "cloudflare_sfu") throw new TypeError("The Cloudflare SFU adapter requires a Cloudflare SFU access grant");
|
|
164
|
+
return replacement.clientPayload;
|
|
165
|
+
}
|
|
166
|
+
: undefined,
|
|
159
167
|
peerConnectionFactory: (configuration) => {
|
|
160
168
|
const connection = new RTCPeerConnection(configuration);
|
|
161
169
|
observePeerConnection?.(connection as unknown as RtcPeerConnection);
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"LogoElements.d.ts","sourceRoot":"","sources":["../../src/components/LogoElements.tsx"],"names":[],"mappings":"AASA,UAAU,iBAAiB;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,wBAAgB,YAAY,CAAC,EAAE,IAAS,EAAE,EAAE,iBAAiB,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAyGhF"}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import type { ComponentType, ReactNode } from "react";
|
|
2
|
-
type RenderHookOptions<Props> = {
|
|
3
|
-
readonly initialProps?: Props;
|
|
4
|
-
readonly wrapper?: ComponentType<{
|
|
5
|
-
readonly children?: ReactNode;
|
|
6
|
-
}>;
|
|
7
|
-
};
|
|
8
|
-
type RenderHookResult<Result, Props> = {
|
|
9
|
-
readonly result: {
|
|
10
|
-
readonly current: Result;
|
|
11
|
-
};
|
|
12
|
-
readonly rerender: (props?: Props) => void;
|
|
13
|
-
readonly unmount: () => void;
|
|
14
|
-
};
|
|
15
|
-
type RenderHook = <Result, Props = undefined>(callback: (props: Props) => Result, options?: RenderHookOptions<Props>) => RenderHookResult<Result, Props>;
|
|
16
|
-
type Act = (callback: () => void | Promise<void>) => void | Promise<void>;
|
|
17
|
-
type WaitFor = (callback: () => void | Promise<void>) => Promise<void>;
|
|
18
|
-
export declare const act: Act, renderHook: RenderHook, waitFor: WaitFor;
|
|
19
|
-
export {};
|
|
20
|
-
//# sourceMappingURL=test-renderer.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"test-renderer.d.ts","sourceRoot":"","sources":["../../src/test-support/test-renderer.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEtD,KAAK,iBAAiB,CAAC,KAAK,IAAI;IAC9B,QAAQ,CAAC,YAAY,CAAC,EAAE,KAAK,CAAC;IAC9B,QAAQ,CAAC,OAAO,CAAC,EAAE,aAAa,CAAC;QAAE,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,CAAA;KAAE,CAAC,CAAC;CACrE,CAAC;AAEF,KAAK,gBAAgB,CAAC,MAAM,EAAE,KAAK,IAAI;IACrC,QAAQ,CAAC,MAAM,EAAE;QAAE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAC9C,QAAQ,CAAC,QAAQ,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,KAAK,IAAI,CAAC;IAC3C,QAAQ,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC;CAC9B,CAAC;AAEF,KAAK,UAAU,GAAG,CAAC,MAAM,EAAE,KAAK,GAAG,SAAS,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,MAAM,EAAE,OAAO,CAAC,EAAE,iBAAiB,CAAC,KAAK,CAAC,KAAK,gBAAgB,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;AACzJ,KAAK,GAAG,GAAG,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAC1E,KAAK,OAAO,GAAG,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAQvE,eAAO,MAAQ,GAAG,OAAE,UAAU,cAAE,OAAO,SAAmB,CAAC"}
|
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
2
|
-
|
|
3
|
-
const nativeModule = {
|
|
4
|
-
addListener: vi.fn(),
|
|
5
|
-
endCall: vi.fn(async () => true),
|
|
6
|
-
isSupported: vi.fn(async () => true),
|
|
7
|
-
registerPhoneAccount: vi.fn(async () => true),
|
|
8
|
-
removeListeners: vi.fn(),
|
|
9
|
-
setActive: vi.fn(async () => true),
|
|
10
|
-
startCall: vi.fn(async () => true),
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
const subscriptions = new Map<string, (payload: unknown) => void>();
|
|
14
|
-
const platform = { OS: "android" };
|
|
15
|
-
|
|
16
|
-
class MockNativeEventEmitter {
|
|
17
|
-
addListener(eventName: string, listener: (payload: unknown) => void) {
|
|
18
|
-
subscriptions.set(eventName, listener);
|
|
19
|
-
return {
|
|
20
|
-
remove: () => {
|
|
21
|
-
subscriptions.delete(eventName);
|
|
22
|
-
},
|
|
23
|
-
};
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
vi.mock("react-native", () => ({
|
|
28
|
-
NativeEventEmitter: MockNativeEventEmitter,
|
|
29
|
-
NativeModules: {
|
|
30
|
-
ChalkAndroidConnectionService: nativeModule,
|
|
31
|
-
},
|
|
32
|
-
Platform: platform,
|
|
33
|
-
}));
|
|
34
|
-
|
|
35
|
-
describe("android connection service bridge", () => {
|
|
36
|
-
beforeEach(() => {
|
|
37
|
-
vi.resetModules();
|
|
38
|
-
vi.clearAllMocks();
|
|
39
|
-
subscriptions.clear();
|
|
40
|
-
platform.OS = "android";
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
it("no-ops when Android native support is unavailable", async () => {
|
|
44
|
-
platform.OS = "ios";
|
|
45
|
-
|
|
46
|
-
const { addAndroidConnectionServiceListener, ensureAndroidConnectionServiceRegistered, endAndroidConnectionServiceCall, isAndroidConnectionServiceSupported, setAndroidConnectionServiceActive, startAndroidConnectionServiceCall } = await import("./connection-service");
|
|
47
|
-
|
|
48
|
-
expect(await isAndroidConnectionServiceSupported()).toBe(false);
|
|
49
|
-
expect(await ensureAndroidConnectionServiceRegistered()).toBe(false);
|
|
50
|
-
expect(
|
|
51
|
-
await startAndroidConnectionServiceCall({
|
|
52
|
-
callId: "space-1:1",
|
|
53
|
-
displayName: "Host",
|
|
54
|
-
spaceId: "space-1",
|
|
55
|
-
spaceName: "Daily Standup",
|
|
56
|
-
}),
|
|
57
|
-
).toBe(false);
|
|
58
|
-
expect(await setAndroidConnectionServiceActive("space-1:1")).toBe(false);
|
|
59
|
-
expect(await endAndroidConnectionServiceCall("space-1:1")).toBe(false);
|
|
60
|
-
|
|
61
|
-
const unsubscribe = addAndroidConnectionServiceListener(() => {
|
|
62
|
-
throw new Error("listener should not be called on iOS");
|
|
63
|
-
});
|
|
64
|
-
unsubscribe();
|
|
65
|
-
|
|
66
|
-
expect(nativeModule.isSupported).not.toHaveBeenCalled();
|
|
67
|
-
expect(nativeModule.registerPhoneAccount).not.toHaveBeenCalled();
|
|
68
|
-
expect(nativeModule.startCall).not.toHaveBeenCalled();
|
|
69
|
-
expect(nativeModule.setActive).not.toHaveBeenCalled();
|
|
70
|
-
expect(nativeModule.endCall).not.toHaveBeenCalled();
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
it("passes through Android native module calls and emits disconnect events", async () => {
|
|
74
|
-
const { addAndroidConnectionServiceListener, ensureAndroidConnectionServiceRegistered, endAndroidConnectionServiceCall, isAndroidConnectionServiceSupported, setAndroidConnectionServiceActive, startAndroidConnectionServiceCall } = await import("./connection-service");
|
|
75
|
-
|
|
76
|
-
expect(await isAndroidConnectionServiceSupported()).toBe(true);
|
|
77
|
-
expect(await ensureAndroidConnectionServiceRegistered()).toBe(true);
|
|
78
|
-
expect(
|
|
79
|
-
await startAndroidConnectionServiceCall({
|
|
80
|
-
callId: "space-1:2",
|
|
81
|
-
displayName: "Guest",
|
|
82
|
-
hasVideo: false,
|
|
83
|
-
spaceId: "space-1",
|
|
84
|
-
spaceName: "Board Review",
|
|
85
|
-
}),
|
|
86
|
-
).toBe(true);
|
|
87
|
-
expect(await setAndroidConnectionServiceActive("space-1:2")).toBe(true);
|
|
88
|
-
expect(await endAndroidConnectionServiceCall("space-1:2", { reason: "remote", label: "Space ended" })).toBe(true);
|
|
89
|
-
|
|
90
|
-
const listener = vi.fn();
|
|
91
|
-
const unsubscribe = addAndroidConnectionServiceListener(listener);
|
|
92
|
-
const disconnectPayload = {
|
|
93
|
-
callId: "space-1:2",
|
|
94
|
-
reason: "local",
|
|
95
|
-
type: "disconnect",
|
|
96
|
-
};
|
|
97
|
-
|
|
98
|
-
subscriptions.get("ChalkAndroidConnectionServiceEvent")?.(disconnectPayload);
|
|
99
|
-
unsubscribe();
|
|
100
|
-
|
|
101
|
-
expect(nativeModule.isSupported).toHaveBeenCalledTimes(1);
|
|
102
|
-
expect(nativeModule.registerPhoneAccount).toHaveBeenCalledTimes(1);
|
|
103
|
-
expect(nativeModule.startCall).toHaveBeenCalledWith({
|
|
104
|
-
callId: "space-1:2",
|
|
105
|
-
displayName: "Guest",
|
|
106
|
-
hasVideo: false,
|
|
107
|
-
spaceId: "space-1",
|
|
108
|
-
spaceName: "Board Review",
|
|
109
|
-
});
|
|
110
|
-
expect(nativeModule.setActive).toHaveBeenCalledWith("space-1:2");
|
|
111
|
-
expect(nativeModule.endCall).toHaveBeenCalledWith("space-1:2", "remote", "Space ended");
|
|
112
|
-
expect(listener).toHaveBeenCalledWith(disconnectPayload);
|
|
113
|
-
});
|
|
114
|
-
});
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from "vitest";
|
|
2
|
-
import { resolveSpaceCallKitOptions } from "./resolve-space-callkit-options";
|
|
3
|
-
|
|
4
|
-
describe("resolveSpaceCallKitOptions", () => {
|
|
5
|
-
it("returns null when CallKit is disabled", () => {
|
|
6
|
-
expect(
|
|
7
|
-
resolveSpaceCallKitOptions({
|
|
8
|
-
callKit: false,
|
|
9
|
-
hasVideo: true,
|
|
10
|
-
spaceId: "space-123",
|
|
11
|
-
spaceName: "Design Review",
|
|
12
|
-
}),
|
|
13
|
-
).toBeNull();
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
it("fills sensible defaults for enabled Spaces", () => {
|
|
17
|
-
expect(
|
|
18
|
-
resolveSpaceCallKitOptions({
|
|
19
|
-
callKit: true,
|
|
20
|
-
hasVideo: true,
|
|
21
|
-
spaceId: "space-123",
|
|
22
|
-
spaceName: "Design Review",
|
|
23
|
-
}),
|
|
24
|
-
).toEqual({
|
|
25
|
-
appName: "Chalk",
|
|
26
|
-
displayName: "Design Review",
|
|
27
|
-
handle: "space-123",
|
|
28
|
-
handleType: "generic",
|
|
29
|
-
hasVideo: true,
|
|
30
|
-
includesCallsInRecents: false,
|
|
31
|
-
maximumCallGroups: 1,
|
|
32
|
-
maximumCallsPerCallGroup: 1,
|
|
33
|
-
iconTemplateImageName: undefined,
|
|
34
|
-
ringtoneSound: undefined,
|
|
35
|
-
});
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
it("prefers explicit overrides from the caller", () => {
|
|
39
|
-
expect(
|
|
40
|
-
resolveSpaceCallKitOptions({
|
|
41
|
-
callKit: {
|
|
42
|
-
appName: "Chalk Meet",
|
|
43
|
-
displayName: "Board Space",
|
|
44
|
-
handle: "board-space",
|
|
45
|
-
handleType: "emailAddress",
|
|
46
|
-
hasVideo: false,
|
|
47
|
-
includesCallsInRecents: true,
|
|
48
|
-
maximumCallGroups: 2,
|
|
49
|
-
maximumCallsPerCallGroup: 3,
|
|
50
|
-
ringtoneSound: "ring.caf",
|
|
51
|
-
},
|
|
52
|
-
hasVideo: true,
|
|
53
|
-
spaceId: "space-123",
|
|
54
|
-
}),
|
|
55
|
-
).toEqual({
|
|
56
|
-
appName: "Chalk Meet",
|
|
57
|
-
displayName: "Board Space",
|
|
58
|
-
handle: "board-space",
|
|
59
|
-
handleType: "emailAddress",
|
|
60
|
-
hasVideo: false,
|
|
61
|
-
includesCallsInRecents: true,
|
|
62
|
-
maximumCallGroups: 2,
|
|
63
|
-
maximumCallsPerCallGroup: 3,
|
|
64
|
-
iconTemplateImageName: undefined,
|
|
65
|
-
ringtoneSound: "ring.caf",
|
|
66
|
-
});
|
|
67
|
-
});
|
|
68
|
-
});
|
package/src/client.test.ts
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import type { GetAccess, SpaceClient } from "@q9labsai/chalk-client";
|
|
2
|
-
import { expectTypeOf, test } from "vitest";
|
|
3
|
-
|
|
4
|
-
import type { NativeSpaceClientOptions } from "./client";
|
|
5
|
-
|
|
6
|
-
test("the native client subpath exposes the advanced-construction contract", () => {
|
|
7
|
-
expectTypeOf<NativeSpaceClientOptions>().toMatchTypeOf<{
|
|
8
|
-
readonly space: string;
|
|
9
|
-
readonly getAccess: GetAccess;
|
|
10
|
-
}>();
|
|
11
|
-
expectTypeOf<typeof import("./client").createNativeSpaceClient>().returns.toEqualTypeOf<SpaceClient>();
|
|
12
|
-
});
|
package/src/clipboard.test.ts
DELETED
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it, vi } from "vitest";
|
|
2
|
-
import { createClipboardTextStore } from "./clipboard-store";
|
|
3
|
-
|
|
4
|
-
vi.mock("react-native", () => ({
|
|
5
|
-
AppState: { addEventListener: vi.fn(() => ({ remove: vi.fn() })) },
|
|
6
|
-
NativeModules: { ChalkRuntimeInfo: { isSimulator: false } },
|
|
7
|
-
Platform: { OS: "ios" },
|
|
8
|
-
}));
|
|
9
|
-
|
|
10
|
-
describe("clipboard invite suggestion hook", () => {
|
|
11
|
-
it("exposes the extracted clipboard suggestion hook", async () => {
|
|
12
|
-
const { useClipboardInviteSuggestion } = await import("./clipboard");
|
|
13
|
-
|
|
14
|
-
expect(typeof useClipboardInviteSuggestion).toBe("function");
|
|
15
|
-
});
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
describe("createClipboardTextStore", () => {
|
|
19
|
-
it("refreshes on subscription and active app-state events, then stops after unsubscribe", async () => {
|
|
20
|
-
let appStateListener: ((nextState: string) => void) | undefined;
|
|
21
|
-
const removeAppStateListener = vi.fn();
|
|
22
|
-
const clipboard = {
|
|
23
|
-
hasStringAsync: vi.fn().mockResolvedValue(true),
|
|
24
|
-
getStringAsync: vi.fn().mockResolvedValue("chalk invite"),
|
|
25
|
-
};
|
|
26
|
-
const store = createClipboardTextStore({
|
|
27
|
-
clipboard,
|
|
28
|
-
shouldReadClipboard: true,
|
|
29
|
-
subscribeToAppState: (listener) => {
|
|
30
|
-
appStateListener = listener;
|
|
31
|
-
return { remove: removeAppStateListener };
|
|
32
|
-
},
|
|
33
|
-
});
|
|
34
|
-
const listener = vi.fn();
|
|
35
|
-
|
|
36
|
-
const unsubscribe = store.subscribe(listener);
|
|
37
|
-
await Promise.resolve();
|
|
38
|
-
await Promise.resolve();
|
|
39
|
-
|
|
40
|
-
expect(store.getSnapshot()).toBe("chalk invite");
|
|
41
|
-
expect(listener).toHaveBeenCalledOnce();
|
|
42
|
-
|
|
43
|
-
appStateListener?.("active");
|
|
44
|
-
await Promise.resolve();
|
|
45
|
-
await Promise.resolve();
|
|
46
|
-
|
|
47
|
-
expect(clipboard.hasStringAsync).toHaveBeenCalledTimes(2);
|
|
48
|
-
|
|
49
|
-
unsubscribe();
|
|
50
|
-
expect(removeAppStateListener).toHaveBeenCalledOnce();
|
|
51
|
-
appStateListener?.("active");
|
|
52
|
-
await Promise.resolve();
|
|
53
|
-
await Promise.resolve();
|
|
54
|
-
|
|
55
|
-
expect(clipboard.hasStringAsync).toHaveBeenCalledTimes(2);
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
it("does not read the clipboard when the platform policy disables automatic reads", async () => {
|
|
59
|
-
const clipboard = {
|
|
60
|
-
hasStringAsync: vi.fn(),
|
|
61
|
-
getStringAsync: vi.fn(),
|
|
62
|
-
};
|
|
63
|
-
const subscribeToAppState = vi.fn();
|
|
64
|
-
const store = createClipboardTextStore({
|
|
65
|
-
clipboard,
|
|
66
|
-
shouldReadClipboard: false,
|
|
67
|
-
subscribeToAppState,
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
const unsubscribe = store.subscribe(vi.fn());
|
|
71
|
-
await Promise.resolve();
|
|
72
|
-
|
|
73
|
-
expect(store.getSnapshot()).toBeNull();
|
|
74
|
-
expect(clipboard.hasStringAsync).not.toHaveBeenCalled();
|
|
75
|
-
expect(subscribeToAppState).not.toHaveBeenCalled();
|
|
76
|
-
|
|
77
|
-
unsubscribe();
|
|
78
|
-
});
|
|
79
|
-
});
|
|
@@ -1,223 +0,0 @@
|
|
|
1
|
-
// @vitest-environment happy-dom
|
|
2
|
-
import type { SpaceClient, SpaceSnapshot } from "@q9labsai/chalk-client";
|
|
3
|
-
import { createRequire } from "node:module";
|
|
4
|
-
import { join } from "node:path";
|
|
5
|
-
import type { ReactNode } from "react";
|
|
6
|
-
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
7
|
-
|
|
8
|
-
const testingLibrary = createRequire(import.meta.url)(join(process.cwd(), "../react/node_modules", "@testing-library/react")) as {
|
|
9
|
-
readonly act: (callback: () => void | Promise<void>) => void | Promise<void>;
|
|
10
|
-
readonly cleanup: () => void;
|
|
11
|
-
readonly render: (element: ReactNode) => { readonly container: HTMLElement; readonly unmount: () => void; readonly rerender: (element: ReactNode) => void };
|
|
12
|
-
};
|
|
13
|
-
const { act, cleanup, render } = testingLibrary;
|
|
14
|
-
|
|
15
|
-
const nativeClientFactory = vi.hoisted(() => vi.fn());
|
|
16
|
-
const spaceViewSpy = vi.hoisted(() => vi.fn(() => <div data-testid="space" />));
|
|
17
|
-
|
|
18
|
-
vi.mock("react-native", () => ({
|
|
19
|
-
StyleSheet: { create: <T,>(styles: T) => styles },
|
|
20
|
-
View: ({ children }: { readonly children?: ReactNode }) => children,
|
|
21
|
-
Text: ({ children }: { readonly children?: ReactNode }) => children,
|
|
22
|
-
Pressable: ({ children }: { readonly children?: ReactNode }) => children,
|
|
23
|
-
}));
|
|
24
|
-
vi.mock("../space-client/create-native-space-client", () => ({ createNativeSpaceClient: nativeClientFactory }));
|
|
25
|
-
vi.mock("./SpaceView", () => ({ SpaceView: spaceViewSpy }));
|
|
26
|
-
vi.mock("./Entrance", () => ({ Entrance: () => <div data-testid="entrance" /> }));
|
|
27
|
-
|
|
28
|
-
import { Chalk } from "./Chalk";
|
|
29
|
-
|
|
30
|
-
afterEach(() => {
|
|
31
|
-
cleanup();
|
|
32
|
-
nativeClientFactory.mockReset();
|
|
33
|
-
spaceViewSpy.mockClear();
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
describe("Chalk", () => {
|
|
37
|
-
it("fires joined and left only for the specified connection transitions", () => {
|
|
38
|
-
const client = createClient("joining");
|
|
39
|
-
const onJoined = vi.fn();
|
|
40
|
-
const onLeft = vi.fn();
|
|
41
|
-
render(<Chalk client={client.client} entrance={false} onJoined={onJoined} onLeft={onLeft} />);
|
|
42
|
-
|
|
43
|
-
act(() => client.setStatus("live"));
|
|
44
|
-
act(() => client.setStatus("reconnecting"));
|
|
45
|
-
act(() => client.setStatus("live"));
|
|
46
|
-
act(() => client.setStatus("left"));
|
|
47
|
-
|
|
48
|
-
expect(onJoined).toHaveBeenCalledTimes(1);
|
|
49
|
-
expect(onLeft).toHaveBeenCalledTimes(1);
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
it("does not fire joined for an already-live supplied client", () => {
|
|
53
|
-
const client = createClient("live");
|
|
54
|
-
const onJoined = vi.fn();
|
|
55
|
-
render(<Chalk client={client.client} entrance={false} onJoined={onJoined} />);
|
|
56
|
-
|
|
57
|
-
expect(onJoined).not.toHaveBeenCalled();
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
it("forwards the optional diagnostics action to the live Space", () => {
|
|
61
|
-
const client = createClient("live");
|
|
62
|
-
const onOpenDiagnostics = vi.fn();
|
|
63
|
-
render(<Chalk client={client.client} onOpenDiagnostics={onOpenDiagnostics} />);
|
|
64
|
-
|
|
65
|
-
expect(spaceViewSpy).toHaveBeenCalledWith(expect.objectContaining({ onOpenDiagnostics }), undefined);
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
it("forwards canonical client events and cleans their subscriptions up", () => {
|
|
69
|
-
const client = createClient("live");
|
|
70
|
-
const handlers = new Map<string, (event: unknown) => void>();
|
|
71
|
-
const unsubscribe = vi.fn();
|
|
72
|
-
const eventClient = client.client as { on: (event: string, handler: unknown) => () => void };
|
|
73
|
-
eventClient.on = vi.fn((event, handler) => {
|
|
74
|
-
handlers.set(event, handler as (event: unknown) => void);
|
|
75
|
-
return unsubscribe;
|
|
76
|
-
});
|
|
77
|
-
const onError = vi.fn();
|
|
78
|
-
const view = render(<Chalk client={client.client} onEpisodeEnded={vi.fn()} onError={onError} onParticipantJoined={vi.fn()} onParticipantLeft={vi.fn()} onScreenShareStarted={vi.fn()} onScreenShareStopped={vi.fn()} />);
|
|
79
|
-
|
|
80
|
-
const error = { error: { code: "client.internal_error", message: "test", recoverable: true } };
|
|
81
|
-
handlers.get("error")?.(error);
|
|
82
|
-
expect(onError).toHaveBeenCalledWith(error);
|
|
83
|
-
|
|
84
|
-
view.unmount();
|
|
85
|
-
expect(unsubscribe).toHaveBeenCalledTimes(6);
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
it("leaves an owned client before disposing it on unmount", async () => {
|
|
89
|
-
const client = createClient("joining");
|
|
90
|
-
let resolveLeave: (() => void) | undefined;
|
|
91
|
-
client.client.leave = vi.fn(
|
|
92
|
-
() =>
|
|
93
|
-
new Promise<void>((resolve) => {
|
|
94
|
-
resolveLeave = resolve;
|
|
95
|
-
}),
|
|
96
|
-
);
|
|
97
|
-
nativeClientFactory.mockReturnValue(client.client);
|
|
98
|
-
|
|
99
|
-
const view = render(<Chalk entrance={false} getAccess={vi.fn()} space="space-1" />);
|
|
100
|
-
view.unmount();
|
|
101
|
-
|
|
102
|
-
expect(client.client.leave).toHaveBeenCalledTimes(1);
|
|
103
|
-
expect(client.client.dispose).not.toHaveBeenCalled();
|
|
104
|
-
await act(async () => resolveLeave?.());
|
|
105
|
-
expect(client.client.dispose).toHaveBeenCalledTimes(1);
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
it("keeps an owned SpaceClient when getAccess changes identity and uses the latest callback", async () => {
|
|
109
|
-
const client = createClient("idle");
|
|
110
|
-
const firstAccess = vi.fn(async () => ({ token: "first" }));
|
|
111
|
-
const latestAccess = vi.fn(async () => ({ token: "latest" }));
|
|
112
|
-
nativeClientFactory.mockReturnValue(client.client);
|
|
113
|
-
|
|
114
|
-
const view = render(<Chalk entrance getAccess={firstAccess} space="space-1" />);
|
|
115
|
-
view.rerender(<Chalk entrance getAccess={latestAccess} space="space-1" />);
|
|
116
|
-
|
|
117
|
-
expect(nativeClientFactory).toHaveBeenCalledTimes(1);
|
|
118
|
-
const access = nativeClientFactory.mock.calls[0]?.[0].getAccess as (input: unknown) => Promise<unknown>;
|
|
119
|
-
await expect(access({})).resolves.toEqual({ token: "latest" });
|
|
120
|
-
expect(firstAccess).not.toHaveBeenCalled();
|
|
121
|
-
expect(latestAccess).toHaveBeenCalledTimes(1);
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
it("omits an absent display name when joining without Entrance", async () => {
|
|
125
|
-
const client = createClient("idle");
|
|
126
|
-
render(<Chalk client={client.client} entrance={false} />);
|
|
127
|
-
|
|
128
|
-
await act(async () => undefined);
|
|
129
|
-
expect(client.client.join).toHaveBeenCalledWith({ microphone: true, camera: true });
|
|
130
|
-
});
|
|
131
|
-
|
|
132
|
-
it("retries automatic join when an owned client is replaced for a new Space", async () => {
|
|
133
|
-
const first = createClient("idle");
|
|
134
|
-
const replacement = createClient("idle");
|
|
135
|
-
nativeClientFactory.mockReturnValueOnce(first.client).mockReturnValueOnce(replacement.client);
|
|
136
|
-
|
|
137
|
-
const view = render(<Chalk entrance={false} getAccess={vi.fn()} space="space-1" />);
|
|
138
|
-
await act(async () => undefined);
|
|
139
|
-
expect(first.client.join).toHaveBeenCalledWith({ microphone: true, camera: true });
|
|
140
|
-
|
|
141
|
-
view.rerender(<Chalk entrance={false} getAccess={vi.fn()} space="space-2" />);
|
|
142
|
-
await act(async () => undefined);
|
|
143
|
-
|
|
144
|
-
expect(nativeClientFactory).toHaveBeenCalledTimes(2);
|
|
145
|
-
expect(replacement.client.join).toHaveBeenCalledWith({ microphone: true, camera: true });
|
|
146
|
-
});
|
|
147
|
-
|
|
148
|
-
it("treats a replacement client's initial failure as an Entrance failure", () => {
|
|
149
|
-
const first = createClient("live");
|
|
150
|
-
const replacement = createClient("failed");
|
|
151
|
-
nativeClientFactory.mockReturnValueOnce(first.client).mockReturnValueOnce(replacement.client);
|
|
152
|
-
|
|
153
|
-
const view = render(<Chalk entrance getAccess={vi.fn()} space="space-1" />);
|
|
154
|
-
view.rerender(<Chalk entrance getAccess={vi.fn()} space="space-2" />);
|
|
155
|
-
|
|
156
|
-
expect(view.container.querySelector('[data-testid="entrance"]')).not.toBeNull();
|
|
157
|
-
});
|
|
158
|
-
|
|
159
|
-
it("keeps the active Space visible during reconnecting and never after left", () => {
|
|
160
|
-
const client = createClient("live");
|
|
161
|
-
const view = render(<Chalk client={client.client} />);
|
|
162
|
-
|
|
163
|
-
expect(view.container.querySelector('[data-testid="space"]')).not.toBeNull();
|
|
164
|
-
act(() => client.setStatus("reconnecting"));
|
|
165
|
-
expect(view.container.querySelector('[data-testid="space"]')).not.toBeNull();
|
|
166
|
-
act(() => client.setStatus("left"));
|
|
167
|
-
expect(view.container.querySelector('[data-testid="space"]')).toBeNull();
|
|
168
|
-
expect(view.container.textContent).toContain("You have left this Space.");
|
|
169
|
-
});
|
|
170
|
-
});
|
|
171
|
-
|
|
172
|
-
function createClient(status: SpaceSnapshot["connection"]["status"]): { readonly client: SpaceClient; readonly setStatus: (nextStatus: SpaceSnapshot["connection"]["status"]) => void } {
|
|
173
|
-
let snapshot = createSnapshot(status);
|
|
174
|
-
const listeners = new Set<() => void>();
|
|
175
|
-
const client = {
|
|
176
|
-
getSnapshot: () => snapshot,
|
|
177
|
-
subscribe: (listener: () => void) => {
|
|
178
|
-
listeners.add(listener);
|
|
179
|
-
return () => listeners.delete(listener);
|
|
180
|
-
},
|
|
181
|
-
on: vi.fn(() => () => undefined),
|
|
182
|
-
join: vi.fn(async () => undefined),
|
|
183
|
-
leave: vi.fn(async () => undefined),
|
|
184
|
-
dispose: vi.fn(),
|
|
185
|
-
endEpisode: vi.fn(async () => undefined),
|
|
186
|
-
media: {},
|
|
187
|
-
chat: {},
|
|
188
|
-
participants: {},
|
|
189
|
-
reactions: {},
|
|
190
|
-
whiteboard: {},
|
|
191
|
-
} as unknown as SpaceClient;
|
|
192
|
-
return {
|
|
193
|
-
client,
|
|
194
|
-
setStatus(nextStatus) {
|
|
195
|
-
snapshot = { ...snapshot, connection: { ...snapshot.connection, status: nextStatus } };
|
|
196
|
-
listeners.forEach((listener) => listener());
|
|
197
|
-
},
|
|
198
|
-
};
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
function createSnapshot(status: SpaceSnapshot["connection"]["status"]): SpaceSnapshot {
|
|
202
|
-
const capabilities = [] as const;
|
|
203
|
-
return {
|
|
204
|
-
connection: { status, episode: null, lastError: null },
|
|
205
|
-
self: { participantId: null, displayName: null, role: null, capabilities, handRaised: false, can: () => false },
|
|
206
|
-
participants: { roster: [], admissionQueue: [] },
|
|
207
|
-
media: {
|
|
208
|
-
devices: { microphones: [], cameras: [], speakers: [] },
|
|
209
|
-
selection: { microphone: null, camera: null, speaker: null },
|
|
210
|
-
local: {
|
|
211
|
-
microphone: { source: "microphone", state: "disabled", track: null },
|
|
212
|
-
camera: { source: "camera", state: "disabled", track: null },
|
|
213
|
-
screen: { source: "screen", state: "disabled", track: null },
|
|
214
|
-
},
|
|
215
|
-
remote: [],
|
|
216
|
-
screenShare: { source: "screen", state: "disabled", track: null },
|
|
217
|
-
incomingRequests: [],
|
|
218
|
-
},
|
|
219
|
-
chat: { status: "idle", messages: [], pendingSends: [], readReceipts: [], unreadCount: 0, pagination: { cursor: null, hasOlder: false, historyTruncated: false }, lastError: null },
|
|
220
|
-
reactions: { active: [] },
|
|
221
|
-
whiteboard: { open: false, engine: { status: "unsubscribed", sceneId: null, revision: null, presenting: false, error: null } },
|
|
222
|
-
};
|
|
223
|
-
}
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it, vi } from "vitest";
|
|
2
|
-
|
|
3
|
-
const nativeTheme = vi.hoisted(() => ({
|
|
4
|
-
colorScheme: "light" as const,
|
|
5
|
-
colors: {
|
|
6
|
-
dangerSurfaceOverlay94: "#danger",
|
|
7
|
-
info: "#info",
|
|
8
|
-
lightMutedText: "#muted",
|
|
9
|
-
lightSubtleText: "#subtle",
|
|
10
|
-
lightSurface: "#surface",
|
|
11
|
-
lightText: "#text",
|
|
12
|
-
onDark: "#on-dark",
|
|
13
|
-
},
|
|
14
|
-
}));
|
|
15
|
-
const controllerOptions = vi.hoisted(() => [] as unknown[]);
|
|
16
|
-
|
|
17
|
-
vi.mock("react", () => ({
|
|
18
|
-
useCallback: <T,>(callback: T) => callback,
|
|
19
|
-
useEffect: (effect: () => void) => effect(),
|
|
20
|
-
useMemo: <T,>(factory: () => T) => factory(),
|
|
21
|
-
useRef: <T,>(current: T) => ({ current }),
|
|
22
|
-
useState: <T,>(initial: T | (() => T)): readonly [T, () => void] => [typeof initial === "function" ? (initial as () => T)() : initial, () => undefined],
|
|
23
|
-
}));
|
|
24
|
-
vi.mock("@q9labsai/chalk-whiteboard/embedded", () => ({
|
|
25
|
-
ChalkWhiteboardController: class {
|
|
26
|
-
constructor(options: unknown) {
|
|
27
|
-
controllerOptions.push(options);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
rendererReloaded(): void {}
|
|
31
|
-
|
|
32
|
-
setCapabilities(): void {}
|
|
33
|
-
|
|
34
|
-
setViewport(): void {}
|
|
35
|
-
|
|
36
|
-
start(): void {}
|
|
37
|
-
|
|
38
|
-
stop(): void {}
|
|
39
|
-
},
|
|
40
|
-
}));
|
|
41
|
-
vi.mock("react-native", () => ({
|
|
42
|
-
ActivityIndicator: "ActivityIndicator",
|
|
43
|
-
Pressable: "Pressable",
|
|
44
|
-
StyleSheet: { create: <Styles,>(styles: Styles) => styles },
|
|
45
|
-
Text: "Text",
|
|
46
|
-
View: "View",
|
|
47
|
-
useWindowDimensions: () => ({ width: 320, height: 640, scale: 2 }),
|
|
48
|
-
}));
|
|
49
|
-
vi.mock("react-native-webview", () => ({ default: "WebView" }));
|
|
50
|
-
vi.mock("../ui/native-theme", () => ({ useNativeTheme: () => nativeTheme }));
|
|
51
|
-
vi.mock("../whiteboard/embedded-whiteboard-assets", () => ({
|
|
52
|
-
isEmbeddedWhiteboardNavigationAllowed: () => true,
|
|
53
|
-
rendererURLWithContext: (url: string) => url,
|
|
54
|
-
resolveEmbeddedWhiteboardRendererURL: async () => "file:///android_asset/chalk-whiteboard/index.html",
|
|
55
|
-
}));
|
|
56
|
-
|
|
57
|
-
import type { ChalkEmbeddedWhiteboardTransport } from "@q9labsai/chalk-whiteboard/embedded";
|
|
58
|
-
import { EmbeddedWhiteboard, embeddedWhiteboardWebViewSecurityPolicy } from "./EmbeddedWhiteboard";
|
|
59
|
-
|
|
60
|
-
describe("EmbeddedWhiteboard WebView policy", () => {
|
|
61
|
-
it("keeps the offline renderer isolated from files, networks, storage, and cookies", () => {
|
|
62
|
-
expect(embeddedWhiteboardWebViewSecurityPolicy).toEqual({
|
|
63
|
-
allowFileAccess: true,
|
|
64
|
-
allowFileAccessFromFileURLs: false,
|
|
65
|
-
allowUniversalAccessFromFileURLs: false,
|
|
66
|
-
cacheEnabled: false,
|
|
67
|
-
domStorageEnabled: false,
|
|
68
|
-
javaScriptCanOpenWindowsAutomatically: false,
|
|
69
|
-
javaScriptEnabled: true,
|
|
70
|
-
mixedContentMode: "never",
|
|
71
|
-
setSupportMultipleWindows: false,
|
|
72
|
-
sharedCookiesEnabled: false,
|
|
73
|
-
thirdPartyCookiesEnabled: false,
|
|
74
|
-
});
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
it("uses the active NativeTheme colors throughout its loading surface", () => {
|
|
78
|
-
controllerOptions.length = 0;
|
|
79
|
-
const rendered = EmbeddedWhiteboard({
|
|
80
|
-
canClear: false,
|
|
81
|
-
canDraw: true,
|
|
82
|
-
journeyId: "journey-test",
|
|
83
|
-
transport: {} as ChalkEmbeddedWhiteboardTransport,
|
|
84
|
-
});
|
|
85
|
-
const children = rendered.props.children as readonly [{ readonly props: { readonly color: string } }, { readonly props: { readonly style: readonly unknown[] } }];
|
|
86
|
-
|
|
87
|
-
expect(rendered.props.style).toContainEqual({ backgroundColor: "#surface" });
|
|
88
|
-
expect(children[0]?.props.color).toBe("#info");
|
|
89
|
-
expect(children[1]?.props.style).toContainEqual({ color: "#muted" });
|
|
90
|
-
expect(controllerOptions[0]).toMatchObject({ theme: "light" });
|
|
91
|
-
});
|
|
92
|
-
});
|