@fluid-internal/presence-runtime 2.101.1 → 2.103.0
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/packageVersion.d.ts +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/runtime/extension/containerPresence.d.ts +1 -1
- package/dist/runtime/presenceDatastoreManager.d.ts +2 -2
- package/dist/runtime/presenceDatastoreManager.d.ts.map +1 -1
- package/dist/runtime/presenceDatastoreManager.js.map +1 -1
- package/dist/runtime/presenceManager.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/runtime/extension/containerPresence.d.ts +1 -1
- package/lib/runtime/presenceDatastoreManager.d.ts +2 -2
- package/lib/runtime/presenceDatastoreManager.d.ts.map +1 -1
- package/lib/runtime/presenceDatastoreManager.js.map +1 -1
- package/lib/runtime/presenceManager.js.map +1 -1
- package/package.json +14 -14
- package/dist/runtime/test/presenceDatastoreManager.spec.js +0 -618
- package/dist/runtime/test/presenceDatastoreManager.spec.js.map +0 -1
- package/dist/runtime/test/presenceManager.spec.js +0 -651
- package/dist/runtime/test/presenceManager.spec.js.map +0 -1
- package/dist/states/test/batching.spec.js +0 -843
- package/dist/states/test/batching.spec.js.map +0 -1
- package/dist/states/test/broadcastControlsTests.js +0 -60
- package/dist/states/test/broadcastControlsTests.js.map +0 -1
- package/dist/states/test/eventing.spec.js +0 -576
- package/dist/states/test/eventing.spec.js.map +0 -1
- package/dist/states/test/latestMapValueManager.spec.js +0 -210
- package/dist/states/test/latestMapValueManager.spec.js.map +0 -1
- package/dist/states/test/latestValueManager.spec.js +0 -193
- package/dist/states/test/latestValueManager.spec.js.map +0 -1
- package/dist/states/test/mockEphemeralRuntime.js +0 -11
- package/dist/states/test/mockEphemeralRuntime.js.map +0 -1
- package/dist/states/test/notificationsManager.spec.js +0 -460
- package/dist/states/test/notificationsManager.spec.js.map +0 -1
- package/dist/states/test/presenceStates.spec.js +0 -73
- package/dist/states/test/presenceStates.spec.js.map +0 -1
- package/dist/states/test/schemaValidation/protocol.spec.js +0 -246
- package/dist/states/test/schemaValidation/protocol.spec.js.map +0 -1
- package/dist/states/test/schemaValidation/valueManagers.spec.js +0 -784
- package/dist/states/test/schemaValidation/valueManagers.spec.js.map +0 -1
- package/dist/states/test/testUtils.js +0 -21
- package/dist/states/test/testUtils.js.map +0 -1
- package/dist/test/mockEphemeralRuntime.js +0 -175
- package/dist/test/mockEphemeralRuntime.js.map +0 -1
- package/dist/test/testUtils.js +0 -262
- package/dist/test/testUtils.js.map +0 -1
- package/dist/test/utils/index.js +0 -27
- package/dist/test/utils/index.js.map +0 -1
- package/dist/utils/test/timerManager.spec.js +0 -93
- package/dist/utils/test/timerManager.spec.js.map +0 -1
- package/lib/runtime/test/presenceDatastoreManager.spec.js +0 -616
- package/lib/runtime/test/presenceDatastoreManager.spec.js.map +0 -1
- package/lib/runtime/test/presenceManager.spec.js +0 -649
- package/lib/runtime/test/presenceManager.spec.js.map +0 -1
- package/lib/states/test/batching.spec.js +0 -841
- package/lib/states/test/batching.spec.js.map +0 -1
- package/lib/states/test/broadcastControlsTests.js +0 -56
- package/lib/states/test/broadcastControlsTests.js.map +0 -1
- package/lib/states/test/eventing.spec.js +0 -574
- package/lib/states/test/eventing.spec.js.map +0 -1
- package/lib/states/test/latestMapValueManager.spec.js +0 -206
- package/lib/states/test/latestMapValueManager.spec.js.map +0 -1
- package/lib/states/test/latestValueManager.spec.js +0 -189
- package/lib/states/test/latestValueManager.spec.js.map +0 -1
- package/lib/states/test/mockEphemeralRuntime.js +0 -6
- package/lib/states/test/mockEphemeralRuntime.js.map +0 -1
- package/lib/states/test/notificationsManager.spec.js +0 -456
- package/lib/states/test/notificationsManager.spec.js.map +0 -1
- package/lib/states/test/presenceStates.spec.js +0 -69
- package/lib/states/test/presenceStates.spec.js.map +0 -1
- package/lib/states/test/schemaValidation/protocol.spec.js +0 -244
- package/lib/states/test/schemaValidation/protocol.spec.js.map +0 -1
- package/lib/states/test/schemaValidation/valueManagers.spec.js +0 -782
- package/lib/states/test/schemaValidation/valueManagers.spec.js.map +0 -1
- package/lib/states/test/testUtils.js +0 -6
- package/lib/states/test/testUtils.js.map +0 -1
- package/lib/test/mockEphemeralRuntime.js +0 -171
- package/lib/test/mockEphemeralRuntime.js.map +0 -1
- package/lib/test/testUtils.js +0 -251
- package/lib/test/testUtils.js.map +0 -1
- package/lib/test/utils/index.js +0 -8
- package/lib/test/utils/index.js.map +0 -1
- package/lib/utils/test/timerManager.spec.js +0 -91
- package/lib/utils/test/timerManager.spec.js.map +0 -1
|
@@ -1,460 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/*!
|
|
3
|
-
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
4
|
-
* Licensed under the MIT License.
|
|
5
|
-
*/
|
|
6
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.checkCompiles = void 0;
|
|
8
|
-
const node_assert_1 = require("node:assert");
|
|
9
|
-
const internal_1 = require("@fluidframework/test-utils/internal");
|
|
10
|
-
const sinon_1 = require("sinon");
|
|
11
|
-
const states_1 = require("@fluid-internal/presence-runtime/states");
|
|
12
|
-
const utils_1 = require("@fluid-internal/presence-runtime/utils");
|
|
13
|
-
const mockEphemeralRuntime_js_1 = require("./mockEphemeralRuntime.js");
|
|
14
|
-
const testUtils_js_1 = require("./testUtils.js");
|
|
15
|
-
const attendeeId3 = (0, testUtils_js_1.createSpecificAttendeeId)("attendeeId-3");
|
|
16
|
-
const connectionId3 = "client3";
|
|
17
|
-
describe("Presence/States", () => {
|
|
18
|
-
describe("Notifications Workspace", () => {
|
|
19
|
-
/**
|
|
20
|
-
* See {@link checkCompiles} below
|
|
21
|
-
*/
|
|
22
|
-
it("API use compiles", () => { });
|
|
23
|
-
});
|
|
24
|
-
describe("NotificationsManager", () => {
|
|
25
|
-
// Note: this test setup mimics the setup in src/test/presenceManager.spec.ts
|
|
26
|
-
let runtime;
|
|
27
|
-
let logger;
|
|
28
|
-
const initialTime = 1000;
|
|
29
|
-
let clock;
|
|
30
|
-
let presence;
|
|
31
|
-
let processSignal;
|
|
32
|
-
before(async () => {
|
|
33
|
-
clock = (0, sinon_1.useFakeTimers)();
|
|
34
|
-
});
|
|
35
|
-
beforeEach(() => {
|
|
36
|
-
logger = new internal_1.EventAndErrorTrackingLogger();
|
|
37
|
-
runtime = new mockEphemeralRuntime_js_1.MockEphemeralRuntime(logger);
|
|
38
|
-
// We are configuring the runtime to be in a connected state, so ensure it looks connected
|
|
39
|
-
runtime.joined = true;
|
|
40
|
-
clock.setSystemTime(initialTime);
|
|
41
|
-
// Set up the presence connection
|
|
42
|
-
({ presence, processSignal } = (0, testUtils_js_1.prepareConnectedPresence)(runtime, testUtils_js_1.localAttendeeId, testUtils_js_1.initialLocalClientConnectionId, clock, logger));
|
|
43
|
-
});
|
|
44
|
-
afterEach(function (done) {
|
|
45
|
-
clock.reset();
|
|
46
|
-
// If the test passed so far, check final expectations.
|
|
47
|
-
if (this.currentTest?.state === "passed") {
|
|
48
|
-
(0, testUtils_js_1.assertFinalExpectations)(runtime, logger);
|
|
49
|
-
}
|
|
50
|
-
done();
|
|
51
|
-
});
|
|
52
|
-
after(() => {
|
|
53
|
-
clock.restore();
|
|
54
|
-
});
|
|
55
|
-
it("can be created with explicit schema via `Notifications` in `getWorkspace` schema", () => {
|
|
56
|
-
// Act
|
|
57
|
-
const notificationsWorkspace = presence.notifications.getWorkspace("name:testNotificationWorkspace", {
|
|
58
|
-
"testEvents": (0, states_1.Notifications)(
|
|
59
|
-
// A default handler is not required
|
|
60
|
-
{}),
|
|
61
|
-
});
|
|
62
|
-
// Verify
|
|
63
|
-
node_assert_1.strict.notEqual(notificationsWorkspace.notifications.testEvents, undefined);
|
|
64
|
-
(0, testUtils_js_1.assertIdenticalTypes)(notificationsWorkspace.notifications.testEvents, (0, testUtils_js_1.createInstanceOf)());
|
|
65
|
-
});
|
|
66
|
-
it("can be created with inferred schema via `Notifications` in `getWorkspace` schema", () => {
|
|
67
|
-
// Act
|
|
68
|
-
const notificationsWorkspace = presence.notifications.getWorkspace("name:testNotificationWorkspace", {
|
|
69
|
-
"testEvents": (0, states_1.Notifications)({
|
|
70
|
-
newId: (_attendee, _id) => { },
|
|
71
|
-
}),
|
|
72
|
-
});
|
|
73
|
-
// Verify
|
|
74
|
-
node_assert_1.strict.notEqual(notificationsWorkspace.notifications.testEvents, undefined);
|
|
75
|
-
(0, testUtils_js_1.assertIdenticalTypes)(notificationsWorkspace.notifications.testEvents, (0, testUtils_js_1.createInstanceOf)());
|
|
76
|
-
});
|
|
77
|
-
it("can be created via `Notifications` added to workspace", async () => {
|
|
78
|
-
const notificationsWorkspace = presence.notifications.getWorkspace("name:testNotificationWorkspace", {});
|
|
79
|
-
// Act
|
|
80
|
-
notificationsWorkspace.add("testEvents", (0, states_1.Notifications)(
|
|
81
|
-
// A default handler is not required
|
|
82
|
-
{}));
|
|
83
|
-
// Verify
|
|
84
|
-
node_assert_1.strict.notEqual(notificationsWorkspace.notifications.testEvents, undefined);
|
|
85
|
-
(0, testUtils_js_1.assertIdenticalTypes)(notificationsWorkspace.notifications.testEvents, (0, testUtils_js_1.createInstanceOf)());
|
|
86
|
-
});
|
|
87
|
-
it("typing won't be updated attempting duplicate `add` to workspace with different schema", () => {
|
|
88
|
-
const notificationsWorkspace = presence.notifications.getWorkspace("name:testNotifications", {
|
|
89
|
-
testEvents: (0, states_1.Notifications)({
|
|
90
|
-
hotSpot: (_sender, _) => { },
|
|
91
|
-
}),
|
|
92
|
-
});
|
|
93
|
-
// For type checking that "hotSpot" is a valid event name
|
|
94
|
-
notificationsWorkspace.notifications.testEvents.notifications.on("hotSpot", (_sender, _position) => { });
|
|
95
|
-
// Workaround ts(2775): Assertions require every name in the call target to be declared with an explicit type annotation.
|
|
96
|
-
const workspace = notificationsWorkspace;
|
|
97
|
-
// Act
|
|
98
|
-
node_assert_1.strict.throws(() => {
|
|
99
|
-
workspace.add(
|
|
100
|
-
// Same name as existing NotificationsManager
|
|
101
|
-
"testEvents",
|
|
102
|
-
// Different schema than existing NotificationsManager
|
|
103
|
-
(0, states_1.Notifications)({}));
|
|
104
|
-
});
|
|
105
|
-
// Verify
|
|
106
|
-
// Typing is unchanged - "moveCaret" is not a valid event name
|
|
107
|
-
workspace.notifications.testEvents.notifications.on(
|
|
108
|
-
// @ts-expect-error - "moveCaret" is not a valid event name
|
|
109
|
-
"moveCaret", () => { });
|
|
110
|
-
// For type checking that "hotSpot" is still a valid event name
|
|
111
|
-
workspace.notifications.testEvents.notifications.on("hotSpot",
|
|
112
|
-
// @ts-expect-error - "position" is the wrong type
|
|
113
|
-
(_sender, _position) => { });
|
|
114
|
-
});
|
|
115
|
-
it("can be created with explicit schema and partial subscribers via `Notifications`", () => {
|
|
116
|
-
// Act
|
|
117
|
-
const notificationsWorkspace = presence.notifications.getWorkspace("name:testNotificationWorkspace", {
|
|
118
|
-
"testEvents": (0, states_1.Notifications)({
|
|
119
|
-
newId: (_attendee, _id) => { },
|
|
120
|
-
}),
|
|
121
|
-
});
|
|
122
|
-
// Verify
|
|
123
|
-
node_assert_1.strict.notEqual(notificationsWorkspace.notifications.testEvents, undefined);
|
|
124
|
-
(0, testUtils_js_1.assertIdenticalTypes)(notificationsWorkspace.notifications.testEvents, (0, testUtils_js_1.createInstanceOf)());
|
|
125
|
-
});
|
|
126
|
-
it("strips bad events when created with improperly typed subscribers", () => {
|
|
127
|
-
// Act
|
|
128
|
-
const notificationsWorkspace = presence.notifications.getWorkspace("name:testNotificationWorkspace", {
|
|
129
|
-
"testEvents": (0, states_1.Notifications)({
|
|
130
|
-
missingAttendeeParam: (_id) => { },
|
|
131
|
-
nonSerializableArg: (_attendee, _fn) => { },
|
|
132
|
-
okay: (_attendee, _id) => { },
|
|
133
|
-
}),
|
|
134
|
-
});
|
|
135
|
-
// Verify
|
|
136
|
-
node_assert_1.strict.notEqual(notificationsWorkspace.notifications.testEvents, undefined);
|
|
137
|
-
(0, testUtils_js_1.assertIdenticalTypes)(notificationsWorkspace.notifications.testEvents, (0, testUtils_js_1.createInstanceOf)());
|
|
138
|
-
});
|
|
139
|
-
it("emit.broadcast sends broadcast signal", async () => {
|
|
140
|
-
// Setup
|
|
141
|
-
const notificationsWorkspace = presence.notifications.getWorkspace("name:testNotificationWorkspace", {
|
|
142
|
-
"testEvents": (0, states_1.Notifications)({
|
|
143
|
-
newId: (_attendee, _id) => { },
|
|
144
|
-
}),
|
|
145
|
-
});
|
|
146
|
-
const { testEvents } = notificationsWorkspace.notifications;
|
|
147
|
-
clock.tick(10);
|
|
148
|
-
runtime.signalsExpected.push([
|
|
149
|
-
{
|
|
150
|
-
type: "Pres:DatastoreUpdate",
|
|
151
|
-
content: {
|
|
152
|
-
"sendTimestamp": clock.now,
|
|
153
|
-
"avgLatency": 10,
|
|
154
|
-
"data": {
|
|
155
|
-
"system:presence": {
|
|
156
|
-
"clientToSessionId": {
|
|
157
|
-
[testUtils_js_1.initialLocalClientConnectionId]: {
|
|
158
|
-
"rev": 0,
|
|
159
|
-
"timestamp": initialTime,
|
|
160
|
-
"value": testUtils_js_1.localAttendeeId,
|
|
161
|
-
},
|
|
162
|
-
},
|
|
163
|
-
},
|
|
164
|
-
"n:name:testNotificationWorkspace": {
|
|
165
|
-
"testEvents": {
|
|
166
|
-
[testUtils_js_1.localAttendeeId]: {
|
|
167
|
-
"rev": 0,
|
|
168
|
-
"timestamp": 0,
|
|
169
|
-
"value": (0, utils_1.toOpaqueJson)({ "name": "newId", "args": [42] }),
|
|
170
|
-
"ignoreUnmonitored": true,
|
|
171
|
-
},
|
|
172
|
-
},
|
|
173
|
-
},
|
|
174
|
-
},
|
|
175
|
-
},
|
|
176
|
-
},
|
|
177
|
-
]);
|
|
178
|
-
// Act & Verify
|
|
179
|
-
testEvents.emit.broadcast("newId", 42);
|
|
180
|
-
(0, testUtils_js_1.assertFinalExpectations)(runtime, logger);
|
|
181
|
-
});
|
|
182
|
-
// TODO: Implement `unicast` method in NotificationsManager and in supporting code.
|
|
183
|
-
it.skip("emit.unicast sends directed signal", async () => {
|
|
184
|
-
// Setup
|
|
185
|
-
const notificationsWorkspace = presence.notifications.getWorkspace("name:testNotificationWorkspace", {
|
|
186
|
-
"testEvents": (0, states_1.Notifications)({
|
|
187
|
-
newId: (_attendee, _id) => { },
|
|
188
|
-
}),
|
|
189
|
-
});
|
|
190
|
-
const { testEvents } = notificationsWorkspace.notifications;
|
|
191
|
-
clock.tick(10);
|
|
192
|
-
runtime.signalsExpected.push([
|
|
193
|
-
{
|
|
194
|
-
type: "Pres:DatastoreUpdate",
|
|
195
|
-
content: {
|
|
196
|
-
"sendTimestamp": clock.now,
|
|
197
|
-
"avgLatency": 10,
|
|
198
|
-
"data": {
|
|
199
|
-
"system:presence": {
|
|
200
|
-
"clientToSessionId": {
|
|
201
|
-
[testUtils_js_1.initialLocalClientConnectionId]: {
|
|
202
|
-
"rev": 0,
|
|
203
|
-
"timestamp": initialTime,
|
|
204
|
-
"value": testUtils_js_1.localAttendeeId,
|
|
205
|
-
},
|
|
206
|
-
},
|
|
207
|
-
},
|
|
208
|
-
"n:name:testNotificationWorkspace": {
|
|
209
|
-
"testEvents": {
|
|
210
|
-
[testUtils_js_1.localAttendeeId]: {
|
|
211
|
-
"rev": 0,
|
|
212
|
-
"timestamp": 0,
|
|
213
|
-
"value": (0, utils_1.toOpaqueJson)({ "name": "newId", "args": [42] }),
|
|
214
|
-
"ignoreUnmonitored": true,
|
|
215
|
-
},
|
|
216
|
-
},
|
|
217
|
-
},
|
|
218
|
-
},
|
|
219
|
-
},
|
|
220
|
-
// Targeting self for simplicity
|
|
221
|
-
targetClientId: testUtils_js_1.initialLocalClientConnectionId,
|
|
222
|
-
},
|
|
223
|
-
]);
|
|
224
|
-
// Act & Verify
|
|
225
|
-
testEvents.emit.unicast("newId", presence.attendees.getMyself(), 42);
|
|
226
|
-
(0, testUtils_js_1.assertFinalExpectations)(runtime, logger);
|
|
227
|
-
});
|
|
228
|
-
it("raises named event when notification is received", async () => {
|
|
229
|
-
const eventHandlerCalls = {
|
|
230
|
-
original: [],
|
|
231
|
-
secondary: [],
|
|
232
|
-
tertiary: [],
|
|
233
|
-
};
|
|
234
|
-
function originalEventHandler(attendee, id) {
|
|
235
|
-
node_assert_1.strict.equal(attendee.attendeeId, attendeeId3);
|
|
236
|
-
node_assert_1.strict.equal(id, 42);
|
|
237
|
-
eventHandlerCalls.original.push({ attendee, id });
|
|
238
|
-
}
|
|
239
|
-
const notificationsWorkspace = presence.notifications.getWorkspace("name:testNotificationWorkspace", {
|
|
240
|
-
"testEvents": (0, states_1.Notifications)({
|
|
241
|
-
newId: originalEventHandler,
|
|
242
|
-
}),
|
|
243
|
-
});
|
|
244
|
-
const { testEvents } = notificationsWorkspace.notifications;
|
|
245
|
-
testEvents.events.on("unattendedNotification", (name) => {
|
|
246
|
-
(0, node_assert_1.fail)(`Unexpected unattendedNotification: ${name}`);
|
|
247
|
-
});
|
|
248
|
-
const disconnectFunctions = [
|
|
249
|
-
testEvents.notifications.on("newId", (attendee, id) => {
|
|
250
|
-
eventHandlerCalls.secondary.push({ attendee, id });
|
|
251
|
-
}),
|
|
252
|
-
testEvents.notifications.on("newId", (attendee, id) => {
|
|
253
|
-
eventHandlerCalls.tertiary.push({ attendee, id });
|
|
254
|
-
}),
|
|
255
|
-
];
|
|
256
|
-
// Processing this signal should trigger the testEvents.newId event listeners
|
|
257
|
-
processSignal([], {
|
|
258
|
-
type: "Pres:DatastoreUpdate",
|
|
259
|
-
content: {
|
|
260
|
-
"sendTimestamp": 1020,
|
|
261
|
-
"avgLatency": 10,
|
|
262
|
-
"data": {
|
|
263
|
-
"system:presence": {
|
|
264
|
-
"clientToSessionId": {
|
|
265
|
-
[connectionId3]: { "rev": 0, "timestamp": 1000, "value": attendeeId3 },
|
|
266
|
-
},
|
|
267
|
-
},
|
|
268
|
-
"n:name:testNotificationWorkspace": {
|
|
269
|
-
"testEvents": {
|
|
270
|
-
[attendeeId3]: {
|
|
271
|
-
"rev": 0,
|
|
272
|
-
"timestamp": 0,
|
|
273
|
-
"value": (0, utils_1.toOpaqueJson)({ "name": "newId", "args": [42] }),
|
|
274
|
-
"ignoreUnmonitored": true,
|
|
275
|
-
},
|
|
276
|
-
},
|
|
277
|
-
},
|
|
278
|
-
},
|
|
279
|
-
},
|
|
280
|
-
clientId: "client3",
|
|
281
|
-
}, false);
|
|
282
|
-
(0, node_assert_1.strict)(eventHandlerCalls.original.length === 1, `original event handler was called ${eventHandlerCalls.original.length} times; expected 1`);
|
|
283
|
-
(0, node_assert_1.strict)(eventHandlerCalls.secondary.length === 1, `secondary event handler was called ${eventHandlerCalls.secondary.length} times; expected 1`);
|
|
284
|
-
(0, node_assert_1.strict)(eventHandlerCalls.tertiary.length === 1, `secondary event handler was called ${eventHandlerCalls.tertiary.length} times; expected 1`);
|
|
285
|
-
// Cleanup
|
|
286
|
-
for (const disconnect of disconnectFunctions) {
|
|
287
|
-
disconnect();
|
|
288
|
-
}
|
|
289
|
-
});
|
|
290
|
-
it("raises `unattendedEvent` event when unrecognized notification is received", async () => {
|
|
291
|
-
let unattendedEventCalled = false;
|
|
292
|
-
const notificationsWorkspace = presence.notifications.getWorkspace("name:testNotificationWorkspace", {
|
|
293
|
-
"testEvents": (0, states_1.Notifications)({
|
|
294
|
-
newId: (attendee, id) => {
|
|
295
|
-
(0, node_assert_1.fail)(`Unexpected newId event`);
|
|
296
|
-
},
|
|
297
|
-
}),
|
|
298
|
-
});
|
|
299
|
-
const { testEvents } = notificationsWorkspace.notifications;
|
|
300
|
-
testEvents.events.on("unattendedNotification", (name, sender, ...content) => {
|
|
301
|
-
node_assert_1.strict.equal(name, "oldId");
|
|
302
|
-
node_assert_1.strict.equal(sender.attendeeId, attendeeId3);
|
|
303
|
-
node_assert_1.strict.deepEqual(content, [41]);
|
|
304
|
-
(0, node_assert_1.strict)(!unattendedEventCalled);
|
|
305
|
-
unattendedEventCalled = true;
|
|
306
|
-
});
|
|
307
|
-
// Processing this signal should trigger the testEvents.newId event listeners
|
|
308
|
-
processSignal([], {
|
|
309
|
-
type: "Pres:DatastoreUpdate",
|
|
310
|
-
content: {
|
|
311
|
-
"sendTimestamp": 1020,
|
|
312
|
-
"avgLatency": 10,
|
|
313
|
-
"data": {
|
|
314
|
-
"system:presence": {
|
|
315
|
-
"clientToSessionId": {
|
|
316
|
-
[connectionId3]: { "rev": 0, "timestamp": 1000, "value": attendeeId3 },
|
|
317
|
-
},
|
|
318
|
-
},
|
|
319
|
-
"n:name:testNotificationWorkspace": {
|
|
320
|
-
"testEvents": {
|
|
321
|
-
[attendeeId3]: {
|
|
322
|
-
"rev": 0,
|
|
323
|
-
"timestamp": 0,
|
|
324
|
-
"value": (0, utils_1.toOpaqueJson)({ "name": "oldId", "args": [41] }),
|
|
325
|
-
"ignoreUnmonitored": true,
|
|
326
|
-
},
|
|
327
|
-
},
|
|
328
|
-
},
|
|
329
|
-
},
|
|
330
|
-
},
|
|
331
|
-
clientId: "client3",
|
|
332
|
-
}, false);
|
|
333
|
-
(0, node_assert_1.strict)(unattendedEventCalled, "unattendedEvent not called");
|
|
334
|
-
});
|
|
335
|
-
it("raises `unattendedEvent` event when recognized notification is received without listeners", async () => {
|
|
336
|
-
let unattendedEventCalled = false;
|
|
337
|
-
function newIdEventHandler(attendee, id) {
|
|
338
|
-
(0, node_assert_1.fail)(`Unexpected newId event`);
|
|
339
|
-
}
|
|
340
|
-
const notificationsWorkspace = presence.notifications.getWorkspace("name:testNotificationWorkspace", {
|
|
341
|
-
"testEvents": (0, states_1.Notifications)({
|
|
342
|
-
newId: newIdEventHandler,
|
|
343
|
-
}),
|
|
344
|
-
});
|
|
345
|
-
const { testEvents } = notificationsWorkspace.notifications;
|
|
346
|
-
testEvents.events.on("unattendedNotification", (name, sender, ...content) => {
|
|
347
|
-
node_assert_1.strict.equal(name, "newId");
|
|
348
|
-
node_assert_1.strict.equal(sender.attendeeId, attendeeId3);
|
|
349
|
-
node_assert_1.strict.deepEqual(content, [43]);
|
|
350
|
-
(0, node_assert_1.strict)(!unattendedEventCalled);
|
|
351
|
-
unattendedEventCalled = true;
|
|
352
|
-
});
|
|
353
|
-
testEvents.notifications.off("newId", newIdEventHandler);
|
|
354
|
-
// Processing this signal should trigger the testEvents.newId event listeners
|
|
355
|
-
processSignal([], {
|
|
356
|
-
type: "Pres:DatastoreUpdate",
|
|
357
|
-
content: {
|
|
358
|
-
"sendTimestamp": 1020,
|
|
359
|
-
"avgLatency": 10,
|
|
360
|
-
"data": {
|
|
361
|
-
"system:presence": {
|
|
362
|
-
"clientToSessionId": {
|
|
363
|
-
[connectionId3]: { "rev": 0, "timestamp": 1000, "value": attendeeId3 },
|
|
364
|
-
},
|
|
365
|
-
},
|
|
366
|
-
"n:name:testNotificationWorkspace": {
|
|
367
|
-
"testEvents": {
|
|
368
|
-
[attendeeId3]: {
|
|
369
|
-
"rev": 0,
|
|
370
|
-
"timestamp": 0,
|
|
371
|
-
"value": (0, utils_1.toOpaqueJson)({ "name": "newId", "args": [43] }),
|
|
372
|
-
"ignoreUnmonitored": true,
|
|
373
|
-
},
|
|
374
|
-
},
|
|
375
|
-
},
|
|
376
|
-
},
|
|
377
|
-
},
|
|
378
|
-
clientId: "client3",
|
|
379
|
-
}, false);
|
|
380
|
-
(0, node_assert_1.strict)(unattendedEventCalled, "unattendedEvent not called");
|
|
381
|
-
});
|
|
382
|
-
it("removed listeners are not called when related notification is received", async () => {
|
|
383
|
-
let originalEventHandlerCalled = false;
|
|
384
|
-
function originalEventHandler(attendee, id) {
|
|
385
|
-
node_assert_1.strict.equal(attendee.attendeeId, attendeeId3);
|
|
386
|
-
node_assert_1.strict.equal(id, 44);
|
|
387
|
-
node_assert_1.strict.equal(originalEventHandlerCalled, false);
|
|
388
|
-
originalEventHandlerCalled = true;
|
|
389
|
-
}
|
|
390
|
-
const notificationsWorkspace = presence.notifications.getWorkspace("name:testNotificationWorkspace", {
|
|
391
|
-
"testEvents": (0, states_1.Notifications)({
|
|
392
|
-
newId: originalEventHandler,
|
|
393
|
-
}),
|
|
394
|
-
});
|
|
395
|
-
const { testEvents } = notificationsWorkspace.notifications;
|
|
396
|
-
testEvents.events.on("unattendedNotification", (name) => {
|
|
397
|
-
(0, node_assert_1.fail)(`Unexpected unattendedNotification: ${name}`);
|
|
398
|
-
});
|
|
399
|
-
const disconnect = testEvents.notifications.on("newId", (_attendee, _id) => {
|
|
400
|
-
(0, node_assert_1.fail)(`Unexpected event raised on disconnected listener`);
|
|
401
|
-
});
|
|
402
|
-
// Remove the listener
|
|
403
|
-
disconnect();
|
|
404
|
-
// Act
|
|
405
|
-
processSignal([], {
|
|
406
|
-
type: "Pres:DatastoreUpdate",
|
|
407
|
-
content: {
|
|
408
|
-
"sendTimestamp": 1020,
|
|
409
|
-
"avgLatency": 10,
|
|
410
|
-
"data": {
|
|
411
|
-
"system:presence": {
|
|
412
|
-
"clientToSessionId": {
|
|
413
|
-
[connectionId3]: { "rev": 0, "timestamp": 1000, "value": attendeeId3 },
|
|
414
|
-
},
|
|
415
|
-
},
|
|
416
|
-
"n:name:testNotificationWorkspace": {
|
|
417
|
-
"testEvents": {
|
|
418
|
-
[attendeeId3]: {
|
|
419
|
-
"rev": 0,
|
|
420
|
-
"timestamp": 0,
|
|
421
|
-
"value": (0, utils_1.toOpaqueJson)({ "name": "newId", "args": [44] }),
|
|
422
|
-
"ignoreUnmonitored": true,
|
|
423
|
-
},
|
|
424
|
-
},
|
|
425
|
-
},
|
|
426
|
-
},
|
|
427
|
-
},
|
|
428
|
-
clientId: "client3",
|
|
429
|
-
}, false);
|
|
430
|
-
// Verify
|
|
431
|
-
(0, node_assert_1.strict)(originalEventHandlerCalled, "originalEventHandler not called");
|
|
432
|
-
});
|
|
433
|
-
it(".presence provides Presence it was created under", () => {
|
|
434
|
-
const notificationsWorkspace = presence.notifications.getWorkspace("name:testNotificationWorkspace", {
|
|
435
|
-
"testEvents": (0, states_1.Notifications)(
|
|
436
|
-
// A default handler is not required
|
|
437
|
-
{}),
|
|
438
|
-
});
|
|
439
|
-
node_assert_1.strict.strictEqual(notificationsWorkspace.notifications.testEvents.presence, presence);
|
|
440
|
-
node_assert_1.strict.strictEqual(notificationsWorkspace.presence, presence);
|
|
441
|
-
});
|
|
442
|
-
});
|
|
443
|
-
});
|
|
444
|
-
// ---- test (example) code ----
|
|
445
|
-
/**
|
|
446
|
-
* Check that the code compiles.
|
|
447
|
-
*/
|
|
448
|
-
function checkCompiles() {
|
|
449
|
-
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
450
|
-
const presence = {};
|
|
451
|
-
presence.notifications.getWorkspace("name:testNotifications", {
|
|
452
|
-
testEvents: (0, states_1.Notifications)({
|
|
453
|
-
hotSpot: (_sender, _) => { },
|
|
454
|
-
}),
|
|
455
|
-
// @ts-expect-error - Notifications Workspace only permits NotificationsManagers
|
|
456
|
-
camera: states_1.StateFactory.latest({ local: { x: 0, y: 0, z: 0 } }),
|
|
457
|
-
});
|
|
458
|
-
}
|
|
459
|
-
exports.checkCompiles = checkCompiles;
|
|
460
|
-
//# sourceMappingURL=notificationsManager.spec.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"notificationsManager.spec.js","sourceRoot":"","sources":["../../../src/states/test/notificationsManager.spec.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { strict as assert, fail } from \"node:assert\";\n\nimport type {\n\tAttendee,\n\tClientConnectionId,\n\tNotificationsManager,\n\tNotificationsWorkspace,\n\tPresenceWithNotifications,\n} from \"@fluid-internal/presence-definitions\";\nimport { EventAndErrorTrackingLogger } from \"@fluidframework/test-utils/internal\";\nimport type { SinonFakeTimers } from \"sinon\";\nimport { useFakeTimers } from \"sinon\";\n\nimport { Notifications, StateFactory } from \"@fluid-internal/presence-runtime/states\";\nimport { toOpaqueJson } from \"@fluid-internal/presence-runtime/utils\";\n\nimport { MockEphemeralRuntime } from \"./mockEphemeralRuntime.js\";\nimport type { ProcessSignalFunction } from \"./testUtils.js\";\nimport {\n\tassertFinalExpectations,\n\tassertIdenticalTypes,\n\tinitialLocalClientConnectionId,\n\tcreateInstanceOf,\n\tcreateSpecificAttendeeId,\n\tprepareConnectedPresence,\n\tlocalAttendeeId,\n} from \"./testUtils.js\";\n\nconst attendeeId3 = createSpecificAttendeeId(\"attendeeId-3\");\nconst connectionId3 = \"client3\" as const satisfies ClientConnectionId;\n\ndescribe(\"Presence/States\", () => {\n\tdescribe(\"Notifications Workspace\", () => {\n\t\t/**\n\t\t * See {@link checkCompiles} below\n\t\t */\n\t\tit(\"API use compiles\", () => {});\n\t});\n\n\tdescribe(\"NotificationsManager\", () => {\n\t\t// Note: this test setup mimics the setup in src/test/presenceManager.spec.ts\n\t\tlet runtime: MockEphemeralRuntime;\n\t\tlet logger: EventAndErrorTrackingLogger;\n\t\tconst initialTime = 1000;\n\t\tlet clock: SinonFakeTimers;\n\t\tlet presence: PresenceWithNotifications;\n\t\tlet processSignal: ProcessSignalFunction;\n\n\t\tbefore(async () => {\n\t\t\tclock = useFakeTimers();\n\t\t});\n\n\t\tbeforeEach(() => {\n\t\t\tlogger = new EventAndErrorTrackingLogger();\n\t\t\truntime = new MockEphemeralRuntime(logger);\n\n\t\t\t// We are configuring the runtime to be in a connected state, so ensure it looks connected\n\t\t\truntime.joined = true;\n\n\t\t\tclock.setSystemTime(initialTime);\n\n\t\t\t// Set up the presence connection\n\t\t\t({ presence, processSignal } = prepareConnectedPresence(\n\t\t\t\truntime,\n\t\t\t\tlocalAttendeeId,\n\t\t\t\tinitialLocalClientConnectionId,\n\t\t\t\tclock,\n\t\t\t\tlogger,\n\t\t\t));\n\t\t});\n\n\t\tafterEach(function (done: Mocha.Done) {\n\t\t\tclock.reset();\n\n\t\t\t// If the test passed so far, check final expectations.\n\t\t\tif (this.currentTest?.state === \"passed\") {\n\t\t\t\tassertFinalExpectations(runtime, logger);\n\t\t\t}\n\t\t\tdone();\n\t\t});\n\n\t\tafter(() => {\n\t\t\tclock.restore();\n\t\t});\n\n\t\tit(\"can be created with explicit schema via `Notifications` in `getWorkspace` schema\", () => {\n\t\t\t// Act\n\t\t\tconst notificationsWorkspace = presence.notifications.getWorkspace(\n\t\t\t\t\"name:testNotificationWorkspace\",\n\t\t\t\t{\n\t\t\t\t\t\"testEvents\": Notifications<{\n\t\t\t\t\t\tnewId: (id: number) => void;\n\t\t\t\t\t}>(\n\t\t\t\t\t\t// A default handler is not required\n\t\t\t\t\t\t{},\n\t\t\t\t\t),\n\t\t\t\t},\n\t\t\t);\n\n\t\t\t// Verify\n\t\t\tassert.notEqual(notificationsWorkspace.notifications.testEvents, undefined);\n\t\t\tassertIdenticalTypes(\n\t\t\t\tnotificationsWorkspace.notifications.testEvents,\n\t\t\t\tcreateInstanceOf<NotificationsManager<{ newId: (id: number) => void }>>(),\n\t\t\t);\n\t\t});\n\n\t\tit(\"can be created with inferred schema via `Notifications` in `getWorkspace` schema\", () => {\n\t\t\t// Act\n\t\t\tconst notificationsWorkspace = presence.notifications.getWorkspace(\n\t\t\t\t\"name:testNotificationWorkspace\",\n\t\t\t\t{\n\t\t\t\t\t\"testEvents\": Notifications({\n\t\t\t\t\t\tnewId: (_attendee: Attendee, _id: number) => {},\n\t\t\t\t\t}),\n\t\t\t\t},\n\t\t\t);\n\n\t\t\t// Verify\n\t\t\tassert.notEqual(notificationsWorkspace.notifications.testEvents, undefined);\n\t\t\tassertIdenticalTypes(\n\t\t\t\tnotificationsWorkspace.notifications.testEvents,\n\t\t\t\tcreateInstanceOf<NotificationsManager<{ newId: (id: number) => void }>>(),\n\t\t\t);\n\t\t});\n\n\t\tit(\"can be created via `Notifications` added to workspace\", async () => {\n\t\t\t// Setup\n\t\t\t// Get an empty notifications workspace\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-empty-object-type\n\t\t\ttype EmptyNotificationsWorkspace = NotificationsWorkspace<{}>;\n\t\t\tconst notificationsWorkspace: EmptyNotificationsWorkspace =\n\t\t\t\tpresence.notifications.getWorkspace(\"name:testNotificationWorkspace\", {});\n\n\t\t\t// Act\n\t\t\tnotificationsWorkspace.add(\n\t\t\t\t\"testEvents\",\n\t\t\t\tNotifications<{\n\t\t\t\t\tnewId: (id: number) => void;\n\t\t\t\t}>(\n\t\t\t\t\t// A default handler is not required\n\t\t\t\t\t{},\n\t\t\t\t),\n\t\t\t);\n\n\t\t\t// Verify\n\t\t\tassert.notEqual(notificationsWorkspace.notifications.testEvents, undefined);\n\t\t\tassertIdenticalTypes(\n\t\t\t\tnotificationsWorkspace.notifications.testEvents,\n\t\t\t\tcreateInstanceOf<NotificationsManager<{ newId: (id: number) => void }>>(),\n\t\t\t);\n\t\t});\n\n\t\tit(\"typing won't be updated attempting duplicate `add` to workspace with different schema\", () => {\n\t\t\tconst notificationsWorkspace = presence.notifications.getWorkspace(\n\t\t\t\t\"name:testNotifications\",\n\t\t\t\t{\n\t\t\t\t\ttestEvents: Notifications({\n\t\t\t\t\t\thotSpot: (_sender: Attendee, _: { x: number; y: number }): void => {},\n\t\t\t\t\t}),\n\t\t\t\t},\n\t\t\t);\n\t\t\t// For type checking that \"hotSpot\" is a valid event name\n\t\t\tnotificationsWorkspace.notifications.testEvents.notifications.on(\n\t\t\t\t\"hotSpot\",\n\t\t\t\t(_sender: Attendee, _position: { x: number; y: number }) => {},\n\t\t\t);\n\n\t\t\t// Workaround ts(2775): Assertions require every name in the call target to be declared with an explicit type annotation.\n\t\t\tconst workspace: typeof notificationsWorkspace = notificationsWorkspace;\n\n\t\t\t// Act\n\t\t\tassert.throws(() => {\n\t\t\t\tworkspace.add(\n\t\t\t\t\t// Same name as existing NotificationsManager\n\t\t\t\t\t\"testEvents\",\n\t\t\t\t\t// Different schema than existing NotificationsManager\n\t\t\t\t\tNotifications<{\n\t\t\t\t\t\tmoveCaret: (moveDetails: { id: string; pos: number }) => void;\n\t\t\t\t\t}>({}),\n\t\t\t\t);\n\t\t\t});\n\n\t\t\t// Verify\n\t\t\t// Typing is unchanged - \"moveCaret\" is not a valid event name\n\t\t\tworkspace.notifications.testEvents.notifications.on(\n\t\t\t\t// @ts-expect-error - \"moveCaret\" is not a valid event name\n\t\t\t\t\"moveCaret\",\n\t\t\t\t() => {},\n\t\t\t);\n\n\t\t\t// For type checking that \"hotSpot\" is still a valid event name\n\t\t\tworkspace.notifications.testEvents.notifications.on(\n\t\t\t\t\"hotSpot\",\n\t\t\t\t// @ts-expect-error - \"position\" is the wrong type\n\t\t\t\t(_sender: Attendee, _position: number) => {},\n\t\t\t);\n\t\t});\n\n\t\tit(\"can be created with explicit schema and partial subscribers via `Notifications`\", () => {\n\t\t\t// Act\n\t\t\tconst notificationsWorkspace = presence.notifications.getWorkspace(\n\t\t\t\t\"name:testNotificationWorkspace\",\n\t\t\t\t{\n\t\t\t\t\t\"testEvents\": Notifications<{\n\t\t\t\t\t\tnewId: (id: number) => void;\n\t\t\t\t\t\thotSpot: (pos: { x: number; y: number }) => void;\n\t\t\t\t\t}>({\n\t\t\t\t\t\tnewId: (_attendee: Attendee, _id: number) => {},\n\t\t\t\t\t}),\n\t\t\t\t},\n\t\t\t);\n\n\t\t\t// Verify\n\t\t\tassert.notEqual(notificationsWorkspace.notifications.testEvents, undefined);\n\t\t\tassertIdenticalTypes(\n\t\t\t\tnotificationsWorkspace.notifications.testEvents,\n\t\t\t\tcreateInstanceOf<\n\t\t\t\t\tNotificationsManager<{\n\t\t\t\t\t\tnewId: (id: number) => void;\n\t\t\t\t\t\thotSpot: (pos: { x: number; y: number }) => void;\n\t\t\t\t\t}>\n\t\t\t\t>(),\n\t\t\t);\n\t\t});\n\n\t\tit(\"strips bad events when created with improperly typed subscribers\", () => {\n\t\t\t// Act\n\t\t\tconst notificationsWorkspace = presence.notifications.getWorkspace(\n\t\t\t\t\"name:testNotificationWorkspace\",\n\t\t\t\t{\n\t\t\t\t\t\"testEvents\": Notifications({\n\t\t\t\t\t\tmissingAttendeeParam: (_id: number) => {},\n\t\t\t\t\t\tnonSerializableArg: (_attendee: Attendee, _fn: () => void) => {},\n\t\t\t\t\t\tokay: (_attendee: Attendee, _id: number) => {},\n\t\t\t\t\t}),\n\t\t\t\t},\n\t\t\t);\n\n\t\t\t// Verify\n\t\t\tassert.notEqual(notificationsWorkspace.notifications.testEvents, undefined);\n\t\t\tassertIdenticalTypes(\n\t\t\t\tnotificationsWorkspace.notifications.testEvents,\n\t\t\t\tcreateInstanceOf<NotificationsManager<{ okay: (id: number) => void }>>(),\n\t\t\t);\n\t\t});\n\n\t\tit(\"emit.broadcast sends broadcast signal\", async () => {\n\t\t\t// Setup\n\t\t\tconst notificationsWorkspace = presence.notifications.getWorkspace(\n\t\t\t\t\"name:testNotificationWorkspace\",\n\t\t\t\t{\n\t\t\t\t\t\"testEvents\": Notifications({\n\t\t\t\t\t\tnewId: (_attendee: Attendee, _id: number) => {},\n\t\t\t\t\t}),\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tconst { testEvents } = notificationsWorkspace.notifications;\n\n\t\t\tclock.tick(10);\n\n\t\t\truntime.signalsExpected.push([\n\t\t\t\t{\n\t\t\t\t\ttype: \"Pres:DatastoreUpdate\",\n\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\"sendTimestamp\": clock.now,\n\t\t\t\t\t\t\"avgLatency\": 10,\n\t\t\t\t\t\t\"data\": {\n\t\t\t\t\t\t\t\"system:presence\": {\n\t\t\t\t\t\t\t\t\"clientToSessionId\": {\n\t\t\t\t\t\t\t\t\t[initialLocalClientConnectionId]: {\n\t\t\t\t\t\t\t\t\t\t\"rev\": 0,\n\t\t\t\t\t\t\t\t\t\t\"timestamp\": initialTime,\n\t\t\t\t\t\t\t\t\t\t\"value\": localAttendeeId,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"n:name:testNotificationWorkspace\": {\n\t\t\t\t\t\t\t\t\"testEvents\": {\n\t\t\t\t\t\t\t\t\t[localAttendeeId]: {\n\t\t\t\t\t\t\t\t\t\t\"rev\": 0,\n\t\t\t\t\t\t\t\t\t\t\"timestamp\": 0,\n\t\t\t\t\t\t\t\t\t\t\"value\": toOpaqueJson({ \"name\": \"newId\", \"args\": [42] }),\n\t\t\t\t\t\t\t\t\t\t\"ignoreUnmonitored\": true,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t]);\n\n\t\t\t// Act & Verify\n\t\t\ttestEvents.emit.broadcast(\"newId\", 42);\n\n\t\t\tassertFinalExpectations(runtime, logger);\n\t\t});\n\n\t\t// TODO: Implement `unicast` method in NotificationsManager and in supporting code.\n\t\tit.skip(\"emit.unicast sends directed signal\", async () => {\n\t\t\t// Setup\n\t\t\tconst notificationsWorkspace = presence.notifications.getWorkspace(\n\t\t\t\t\"name:testNotificationWorkspace\",\n\t\t\t\t{\n\t\t\t\t\t\"testEvents\": Notifications({\n\t\t\t\t\t\tnewId: (_attendee: Attendee, _id: number) => {},\n\t\t\t\t\t}),\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tconst { testEvents } = notificationsWorkspace.notifications;\n\n\t\t\tclock.tick(10);\n\n\t\t\truntime.signalsExpected.push([\n\t\t\t\t{\n\t\t\t\t\ttype: \"Pres:DatastoreUpdate\",\n\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\"sendTimestamp\": clock.now,\n\t\t\t\t\t\t\"avgLatency\": 10,\n\t\t\t\t\t\t\"data\": {\n\t\t\t\t\t\t\t\"system:presence\": {\n\t\t\t\t\t\t\t\t\"clientToSessionId\": {\n\t\t\t\t\t\t\t\t\t[initialLocalClientConnectionId]: {\n\t\t\t\t\t\t\t\t\t\t\"rev\": 0,\n\t\t\t\t\t\t\t\t\t\t\"timestamp\": initialTime,\n\t\t\t\t\t\t\t\t\t\t\"value\": localAttendeeId,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"n:name:testNotificationWorkspace\": {\n\t\t\t\t\t\t\t\t\"testEvents\": {\n\t\t\t\t\t\t\t\t\t[localAttendeeId]: {\n\t\t\t\t\t\t\t\t\t\t\"rev\": 0,\n\t\t\t\t\t\t\t\t\t\t\"timestamp\": 0,\n\t\t\t\t\t\t\t\t\t\t\"value\": toOpaqueJson({ \"name\": \"newId\", \"args\": [42] }),\n\t\t\t\t\t\t\t\t\t\t\"ignoreUnmonitored\": true,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t// Targeting self for simplicity\n\t\t\t\t\ttargetClientId: initialLocalClientConnectionId,\n\t\t\t\t},\n\t\t\t]);\n\n\t\t\t// Act & Verify\n\t\t\ttestEvents.emit.unicast(\"newId\", presence.attendees.getMyself(), 42);\n\n\t\t\tassertFinalExpectations(runtime, logger);\n\t\t});\n\n\t\tit(\"raises named event when notification is received\", async () => {\n\t\t\ttype EventCalls = { attendee: Attendee; id: number }[];\n\t\t\tconst eventHandlerCalls = {\n\t\t\t\toriginal: [] as EventCalls,\n\t\t\t\tsecondary: [] as EventCalls,\n\t\t\t\ttertiary: [] as EventCalls,\n\t\t\t};\n\n\t\t\tfunction originalEventHandler(attendee: Attendee, id: number): void {\n\t\t\t\tassert.equal(attendee.attendeeId, attendeeId3);\n\t\t\t\tassert.equal(id, 42);\n\t\t\t\teventHandlerCalls.original.push({ attendee, id });\n\t\t\t}\n\n\t\t\tconst notificationsWorkspace = presence.notifications.getWorkspace(\n\t\t\t\t\"name:testNotificationWorkspace\",\n\t\t\t\t{\n\t\t\t\t\t\"testEvents\": Notifications({\n\t\t\t\t\t\tnewId: originalEventHandler,\n\t\t\t\t\t}),\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tconst { testEvents } = notificationsWorkspace.notifications;\n\n\t\t\ttestEvents.events.on(\"unattendedNotification\", (name) => {\n\t\t\t\tfail(`Unexpected unattendedNotification: ${name}`);\n\t\t\t});\n\n\t\t\tconst disconnectFunctions = [\n\t\t\t\ttestEvents.notifications.on(\"newId\", (attendee: Attendee, id: number) => {\n\t\t\t\t\teventHandlerCalls.secondary.push({ attendee, id });\n\t\t\t\t}),\n\t\t\t\ttestEvents.notifications.on(\"newId\", (attendee: Attendee, id: number) => {\n\t\t\t\t\teventHandlerCalls.tertiary.push({ attendee, id });\n\t\t\t\t}),\n\t\t\t];\n\n\t\t\t// Processing this signal should trigger the testEvents.newId event listeners\n\t\t\tprocessSignal(\n\t\t\t\t[],\n\t\t\t\t{\n\t\t\t\t\ttype: \"Pres:DatastoreUpdate\",\n\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\"sendTimestamp\": 1020,\n\t\t\t\t\t\t\"avgLatency\": 10,\n\t\t\t\t\t\t\"data\": {\n\t\t\t\t\t\t\t\"system:presence\": {\n\t\t\t\t\t\t\t\t\"clientToSessionId\": {\n\t\t\t\t\t\t\t\t\t[connectionId3]: { \"rev\": 0, \"timestamp\": 1000, \"value\": attendeeId3 },\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"n:name:testNotificationWorkspace\": {\n\t\t\t\t\t\t\t\t\"testEvents\": {\n\t\t\t\t\t\t\t\t\t[attendeeId3]: {\n\t\t\t\t\t\t\t\t\t\t\"rev\": 0,\n\t\t\t\t\t\t\t\t\t\t\"timestamp\": 0,\n\t\t\t\t\t\t\t\t\t\t\"value\": toOpaqueJson({ \"name\": \"newId\", \"args\": [42] }),\n\t\t\t\t\t\t\t\t\t\t\"ignoreUnmonitored\": true,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tclientId: \"client3\",\n\t\t\t\t},\n\t\t\t\tfalse,\n\t\t\t);\n\n\t\t\tassert(\n\t\t\t\teventHandlerCalls.original.length === 1,\n\t\t\t\t`original event handler was called ${eventHandlerCalls.original.length} times; expected 1`,\n\t\t\t);\n\t\t\tassert(\n\t\t\t\teventHandlerCalls.secondary.length === 1,\n\t\t\t\t`secondary event handler was called ${eventHandlerCalls.secondary.length} times; expected 1`,\n\t\t\t);\n\t\t\tassert(\n\t\t\t\teventHandlerCalls.tertiary.length === 1,\n\t\t\t\t`secondary event handler was called ${eventHandlerCalls.tertiary.length} times; expected 1`,\n\t\t\t);\n\n\t\t\t// Cleanup\n\t\t\tfor (const disconnect of disconnectFunctions) {\n\t\t\t\tdisconnect();\n\t\t\t}\n\t\t});\n\n\t\tit(\"raises `unattendedEvent` event when unrecognized notification is received\", async () => {\n\t\t\tlet unattendedEventCalled = false;\n\n\t\t\tconst notificationsWorkspace = presence.notifications.getWorkspace(\n\t\t\t\t\"name:testNotificationWorkspace\",\n\t\t\t\t{\n\t\t\t\t\t\"testEvents\": Notifications({\n\t\t\t\t\t\tnewId: (attendee: Attendee, id: number) => {\n\t\t\t\t\t\t\tfail(`Unexpected newId event`);\n\t\t\t\t\t\t},\n\t\t\t\t\t}),\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tconst { testEvents } = notificationsWorkspace.notifications;\n\n\t\t\ttestEvents.events.on(\"unattendedNotification\", (name, sender, ...content) => {\n\t\t\t\tassert.equal(name, \"oldId\");\n\t\t\t\tassert.equal(sender.attendeeId, attendeeId3);\n\t\t\t\tassert.deepEqual(content, [41]);\n\t\t\t\tassert(!unattendedEventCalled);\n\t\t\t\tunattendedEventCalled = true;\n\t\t\t});\n\n\t\t\t// Processing this signal should trigger the testEvents.newId event listeners\n\t\t\tprocessSignal(\n\t\t\t\t[],\n\t\t\t\t{\n\t\t\t\t\ttype: \"Pres:DatastoreUpdate\",\n\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\"sendTimestamp\": 1020,\n\t\t\t\t\t\t\"avgLatency\": 10,\n\t\t\t\t\t\t\"data\": {\n\t\t\t\t\t\t\t\"system:presence\": {\n\t\t\t\t\t\t\t\t\"clientToSessionId\": {\n\t\t\t\t\t\t\t\t\t[connectionId3]: { \"rev\": 0, \"timestamp\": 1000, \"value\": attendeeId3 },\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"n:name:testNotificationWorkspace\": {\n\t\t\t\t\t\t\t\t\"testEvents\": {\n\t\t\t\t\t\t\t\t\t[attendeeId3]: {\n\t\t\t\t\t\t\t\t\t\t\"rev\": 0,\n\t\t\t\t\t\t\t\t\t\t\"timestamp\": 0,\n\t\t\t\t\t\t\t\t\t\t\"value\": toOpaqueJson({ \"name\": \"oldId\", \"args\": [41] }),\n\t\t\t\t\t\t\t\t\t\t\"ignoreUnmonitored\": true,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tclientId: \"client3\",\n\t\t\t\t},\n\t\t\t\tfalse,\n\t\t\t);\n\n\t\t\tassert(unattendedEventCalled, \"unattendedEvent not called\");\n\t\t});\n\n\t\tit(\"raises `unattendedEvent` event when recognized notification is received without listeners\", async () => {\n\t\t\tlet unattendedEventCalled = false;\n\n\t\t\tfunction newIdEventHandler(attendee: Attendee, id: number): void {\n\t\t\t\tfail(`Unexpected newId event`);\n\t\t\t}\n\n\t\t\tconst notificationsWorkspace = presence.notifications.getWorkspace(\n\t\t\t\t\"name:testNotificationWorkspace\",\n\t\t\t\t{\n\t\t\t\t\t\"testEvents\": Notifications({\n\t\t\t\t\t\tnewId: newIdEventHandler,\n\t\t\t\t\t}),\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tconst { testEvents } = notificationsWorkspace.notifications;\n\n\t\t\ttestEvents.events.on(\"unattendedNotification\", (name, sender, ...content) => {\n\t\t\t\tassert.equal(name, \"newId\");\n\t\t\t\tassert.equal(sender.attendeeId, attendeeId3);\n\t\t\t\tassert.deepEqual(content, [43]);\n\t\t\t\tassert(!unattendedEventCalled);\n\t\t\t\tunattendedEventCalled = true;\n\t\t\t});\n\n\t\t\ttestEvents.notifications.off(\"newId\", newIdEventHandler);\n\n\t\t\t// Processing this signal should trigger the testEvents.newId event listeners\n\t\t\tprocessSignal(\n\t\t\t\t[],\n\t\t\t\t{\n\t\t\t\t\ttype: \"Pres:DatastoreUpdate\",\n\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\"sendTimestamp\": 1020,\n\t\t\t\t\t\t\"avgLatency\": 10,\n\t\t\t\t\t\t\"data\": {\n\t\t\t\t\t\t\t\"system:presence\": {\n\t\t\t\t\t\t\t\t\"clientToSessionId\": {\n\t\t\t\t\t\t\t\t\t[connectionId3]: { \"rev\": 0, \"timestamp\": 1000, \"value\": attendeeId3 },\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"n:name:testNotificationWorkspace\": {\n\t\t\t\t\t\t\t\t\"testEvents\": {\n\t\t\t\t\t\t\t\t\t[attendeeId3]: {\n\t\t\t\t\t\t\t\t\t\t\"rev\": 0,\n\t\t\t\t\t\t\t\t\t\t\"timestamp\": 0,\n\t\t\t\t\t\t\t\t\t\t\"value\": toOpaqueJson({ \"name\": \"newId\", \"args\": [43] }),\n\t\t\t\t\t\t\t\t\t\t\"ignoreUnmonitored\": true,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tclientId: \"client3\",\n\t\t\t\t},\n\t\t\t\tfalse,\n\t\t\t);\n\n\t\t\tassert(unattendedEventCalled, \"unattendedEvent not called\");\n\t\t});\n\n\t\tit(\"removed listeners are not called when related notification is received\", async () => {\n\t\t\tlet originalEventHandlerCalled = false;\n\n\t\t\tfunction originalEventHandler(attendee: Attendee, id: number): void {\n\t\t\t\tassert.equal(attendee.attendeeId, attendeeId3);\n\t\t\t\tassert.equal(id, 44);\n\t\t\t\tassert.equal(originalEventHandlerCalled, false);\n\t\t\t\toriginalEventHandlerCalled = true;\n\t\t\t}\n\n\t\t\tconst notificationsWorkspace = presence.notifications.getWorkspace(\n\t\t\t\t\"name:testNotificationWorkspace\",\n\t\t\t\t{\n\t\t\t\t\t\"testEvents\": Notifications({\n\t\t\t\t\t\tnewId: originalEventHandler,\n\t\t\t\t\t}),\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tconst { testEvents } = notificationsWorkspace.notifications;\n\n\t\t\ttestEvents.events.on(\"unattendedNotification\", (name) => {\n\t\t\t\tfail(`Unexpected unattendedNotification: ${name}`);\n\t\t\t});\n\n\t\t\tconst disconnect = testEvents.notifications.on(\n\t\t\t\t\"newId\",\n\t\t\t\t(_attendee: Attendee, _id: number) => {\n\t\t\t\t\tfail(`Unexpected event raised on disconnected listener`);\n\t\t\t\t},\n\t\t\t);\n\t\t\t// Remove the listener\n\t\t\tdisconnect();\n\n\t\t\t// Act\n\t\t\tprocessSignal(\n\t\t\t\t[],\n\t\t\t\t{\n\t\t\t\t\ttype: \"Pres:DatastoreUpdate\",\n\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\"sendTimestamp\": 1020,\n\t\t\t\t\t\t\"avgLatency\": 10,\n\t\t\t\t\t\t\"data\": {\n\t\t\t\t\t\t\t\"system:presence\": {\n\t\t\t\t\t\t\t\t\"clientToSessionId\": {\n\t\t\t\t\t\t\t\t\t[connectionId3]: { \"rev\": 0, \"timestamp\": 1000, \"value\": attendeeId3 },\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"n:name:testNotificationWorkspace\": {\n\t\t\t\t\t\t\t\t\"testEvents\": {\n\t\t\t\t\t\t\t\t\t[attendeeId3]: {\n\t\t\t\t\t\t\t\t\t\t\"rev\": 0,\n\t\t\t\t\t\t\t\t\t\t\"timestamp\": 0,\n\t\t\t\t\t\t\t\t\t\t\"value\": toOpaqueJson({ \"name\": \"newId\", \"args\": [44] }),\n\t\t\t\t\t\t\t\t\t\t\"ignoreUnmonitored\": true,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tclientId: \"client3\",\n\t\t\t\t},\n\t\t\t\tfalse,\n\t\t\t);\n\n\t\t\t// Verify\n\t\t\tassert(originalEventHandlerCalled, \"originalEventHandler not called\");\n\t\t});\n\n\t\tit(\".presence provides Presence it was created under\", () => {\n\t\t\tconst notificationsWorkspace = presence.notifications.getWorkspace(\n\t\t\t\t\"name:testNotificationWorkspace\",\n\t\t\t\t{\n\t\t\t\t\t\"testEvents\": Notifications<{\n\t\t\t\t\t\tnewId: (id: number) => void;\n\t\t\t\t\t}>(\n\t\t\t\t\t\t// A default handler is not required\n\t\t\t\t\t\t{},\n\t\t\t\t\t),\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tassert.strictEqual(notificationsWorkspace.notifications.testEvents.presence, presence);\n\t\t\tassert.strictEqual(notificationsWorkspace.presence, presence);\n\t\t});\n\t});\n});\n\n// ---- test (example) code ----\n\n/**\n * Check that the code compiles.\n */\nexport function checkCompiles(): void {\n\t// eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n\tconst presence = {} as PresenceWithNotifications;\n\tpresence.notifications.getWorkspace(\"name:testNotifications\", {\n\t\ttestEvents: Notifications({\n\t\t\thotSpot: (_sender: Attendee, _: { x: number; y: number }): void => {},\n\t\t}),\n\t\t// @ts-expect-error - Notifications Workspace only permits NotificationsManagers\n\t\tcamera: StateFactory.latest({ local: { x: 0, y: 0, z: 0 } }),\n\t});\n}\n"]}
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/*!
|
|
3
|
-
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
4
|
-
* Licensed under the MIT License.
|
|
5
|
-
*/
|
|
6
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.checkCompiles = void 0;
|
|
8
|
-
const node_assert_1 = require("node:assert");
|
|
9
|
-
const test_1 = require("@fluid-internal/presence-runtime/internal/test");
|
|
10
|
-
const states_1 = require("@fluid-internal/presence-runtime/states");
|
|
11
|
-
const broadcastControlsTests_js_1 = require("./broadcastControlsTests.js");
|
|
12
|
-
const mockEphemeralRuntime_js_1 = require("./mockEphemeralRuntime.js");
|
|
13
|
-
const testWorkspaceName = "name:testWorkspaceA";
|
|
14
|
-
describe("Presence/States", () => {
|
|
15
|
-
describe("StatesWorkspace", () => {
|
|
16
|
-
/**
|
|
17
|
-
* See {@link checkCompiles} below
|
|
18
|
-
*/
|
|
19
|
-
it("API use compiles", () => { });
|
|
20
|
-
(0, broadcastControlsTests_js_1.addControlsTests)((presence, controlSettings) => {
|
|
21
|
-
return presence.states.getWorkspace(testWorkspaceName, {}, controlSettings);
|
|
22
|
-
});
|
|
23
|
-
it(".presence provides Presence it was created under", () => {
|
|
24
|
-
const presence = (0, test_1.createPresenceManager)(new mockEphemeralRuntime_js_1.MockEphemeralRuntime());
|
|
25
|
-
const states = presence.states.getWorkspace(testWorkspaceName, {
|
|
26
|
-
obj: states_1.StateFactory.latest({ local: {} }),
|
|
27
|
-
});
|
|
28
|
-
node_assert_1.strict.strictEqual(states.presence, presence);
|
|
29
|
-
});
|
|
30
|
-
});
|
|
31
|
-
});
|
|
32
|
-
// ---- test (example) code ----
|
|
33
|
-
/**
|
|
34
|
-
* Check that the code compiles.
|
|
35
|
-
*/
|
|
36
|
-
function checkCompiles() {
|
|
37
|
-
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
38
|
-
const presence = {};
|
|
39
|
-
const statesWorkspace = presence.states.getWorkspace("name:testWorkspaceA", {
|
|
40
|
-
cursor: createValueManager({ x: 0, y: 0 }),
|
|
41
|
-
// eslint-disable-next-line prefer-object-spread
|
|
42
|
-
camera: Object.assign({ instanceBase: undefined }, () => ({
|
|
43
|
-
value: { rev: 0, timestamp: Date.now(), value: { x: 0, y: 0, z: 0 } },
|
|
44
|
-
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
45
|
-
manager: {},
|
|
46
|
-
})),
|
|
47
|
-
});
|
|
48
|
-
// Workaround ts(2775): Assertions require every name in the call target to be declared with an explicit type annotation.
|
|
49
|
-
const states = statesWorkspace;
|
|
50
|
-
const initialCaret = { id: "", pos: 0 };
|
|
51
|
-
states.add("caret", createValueManager(initialCaret));
|
|
52
|
-
const statesProps = states.states;
|
|
53
|
-
const fakeAdd = statesProps.camera.z + statesProps.cursor.x + statesProps.caret.pos;
|
|
54
|
-
console.log(fakeAdd);
|
|
55
|
-
// @ts-expect-error should error on typo detection
|
|
56
|
-
console.log(states.curso); // error to highlight typo detection (proper typing in effect)
|
|
57
|
-
// example of second add at existing key - results in union of types (should throw at runtime)
|
|
58
|
-
states.add("caret", createValueManager({ dupe: 0 }));
|
|
59
|
-
states.add("undefined",
|
|
60
|
-
// @ts-expect-error should error non-optional undefined
|
|
61
|
-
createValueManager({ undef: undefined }));
|
|
62
|
-
states.add("undefOrNum",
|
|
63
|
-
// @ts-expect-error should error on non-optional that may be undefined
|
|
64
|
-
createValueManager({ undefOrNum: 4 }));
|
|
65
|
-
// optional undefined is ok - though not recommended to actually specify such properties with
|
|
66
|
-
// undefined values as the properties won't come back; they will be absent.
|
|
67
|
-
states.add("optionalUndefined",
|
|
68
|
-
// @ts-expect-error should error on exact optional property
|
|
69
|
-
createValueManager({ undef: undefined }));
|
|
70
|
-
states.add("optionalUndefinedPreferred", createValueManager({}));
|
|
71
|
-
}
|
|
72
|
-
exports.checkCompiles = checkCompiles;
|
|
73
|
-
//# sourceMappingURL=presenceStates.spec.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"presenceStates.spec.js","sourceRoot":"","sources":["../../../src/states/test/presenceStates.spec.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { strict as assert } from \"node:assert\";\n\nimport type { InternalPresenceTypes, Presence } from \"@fluid-internal/presence-definitions\";\nimport type {\n\tJsonDeserialized,\n\tJsonSerializable,\n} from \"@fluidframework/core-interfaces/internal/exposedUtilityTypes\";\n\nimport { createPresenceManager } from \"@fluid-internal/presence-runtime/internal/test\";\nimport { StateFactory } from \"@fluid-internal/presence-runtime/states\";\n\nimport { addControlsTests } from \"./broadcastControlsTests.js\";\nimport { MockEphemeralRuntime } from \"./mockEphemeralRuntime.js\";\n\nconst testWorkspaceName = \"name:testWorkspaceA\";\n\ndescribe(\"Presence/States\", () => {\n\tdescribe(\"StatesWorkspace\", () => {\n\t\t/**\n\t\t * See {@link checkCompiles} below\n\t\t */\n\t\tit(\"API use compiles\", () => {});\n\n\t\taddControlsTests((presence, controlSettings) => {\n\t\t\treturn presence.states.getWorkspace(testWorkspaceName, {}, controlSettings);\n\t\t});\n\n\t\tit(\".presence provides Presence it was created under\", () => {\n\t\t\tconst presence = createPresenceManager(new MockEphemeralRuntime());\n\t\t\tconst states = presence.states.getWorkspace(testWorkspaceName, {\n\t\t\t\tobj: StateFactory.latest({ local: {} }),\n\t\t\t});\n\t\t\tassert.strictEqual(states.presence, presence);\n\t\t});\n\t});\n});\n\ndeclare function createValueManager<T, Key extends string>(\n\tinitial: JsonSerializable<T>,\n): { instanceBase: new () => unknown } & ((\n\tkey: Key,\n\tdatastoreHandle: InternalPresenceTypes.StateDatastoreHandle<\n\t\tKey,\n\t\tInternalPresenceTypes.ValueRequiredState<T>\n\t>,\n) => {\n\tvalue: InternalPresenceTypes.ValueRequiredState<T>;\n\tmanager: InternalPresenceTypes.StateValue<JsonDeserialized<T>>;\n});\n\n// ---- test (example) code ----\n\n/**\n * Check that the code compiles.\n */\nexport function checkCompiles(): void {\n\t// eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n\tconst presence = {} as Presence;\n\tconst statesWorkspace = presence.states.getWorkspace(\"name:testWorkspaceA\", {\n\t\tcursor: createValueManager({ x: 0, y: 0 }),\n\t\t// eslint-disable-next-line prefer-object-spread\n\t\tcamera: Object.assign({ instanceBase: undefined as unknown as new () => unknown }, () => ({\n\t\t\tvalue: { rev: 0, timestamp: Date.now(), value: { x: 0, y: 0, z: 0 } },\n\t\t\t// eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n\t\t\tmanager: {} as InternalPresenceTypes.StateValue<{ x: number; y: number; z: number }>,\n\t\t})),\n\t});\n\t// Workaround ts(2775): Assertions require every name in the call target to be declared with an explicit type annotation.\n\tconst states: typeof statesWorkspace = statesWorkspace;\n\n\tconst initialCaret = { id: \"\", pos: 0 };\n\tstates.add(\"caret\", createValueManager(initialCaret));\n\tconst statesProps = states.states;\n\n\tconst fakeAdd = statesProps.camera.z + statesProps.cursor.x + statesProps.caret.pos;\n\tconsole.log(fakeAdd);\n\n\t// @ts-expect-error should error on typo detection\n\tconsole.log(states.curso); // error to highlight typo detection (proper typing in effect)\n\n\t// example of second add at existing key - results in union of types (should throw at runtime)\n\tstates.add(\"caret\", createValueManager({ dupe: 0 }));\n\n\tstates.add(\n\t\t\"undefined\",\n\t\t// @ts-expect-error should error non-optional undefined\n\t\tcreateValueManager({ undef: undefined }),\n\t);\n\n\tstates.add(\n\t\t\"undefOrNum\",\n\t\t// @ts-expect-error should error on non-optional that may be undefined\n\t\tcreateValueManager<{ undefOrNum: undefined | number }, \"undefOrNum\">({ undefOrNum: 4 }),\n\t);\n\n\t// optional undefined is ok - though not recommended to actually specify such properties with\n\t// undefined values as the properties won't come back; they will be absent.\n\tstates.add(\n\t\t\"optionalUndefined\",\n\t\t// @ts-expect-error should error on exact optional property\n\t\tcreateValueManager<{ undef?: number }, \"optionalUndefined\">({ undef: undefined }),\n\t);\n\tstates.add(\n\t\t\"optionalUndefinedPreferred\",\n\t\tcreateValueManager<{ undef?: number }, \"optionalUndefinedPreferred\">({}),\n\t);\n}\n"]}
|