@sockethub/platform-xmpp 5.0.0-alpha.11 → 5.0.0-alpha.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/README.md +243 -31
- package/dist/incoming-handlers.d.ts +25 -0
- package/dist/index.d.ts +168 -0
- package/dist/index.js +16903 -409
- package/dist/index.js.map +155 -7
- package/dist/schema.d.ts +2 -0
- package/dist/types.d.ts +33 -0
- package/dist/utils.d.ts +19 -0
- package/package.json +14 -11
- package/src/incoming-handlers.js +0 -350
- package/src/incoming-handlers.test.data.js +0 -260
- package/src/incoming-handlers.test.js +0 -107
- package/src/index.js +0 -774
- package/src/index.test.js +0 -631
- package/src/schema.js +0 -61
- package/src/utils.js +0 -21
- package/src/utils.test.js +0 -58
package/src/index.test.js
DELETED
|
@@ -1,631 +0,0 @@
|
|
|
1
|
-
import { afterEach, beforeEach, describe, expect, it } from "bun:test";
|
|
2
|
-
import sinon from "sinon";
|
|
3
|
-
|
|
4
|
-
import XMPP from "./index.js";
|
|
5
|
-
|
|
6
|
-
const actor = {
|
|
7
|
-
type: "person",
|
|
8
|
-
id: "testingham@jabber.net",
|
|
9
|
-
name: "testing ham",
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
const credentials = {
|
|
13
|
-
actor: actor,
|
|
14
|
-
object: {
|
|
15
|
-
type: "credentials",
|
|
16
|
-
userAddress: "testingham@jabber.net",
|
|
17
|
-
password: "foobar",
|
|
18
|
-
resource: "home",
|
|
19
|
-
},
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
const target = {
|
|
23
|
-
mrfoobar: {
|
|
24
|
-
type: "person",
|
|
25
|
-
id: "mrfoobar@jabber.net",
|
|
26
|
-
name: "Mr FooBar",
|
|
27
|
-
},
|
|
28
|
-
partyroom: {
|
|
29
|
-
type: "room",
|
|
30
|
-
id: "partyroom@jabber.net",
|
|
31
|
-
},
|
|
32
|
-
roomuser: {
|
|
33
|
-
type: "room",
|
|
34
|
-
id: "partyroom@jabber.net/ms tut",
|
|
35
|
-
},
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
const job = {
|
|
39
|
-
connect: {
|
|
40
|
-
context: "xmpp",
|
|
41
|
-
type: "connect",
|
|
42
|
-
actor: {
|
|
43
|
-
id: "slvrbckt@jabber.net/Home",
|
|
44
|
-
type: "person",
|
|
45
|
-
name: "Nick Jennings",
|
|
46
|
-
userName: "slvrbckt",
|
|
47
|
-
},
|
|
48
|
-
},
|
|
49
|
-
join: {
|
|
50
|
-
actor: actor,
|
|
51
|
-
object: {
|
|
52
|
-
type: "update",
|
|
53
|
-
name: "Frank",
|
|
54
|
-
},
|
|
55
|
-
target: target.partyroom,
|
|
56
|
-
},
|
|
57
|
-
leave: {
|
|
58
|
-
actor: actor,
|
|
59
|
-
target: target.partyroom,
|
|
60
|
-
},
|
|
61
|
-
send: {
|
|
62
|
-
chat: {
|
|
63
|
-
actor: actor,
|
|
64
|
-
object: {
|
|
65
|
-
type: "message",
|
|
66
|
-
id: "hc-1234abcd",
|
|
67
|
-
content: "hello",
|
|
68
|
-
},
|
|
69
|
-
target: target.mrfoobar,
|
|
70
|
-
},
|
|
71
|
-
groupchat: {
|
|
72
|
-
actor: actor,
|
|
73
|
-
object: {
|
|
74
|
-
type: "message",
|
|
75
|
-
id: "hc-1234abcd",
|
|
76
|
-
content: "hi all",
|
|
77
|
-
},
|
|
78
|
-
target: target.roomuser,
|
|
79
|
-
},
|
|
80
|
-
correction: {
|
|
81
|
-
actor: actor,
|
|
82
|
-
object: {
|
|
83
|
-
type: "message",
|
|
84
|
-
id: "hc-1234abcd",
|
|
85
|
-
content: "hi yall",
|
|
86
|
-
"xmpp:replace": { id: "hc-234bcde" },
|
|
87
|
-
},
|
|
88
|
-
target: target.roomuser,
|
|
89
|
-
},
|
|
90
|
-
},
|
|
91
|
-
update: {
|
|
92
|
-
presenceOnline: {
|
|
93
|
-
actor: actor,
|
|
94
|
-
object: {
|
|
95
|
-
type: "presence",
|
|
96
|
-
presence: "online",
|
|
97
|
-
content: "ready to chat",
|
|
98
|
-
},
|
|
99
|
-
},
|
|
100
|
-
presenceUnavailable: {
|
|
101
|
-
actor: actor,
|
|
102
|
-
object: {
|
|
103
|
-
type: "presence",
|
|
104
|
-
presence: "away",
|
|
105
|
-
content: "eating popcorn",
|
|
106
|
-
},
|
|
107
|
-
},
|
|
108
|
-
presenceOffline: {
|
|
109
|
-
actor: actor,
|
|
110
|
-
object: {
|
|
111
|
-
type: "presence",
|
|
112
|
-
presence: "offline",
|
|
113
|
-
content: "",
|
|
114
|
-
},
|
|
115
|
-
},
|
|
116
|
-
},
|
|
117
|
-
"request-friend": {
|
|
118
|
-
actor: actor,
|
|
119
|
-
target: target.mrfoobar,
|
|
120
|
-
},
|
|
121
|
-
"remove-friend": {
|
|
122
|
-
actor: actor,
|
|
123
|
-
target: target.mrfoobar,
|
|
124
|
-
},
|
|
125
|
-
"make-friend": {
|
|
126
|
-
actor: actor,
|
|
127
|
-
target: target.mrfoobar,
|
|
128
|
-
},
|
|
129
|
-
query: {
|
|
130
|
-
actor: actor,
|
|
131
|
-
target: target.partyroom,
|
|
132
|
-
object: {
|
|
133
|
-
type: "attendance",
|
|
134
|
-
},
|
|
135
|
-
},
|
|
136
|
-
};
|
|
137
|
-
|
|
138
|
-
describe("XMPP", () => {
|
|
139
|
-
let clientFake, xmlFake, clientObjectFake, xp;
|
|
140
|
-
|
|
141
|
-
beforeEach(() => {
|
|
142
|
-
clientObjectFake = {
|
|
143
|
-
on: sinon.fake(),
|
|
144
|
-
start: sinon.fake.resolves(),
|
|
145
|
-
send: sinon.fake.resolves(),
|
|
146
|
-
join: sinon.fake.resolves(),
|
|
147
|
-
stop: sinon.fake.resolves()
|
|
148
|
-
};
|
|
149
|
-
clientFake = sinon.fake.returns(clientObjectFake);
|
|
150
|
-
|
|
151
|
-
// Mock XML object with chainable .c() method for building stanzas
|
|
152
|
-
const mockXmlElement = {
|
|
153
|
-
name: "presence",
|
|
154
|
-
attrs: {},
|
|
155
|
-
children: [],
|
|
156
|
-
c: sinon.fake.returns({
|
|
157
|
-
name: "x",
|
|
158
|
-
attrs: { xmlns: "http://jabber.org/protocol/muc" },
|
|
159
|
-
parent: null
|
|
160
|
-
}),
|
|
161
|
-
getChild: sinon.fake((name, xmlns) => {
|
|
162
|
-
if (name === "x" && xmlns === "http://jabber.org/protocol/muc") {
|
|
163
|
-
return { attrs: { xmlns: "http://jabber.org/protocol/muc" } };
|
|
164
|
-
}
|
|
165
|
-
return null;
|
|
166
|
-
})
|
|
167
|
-
};
|
|
168
|
-
|
|
169
|
-
// Create a smart fake that returns complex object for presence, simple for others
|
|
170
|
-
xmlFake = sinon.fake((elementName) => {
|
|
171
|
-
if (elementName === "presence") {
|
|
172
|
-
return mockXmlElement;
|
|
173
|
-
}
|
|
174
|
-
return undefined; // Default return for other elements
|
|
175
|
-
});
|
|
176
|
-
|
|
177
|
-
class TestXMPP extends XMPP {
|
|
178
|
-
createClient() {
|
|
179
|
-
this.__clientConstructor = clientFake;
|
|
180
|
-
}
|
|
181
|
-
createXml() {
|
|
182
|
-
this.__xml = xmlFake;
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
xp = new TestXMPP({
|
|
187
|
-
id: actor,
|
|
188
|
-
log: {
|
|
189
|
-
error: sinon.fake(),
|
|
190
|
-
warn: sinon.fake(),
|
|
191
|
-
info: sinon.fake(),
|
|
192
|
-
debug: sinon.fake(),
|
|
193
|
-
},
|
|
194
|
-
sendToClient: sinon.fake(),
|
|
195
|
-
});
|
|
196
|
-
});
|
|
197
|
-
|
|
198
|
-
afterEach(() => {
|
|
199
|
-
sinon.restore();
|
|
200
|
-
});
|
|
201
|
-
|
|
202
|
-
describe("Successful initialization", () => {
|
|
203
|
-
it("works as intended", (done) => {
|
|
204
|
-
xp.connect(job.connect, credentials, () => {
|
|
205
|
-
sinon.assert.calledOnce(clientFake);
|
|
206
|
-
expect(xp.__client.on).toBeDefined();
|
|
207
|
-
expect(xp.__client.start).toBeDefined();
|
|
208
|
-
expect(xp.__client.send).toBeDefined();
|
|
209
|
-
expect(xp.__client.send.callCount).toEqual(0);
|
|
210
|
-
sinon.assert.calledOnce(clientObjectFake.start);
|
|
211
|
-
sinon.assert.notCalled(xp.sendToClient);
|
|
212
|
-
done();
|
|
213
|
-
});
|
|
214
|
-
});
|
|
215
|
-
});
|
|
216
|
-
|
|
217
|
-
describe("Bad initialization", () => {
|
|
218
|
-
it("returns the existing __client object", (done) => {
|
|
219
|
-
const dummyClient = {
|
|
220
|
-
foo: "bar",
|
|
221
|
-
socket: {
|
|
222
|
-
writable: true
|
|
223
|
-
},
|
|
224
|
-
status: "online"
|
|
225
|
-
};
|
|
226
|
-
xp.__client = dummyClient
|
|
227
|
-
xp.connect(job.connect, credentials, (d) => {
|
|
228
|
-
console.log('result: ', d);
|
|
229
|
-
expect(xp.__client).toEqual(dummyClient);
|
|
230
|
-
sinon.assert.notCalled(clientFake);
|
|
231
|
-
sinon.assert.notCalled(xp.sendToClient);
|
|
232
|
-
// sinon.assert.calledOnce(clientFake);
|
|
233
|
-
// sinon.assert.calledOnce(xp.sendToClient);
|
|
234
|
-
done();
|
|
235
|
-
});
|
|
236
|
-
});
|
|
237
|
-
|
|
238
|
-
it("deletes the __client property on failed connect", (done) => {
|
|
239
|
-
clientObjectFake.start = sinon.fake.rejects("foo");
|
|
240
|
-
xp.connect(job.connect, credentials, () => {
|
|
241
|
-
expect(xp.__client).toBeUndefined();
|
|
242
|
-
sinon.assert.notCalled(xp.sendToClient);
|
|
243
|
-
done();
|
|
244
|
-
});
|
|
245
|
-
});
|
|
246
|
-
});
|
|
247
|
-
|
|
248
|
-
describe("Error handling", () => {
|
|
249
|
-
let processExitStub;
|
|
250
|
-
|
|
251
|
-
beforeEach(() => {
|
|
252
|
-
// Stub process.exit to prevent test process from exiting
|
|
253
|
-
processExitStub = sinon.stub(process, "exit");
|
|
254
|
-
});
|
|
255
|
-
|
|
256
|
-
afterEach(() => {
|
|
257
|
-
processExitStub.restore();
|
|
258
|
-
});
|
|
259
|
-
|
|
260
|
-
it("terminates process on TypeError (internal code error)", (done) => {
|
|
261
|
-
xp.connect(job.connect, credentials, () => {
|
|
262
|
-
// Get the error event handler that was registered
|
|
263
|
-
const errorHandler = clientObjectFake.on.getCalls().find(
|
|
264
|
-
(call) => call.args[0] === "error",
|
|
265
|
-
).args[1];
|
|
266
|
-
|
|
267
|
-
// Simulate a TypeError (internal code error)
|
|
268
|
-
const typeError = new TypeError("this.session.debug is not a function");
|
|
269
|
-
errorHandler(typeError);
|
|
270
|
-
|
|
271
|
-
// Verify process.exit(1) was called
|
|
272
|
-
sinon.assert.calledOnce(processExitStub);
|
|
273
|
-
sinon.assert.calledWith(processExitStub, 1);
|
|
274
|
-
|
|
275
|
-
// Verify error was logged
|
|
276
|
-
sinon.assert.called(xp.log.error);
|
|
277
|
-
expect(
|
|
278
|
-
xp.log.error
|
|
279
|
-
.getCalls()
|
|
280
|
-
.some((call) =>
|
|
281
|
-
call.args[0].includes("FATAL: Internal code error"),
|
|
282
|
-
),
|
|
283
|
-
).toBeTrue();
|
|
284
|
-
|
|
285
|
-
done();
|
|
286
|
-
});
|
|
287
|
-
});
|
|
288
|
-
|
|
289
|
-
it("terminates process on ReferenceError (internal code error)", (done) => {
|
|
290
|
-
xp.connect(job.connect, credentials, () => {
|
|
291
|
-
const errorHandler = clientObjectFake.on.getCalls().find(
|
|
292
|
-
(call) => call.args[0] === "error",
|
|
293
|
-
).args[1];
|
|
294
|
-
|
|
295
|
-
const refError = new ReferenceError("foo is not defined");
|
|
296
|
-
errorHandler(refError);
|
|
297
|
-
|
|
298
|
-
sinon.assert.calledOnce(processExitStub);
|
|
299
|
-
sinon.assert.calledWith(processExitStub, 1);
|
|
300
|
-
sinon.assert.called(xp.log.error);
|
|
301
|
-
|
|
302
|
-
done();
|
|
303
|
-
});
|
|
304
|
-
});
|
|
305
|
-
|
|
306
|
-
it("does NOT terminate process on network errors (recoverable)", (done) => {
|
|
307
|
-
xp.connect(job.connect, credentials, () => {
|
|
308
|
-
const errorHandler = clientObjectFake.on.getCalls().find(
|
|
309
|
-
(call) => call.args[0] === "error",
|
|
310
|
-
).args[1];
|
|
311
|
-
|
|
312
|
-
// Simulate a network error
|
|
313
|
-
const networkError = new Error("ECONNRESET");
|
|
314
|
-
networkError.code = "ECONNRESET";
|
|
315
|
-
errorHandler(networkError);
|
|
316
|
-
|
|
317
|
-
// Should NOT call process.exit for network errors
|
|
318
|
-
sinon.assert.notCalled(processExitStub);
|
|
319
|
-
|
|
320
|
-
// Should send error to client instead
|
|
321
|
-
sinon.assert.called(xp.sendToClient);
|
|
322
|
-
|
|
323
|
-
done();
|
|
324
|
-
});
|
|
325
|
-
});
|
|
326
|
-
|
|
327
|
-
it("does NOT terminate process on XMPP protocol errors (non-recoverable)", (done) => {
|
|
328
|
-
xp.connect(job.connect, credentials, () => {
|
|
329
|
-
const errorHandler = clientObjectFake.on.getCalls().find(
|
|
330
|
-
(call) => call.args[0] === "error",
|
|
331
|
-
).args[1];
|
|
332
|
-
|
|
333
|
-
// Simulate an XMPP protocol error (e.g., auth failure)
|
|
334
|
-
const authError = new Error("not-authorized");
|
|
335
|
-
authError.condition = "not-authorized";
|
|
336
|
-
errorHandler(authError);
|
|
337
|
-
|
|
338
|
-
// Should NOT call process.exit for XMPP errors
|
|
339
|
-
sinon.assert.notCalled(processExitStub);
|
|
340
|
-
|
|
341
|
-
// Should send error to client and mark disconnected
|
|
342
|
-
sinon.assert.called(xp.sendToClient);
|
|
343
|
-
|
|
344
|
-
done();
|
|
345
|
-
});
|
|
346
|
-
});
|
|
347
|
-
});
|
|
348
|
-
|
|
349
|
-
describe("Platform functionality", () => {
|
|
350
|
-
beforeEach((done) => {
|
|
351
|
-
xp.connect(job.join, credentials, () => done());
|
|
352
|
-
});
|
|
353
|
-
|
|
354
|
-
describe("#join", () => {
|
|
355
|
-
it("calls xmpp.js correctly", (done) => {
|
|
356
|
-
expect(xp.__client.send).toBeInstanceOf(Function);
|
|
357
|
-
xp.join(job.join, () => {
|
|
358
|
-
sinon.assert.calledOnce(xp.__client.send);
|
|
359
|
-
|
|
360
|
-
// Verify MUC <x> element was created with correct namespace
|
|
361
|
-
sinon.assert.calledWith(xmlFake, "x", { xmlns: "http://jabber.org/protocol/muc" });
|
|
362
|
-
|
|
363
|
-
// Verify presence stanza was created with correct attributes
|
|
364
|
-
sinon.assert.calledWith(xmlFake, "presence", {
|
|
365
|
-
from: "testingham@jabber.net",
|
|
366
|
-
to: "partyroom@jabber.net/testing ham",
|
|
367
|
-
});
|
|
368
|
-
|
|
369
|
-
done();
|
|
370
|
-
});
|
|
371
|
-
});
|
|
372
|
-
});
|
|
373
|
-
|
|
374
|
-
describe("#leave", () => {
|
|
375
|
-
it("calls xmpp.js correctly", (done) => {
|
|
376
|
-
expect(xp.__client).toBeDefined();
|
|
377
|
-
expect(xp.__client.send).toBeInstanceOf(Function);
|
|
378
|
-
xp.leave(job.leave, () => {
|
|
379
|
-
sinon.assert.calledOnce(xp.__client.send);
|
|
380
|
-
sinon.assert.calledWith(xmlFake, "presence", {
|
|
381
|
-
from: "testingham@jabber.net",
|
|
382
|
-
to: "partyroom@jabber.net/testing ham",
|
|
383
|
-
type: "unavailable",
|
|
384
|
-
});
|
|
385
|
-
done();
|
|
386
|
-
});
|
|
387
|
-
});
|
|
388
|
-
});
|
|
389
|
-
|
|
390
|
-
describe("#send", () => {
|
|
391
|
-
it("calls xmpp.js correctly", (done) => {
|
|
392
|
-
expect(xp.__client).toBeDefined();
|
|
393
|
-
expect(xp.__client.send).toBeInstanceOf(Function);
|
|
394
|
-
xp.send(job.send.chat, () => {
|
|
395
|
-
sinon.assert.calledOnce(xp.__client.send);
|
|
396
|
-
expect(xmlFake.getCall(0).args).toEqual([
|
|
397
|
-
"body",
|
|
398
|
-
{},
|
|
399
|
-
job.send.chat.object.content,
|
|
400
|
-
]);
|
|
401
|
-
expect(xmlFake.getCall(1).args).toEqual([
|
|
402
|
-
"message",
|
|
403
|
-
{
|
|
404
|
-
type: "chat",
|
|
405
|
-
to: job.send.chat.target.id,
|
|
406
|
-
id: job.send.chat.object.id,
|
|
407
|
-
},
|
|
408
|
-
undefined,
|
|
409
|
-
undefined,
|
|
410
|
-
]);
|
|
411
|
-
done();
|
|
412
|
-
});
|
|
413
|
-
});
|
|
414
|
-
|
|
415
|
-
it("calls xmpp.js correctly for a groupchat", (done) => {
|
|
416
|
-
xp.send(job.send.groupchat, () => {
|
|
417
|
-
sinon.assert.calledOnce(xp.__client.send);
|
|
418
|
-
expect(xmlFake.getCall(0).args).toEqual([
|
|
419
|
-
"body",
|
|
420
|
-
{},
|
|
421
|
-
job.send.groupchat.object.content,
|
|
422
|
-
]);
|
|
423
|
-
expect(xmlFake.getCall(1).args).toEqual([
|
|
424
|
-
"message",
|
|
425
|
-
{
|
|
426
|
-
type: "groupchat",
|
|
427
|
-
to: job.send.groupchat.target.id,
|
|
428
|
-
id: job.send.groupchat.object.id,
|
|
429
|
-
},
|
|
430
|
-
undefined,
|
|
431
|
-
undefined,
|
|
432
|
-
]);
|
|
433
|
-
done();
|
|
434
|
-
});
|
|
435
|
-
});
|
|
436
|
-
|
|
437
|
-
it("calls xmpp.js correctly for a message correction", (done) => {
|
|
438
|
-
xp.send(job.send.correction, () => {
|
|
439
|
-
sinon.assert.calledOnce(xp.__client.send);
|
|
440
|
-
expect(xmlFake.getCall(0).args).toEqual([
|
|
441
|
-
"body",
|
|
442
|
-
{},
|
|
443
|
-
job.send.correction.object.content,
|
|
444
|
-
]);
|
|
445
|
-
expect(xmlFake.getCall(1).args).toEqual([
|
|
446
|
-
"replace",
|
|
447
|
-
{
|
|
448
|
-
id: job.send.correction.object["xmpp:replace"].id,
|
|
449
|
-
xmlns: "urn:xmpp:message-correct:0",
|
|
450
|
-
},
|
|
451
|
-
]);
|
|
452
|
-
expect(xmlFake.getCall(2).args).toEqual([
|
|
453
|
-
"message",
|
|
454
|
-
{
|
|
455
|
-
type: "groupchat",
|
|
456
|
-
to: job.send.correction.target.id,
|
|
457
|
-
id: job.send.correction.object.id,
|
|
458
|
-
},
|
|
459
|
-
undefined,
|
|
460
|
-
undefined,
|
|
461
|
-
]);
|
|
462
|
-
done();
|
|
463
|
-
});
|
|
464
|
-
});
|
|
465
|
-
});
|
|
466
|
-
|
|
467
|
-
describe("#update", () => {
|
|
468
|
-
it("calls xml() correctly for available", (done) => {
|
|
469
|
-
xp.update(job.update.presenceOnline, () => {
|
|
470
|
-
sinon.assert.calledOnce(xp.__client.send);
|
|
471
|
-
expect(xmlFake.getCall(0).args).toEqual([
|
|
472
|
-
"presence",
|
|
473
|
-
{},
|
|
474
|
-
{},
|
|
475
|
-
{ status: "ready to chat" },
|
|
476
|
-
]);
|
|
477
|
-
done();
|
|
478
|
-
});
|
|
479
|
-
});
|
|
480
|
-
it("calls xml() correctly for unavailable", (done) => {
|
|
481
|
-
xp.update(job.update.presenceUnavailable, () => {
|
|
482
|
-
sinon.assert.calledOnce(xp.__client.send);
|
|
483
|
-
expect(xmlFake.getCall(0).args).toEqual([
|
|
484
|
-
"presence",
|
|
485
|
-
{},
|
|
486
|
-
{ show: "away" },
|
|
487
|
-
{ status: "eating popcorn" },
|
|
488
|
-
]);
|
|
489
|
-
done();
|
|
490
|
-
});
|
|
491
|
-
});
|
|
492
|
-
it("calls xml() correctly for offline", (done) => {
|
|
493
|
-
xp.update(job.update.presenceOffline, () => {
|
|
494
|
-
sinon.assert.calledOnce(xp.__client.send);
|
|
495
|
-
expect(xmlFake.getCall(0).args).toEqual([
|
|
496
|
-
"presence",
|
|
497
|
-
{ type: "unavailable" },
|
|
498
|
-
{},
|
|
499
|
-
{},
|
|
500
|
-
]);
|
|
501
|
-
done();
|
|
502
|
-
});
|
|
503
|
-
});
|
|
504
|
-
});
|
|
505
|
-
|
|
506
|
-
describe("#request-friend", () => {
|
|
507
|
-
it("calls xmpp.js correctly", (done) => {
|
|
508
|
-
xp["request-friend"](job["request-friend"], () => {
|
|
509
|
-
sinon.assert.calledOnce(xp.__client.send);
|
|
510
|
-
expect(xmlFake.getCall(0).args).toEqual([
|
|
511
|
-
"presence",
|
|
512
|
-
{
|
|
513
|
-
type: "subscribe",
|
|
514
|
-
to: job["request-friend"].target["id"],
|
|
515
|
-
},
|
|
516
|
-
]);
|
|
517
|
-
done();
|
|
518
|
-
});
|
|
519
|
-
});
|
|
520
|
-
});
|
|
521
|
-
|
|
522
|
-
describe("#remove-friend", () => {
|
|
523
|
-
it("calls xmpp.js correctly", (done) => {
|
|
524
|
-
xp["remove-friend"](job["remove-friend"], () => {
|
|
525
|
-
sinon.assert.calledOnce(xp.__client.send);
|
|
526
|
-
expect(xmlFake.getCall(0).args).toEqual([
|
|
527
|
-
"presence",
|
|
528
|
-
{
|
|
529
|
-
type: "unsubscribe",
|
|
530
|
-
to: job["remove-friend"].target["id"],
|
|
531
|
-
},
|
|
532
|
-
]);
|
|
533
|
-
done();
|
|
534
|
-
});
|
|
535
|
-
});
|
|
536
|
-
});
|
|
537
|
-
|
|
538
|
-
describe("#make-friend", () => {
|
|
539
|
-
it("calls xmpp.js correctly", (done) => {
|
|
540
|
-
xp["remove-friend"](job["remove-friend"], () => {
|
|
541
|
-
sinon.assert.calledOnce(xp.__client.send);
|
|
542
|
-
expect(xmlFake.getCall(0).args).toEqual([
|
|
543
|
-
"presence",
|
|
544
|
-
{
|
|
545
|
-
type: "unsubscribe",
|
|
546
|
-
to: job["make-friend"].target["id"],
|
|
547
|
-
},
|
|
548
|
-
]);
|
|
549
|
-
done();
|
|
550
|
-
});
|
|
551
|
-
});
|
|
552
|
-
});
|
|
553
|
-
|
|
554
|
-
describe("#query", () => {
|
|
555
|
-
it("calls xmpp.js correctly", (done) => {
|
|
556
|
-
xp.query(job.query, () => {
|
|
557
|
-
sinon.assert.calledOnce(xp.__client.send);
|
|
558
|
-
expect(xmlFake.getCall(0).args).toEqual([
|
|
559
|
-
"query",
|
|
560
|
-
{ xmlns: "http://jabber.org/protocol/disco#items" },
|
|
561
|
-
]);
|
|
562
|
-
expect(xmlFake.getCall(1).args).toEqual([
|
|
563
|
-
"iq",
|
|
564
|
-
{
|
|
565
|
-
id: "muc_id",
|
|
566
|
-
type: "get",
|
|
567
|
-
from: "testingham@jabber.net",
|
|
568
|
-
to: "partyroom@jabber.net",
|
|
569
|
-
},
|
|
570
|
-
undefined,
|
|
571
|
-
]);
|
|
572
|
-
done();
|
|
573
|
-
});
|
|
574
|
-
});
|
|
575
|
-
});
|
|
576
|
-
|
|
577
|
-
describe("#disconnect", () => {
|
|
578
|
-
it("calls cleanup", (done) => {
|
|
579
|
-
let cleanupCalled = false;
|
|
580
|
-
xp.cleanup = (done) => {
|
|
581
|
-
cleanupCalled = true;
|
|
582
|
-
done();
|
|
583
|
-
}
|
|
584
|
-
xp.disconnect(job, () => {
|
|
585
|
-
expect(cleanupCalled).toEqual(true);
|
|
586
|
-
done()
|
|
587
|
-
});
|
|
588
|
-
})
|
|
589
|
-
});
|
|
590
|
-
|
|
591
|
-
describe("#cleanup", () => {
|
|
592
|
-
it("calls client.stop", (done) => {
|
|
593
|
-
expect(xp.isInitialized()).toEqual(true);
|
|
594
|
-
xp.cleanup(() => {
|
|
595
|
-
expect(xp.isInitialized()).toEqual(false);
|
|
596
|
-
sinon.assert.calledOnce(xp.__client.stop);
|
|
597
|
-
done()
|
|
598
|
-
});
|
|
599
|
-
})
|
|
600
|
-
});
|
|
601
|
-
|
|
602
|
-
describe("#join", () => {
|
|
603
|
-
it("creates correct MUC presence stanza with namespace", (done) => {
|
|
604
|
-
const joinJob = {
|
|
605
|
-
actor: {
|
|
606
|
-
id: "testingham@jabber.net",
|
|
607
|
-
name: "Testing Ham"
|
|
608
|
-
},
|
|
609
|
-
target: {
|
|
610
|
-
id: "testroom@conference.jabber.net"
|
|
611
|
-
}
|
|
612
|
-
};
|
|
613
|
-
|
|
614
|
-
xp.join(joinJob, () => {
|
|
615
|
-
sinon.assert.calledOnce(xp.__client.send);
|
|
616
|
-
|
|
617
|
-
// Verify MUC <x> element was created with correct namespace
|
|
618
|
-
sinon.assert.calledWith(xmlFake, "x", { xmlns: "http://jabber.org/protocol/muc" });
|
|
619
|
-
|
|
620
|
-
// Verify presence stanza was created with correct attributes
|
|
621
|
-
sinon.assert.calledWith(xmlFake, "presence", {
|
|
622
|
-
from: "testingham@jabber.net",
|
|
623
|
-
to: "testroom@conference.jabber.net/Testing Ham",
|
|
624
|
-
});
|
|
625
|
-
|
|
626
|
-
done();
|
|
627
|
-
});
|
|
628
|
-
});
|
|
629
|
-
});
|
|
630
|
-
});
|
|
631
|
-
});
|
package/src/schema.js
DELETED
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import PackageJSON from "../package.json" with { type: "json" };
|
|
2
|
-
|
|
3
|
-
export const PlatformSchema = {
|
|
4
|
-
name: "xmpp",
|
|
5
|
-
version: PackageJSON.version,
|
|
6
|
-
messages: {
|
|
7
|
-
required: ["type"],
|
|
8
|
-
properties: {
|
|
9
|
-
type: {
|
|
10
|
-
enum: [
|
|
11
|
-
"connect",
|
|
12
|
-
"join",
|
|
13
|
-
"leave",
|
|
14
|
-
"send",
|
|
15
|
-
"update",
|
|
16
|
-
"request-friend",
|
|
17
|
-
"remove-friend",
|
|
18
|
-
"make-friend",
|
|
19
|
-
"query",
|
|
20
|
-
"disconnect",
|
|
21
|
-
],
|
|
22
|
-
},
|
|
23
|
-
},
|
|
24
|
-
},
|
|
25
|
-
credentials: {
|
|
26
|
-
required: ["object"],
|
|
27
|
-
properties: {
|
|
28
|
-
// TODO platforms shouldn't have to define the actor property if
|
|
29
|
-
// they don't want to, just credential specifics
|
|
30
|
-
actor: {
|
|
31
|
-
type: "object",
|
|
32
|
-
required: ["id"],
|
|
33
|
-
},
|
|
34
|
-
object: {
|
|
35
|
-
type: "object",
|
|
36
|
-
required: ["type", "userAddress", "password", "resource"],
|
|
37
|
-
additionalProperties: false,
|
|
38
|
-
properties: {
|
|
39
|
-
type: {
|
|
40
|
-
type: "string",
|
|
41
|
-
},
|
|
42
|
-
userAddress: {
|
|
43
|
-
type: "string",
|
|
44
|
-
},
|
|
45
|
-
password: {
|
|
46
|
-
type: "string",
|
|
47
|
-
},
|
|
48
|
-
server: {
|
|
49
|
-
type: "string",
|
|
50
|
-
},
|
|
51
|
-
port: {
|
|
52
|
-
type: "number",
|
|
53
|
-
},
|
|
54
|
-
resource: {
|
|
55
|
-
type: "string",
|
|
56
|
-
},
|
|
57
|
-
},
|
|
58
|
-
},
|
|
59
|
-
},
|
|
60
|
-
},
|
|
61
|
-
};
|