@nymphjs/pubsub 1.0.0-beta.11 → 1.0.0-beta.111

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.
@@ -1,39 +1,40 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- const express_1 = __importDefault(require("express"));
7
- const driver_sqlite3_1 = __importDefault(require("@nymphjs/driver-sqlite3"));
8
- const nymph_1 = require("@nymphjs/nymph");
9
- const client_node_1 = require("@nymphjs/client-node");
10
- const server_1 = __importDefault(require("@nymphjs/server"));
11
- const testArtifacts_js_1 = require("@nymphjs/server/dist/testArtifacts.js");
12
- const index_1 = __importDefault(require("./index"));
13
- const PubSub_1 = __importDefault(require("./PubSub"));
1
+ import express from 'express';
2
+ import ws from 'websocket';
3
+ import SQLite3Driver from '@nymphjs/driver-sqlite3';
4
+ import { Nymph as NymphServer } from '@nymphjs/nymph';
5
+ import { Nymph, PubSub } from '@nymphjs/client';
6
+ import createRestServer from '@nymphjs/server';
7
+ import { EmployeeModel as EmployeeModelClass, Employee as EmployeeClass, RestrictedModel as RestrictedModelClass, Restricted as RestrictedClass, PubSubDisabledModel as PubSubDisabledModelClass, PubSubDisabled as PubSubDisabledClass, } from '@nymphjs/server/dist/testArtifacts.js';
8
+ import createServer from './index.js';
9
+ import PubSubServer from './PubSub.js';
14
10
  const sqliteConfig = {
15
11
  filename: ':memory:',
16
12
  };
17
13
  const pubSubConfig = {
18
14
  originIsAllowed: () => true,
19
- entries: ['ws://localhost:5081/'],
15
+ entries: ['ws://localhost:5083/'],
20
16
  logger: () => { },
21
17
  };
22
- const nymphServer = new nymph_1.Nymph({}, new driver_sqlite3_1.default(sqliteConfig));
23
- const EmployeeModel = nymphServer.addEntityClass(testArtifacts_js_1.EmployeeModel);
24
- PubSub_1.default.initPublisher(pubSubConfig, nymphServer);
25
- const app = (0, express_1.default)();
26
- app.use((0, server_1.default)(nymphServer));
27
- const server = app.listen(5080);
28
- const pubsubServer = (0, index_1.default)(5081, pubSubConfig, nymphServer);
18
+ const nymphServer = new NymphServer({}, new SQLite3Driver(sqliteConfig));
19
+ const EmployeeModel = nymphServer.addEntityClass(EmployeeModelClass);
20
+ const RestrictedModel = nymphServer.addEntityClass(RestrictedModelClass);
21
+ const PubSubDisabledModel = nymphServer.addEntityClass(PubSubDisabledModelClass);
22
+ const removePublisher = PubSubServer.initPublisher(pubSubConfig, nymphServer);
23
+ const app = express();
24
+ app.use(createRestServer(nymphServer));
25
+ const server = app.listen(5082);
26
+ const pubsubServer = createServer(5083, pubSubConfig, nymphServer);
29
27
  const nymphOptions = {
30
- restUrl: 'http://localhost:5080/',
31
- pubsubUrl: 'ws://localhost:5081/',
28
+ restUrl: 'http://localhost:5082/',
29
+ pubsubUrl: 'ws://localhost:5083/',
32
30
  noConsole: true,
31
+ WebSocket: ws.w3cwebsocket,
33
32
  };
34
- const nymph = new client_node_1.Nymph(nymphOptions);
35
- const pubsub = new client_node_1.PubSub(nymphOptions, nymph);
36
- const Employee = nymph.addEntityClass(testArtifacts_js_1.Employee);
33
+ const nymph = new Nymph(nymphOptions);
34
+ const pubsub = new PubSub(nymphOptions, nymph);
35
+ const Employee = nymph.addEntityClass(EmployeeClass);
36
+ const Restricted = nymph.addEntityClass(RestrictedClass);
37
+ const PubSubDisabled = nymph.addEntityClass(PubSubDisabledClass);
37
38
  describe('Nymph REST Server and Client', () => {
38
39
  async function createJane() {
39
40
  const jane = await Employee.factory();
@@ -95,7 +96,7 @@ describe('Nymph REST Server and Client', () => {
95
96
  expect('added' in update && update.added).toEqual((await jane).guid);
96
97
  expect('data' in update && update.data.guid).toEqual((await jane).guid);
97
98
  subscription.unsubscribe();
98
- resolve(true);
99
+ resolve();
99
100
  }
100
101
  else {
101
102
  expect(update).toEqual([]);
@@ -105,6 +106,167 @@ describe('Nymph REST Server and Client', () => {
105
106
  });
106
107
  });
107
108
  });
109
+ it('notified of new match only after transaction committed', async () => {
110
+ let guid;
111
+ let committed = false;
112
+ await new Promise((resolve) => {
113
+ let updated = false;
114
+ const subscription = pubsub.subscribeEntities({ class: Employee }, {
115
+ type: '&',
116
+ equal: ['name', 'Steve Transaction'],
117
+ })(async (update) => {
118
+ if (updated) {
119
+ if (committed) {
120
+ expect('added' in update && update.added).toEqual(guid);
121
+ expect('data' in update && update.data.guid).toEqual(guid);
122
+ }
123
+ else {
124
+ throw new Error('Update arrived before transaction committed.');
125
+ }
126
+ subscription.unsubscribe();
127
+ resolve();
128
+ }
129
+ else {
130
+ expect(update).toEqual([]);
131
+ updated = true;
132
+ const tnymph = await nymphServer.startTransaction('steve');
133
+ const Employee = tnymph.getEntityClass(EmployeeModel);
134
+ const steve = await Employee.factory();
135
+ steve.name = 'Steve Transaction';
136
+ steve.current = true;
137
+ steve.salary = 8000000;
138
+ steve.startDate = Date.now();
139
+ steve.subordinates = [];
140
+ steve.title = 'Seniorer Person';
141
+ try {
142
+ await steve.$save();
143
+ guid = steve.guid;
144
+ await new Promise((res) => setTimeout(res, 1000));
145
+ committed = true;
146
+ await tnymph.commit('steve');
147
+ }
148
+ catch (e) {
149
+ console.error('Error creating entity: ', e);
150
+ throw e;
151
+ }
152
+ }
153
+ });
154
+ });
155
+ });
156
+ it('not notified of new match when transaction rolled back', async () => {
157
+ let guid;
158
+ await new Promise((resolve) => {
159
+ let updated = false;
160
+ const subscription = pubsub.subscribeEntities({ class: Employee }, {
161
+ type: '&',
162
+ equal: ['name', 'Steve Rollback'],
163
+ })(async (update) => {
164
+ if (updated) {
165
+ if ('added' in update && update.added === guid) {
166
+ throw new Error('Update arrived after transaction rolled back.');
167
+ }
168
+ throw new Error('Update arrived unrelated to transaction.');
169
+ }
170
+ else {
171
+ expect(update).toEqual([]);
172
+ updated = true;
173
+ const tnymph = await nymphServer.startTransaction('steve');
174
+ const Employee = tnymph.getEntityClass(EmployeeModel);
175
+ const steve = await Employee.factory();
176
+ steve.name = 'Steve Rollback';
177
+ steve.current = true;
178
+ steve.salary = 8000000;
179
+ steve.startDate = Date.now();
180
+ steve.subordinates = [];
181
+ steve.title = 'Seniorer Person';
182
+ try {
183
+ await steve.$save();
184
+ guid = steve.guid;
185
+ await new Promise((res) => setTimeout(res, 600));
186
+ await tnymph.rollback('steve');
187
+ await new Promise((res) => setTimeout(res, 600));
188
+ subscription.unsubscribe();
189
+ resolve();
190
+ }
191
+ catch (e) {
192
+ console.error('Error creating entity: ', e);
193
+ throw e;
194
+ }
195
+ }
196
+ });
197
+ });
198
+ });
199
+ it('notified of new match after complex transactions committed', async () => {
200
+ let guid;
201
+ let committed = false;
202
+ await new Promise((resolve) => {
203
+ let updated = false;
204
+ const subscription = pubsub.subscribeEntities({ class: Employee }, {
205
+ type: '&',
206
+ equal: ['name', 'Steve Complex'],
207
+ })(async (update) => {
208
+ if (updated) {
209
+ if (committed) {
210
+ expect('added' in update && update.added).toEqual(guid);
211
+ expect('data' in update && update.data.guid).toEqual(guid);
212
+ }
213
+ else {
214
+ throw new Error('Update arrived before transaction committed.');
215
+ }
216
+ subscription.unsubscribe();
217
+ resolve();
218
+ }
219
+ else {
220
+ expect(update).toEqual([]);
221
+ updated = true;
222
+ const tnymphTop = await nymphServer.startTransaction('steve-top');
223
+ // Start a transaction that ultimately gets rolled back.
224
+ const tnymphB = await tnymphTop.startTransaction('steve-b');
225
+ const EmployeeB = tnymphB.getEntityClass(EmployeeModel);
226
+ const badSteve = await EmployeeB.factory();
227
+ badSteve.name = 'Steve Complex';
228
+ badSteve.current = true;
229
+ badSteve.salary = 8000000;
230
+ badSteve.startDate = Date.now();
231
+ badSteve.subordinates = [];
232
+ badSteve.title = 'Seniorer Person';
233
+ try {
234
+ await badSteve.$save();
235
+ await new Promise((res) => setTimeout(res, 200));
236
+ await tnymphB.rollback('steve-b');
237
+ await new Promise((res) => setTimeout(res, 200));
238
+ }
239
+ catch (e) {
240
+ console.error('Error creating entity: ', e);
241
+ throw e;
242
+ }
243
+ // Start a transaction that ultimately gets committed.
244
+ const tnymphA = await tnymphTop.startTransaction('steve-a');
245
+ const EmployeeA = tnymphA.getEntityClass(EmployeeModel);
246
+ const goodSteve = await EmployeeA.factory();
247
+ goodSteve.name = 'Steve Complex';
248
+ goodSteve.current = true;
249
+ goodSteve.salary = 8000000;
250
+ goodSteve.startDate = Date.now();
251
+ goodSteve.subordinates = [];
252
+ goodSteve.title = 'Seniorer Person';
253
+ try {
254
+ await goodSteve.$save();
255
+ guid = goodSteve.guid;
256
+ await new Promise((res) => setTimeout(res, 200));
257
+ await tnymphA.commit('steve-a');
258
+ await new Promise((res) => setTimeout(res, 400));
259
+ committed = true;
260
+ await tnymphTop.commit('steve-top');
261
+ }
262
+ catch (e) {
263
+ console.error('Error creating entity: ', e);
264
+ throw e;
265
+ }
266
+ }
267
+ });
268
+ });
269
+ });
108
270
  it('notified of entity update', async () => {
109
271
  let jane = await createJane();
110
272
  let entities = [];
@@ -120,11 +282,12 @@ describe('Nymph REST Server and Client', () => {
120
282
  pubsub.updateArray(entities, update);
121
283
  if (mdate > 0 && (entities[0]?.mdate ?? -1) === mdate) {
122
284
  subscription.unsubscribe();
123
- resolve(true);
285
+ resolve();
124
286
  }
125
287
  else if (Array.isArray(update)) {
126
288
  expect(update.length).toEqual(1);
127
289
  expect(entities[0].salary).toEqual(8000000);
290
+ // Time for a raise!
128
291
  jane.salary = (jane.salary ?? 0) + 1000000;
129
292
  await jane.$save();
130
293
  mdate = jane.mdate ?? 0;
@@ -151,11 +314,12 @@ describe('Nymph REST Server and Client', () => {
151
314
  pubsub.updateArray(entities, update);
152
315
  if (mdate > 0 && (entities[0]?.mdate ?? -1) === mdate) {
153
316
  subscription.unsubscribe();
154
- resolve(true);
317
+ resolve();
155
318
  }
156
319
  else if (Array.isArray(update)) {
157
320
  expect(update.length).toEqual(1);
158
321
  expect(entities[0].salary).toEqual(8000000);
322
+ // Time for a raise!
159
323
  jane.salary = (jane.salary ?? 0) + 1000000;
160
324
  await jane.$save();
161
325
  mdate = jane.mdate ?? 0;
@@ -167,7 +331,14 @@ describe('Nymph REST Server and Client', () => {
167
331
  it('notified of new match for qref query', async () => {
168
332
  let [jane, john] = await createBossJane();
169
333
  let entities = [];
170
- await new Promise((resolve) => {
334
+ // Create employees that matches qref to test when multiple things match.
335
+ let oldEmployee = await createJane();
336
+ oldEmployee.current = false;
337
+ await oldEmployee.$save();
338
+ let oldEmployee2 = await createJane();
339
+ oldEmployee2.current = false;
340
+ await oldEmployee2.$save();
341
+ expect(await new Promise((resolve) => {
171
342
  if (jane.guid == null || john.guid == null) {
172
343
  throw new Error('Entity is null.');
173
344
  }
@@ -186,13 +357,100 @@ describe('Nymph REST Server and Client', () => {
186
357
  }
187
358
  else if (Array.isArray(update)) {
188
359
  expect(update.length).toEqual(0);
360
+ // John gets fired.
189
361
  john.current = false;
190
362
  await john.$save();
191
363
  }
192
364
  });
193
- });
365
+ })).toEqual(true);
194
366
  expect(entities.length).toEqual(1);
195
367
  });
368
+ it('notified of new match for qref query in transaction', async () => {
369
+ let entities = [];
370
+ const john = await EmployeeModel.factory();
371
+ john.name = 'John Der';
372
+ john.current = true;
373
+ john.salary = 8000000;
374
+ john.startDate = Date.now();
375
+ john.subordinates = [];
376
+ john.title = 'Junior Person';
377
+ try {
378
+ await john.$save();
379
+ }
380
+ catch (e) {
381
+ console.error('Error creating entity: ', e);
382
+ throw e;
383
+ }
384
+ const jane = await EmployeeModel.factory();
385
+ jane.name = 'Jane Doe';
386
+ jane.current = true;
387
+ jane.salary = 8000000;
388
+ jane.startDate = Date.now();
389
+ jane.subordinates = [john];
390
+ jane.title = 'Seniorer Person';
391
+ try {
392
+ await jane.$save();
393
+ }
394
+ catch (e) {
395
+ console.error('Error creating entity: ', e);
396
+ throw e;
397
+ }
398
+ async function createNewBoss() {
399
+ // Create employee that matches qref.
400
+ const tnymph = await nymphServer.startTransaction('qref-test');
401
+ const tnymphDeep = await tnymph.startTransaction('qref-deep-test');
402
+ const TEmployeeModel = tnymph.getEntityClass(EmployeeModel);
403
+ const newBoss = await TEmployeeModel.factory();
404
+ newBoss.name = 'Jill Doe';
405
+ newBoss.current = false;
406
+ newBoss.salary = 8000000;
407
+ newBoss.startDate = Date.now();
408
+ newBoss.subordinates = [john];
409
+ newBoss.title = 'Seniorer Person';
410
+ try {
411
+ await newBoss.$save();
412
+ }
413
+ catch (e) {
414
+ console.error('Error creating entity: ', e);
415
+ throw e;
416
+ }
417
+ newBoss.current = true;
418
+ try {
419
+ await newBoss.$save();
420
+ }
421
+ catch (e) {
422
+ console.error('Error creating entity: ', e);
423
+ throw e;
424
+ }
425
+ await tnymphDeep.commit('qref-deep-test');
426
+ await tnymph.commit('qref-test');
427
+ }
428
+ expect(await new Promise((resolve) => {
429
+ if (jane.guid == null || john.guid == null) {
430
+ throw new Error('Entity is null.');
431
+ }
432
+ const subscription = pubsub.subscribeEntities({ class: Employee }, {
433
+ type: '&',
434
+ truthy: 'current',
435
+ qref: [
436
+ 'subordinates',
437
+ [{ class: Employee }, { type: '&', guid: john.guid }],
438
+ ],
439
+ })(async (update) => {
440
+ pubsub.updateArray(entities, update);
441
+ if (Array.isArray(update)) {
442
+ expect(entities.length).toEqual(1);
443
+ await createNewBoss();
444
+ }
445
+ else {
446
+ expect(entities.length).toEqual(2);
447
+ subscription.unsubscribe();
448
+ resolve(true);
449
+ }
450
+ });
451
+ })).toEqual(true);
452
+ expect(entities.length).toEqual(2);
453
+ });
196
454
  it('notified of removed match for qref query', async () => {
197
455
  let [jane, john] = await createBossJane();
198
456
  let entities = [];
@@ -211,10 +469,11 @@ describe('Nymph REST Server and Client', () => {
211
469
  pubsub.updateArray(entities, update);
212
470
  if (!entities.length) {
213
471
  subscription.unsubscribe();
214
- resolve(true);
472
+ resolve();
215
473
  }
216
474
  else if (Array.isArray(update)) {
217
475
  expect(update.length).toEqual(1);
476
+ // John gets fired.
218
477
  john.current = false;
219
478
  await john.$save();
220
479
  }
@@ -225,8 +484,10 @@ describe('Nymph REST Server and Client', () => {
225
484
  it('receives correct number of updates', async () => {
226
485
  let jane = await createJane();
227
486
  let entities = [];
228
- await new Promise((resolve) => setTimeout(() => resolve(true), 10));
487
+ // Wait for change to propagate. (Only needed since we're not going across network.)
488
+ await new Promise((resolve) => setTimeout(() => resolve(), 10));
229
489
  await new Promise((resolve) => {
490
+ // Should only receive 1 update, since we waited.
230
491
  let updated = false;
231
492
  if (jane.guid == null) {
232
493
  throw new Error('Entity is null.');
@@ -238,12 +499,13 @@ describe('Nymph REST Server and Client', () => {
238
499
  pubsub.updateArray(entities, update);
239
500
  if (updated) {
240
501
  subscription.unsubscribe();
241
- resolve(true);
502
+ resolve();
242
503
  }
243
504
  else if (Array.isArray(update)) {
244
505
  expect(update.length).toEqual(1);
245
506
  expect(entities[0].salary).toEqual(8000000);
246
507
  updated = true;
508
+ // Time for a raise!
247
509
  jane.salary = (jane.salary ?? 0) + 1000000;
248
510
  await jane.$save();
249
511
  }
@@ -252,39 +514,39 @@ describe('Nymph REST Server and Client', () => {
252
514
  expect(entities[0].salary).toEqual(9000000);
253
515
  });
254
516
  it('notified of entity delete', async () => {
255
- let jane = await createJane();
517
+ let jane;
256
518
  let entities = [];
257
- await new Promise((resolve) => setTimeout(() => resolve(true), 10));
258
- let length = -1;
519
+ let removed = false;
259
520
  await new Promise((resolve) => {
260
- let updated = false;
261
- if (jane.guid == null) {
262
- throw new Error('Entity is null.');
263
- }
264
521
  const subscription = pubsub.subscribeEntities({ class: Employee }, {
265
522
  type: '&',
266
523
  equal: ['name', 'Jane Doe'],
267
524
  })(async (update) => {
268
525
  pubsub.updateArray(entities, update);
269
- if (updated) {
270
- subscription.unsubscribe();
271
- resolve(true);
526
+ if (Array.isArray(update)) {
527
+ jane = await createJane();
528
+ if (jane.guid == null) {
529
+ throw new Error('Entity is null.');
530
+ }
272
531
  }
273
- else if (Array.isArray(update)) {
274
- expect(update.length).toBeGreaterThan(0);
275
- updated = true;
276
- length = update.length;
277
- await jane.$delete();
532
+ else if ('added' in update) {
533
+ await entities.find((e) => e.guid === update.added)?.$delete();
534
+ }
535
+ else if ('removed' in update && update.removed === jane.guid) {
536
+ subscription.unsubscribe();
537
+ removed = true;
538
+ resolve();
278
539
  }
279
540
  });
280
541
  });
281
- expect(entities.length).toEqual(length - 1);
542
+ expect(removed).toBeTruthy();
282
543
  });
283
544
  it('entire match is updated', async () => {
284
545
  let jane;
285
546
  let entities = [];
286
547
  await createJane();
287
- await new Promise((resolve) => setTimeout(() => resolve(true), 10));
548
+ // Wait for change to propagate. (Only needed since we're not going across network.)
549
+ await new Promise((resolve) => setTimeout(() => resolve(), 10));
288
550
  await new Promise((resolve) => {
289
551
  let receivedRemove = false;
290
552
  let receivedAdd = false;
@@ -302,7 +564,7 @@ describe('Nymph REST Server and Client', () => {
302
564
  }
303
565
  if (receivedAdd && receivedRemove) {
304
566
  subscription.unsubscribe();
305
- resolve(true);
567
+ resolve();
306
568
  }
307
569
  }
308
570
  else if (Array.isArray(update)) {
@@ -319,9 +581,10 @@ describe('Nymph REST Server and Client', () => {
319
581
  await new Promise(async (resolve) => {
320
582
  let mdate = 0;
321
583
  const subscription = pubsub.subscribeWith(jane, async () => {
584
+ expect(jane.guid).not.toBeNull();
322
585
  if (mdate > 0 && (jane.mdate ?? -1) === mdate) {
323
586
  subscription.unsubscribe();
324
- resolve(true);
587
+ resolve();
325
588
  }
326
589
  });
327
590
  if (jane.guid == null) {
@@ -330,18 +593,72 @@ describe('Nymph REST Server and Client', () => {
330
593
  expect(jane.salary).toEqual(8000000);
331
594
  const janeDupe = await Employee.factory(jane.guid);
332
595
  expect(janeDupe.salary).toEqual(8000000);
596
+ // Time for a raise!
333
597
  janeDupe.salary = (janeDupe.salary ?? 0) + 1000000;
334
598
  await janeDupe.$save();
335
599
  mdate = janeDupe.mdate ?? 0;
336
600
  });
337
601
  expect(jane.salary).toEqual(9000000);
338
602
  });
603
+ it("doesn't allow subscription of a restricted entity class", async () => {
604
+ let receivedBadUpdate = false;
605
+ let error = null;
606
+ await new Promise((resolve) => {
607
+ pubsub.subscribeEntities({ class: Restricted }, {
608
+ type: '&',
609
+ equal: ['name', 'Jane Doe'],
610
+ })(async () => {
611
+ receivedBadUpdate = true;
612
+ resolve();
613
+ }, (e) => {
614
+ error = e;
615
+ resolve();
616
+ });
617
+ });
618
+ expect(receivedBadUpdate).toEqual(false);
619
+ expect(error).toEqual('Not accessible.');
620
+ });
621
+ it("doesn't notify of new pubsub disabled entity class", async () => {
622
+ let receivedBadUpdate = false;
623
+ await new Promise(async (resolve) => {
624
+ const subscription = await new Promise(async (resolve) => {
625
+ let updated = false;
626
+ const subscription = pubsub.subscribeEntities({
627
+ class: PubSubDisabled,
628
+ })(async (update) => {
629
+ if (updated) {
630
+ receivedBadUpdate = true;
631
+ }
632
+ else {
633
+ expect(update).toEqual([]);
634
+ updated = true;
635
+ try {
636
+ const entity = await PubSubDisabled.factory();
637
+ entity.name = 'Someone';
638
+ if (!(await entity.$save())) {
639
+ throw new Error("Couldn't save.");
640
+ }
641
+ resolve(subscription);
642
+ }
643
+ catch (e) {
644
+ console.error('Error creating entity: ', e);
645
+ throw e;
646
+ }
647
+ }
648
+ });
649
+ });
650
+ await new Promise((resolve) => setTimeout(resolve, 200));
651
+ subscription.unsubscribe();
652
+ resolve();
653
+ });
654
+ expect(receivedBadUpdate).toEqual(false);
655
+ });
339
656
  it('new uid', async () => {
340
657
  await new Promise(async (resolve) => {
341
658
  const subscription = pubsub.subscribeUID('testNewUID')(async (value) => {
342
659
  expect(value).toEqual(directValue);
343
660
  subscription.unsubscribe();
344
- resolve(true);
661
+ resolve();
345
662
  }, (err) => {
346
663
  expect(err.status).toEqual(404);
347
664
  });
@@ -362,7 +679,7 @@ describe('Nymph REST Server and Client', () => {
362
679
  lastUpdate = value;
363
680
  if (value == 100) {
364
681
  subscription.unsubscribe();
365
- resolve(true);
682
+ resolve();
366
683
  }
367
684
  }, (err) => {
368
685
  expect(err.status).toEqual(404);
@@ -379,7 +696,7 @@ describe('Nymph REST Server and Client', () => {
379
696
  const subscription = pubsub.subscribeUID('testSetUID')(async (value) => {
380
697
  expect(value).toEqual(123);
381
698
  subscription.unsubscribe();
382
- resolve(true);
699
+ resolve();
383
700
  }, (err) => {
384
701
  expect(err.status).toEqual(404);
385
702
  });
@@ -394,9 +711,9 @@ describe('Nymph REST Server and Client', () => {
394
711
  expect(event).toEqual('renameUID');
395
712
  expect(value).toEqual(null);
396
713
  subscription.unsubscribe();
397
- resolve(true);
714
+ resolve();
398
715
  }
399
- else {
716
+ else if (event === 'setUID') {
400
717
  expect(value).toEqual(456);
401
718
  updated = true;
402
719
  }
@@ -413,7 +730,7 @@ describe('Nymph REST Server and Client', () => {
413
730
  expect(event).toEqual('setUID');
414
731
  expect(value).toEqual(456);
415
732
  subscription.unsubscribe();
416
- resolve(true);
733
+ resolve();
417
734
  }, (err) => {
418
735
  expect(err.status).toEqual(404);
419
736
  });
@@ -429,28 +746,40 @@ describe('Nymph REST Server and Client', () => {
429
746
  if (updated && event === 'deleteUID') {
430
747
  expect(value).toEqual(null);
431
748
  subscription.unsubscribe();
432
- resolve(true);
749
+ resolve();
433
750
  }
434
751
  else {
435
752
  expect(value).toEqual(789);
436
753
  updated = true;
754
+ await nymph.deleteUID('testDeleteUID');
437
755
  }
438
756
  }, (err) => {
439
757
  expect(err.status).toEqual(404);
440
758
  });
441
- await nymph.deleteUID('testDeleteUID');
442
759
  });
443
760
  });
761
+ beforeEach(async () => {
762
+ pubsub.connect();
763
+ while (!pubsub.isConnectionOpen()) {
764
+ await new Promise((resolve) => setTimeout(resolve, 20));
765
+ }
766
+ });
444
767
  afterAll(async () => {
768
+ // Don't publish anything after the tests.
769
+ removePublisher();
770
+ // Avoid jest open handle errors.
445
771
  const closed = new Promise((resolve) => {
446
772
  pubsub.on('disconnect', () => {
447
- resolve(true);
773
+ resolve();
448
774
  });
449
775
  });
450
- pubsub.close();
776
+ pubsub.close(); // close PubSub client.
451
777
  await closed;
452
- pubsubServer.close();
453
- server.close();
778
+ pubsubServer.close(); // close PubSub server.
779
+ server.close(); // close REST server.
780
+ // Wait for the next event loop to prevent websocket importing something
781
+ // after jest teardown.
782
+ await new Promise((resolve) => setImmediate(resolve));
454
783
  });
455
784
  });
456
785
  //# sourceMappingURL=PubSub.test.js.map