spec-3nweb-server 1.8.8 → 1.8.10
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/build/asmail/resources/inbox.d.ts +2 -2
- package/build/asmail/resources/inbox.js +1 -1
- package/build/config/from-yaml.js +1 -1
- package/build/lib-common/canonical-address.js +1 -1
- package/build/main.js +17 -4
- package/build/tests/protocols/asmail/retrieval/specs/events.js +20 -9
- package/package.json +4 -2
- package/ts-code/asmail/resources/inbox.ts +7 -16
- package/ts-code/asmail/resources/recipients.ts +1 -3
- package/ts-code/config/from-yaml.ts +1 -1
- package/ts-code/lib-common/canonical-address.ts +1 -1
- package/ts-code/main.ts +19 -4
- package/ts-code/tests/libs-for-tests/ws-utils.ts +1 -2
- package/ts-code/tests/protocols/asmail/retrieval/specs/events.ts +27 -12
|
@@ -33,9 +33,9 @@ export interface InboxParams {
|
|
|
33
33
|
"authenticated/invites": AuthSenderInvites;
|
|
34
34
|
}
|
|
35
35
|
export declare class Inbox extends UserFiles<InboxParams> {
|
|
36
|
-
private metas;
|
|
37
|
-
private objFiles;
|
|
38
36
|
private mailEventsSink;
|
|
37
|
+
private readonly metas;
|
|
38
|
+
private readonly objFiles;
|
|
39
39
|
constructor(userId: string, path: string, mailEventsSink: MailEventsSink, writeBufferSize?: string | number, readBufferSize?: string | number);
|
|
40
40
|
static make(userFolder: string, userId: string, mailEventsSink: MailEventsSink, writeBufferSize?: string | number, readBufferSize?: string | number): Promise<Inbox>;
|
|
41
41
|
/**
|
|
@@ -85,9 +85,9 @@ async function genMsgIdAndMakeFolder(delivPath, msgsFolder) {
|
|
|
85
85
|
class Inbox extends user_files_1.UserFiles {
|
|
86
86
|
constructor(userId, path, mailEventsSink, writeBufferSize, readBufferSize) {
|
|
87
87
|
super(userId, path, writeBufferSize, readBufferSize);
|
|
88
|
+
this.mailEventsSink = mailEventsSink;
|
|
88
89
|
this.metas = new MsgMetas(5 * 60 * 1000, (0, path_1.join)(this.path, 'delivery'), (0, path_1.join)(this.path, 'messages'));
|
|
89
90
|
this.objFiles = new ObjFiles(5 * 60 * 1000, this.metas.deliveryFolder, this.metas.readyMsgsFolder);
|
|
90
|
-
this.mailEventsSink = mailEventsSink;
|
|
91
91
|
Object.freeze(this);
|
|
92
92
|
}
|
|
93
93
|
static async make(userFolder, userId, mailEventsSink, writeBufferSize, readBufferSize) {
|
|
@@ -23,7 +23,7 @@ const default_confs_1 = require("./default-confs");
|
|
|
23
23
|
function readYamlConfFile(path) {
|
|
24
24
|
const txt = (0, fs_1.readFileSync)(path, 'utf8');
|
|
25
25
|
const conf = yaml.load(txt);
|
|
26
|
-
if (conf.rootFolder) {
|
|
26
|
+
if (!conf.rootFolder) {
|
|
27
27
|
conf.rootFolder = default_confs_1.DEFAULT_DATA_ROOT_PATH;
|
|
28
28
|
}
|
|
29
29
|
return conf;
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
*/
|
|
18
18
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
19
|
exports.checkAndTransformAddress = exports.areAddressesEqual = exports.toCanonicalAddress = void 0;
|
|
20
|
-
const punycode_1 = require("punycode");
|
|
20
|
+
const punycode_1 = require("punycode/");
|
|
21
21
|
/**
|
|
22
22
|
* @param address
|
|
23
23
|
* @return a canonical form of a given address.
|
package/build/main.js
CHANGED
|
@@ -24,6 +24,7 @@ const lib_1 = require("./lib");
|
|
|
24
24
|
const signup_1 = require("./config/signup");
|
|
25
25
|
const default_confs_1 = require("./config/default-confs");
|
|
26
26
|
const file_1 = require("./lib-common/exceptions/file");
|
|
27
|
+
const qrcode = require("qrcode-terminal");
|
|
27
28
|
async function run(conf) {
|
|
28
29
|
if (!conf.servicesConnect) {
|
|
29
30
|
console.error(`❌ No connection settings found in configuration.`);
|
|
@@ -142,6 +143,7 @@ async function displaySignupInfo(conf) {
|
|
|
142
143
|
const signupLink = signupLinkFrom(conf, undefined);
|
|
143
144
|
if (signupLink) {
|
|
144
145
|
console.log(`Signup link:\n`, signupLink, `\n`);
|
|
146
|
+
displayAsQR(signupLink);
|
|
145
147
|
}
|
|
146
148
|
}
|
|
147
149
|
else {
|
|
@@ -155,6 +157,10 @@ async function displaySignupInfo(conf) {
|
|
|
155
157
|
console.log(`There are ${multiUserTokens.length} multi-user tokens.\n`);
|
|
156
158
|
console.log(`There are ${singleUserTokens.length} single-user tokens.\n`);
|
|
157
159
|
}
|
|
160
|
+
function displayAsQR(str) {
|
|
161
|
+
qrcode.setErrorLevel('Q');
|
|
162
|
+
qrcode.generate(str, { small: true });
|
|
163
|
+
}
|
|
158
164
|
async function displayTokensList(conf) {
|
|
159
165
|
const { multiUserTokens, singleUserTokens } = await (0, signup_1.readAllSignupTokens)(conf.rootFolder);
|
|
160
166
|
if (multiUserTokens.length > 0) {
|
|
@@ -181,10 +187,6 @@ async function displayTokensList(conf) {
|
|
|
181
187
|
async function displayTokenValue(conf, tokenId) {
|
|
182
188
|
const ctx = await (0, signup_1.readTokenFile)(conf.rootFolder, tokenId);
|
|
183
189
|
if (ctx) {
|
|
184
|
-
const signupLink = signupLinkFrom(conf, ctx.token);
|
|
185
|
-
if (signupLink) {
|
|
186
|
-
console.log(`\nSignup link:\n ${signupLink}`);
|
|
187
|
-
}
|
|
188
190
|
if (ctx.type === 'multi-domain') {
|
|
189
191
|
console.log(`\nMulti-user signup context:`);
|
|
190
192
|
console.log(` domains:`, ctx.domains);
|
|
@@ -201,6 +203,11 @@ async function displayTokenValue(conf, tokenId) {
|
|
|
201
203
|
console.log(` valid till: ${(new Date(ctx.validTill)).toString()}`);
|
|
202
204
|
}
|
|
203
205
|
}
|
|
206
|
+
const signupLink = signupLinkFrom(conf, ctx.token);
|
|
207
|
+
if (signupLink) {
|
|
208
|
+
console.log(`\nSignup link:\n ${signupLink}`);
|
|
209
|
+
displayAsQR(signupLink);
|
|
210
|
+
}
|
|
204
211
|
console.log(``);
|
|
205
212
|
}
|
|
206
213
|
else {
|
|
@@ -241,6 +248,12 @@ async function createSingleUserToken(conf, userId) {
|
|
|
241
248
|
console.log(``);
|
|
242
249
|
}
|
|
243
250
|
const cmd = (0, cli_1.parseProcessArgv)();
|
|
251
|
+
process.on('unhandledRejection', (err, p) => {
|
|
252
|
+
console.error(' -- Unhandled rejection of promise:', err);
|
|
253
|
+
});
|
|
254
|
+
process.on('uncaughtException', err => {
|
|
255
|
+
console.error(' -- Unhandled exception:', err);
|
|
256
|
+
});
|
|
244
257
|
if (cmd.runCmd) {
|
|
245
258
|
const conf = assembleConfig(cmd.runCmd.config);
|
|
246
259
|
run(conf);
|
|
@@ -33,6 +33,7 @@ exports.specs.definition = (setup) => (() => {
|
|
|
33
33
|
let deliveryUrl;
|
|
34
34
|
let user1;
|
|
35
35
|
let sessionId;
|
|
36
|
+
let session2;
|
|
36
37
|
(0, async_jasmine_1.beforeEachAsync)(async () => {
|
|
37
38
|
asmailServer = setup().asmailServer;
|
|
38
39
|
const retrievalUrl = await asmailServer.getRetrievalUrl();
|
|
@@ -40,23 +41,33 @@ exports.specs.definition = (setup) => (() => {
|
|
|
40
41
|
deliveryUrl = await asmailServer.getDeliveryUrl();
|
|
41
42
|
user1 = setup().user1;
|
|
42
43
|
sessionId = await (0, test_utils_1.startSession)(user1, retrievalUrl);
|
|
44
|
+
session2 = await (0, test_utils_1.startSession)(user1, retrievalUrl);
|
|
43
45
|
});
|
|
44
46
|
(0, async_jasmine_1.itAsync)(`requires session to open web socket`, async () => {
|
|
45
47
|
let rep = await (0, ws_utils_1.openSocket)(wsUrl, 'invalid session id');
|
|
46
48
|
expect(rep.status).withContext('status for missing authorized session').toBe(retrieval_1.ERR_SC.needAuth);
|
|
47
49
|
});
|
|
48
50
|
(0, async_jasmine_1.itAsync)(`emits event on completion of message reception`, async () => {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
.
|
|
54
|
-
|
|
51
|
+
globalThis.logTest = true;
|
|
52
|
+
function subscribeAndWaitInSession(rep) {
|
|
53
|
+
expect(rep.status).toBe(retrieval_1.wsEventChannel.SC.ok);
|
|
54
|
+
const eventSrc = (0, ws_ipc_1.makeSubscriber)(rep.data, undefined);
|
|
55
|
+
return rxjs_1.Observable.create(obs => eventSrc.subscribe(retrieval_1.msgRecievedCompletely.EVENT_NAME, obs))
|
|
56
|
+
.take(1)
|
|
57
|
+
.toPromise();
|
|
58
|
+
}
|
|
59
|
+
const eventPromises = [
|
|
60
|
+
subscribeAndWaitInSession(await (0, ws_utils_1.openSocket)(wsUrl, sessionId)),
|
|
61
|
+
subscribeAndWaitInSession(await (0, ws_utils_1.openSocket)(wsUrl, session2)),
|
|
62
|
+
];
|
|
55
63
|
// give some time for subscription to occur
|
|
56
64
|
await (0, processes_1.sleep)(10);
|
|
57
65
|
const msgId = await (0, test_utils_1.sendMsg)(deliveryUrl, user1.id, test_utils_1.msg);
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
|
|
66
|
+
for (const eventPromise of eventPromises) {
|
|
67
|
+
const event = await eventPromise;
|
|
68
|
+
expect(typeof event).toBe('object');
|
|
69
|
+
expect(event.msgId).withContext(`message reception completion event should give a respective message id`).toBe(msgId);
|
|
70
|
+
}
|
|
71
|
+
globalThis.logTest = false;
|
|
61
72
|
});
|
|
62
73
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "spec-3nweb-server",
|
|
3
|
-
"version": "1.8.
|
|
3
|
+
"version": "1.8.10",
|
|
4
4
|
"description": "3NWeb spec server.",
|
|
5
5
|
"main": "build/lib.js",
|
|
6
6
|
"types": "build/lib.d.ts",
|
|
@@ -41,7 +41,8 @@
|
|
|
41
41
|
"express": "^4.22.2",
|
|
42
42
|
"js-yaml": "^4.3.0",
|
|
43
43
|
"prompts": "^2.4.2",
|
|
44
|
-
"punycode": "^2.
|
|
44
|
+
"punycode": "^2.3.1",
|
|
45
|
+
"qrcode-terminal": "^0.12.0",
|
|
45
46
|
"ws": "^7.5.11",
|
|
46
47
|
"xsp-files": "^2.0.0"
|
|
47
48
|
},
|
|
@@ -49,6 +50,7 @@
|
|
|
49
50
|
"@types/express": "4.17.13",
|
|
50
51
|
"@types/jasmine": "^3.9.1",
|
|
51
52
|
"@types/node": "^16.11.7",
|
|
53
|
+
"@types/punycode": "^2.1.4",
|
|
52
54
|
"@types/ws": "^4.0.0",
|
|
53
55
|
"jasmine": "^3.9.0",
|
|
54
56
|
"rxjs": "^5.3.0",
|
|
@@ -56,8 +56,7 @@ type AuthSenderInvites = configApi.p.authSenderInvites.List;
|
|
|
56
56
|
type AnonSenderInvites = configApi.p.anonSenderInvites.List;
|
|
57
57
|
|
|
58
58
|
type MsgMeta = retrievalApi.MsgMeta;
|
|
59
|
-
export type MsgEvents = retrievalApi.msgMainObjRecieved.Event |
|
|
60
|
-
retrievalApi.msgRecievedCompletely.Event;
|
|
59
|
+
export type MsgEvents = retrievalApi.msgMainObjRecieved.Event | retrievalApi.msgRecievedCompletely.Event;
|
|
61
60
|
|
|
62
61
|
export type MailEventsSink = (
|
|
63
62
|
userId: string, channel: string, event: MsgEvents
|
|
@@ -117,20 +116,16 @@ export interface InboxParams {
|
|
|
117
116
|
|
|
118
117
|
export class Inbox extends UserFiles<InboxParams> {
|
|
119
118
|
|
|
120
|
-
private metas = new MsgMetas(
|
|
121
|
-
5*60*1000, join(this.path, 'delivery'), join(this.path, 'messages'));
|
|
119
|
+
private readonly metas = new MsgMetas(5*60*1000, join(this.path, 'delivery'), join(this.path, 'messages'));
|
|
122
120
|
|
|
123
|
-
private objFiles = new ObjFiles(
|
|
124
|
-
5*60*1000, this.metas.deliveryFolder, this.metas.readyMsgsFolder);
|
|
121
|
+
private readonly objFiles = new ObjFiles(5*60*1000, this.metas.deliveryFolder, this.metas.readyMsgsFolder);
|
|
125
122
|
|
|
126
|
-
private mailEventsSink: MailEventsSink;
|
|
127
|
-
|
|
128
123
|
constructor(
|
|
129
|
-
userId: string, path: string,
|
|
124
|
+
userId: string, path: string,
|
|
125
|
+
private mailEventsSink: MailEventsSink,
|
|
130
126
|
writeBufferSize?: string|number, readBufferSize?: string|number
|
|
131
127
|
) {
|
|
132
128
|
super(userId, path, writeBufferSize, readBufferSize);
|
|
133
|
-
this.mailEventsSink = mailEventsSink;
|
|
134
129
|
Object.freeze(this);
|
|
135
130
|
}
|
|
136
131
|
|
|
@@ -139,9 +134,7 @@ export class Inbox extends UserFiles<InboxParams> {
|
|
|
139
134
|
writeBufferSize?: string|number, readBufferSize?: string|number
|
|
140
135
|
): Promise<Inbox> {
|
|
141
136
|
const path = join(userFolder, 'mail');
|
|
142
|
-
const inbox = new Inbox(
|
|
143
|
-
userId, path, mailEventsSink, writeBufferSize, readBufferSize
|
|
144
|
-
);
|
|
137
|
+
const inbox = new Inbox(userId, path, mailEventsSink, writeBufferSize, readBufferSize);
|
|
145
138
|
await inbox.ensureUserExistsOnDisk();
|
|
146
139
|
return inbox;
|
|
147
140
|
}
|
|
@@ -285,9 +278,7 @@ export class Inbox extends UserFiles<InboxParams> {
|
|
|
285
278
|
this.objFiles.changeToReadingPathsInMsg(msgId);
|
|
286
279
|
|
|
287
280
|
// raise event about completion of receiving a message
|
|
288
|
-
this.mailEventsSink(this.userId,
|
|
289
|
-
retrievalApi.msgRecievedCompletely.EVENT_NAME,
|
|
290
|
-
{ msgId });
|
|
281
|
+
this.mailEventsSink(this.userId, retrievalApi.msgRecievedCompletely.EVENT_NAME, { msgId });
|
|
291
282
|
}
|
|
292
283
|
|
|
293
284
|
private areAllMsgObjsComplete(
|
|
@@ -317,9 +317,7 @@ export function makeRecipients(
|
|
|
317
317
|
}
|
|
318
318
|
} else {
|
|
319
319
|
const userFolder = userDataInRootFolder(rootFolder, userId);
|
|
320
|
-
inbox = await Inbox.make(
|
|
321
|
-
userFolder, userId, mailEventsSink, writeBufferSize, readBufferSize
|
|
322
|
-
);
|
|
320
|
+
inbox = await Inbox.make(userFolder, userId, mailEventsSink, writeBufferSize, readBufferSize);
|
|
323
321
|
boxes.set(userId, inbox);
|
|
324
322
|
return inbox;
|
|
325
323
|
}
|
|
@@ -24,7 +24,7 @@ export function readYamlConfFile(path: string): Configurations {
|
|
|
24
24
|
const txt = readFileSync(path, 'utf8');
|
|
25
25
|
const conf = yaml.load(txt) as Configurations;
|
|
26
26
|
|
|
27
|
-
if (conf.rootFolder) {
|
|
27
|
+
if (!conf.rootFolder) {
|
|
28
28
|
conf.rootFolder = DEFAULT_DATA_ROOT_PATH;
|
|
29
29
|
}
|
|
30
30
|
|
package/ts-code/main.ts
CHANGED
|
@@ -29,6 +29,7 @@ import { Configurations, servicesApp, accountsApp, AppWithWSs } from './lib';
|
|
|
29
29
|
import { addMultiDomainSignup, addSingleUserSignup, readAllSignupTokens, readNoTokensFile, readTokenFile } from './config/signup';
|
|
30
30
|
import { DEFAULT_CONFIG_PATH } from './config/default-confs';
|
|
31
31
|
import { Code } from './lib-common/exceptions/file';
|
|
32
|
+
import * as qrcode from 'qrcode-terminal';
|
|
32
33
|
|
|
33
34
|
async function run(conf: Configurations): Promise<void> {
|
|
34
35
|
|
|
@@ -159,6 +160,7 @@ async function displaySignupInfo(conf: Configurations): Promise<void> {
|
|
|
159
160
|
const signupLink = signupLinkFrom(conf, undefined);
|
|
160
161
|
if (signupLink) {
|
|
161
162
|
console.log(`Signup link:\n`, signupLink, `\n`);
|
|
163
|
+
displayAsQR(signupLink);
|
|
162
164
|
}
|
|
163
165
|
} else {
|
|
164
166
|
console.log(`Signup of users is allowed only with valid signup tokens.\n`);
|
|
@@ -174,6 +176,11 @@ async function displaySignupInfo(conf: Configurations): Promise<void> {
|
|
|
174
176
|
console.log(`There are ${singleUserTokens.length} single-user tokens.\n`);
|
|
175
177
|
}
|
|
176
178
|
|
|
179
|
+
function displayAsQR(str: string): void {
|
|
180
|
+
qrcode.setErrorLevel('Q');
|
|
181
|
+
qrcode.generate(str, { small: true });
|
|
182
|
+
}
|
|
183
|
+
|
|
177
184
|
async function displayTokensList(conf: Configurations): Promise<void> {
|
|
178
185
|
const {
|
|
179
186
|
multiUserTokens, singleUserTokens
|
|
@@ -203,10 +210,6 @@ async function displayTokenValue(
|
|
|
203
210
|
): Promise<void> {
|
|
204
211
|
const ctx = await readTokenFile(conf.rootFolder, tokenId);
|
|
205
212
|
if (ctx) {
|
|
206
|
-
const signupLink = signupLinkFrom(conf, ctx.token);
|
|
207
|
-
if (signupLink) {
|
|
208
|
-
console.log(`\nSignup link:\n ${signupLink}`);
|
|
209
|
-
}
|
|
210
213
|
if (ctx.type === 'multi-domain') {
|
|
211
214
|
console.log(`\nMulti-user signup context:`);
|
|
212
215
|
console.log(` domains:`, ctx.domains);
|
|
@@ -222,6 +225,11 @@ async function displayTokenValue(
|
|
|
222
225
|
console.log(` valid till: ${(new Date(ctx.validTill)).toString()}`);
|
|
223
226
|
}
|
|
224
227
|
}
|
|
228
|
+
const signupLink = signupLinkFrom(conf, ctx.token);
|
|
229
|
+
if (signupLink) {
|
|
230
|
+
console.log(`\nSignup link:\n ${signupLink}`);
|
|
231
|
+
displayAsQR(signupLink);
|
|
232
|
+
}
|
|
225
233
|
console.log(``);
|
|
226
234
|
} else {
|
|
227
235
|
console.error(`Token ${tokenId} is not found.`);
|
|
@@ -269,6 +277,13 @@ async function createSingleUserToken(
|
|
|
269
277
|
|
|
270
278
|
const cmd = parseProcessArgv();
|
|
271
279
|
|
|
280
|
+
process.on('unhandledRejection', (err, p) => {
|
|
281
|
+
console.error(' -- Unhandled rejection of promise:', err);
|
|
282
|
+
});
|
|
283
|
+
process.on('uncaughtException', err => {
|
|
284
|
+
console.error(' -- Unhandled exception:', err);
|
|
285
|
+
});
|
|
286
|
+
|
|
272
287
|
if (cmd.runCmd) {
|
|
273
288
|
const conf = assembleConfig(cmd.runCmd.config!);
|
|
274
289
|
run(conf);
|
|
@@ -22,8 +22,7 @@ import { defer } from '../../lib-common/processes';
|
|
|
22
22
|
import { makeConnectionException } from '../../lib-common/exceptions/http';
|
|
23
23
|
import { globalAgent as agent } from 'https';
|
|
24
24
|
|
|
25
|
-
export function openSocket(url: string, sessionId: string):
|
|
26
|
-
Promise<Reply<WebSocket>> {
|
|
25
|
+
export function openSocket(url: string, sessionId: string): Promise<Reply<WebSocket>> {
|
|
27
26
|
if (!url.startsWith('wss://')) { throw new Error(
|
|
28
27
|
`Url protocol must be wss`); }
|
|
29
28
|
const headers: any = {};
|
|
@@ -34,6 +34,7 @@ specs.definition = (setup: () => TestSetup) => (() => {
|
|
|
34
34
|
let deliveryUrl: string;
|
|
35
35
|
let user1: User;
|
|
36
36
|
let sessionId: string;
|
|
37
|
+
let session2: string;
|
|
37
38
|
|
|
38
39
|
beforeEachAsync(async () => {
|
|
39
40
|
asmailServer = setup().asmailServer;
|
|
@@ -42,6 +43,7 @@ specs.definition = (setup: () => TestSetup) => (() => {
|
|
|
42
43
|
deliveryUrl = await asmailServer.getDeliveryUrl();
|
|
43
44
|
user1 = setup().user1;
|
|
44
45
|
sessionId = await startSession(user1, retrievalUrl);
|
|
46
|
+
session2 = await startSession(user1, retrievalUrl);
|
|
45
47
|
});
|
|
46
48
|
|
|
47
49
|
itAsync(`requires session to open web socket`, async () => {
|
|
@@ -53,26 +55,39 @@ specs.definition = (setup: () => TestSetup) => (() => {
|
|
|
53
55
|
|
|
54
56
|
itAsync(`emits event on completion of message reception`, async () => {
|
|
55
57
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
58
|
+
globalThis.logTest = true;
|
|
59
|
+
|
|
60
|
+
function subscribeAndWaitInSession(rep: Awaited<ReturnType<typeof openSocket>>) {
|
|
61
|
+
expect(rep.status).toBe(api.SC.ok);
|
|
62
|
+
|
|
63
|
+
const eventSrc = makeSubscriber(rep.data, undefined);
|
|
64
|
+
|
|
65
|
+
return (Observable.create(obs => eventSrc.subscribe<msgRecievedCompletely.Event>(
|
|
66
|
+
msgRecievedCompletely.EVENT_NAME, obs
|
|
67
|
+
)) as Observable<msgRecievedCompletely.Event>)
|
|
68
|
+
.take(1)
|
|
69
|
+
.toPromise();
|
|
70
|
+
}
|
|
60
71
|
|
|
61
|
-
const
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
.toPromise();
|
|
72
|
+
const eventPromises = [
|
|
73
|
+
subscribeAndWaitInSession(await openSocket(wsUrl, sessionId)),
|
|
74
|
+
subscribeAndWaitInSession(await openSocket(wsUrl, session2)),
|
|
75
|
+
];
|
|
66
76
|
|
|
67
77
|
// give some time for subscription to occur
|
|
68
78
|
await sleep(10);
|
|
69
79
|
|
|
70
80
|
const msgId = await sendMsg(deliveryUrl, user1.id, msg);
|
|
71
81
|
|
|
72
|
-
const
|
|
73
|
-
|
|
74
|
-
|
|
82
|
+
for (const eventPromise of eventPromises) {
|
|
83
|
+
const event = await eventPromise;
|
|
84
|
+
expect(typeof event).toBe('object');
|
|
85
|
+
expect(event.msgId).withContext(
|
|
86
|
+
`message reception completion event should give a respective message id`
|
|
87
|
+
).toBe(msgId);
|
|
88
|
+
}
|
|
75
89
|
|
|
90
|
+
globalThis.logTest = false;
|
|
76
91
|
});
|
|
77
92
|
|
|
78
93
|
});
|