anear-js-api 0.4.7 → 0.4.9
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.
|
@@ -137,7 +137,6 @@ class AnearMessaging {
|
|
|
137
137
|
|
|
138
138
|
if (!eventExists) {
|
|
139
139
|
const messagingInitializedCallback = async () => {
|
|
140
|
-
await anearEvent.createdEventCallback()
|
|
141
140
|
await anearEvent.persist()
|
|
142
141
|
// start the state machine before initializing Realtime Messaging
|
|
143
142
|
// as REFRESH events come in and the state machine should be ready
|
|
@@ -214,7 +213,7 @@ class AnearMessaging {
|
|
|
214
213
|
this.subscribePresenceEvent(
|
|
215
214
|
spectatorsChannel,
|
|
216
215
|
PRESENCE_ENTER,
|
|
217
|
-
async message => await this.
|
|
216
|
+
async message => await this.spectatorViewMessagingCallback(anearEvent, message)
|
|
218
217
|
)
|
|
219
218
|
|
|
220
219
|
this.subscribePresenceEvent(
|
|
@@ -351,12 +350,11 @@ class AnearMessaging {
|
|
|
351
350
|
})
|
|
352
351
|
}
|
|
353
352
|
|
|
354
|
-
|
|
353
|
+
spectatorViewMessagingCallback(anearEvent, message) {
|
|
355
354
|
const userId = message.clientId
|
|
355
|
+
logger.debug(`**** ENTER SPECTATOR FOR VIEWING **** event: ${anearEvent.id}, user: ${userId}`)
|
|
356
356
|
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
await anearEvent.refreshSpectator()
|
|
357
|
+
anearEvent.spectatorView(userId)
|
|
360
358
|
}
|
|
361
359
|
|
|
362
360
|
async spectatorLeaveMessagingCallback(anearEvent, message) {
|
|
@@ -450,8 +448,8 @@ class AnearMessaging {
|
|
|
450
448
|
logger.debug(`setupPrivatePublishingChannel(${participant.privateChannelName}) state ${privateChannel.state}`)
|
|
451
449
|
}
|
|
452
450
|
|
|
453
|
-
|
|
454
|
-
return
|
|
451
|
+
attachChannel(channel) {
|
|
452
|
+
return channel.attach()
|
|
455
453
|
}
|
|
456
454
|
|
|
457
455
|
subscribeEventMessages(channel, messageType, callback) {
|
package/lib/models/AnearEvent.js
CHANGED
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
const { Mutex } = require('async-mutex')
|
|
4
4
|
|
|
5
5
|
const AnearXstate = require('../utils/AnearXstate')
|
|
6
|
-
const { DefaultConfigFunc, DefaultOptionsFunc } = require('../utils/AnearXstateDefaults')
|
|
7
6
|
|
|
8
7
|
const JsonApiResource = require('./JsonApiResource')
|
|
9
8
|
const Participants = require('../utils/Participants')
|
|
@@ -40,12 +39,12 @@ class AnearEvent extends JsonApiResource {
|
|
|
40
39
|
|
|
41
40
|
stateMachineConfig() {
|
|
42
41
|
// override in subclass with custom Xstate config
|
|
43
|
-
return
|
|
42
|
+
return {}
|
|
44
43
|
}
|
|
45
44
|
|
|
46
45
|
stateMachineOptions() {
|
|
47
46
|
// override in subclass with custom Xstate options
|
|
48
|
-
return
|
|
47
|
+
return {}
|
|
49
48
|
}
|
|
50
49
|
|
|
51
50
|
initStateMachine(previousState) {
|
|
@@ -65,14 +64,13 @@ class AnearEvent extends JsonApiResource {
|
|
|
65
64
|
return this.relationships.zone.data.id
|
|
66
65
|
}
|
|
67
66
|
|
|
68
|
-
|
|
67
|
+
getClonedEvent() {
|
|
69
68
|
// if the current event was a clone of previous event, fetch if from
|
|
70
69
|
// Peristence and return
|
|
71
70
|
const clonedEventData = this.relationships["cloned-event"].data
|
|
72
71
|
if (!clonedEventData) return null
|
|
73
72
|
|
|
74
|
-
|
|
75
|
-
return clonedEvent
|
|
73
|
+
return this.constructor.getFromStorage(clonedEventData.id)
|
|
76
74
|
}
|
|
77
75
|
|
|
78
76
|
async clonedEventContext() {
|
|
@@ -124,55 +122,16 @@ class AnearEvent extends JsonApiResource {
|
|
|
124
122
|
return !this.hasFlag("no_spectators")
|
|
125
123
|
}
|
|
126
124
|
|
|
127
|
-
|
|
128
|
-
return
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
async createdEventCallback(participantCreator) {
|
|
132
|
-
// You may implement createdEventCallback() in your AnearEvent sub-class
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
async participantEnterEventCallback(participant) {
|
|
136
|
-
throw new Error('You must implement an async participantEnterEventCallback() in your AnearEvent sub-class');
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
async participantRefreshEventCallback(participant, remainingTimeout = null) {
|
|
140
|
-
// You may implement an async participantRefreshEventCallback() in your AnearEvent sub-class
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
async spectatorRefreshEventCallback() {
|
|
144
|
-
// You may implement an async spectatorRefreshEventCallback() in your AnearEvent sub-class
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
async participantExitEventCallback(participant) {
|
|
148
|
-
throw new Error('You must implement an async participantExitEventCallback() in your AnearEvent sub-class');
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
async participantActionEventCallback(participant, actionEventName, message) {
|
|
152
|
-
throw new Error('You must implement an async participantActionEventCallback() in your AnearEvent sub-class');
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
async participantTimedOutEventCallback(participant) {
|
|
156
|
-
// You may implement participantTimedOutEventCallback() in your AnearEvent sub-class'
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
async eventBroadcastEventCallback(message) {
|
|
160
|
-
// You may implement eventBroadcastEventCallback() in your AnearEvent sub-class'
|
|
125
|
+
spectatorCount() {
|
|
126
|
+
return this.messaging.getSpectatorCount(this)
|
|
161
127
|
}
|
|
162
128
|
|
|
163
129
|
isParticipantEventCreator(RParticipant) {
|
|
164
130
|
return participant.userId === this.userId
|
|
165
131
|
}
|
|
166
|
-
async refreshParticipant(participant) {
|
|
167
|
-
await this.participantRefreshEventCallback(participant)
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
async refreshSpectator() {
|
|
171
|
-
await this.spectatorRefreshEventCallback()
|
|
172
|
-
}
|
|
173
132
|
|
|
174
|
-
|
|
175
|
-
|
|
133
|
+
publishEventParticipantsMessage(message, timeoutMsecs=0) {
|
|
134
|
+
return this.messaging.publishEventParticipantsMessage(
|
|
176
135
|
this,
|
|
177
136
|
this.participants.active(),
|
|
178
137
|
this.css,
|
|
@@ -193,12 +152,12 @@ class AnearEvent extends JsonApiResource {
|
|
|
193
152
|
logger.debug(`mutex ${name} released!`)
|
|
194
153
|
}
|
|
195
154
|
|
|
196
|
-
|
|
197
|
-
|
|
155
|
+
publishEventSpectatorsMessage(message) {
|
|
156
|
+
return this.messaging.publishEventSpectatorsMessage(this, this.css, message)
|
|
198
157
|
}
|
|
199
158
|
|
|
200
|
-
|
|
201
|
-
|
|
159
|
+
publishEventPrivateMessage(participant, message, timeoutMsecs=0) {
|
|
160
|
+
return this.messaging.publishEventPrivateMessage(
|
|
202
161
|
this,
|
|
203
162
|
participant,
|
|
204
163
|
PrivateDisplayMessageType,
|
|
@@ -208,8 +167,8 @@ class AnearEvent extends JsonApiResource {
|
|
|
208
167
|
)
|
|
209
168
|
}
|
|
210
169
|
|
|
211
|
-
|
|
212
|
-
|
|
170
|
+
publishEventTransitionMessage(newState) {
|
|
171
|
+
return this.messaging.publishEventTransitionMessage(
|
|
213
172
|
this,
|
|
214
173
|
newState
|
|
215
174
|
)
|
|
@@ -247,16 +206,20 @@ class AnearEvent extends JsonApiResource {
|
|
|
247
206
|
}
|
|
248
207
|
}
|
|
249
208
|
|
|
250
|
-
|
|
209
|
+
participantExit(participant) {
|
|
251
210
|
// this informs the state machine that the participant has exited the event
|
|
252
211
|
// and removes that participant completely
|
|
253
212
|
this.anearStateMachine.sendParticipantExitEvent({ participant })
|
|
254
|
-
|
|
213
|
+
return this.participantPurge(participant)
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
spectatorView(userId) {
|
|
217
|
+
this.anearStateMachine.sendSpectatorViewEvent({userId})
|
|
255
218
|
}
|
|
256
219
|
|
|
257
|
-
|
|
220
|
+
participantPurge(participant) {
|
|
258
221
|
this.participants.purge(participant)
|
|
259
|
-
|
|
222
|
+
return participant.remove()
|
|
260
223
|
}
|
|
261
224
|
|
|
262
225
|
participantAction(participant, actionEventName, actionPayload) {
|
|
@@ -267,10 +230,6 @@ class AnearEvent extends JsonApiResource {
|
|
|
267
230
|
this.anearStateMachine.sendTimeoutEvent({ participant })
|
|
268
231
|
}
|
|
269
232
|
|
|
270
|
-
async eventBroadcast(message) {
|
|
271
|
-
await this.eventBroadcastEventCallback(message)
|
|
272
|
-
}
|
|
273
|
-
|
|
274
233
|
async transitionEvent(eventName='next') {
|
|
275
234
|
//
|
|
276
235
|
// Allows the app/game to transition the remote AnearEvent which can un/hide and event
|
|
@@ -302,24 +261,24 @@ class AnearEvent extends JsonApiResource {
|
|
|
302
261
|
await this.transitionEvent('next')
|
|
303
262
|
}
|
|
304
263
|
|
|
305
|
-
|
|
306
|
-
|
|
264
|
+
transitionLive() {
|
|
265
|
+
return this.transitionNextNext()
|
|
307
266
|
}
|
|
308
267
|
|
|
309
|
-
|
|
310
|
-
|
|
268
|
+
transitionClosed() {
|
|
269
|
+
return this.transitionNextNext()
|
|
311
270
|
}
|
|
312
271
|
|
|
313
|
-
|
|
314
|
-
|
|
272
|
+
transitionCanceled() {
|
|
273
|
+
return this.transitionEvent('cancel')
|
|
315
274
|
}
|
|
316
275
|
|
|
317
|
-
|
|
276
|
+
closeOutParticipants() {
|
|
318
277
|
// upon exiting the event, this will clean up any participants remaining
|
|
319
278
|
return Promise.all(
|
|
320
279
|
this.participants.all.map(
|
|
321
|
-
|
|
322
|
-
|
|
280
|
+
p => {
|
|
281
|
+
return this.messaging.closeParticipant(
|
|
323
282
|
this,
|
|
324
283
|
p.id,
|
|
325
284
|
async (anearEvent, participant) => {
|
|
@@ -331,12 +290,12 @@ class AnearEvent extends JsonApiResource {
|
|
|
331
290
|
)
|
|
332
291
|
}
|
|
333
292
|
|
|
334
|
-
|
|
335
|
-
// remove participants from Participants class and from Storage
|
|
293
|
+
purgeParticipants() {
|
|
294
|
+
// remove participants and host from Participants class and from Storage
|
|
336
295
|
const all = this.participants.all
|
|
337
296
|
if (this.participants.host) all.push(this.participants.host)
|
|
338
297
|
|
|
339
|
-
|
|
298
|
+
return Promise.all(
|
|
340
299
|
all.map(p => this.participantPurge(p))
|
|
341
300
|
)
|
|
342
301
|
}
|
|
@@ -366,8 +325,8 @@ class AnearEvent extends JsonApiResource {
|
|
|
366
325
|
await this.closeMessaging()
|
|
367
326
|
}
|
|
368
327
|
|
|
369
|
-
|
|
370
|
-
|
|
328
|
+
closeMessaging () {
|
|
329
|
+
return this.messaging.detachAll(this.id)
|
|
371
330
|
}
|
|
372
331
|
|
|
373
332
|
logDebugMessage(...args) {
|
package/lib/utils/AnearXstate.js
CHANGED
|
@@ -3,7 +3,8 @@ const { createMachine, interpret, State } = require('xstate')
|
|
|
3
3
|
|
|
4
4
|
const logger = require('../utils/Logger')
|
|
5
5
|
|
|
6
|
-
const JoinEvent = '
|
|
6
|
+
const JoinEvent = 'PARTICIPANT_JOIN'
|
|
7
|
+
const SpectatorViewEvent = 'SPECTATOR_VIEW'
|
|
7
8
|
const ParticipantExitEvent = 'PARTICIPANT_EXIT'
|
|
8
9
|
const RefreshEvent = 'REFRESH'
|
|
9
10
|
const CloseEvent = 'EVENT_CLOSE'
|
|
@@ -60,6 +61,10 @@ class AnearXstate {
|
|
|
60
61
|
this.send(ParticipantExitEvent, params)
|
|
61
62
|
}
|
|
62
63
|
|
|
64
|
+
sendSpectatorViewEvent(params) {
|
|
65
|
+
this.send(SpectatorViewEvent, params)
|
|
66
|
+
}
|
|
67
|
+
|
|
63
68
|
sendTimeoutEvent(params) {
|
|
64
69
|
this.send(TimeoutEvent, params)
|
|
65
70
|
}
|
package/package.json
CHANGED
package/tests/AnearEvent.test.js
CHANGED
|
@@ -5,6 +5,7 @@ const AnearParticipant = require('../lib/models/AnearParticipant')
|
|
|
5
5
|
const MockMessaging = require('../lib/messaging/__mocks__/AnearMessaging')
|
|
6
6
|
|
|
7
7
|
const mockParticipantEnterHandler = jest.fn()
|
|
8
|
+
const mockSpectatorViewHandler = jest.fn()
|
|
8
9
|
const mockParticipantRefreshHandler = jest.fn()
|
|
9
10
|
const mockParticipantExitHandler = jest.fn()
|
|
10
11
|
const mockParticipantActionHandler = jest.fn()
|
|
@@ -15,15 +16,19 @@ const TicTacToeMachineConfig = anearEvent => ({
|
|
|
15
16
|
states: {
|
|
16
17
|
waitingForHost: {
|
|
17
18
|
on: {
|
|
18
|
-
|
|
19
|
+
PARTICIPANT_JOIN: {
|
|
19
20
|
actions: 'enterHandler',
|
|
20
21
|
target: 'waitingForOpponent'
|
|
22
|
+
},
|
|
23
|
+
SPECTATOR_VIEW: {
|
|
24
|
+
actions: 'viewHandler',
|
|
25
|
+
target: 'waitingForHost'
|
|
21
26
|
}
|
|
22
27
|
}
|
|
23
28
|
},
|
|
24
29
|
waitingForOpponent: {
|
|
25
30
|
on: {
|
|
26
|
-
|
|
31
|
+
PARTICIPANT_JOIN: {
|
|
27
32
|
actions: 'enterHandler',
|
|
28
33
|
target: 'gameStart'
|
|
29
34
|
},
|
|
@@ -37,6 +42,9 @@ const TicTacToeMachineConfig = anearEvent => ({
|
|
|
37
42
|
},
|
|
38
43
|
gameStart: {
|
|
39
44
|
on: {
|
|
45
|
+
TEST_ACTION: {
|
|
46
|
+
actions: 'testActionHandler'
|
|
47
|
+
},
|
|
40
48
|
BULLSEYE: {
|
|
41
49
|
actions: 'actionHandler'
|
|
42
50
|
},
|
|
@@ -59,10 +67,20 @@ const TicTacToeMachineOptions = anearEvent => ({
|
|
|
59
67
|
refreshHandler: (context, event) => {
|
|
60
68
|
anearEvent.myParticipantRefreshHandler(event.participant)
|
|
61
69
|
},
|
|
70
|
+
viewHandler: (context, event) => {
|
|
71
|
+
anearEvent.mySpectatorViewHandler(event.userId)
|
|
72
|
+
},
|
|
62
73
|
participantExitHandler: (context, event) => {
|
|
63
74
|
anearEvent.myParticipantExitHandler(event.participant)
|
|
64
75
|
},
|
|
65
76
|
actionHandler: assign({score: (context, event) => context.score + event.payload.points}),
|
|
77
|
+
testActionHandler: (context, event) => {
|
|
78
|
+
anearEvent.myParticipantActionHandler(
|
|
79
|
+
event.participant.id,
|
|
80
|
+
event.type,
|
|
81
|
+
event.payload
|
|
82
|
+
)
|
|
83
|
+
}
|
|
66
84
|
}
|
|
67
85
|
})
|
|
68
86
|
|
|
@@ -81,6 +99,9 @@ class TestEvent extends AnearEvent {
|
|
|
81
99
|
return TicTacToeMachineOptions(this)
|
|
82
100
|
}
|
|
83
101
|
|
|
102
|
+
async mySpectatorViewHandler(...args) {
|
|
103
|
+
return mockSpectatorViewHandler(...args)
|
|
104
|
+
}
|
|
84
105
|
async myParticipantEnterHandler(...args) {
|
|
85
106
|
return mockParticipantEnterHandler(...args)
|
|
86
107
|
}
|
|
@@ -90,37 +111,12 @@ class TestEvent extends AnearEvent {
|
|
|
90
111
|
async myParticipantRefreshHandler(...args) {
|
|
91
112
|
return mockParticipantRefreshHandler(...args)
|
|
92
113
|
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
class TestEventWithDefaultXState extends AnearEvent {
|
|
97
|
-
initContext() {
|
|
98
|
-
return {
|
|
99
|
-
playerScores: [83, 22]
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
participantEnterEventCallback(participant) {
|
|
104
|
-
mockParticipantEnterHandler(participant)
|
|
105
|
-
return Promise.resolve()
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
participantRefreshEventCallback(participant) {
|
|
109
|
-
mockParticipantRefreshHandler(participant)
|
|
110
|
-
return Promise.resolve()
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
participantExitEventCallback(participant) {
|
|
114
|
-
mockParticipantExitHandler(participant)
|
|
115
|
-
return Promise.resolve()
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
participantActionEventCallback(participant, actionEventName, payload) {
|
|
119
|
-
mockParticipantActionHandler(participant, actionEventName, payload)
|
|
120
|
-
return Promise.resolve()
|
|
114
|
+
async myParticipantActionHandler(...args) {
|
|
115
|
+
return mockParticipantActionHandler(...args)
|
|
121
116
|
}
|
|
122
117
|
}
|
|
123
118
|
|
|
119
|
+
|
|
124
120
|
class TestPlayer extends AnearParticipant {
|
|
125
121
|
initContext() {
|
|
126
122
|
return {
|
|
@@ -148,23 +144,18 @@ const newTestEvent = (hosted = false) => {
|
|
|
148
144
|
return t
|
|
149
145
|
}
|
|
150
146
|
|
|
151
|
-
|
|
152
|
-
const t =
|
|
153
|
-
t.startStateMachine()
|
|
154
|
-
return t
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
test('participant enter with Default Xstate Config', async () => {
|
|
158
|
-
const t = newTestEventWithDefaultXState(chatEvent)
|
|
147
|
+
test('participant enter', async () => {
|
|
148
|
+
const t = newTestEvent()
|
|
159
149
|
|
|
160
150
|
const id = t.id
|
|
161
151
|
expect(t.id).toBe(chatEvent.data.id)
|
|
162
152
|
expect(t.relationships.user.data.type).toBe("users")
|
|
163
|
-
expect(t.anearStateMachine.currentState.value).toBe("
|
|
164
|
-
expect(t.stateMachineContext.
|
|
153
|
+
expect(t.anearStateMachine.currentState.value).toBe("waitingForHost")
|
|
154
|
+
expect(t.stateMachineContext.score).toBe(90)
|
|
165
155
|
const p1 = new TestPlayer(chatParticipant1, t)
|
|
166
156
|
|
|
167
157
|
await t.participantEnter(p1)
|
|
158
|
+
expect(t.anearStateMachine.currentState.value).toBe("waitingForOpponent")
|
|
168
159
|
await t.persist()
|
|
169
160
|
await t.remove()
|
|
170
161
|
|
|
@@ -176,10 +167,25 @@ test('participant enter with Default Xstate Config', async () => {
|
|
|
176
167
|
await p1.remove()
|
|
177
168
|
})
|
|
178
169
|
|
|
179
|
-
test('
|
|
180
|
-
const t =
|
|
170
|
+
test('spectator viewer', async () => {
|
|
171
|
+
const t = newTestEvent()
|
|
172
|
+
const userId = 999837834
|
|
173
|
+
|
|
174
|
+
const id = t.id
|
|
175
|
+
expect(t.anearStateMachine.currentState.value).toBe("waitingForHost")
|
|
176
|
+
await t.spectatorView(userId)
|
|
177
|
+
expect(t.anearStateMachine.currentState.value).toBe("waitingForHost")
|
|
178
|
+
|
|
179
|
+
expect(mockSpectatorViewHandler).toHaveBeenCalledTimes(1)
|
|
180
|
+
expect(mockSpectatorViewHandler).toHaveBeenCalledWith(userId)
|
|
181
|
+
})
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
test('participant close', async () => {
|
|
185
|
+
const t = newTestEvent()
|
|
181
186
|
|
|
182
187
|
const p1 = new TestPlayer(chatParticipant1, t)
|
|
188
|
+
await t.participantEnter(p1)
|
|
183
189
|
|
|
184
190
|
await t.participantExit(p1)
|
|
185
191
|
await t.update()
|
|
@@ -191,29 +197,20 @@ test('participant close with Default Xstate Config', async () => {
|
|
|
191
197
|
await t.remove()
|
|
192
198
|
})
|
|
193
199
|
|
|
194
|
-
test('participant
|
|
195
|
-
const t =
|
|
200
|
+
test('participant action', async () => {
|
|
201
|
+
const t = newTestEvent()
|
|
196
202
|
const p1 = new TestPlayer(chatParticipant1, t)
|
|
203
|
+
const p2 = new TestPlayer(chatParticipant2, t)
|
|
204
|
+
await t.participantEnter(p1)
|
|
205
|
+
await t.participantEnter(p2)
|
|
197
206
|
|
|
198
|
-
await t.refreshParticipant(p1)
|
|
199
|
-
await t.update()
|
|
200
|
-
|
|
201
|
-
expect(mockParticipantRefreshHandler).toHaveBeenCalledWith(p1)
|
|
202
|
-
expect(mockParticipantRefreshHandler).toHaveBeenCalledTimes(1)
|
|
203
|
-
await p1.remove()
|
|
204
|
-
await t.remove()
|
|
205
|
-
})
|
|
206
|
-
|
|
207
|
-
test('participant action with Default Xstate Config', async () => {
|
|
208
|
-
const t = newTestEventWithDefaultXState(chatEvent)
|
|
209
|
-
const p1 = new TestPlayer(chatParticipant1, t)
|
|
210
207
|
const eventName = "TEST_ACTION"
|
|
211
208
|
const payload = {x: 1, y: 99}
|
|
212
209
|
|
|
213
210
|
await t.participantAction(p1, eventName, payload)
|
|
214
211
|
await t.update()
|
|
215
212
|
|
|
216
|
-
expect(mockParticipantActionHandler).toHaveBeenCalledWith(p1, eventName, payload)
|
|
213
|
+
expect(mockParticipantActionHandler).toHaveBeenCalledWith(p1.id, eventName, payload)
|
|
217
214
|
expect(mockParticipantActionHandler).toHaveBeenCalledTimes(1)
|
|
218
215
|
await p1.remove()
|
|
219
216
|
await t.remove()
|
|
@@ -279,6 +276,7 @@ test('purge all participants', async () => {
|
|
|
279
276
|
await t.purgeParticipants()
|
|
280
277
|
|
|
281
278
|
expect(t.participants.all).toHaveLength(0)
|
|
279
|
+
expect(t.participants.host).toBe(null)
|
|
282
280
|
|
|
283
281
|
await t.remove()
|
|
284
282
|
})
|
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
"use strict"
|
|
2
|
-
|
|
3
|
-
// Default configuration and options funcs provide
|
|
4
|
-
// a simple default state machine for an anear Event. This is
|
|
5
|
-
// so we don't mandate that app developers use xState to drive
|
|
6
|
-
// their app's state transitions. Devs simply provide callbacks
|
|
7
|
-
// override implementations in their AnearEvent subclass.
|
|
8
|
-
// The xState context is simply the anearEvent.context
|
|
9
|
-
//
|
|
10
|
-
// If a developer wants an xState machine to drive the applications
|
|
11
|
-
// state transitions, the developer should override stateMachineConfig()
|
|
12
|
-
// and stateMachineOptions() in their AnearEvent subclass.
|
|
13
|
-
//
|
|
14
|
-
const DefaultConfigFunc = (anearEvent) => {
|
|
15
|
-
|
|
16
|
-
const PromiseResolveReject = {
|
|
17
|
-
onDone: {
|
|
18
|
-
target: 'eventActive'
|
|
19
|
-
},
|
|
20
|
-
onError: {
|
|
21
|
-
actions: 'logError',
|
|
22
|
-
target: 'eventActive'
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
return {
|
|
27
|
-
id: "defaultXstateConfig",
|
|
28
|
-
initial: 'eventActive',
|
|
29
|
-
states: {
|
|
30
|
-
eventActive: {
|
|
31
|
-
on: {
|
|
32
|
-
JOIN: {
|
|
33
|
-
target: 'join'
|
|
34
|
-
},
|
|
35
|
-
REFRESH: {
|
|
36
|
-
target: 'refresh'
|
|
37
|
-
},
|
|
38
|
-
PARTICIPANT_EXIT: {
|
|
39
|
-
target: 'participant_exit'
|
|
40
|
-
},
|
|
41
|
-
TIMEOUT: {
|
|
42
|
-
target: 'timeout'
|
|
43
|
-
},
|
|
44
|
-
'*': {
|
|
45
|
-
// default wildcard state is presumed to be a custom ACTION name
|
|
46
|
-
// embedded in a anear-action-click property in the app's HTML
|
|
47
|
-
target: 'action'
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
},
|
|
51
|
-
join: {
|
|
52
|
-
invoke: {
|
|
53
|
-
id: 'join',
|
|
54
|
-
src: 'joinEventHandler',
|
|
55
|
-
...PromiseResolveReject
|
|
56
|
-
}
|
|
57
|
-
},
|
|
58
|
-
refresh: {
|
|
59
|
-
invoke: {
|
|
60
|
-
id: 'refresh',
|
|
61
|
-
src: 'refreshEventHandler',
|
|
62
|
-
...PromiseResolveReject
|
|
63
|
-
}
|
|
64
|
-
},
|
|
65
|
-
participant_exit: {
|
|
66
|
-
invoke: {
|
|
67
|
-
id: 'participant_exit',
|
|
68
|
-
src: 'participantExitEventHandler',
|
|
69
|
-
...PromiseResolveReject
|
|
70
|
-
}
|
|
71
|
-
},
|
|
72
|
-
timeout: {
|
|
73
|
-
invoke: {
|
|
74
|
-
id: 'timeout',
|
|
75
|
-
src: 'timeoutEventHandler',
|
|
76
|
-
...PromiseResolveReject
|
|
77
|
-
}
|
|
78
|
-
},
|
|
79
|
-
action: {
|
|
80
|
-
invoke: {
|
|
81
|
-
id: 'action',
|
|
82
|
-
src: 'actionEventHandler',
|
|
83
|
-
...PromiseResolveReject
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
const DefaultOptionsFunc = anearEvent => {
|
|
91
|
-
return {
|
|
92
|
-
actions: {
|
|
93
|
-
logError: (context, event) => logger.error(`error message: ${event.data}`)
|
|
94
|
-
},
|
|
95
|
-
services: {
|
|
96
|
-
joinEventHandler: (context, event) => anearEvent.participantEnterEventCallback(event.participant),
|
|
97
|
-
refreshEventHandler: (context, event) => anearEvent.participantRefreshEventCallback(event.participant, event.remainingTimeout),
|
|
98
|
-
participantExitEventHandler: (context, event) => anearEvent.participantExitEventCallback(event.participant),
|
|
99
|
-
timeoutEventHandler: (context, event) => anearEvent.participantTimedOutEventCallback(event.participant),
|
|
100
|
-
actionEventHandler: (context, event) => anearEvent.participantActionEventCallback(event.participant, event.type, event.payload)
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
module.exports = {
|
|
106
|
-
DefaultConfigFunc,
|
|
107
|
-
DefaultOptionsFunc
|
|
108
|
-
}
|