@libp2p/interface-compliance-tests 3.0.7-d853d124 → 3.0.7-e9cafd3d

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.
Files changed (172) hide show
  1. package/README.md +9 -0
  2. package/dist/src/connection/index.d.ts +5 -0
  3. package/dist/src/connection/index.d.ts.map +1 -0
  4. package/dist/src/connection/index.js +150 -0
  5. package/dist/src/connection/index.js.map +1 -0
  6. package/dist/src/connection-encryption/index.d.ts +5 -0
  7. package/dist/src/connection-encryption/index.d.ts.map +1 -0
  8. package/dist/src/connection-encryption/index.js +71 -0
  9. package/dist/src/connection-encryption/index.js.map +1 -0
  10. package/dist/src/connection-encryption/utils/index.d.ts +3 -0
  11. package/dist/src/connection-encryption/utils/index.d.ts.map +1 -0
  12. package/dist/src/connection-encryption/utils/index.js +18 -0
  13. package/dist/src/connection-encryption/utils/index.js.map +1 -0
  14. package/dist/src/mocks/connection-encrypter.d.ts +3 -0
  15. package/dist/src/mocks/connection-encrypter.d.ts.map +1 -0
  16. package/dist/src/mocks/connection-encrypter.js +98 -0
  17. package/dist/src/mocks/connection-encrypter.js.map +1 -0
  18. package/dist/src/mocks/connection-gater.d.ts +3 -0
  19. package/dist/src/mocks/connection-gater.d.ts.map +1 -0
  20. package/dist/src/mocks/connection-gater.js +17 -0
  21. package/dist/src/mocks/connection-gater.js.map +1 -0
  22. package/dist/src/mocks/connection-manager.d.ts +29 -0
  23. package/dist/src/mocks/connection-manager.d.ts.map +1 -0
  24. package/dist/src/mocks/connection-manager.js +145 -0
  25. package/dist/src/mocks/connection-manager.js.map +1 -0
  26. package/dist/src/mocks/connection.d.ts +32 -0
  27. package/dist/src/mocks/connection.d.ts.map +1 -0
  28. package/dist/src/mocks/connection.js +158 -0
  29. package/dist/src/mocks/connection.js.map +1 -0
  30. package/dist/src/mocks/duplex.d.ts +3 -0
  31. package/dist/src/mocks/duplex.d.ts.map +1 -0
  32. package/dist/src/mocks/duplex.js +9 -0
  33. package/dist/src/mocks/duplex.js.map +1 -0
  34. package/dist/src/mocks/index.d.ts +13 -0
  35. package/dist/src/mocks/index.d.ts.map +1 -0
  36. package/dist/src/mocks/index.js +11 -0
  37. package/dist/src/mocks/index.js.map +1 -0
  38. package/dist/src/mocks/metrics.d.ts +3 -0
  39. package/dist/src/mocks/metrics.d.ts.map +1 -0
  40. package/dist/src/mocks/metrics.js +115 -0
  41. package/dist/src/mocks/metrics.js.map +1 -0
  42. package/dist/src/mocks/multiaddr-connection.d.ts +17 -0
  43. package/dist/src/mocks/multiaddr-connection.d.ts.map +1 -0
  44. package/dist/src/mocks/multiaddr-connection.js +51 -0
  45. package/dist/src/mocks/multiaddr-connection.js.map +1 -0
  46. package/dist/src/mocks/muxer.d.ts +8 -0
  47. package/dist/src/mocks/muxer.d.ts.map +1 -0
  48. package/dist/src/mocks/muxer.js +339 -0
  49. package/dist/src/mocks/muxer.js.map +1 -0
  50. package/dist/src/mocks/peer-discovery.d.ts +22 -0
  51. package/dist/src/mocks/peer-discovery.d.ts.map +1 -0
  52. package/dist/src/mocks/peer-discovery.js +47 -0
  53. package/dist/src/mocks/peer-discovery.js.map +1 -0
  54. package/dist/src/mocks/registrar.d.ts +18 -0
  55. package/dist/src/mocks/registrar.d.ts.map +1 -0
  56. package/dist/src/mocks/registrar.js +66 -0
  57. package/dist/src/mocks/registrar.js.map +1 -0
  58. package/dist/src/mocks/upgrader.d.ts +10 -0
  59. package/dist/src/mocks/upgrader.d.ts.map +1 -0
  60. package/dist/src/mocks/upgrader.js +31 -0
  61. package/dist/src/mocks/upgrader.js.map +1 -0
  62. package/dist/src/peer-discovery/index.d.ts +5 -0
  63. package/dist/src/peer-discovery/index.d.ts.map +1 -0
  64. package/dist/src/peer-discovery/index.js +66 -0
  65. package/dist/src/peer-discovery/index.js.map +1 -0
  66. package/dist/src/pubsub/api.d.ts +6 -0
  67. package/dist/src/pubsub/api.d.ts.map +1 -0
  68. package/dist/src/pubsub/api.js +87 -0
  69. package/dist/src/pubsub/api.js.map +1 -0
  70. package/dist/src/pubsub/connection-handlers.d.ts +6 -0
  71. package/dist/src/pubsub/connection-handlers.d.ts.map +1 -0
  72. package/dist/src/pubsub/connection-handlers.js +329 -0
  73. package/dist/src/pubsub/connection-handlers.js.map +1 -0
  74. package/dist/src/pubsub/emit-self.d.ts +6 -0
  75. package/dist/src/pubsub/emit-self.d.ts.map +1 -0
  76. package/dist/src/pubsub/emit-self.js +80 -0
  77. package/dist/src/pubsub/emit-self.js.map +1 -0
  78. package/dist/src/pubsub/index.d.ts +18 -0
  79. package/dist/src/pubsub/index.d.ts.map +1 -0
  80. package/dist/src/pubsub/index.js +17 -0
  81. package/dist/src/pubsub/index.js.map +1 -0
  82. package/dist/src/pubsub/messages.d.ts +6 -0
  83. package/dist/src/pubsub/messages.d.ts.map +1 -0
  84. package/dist/src/pubsub/messages.js +48 -0
  85. package/dist/src/pubsub/messages.js.map +1 -0
  86. package/dist/src/pubsub/multiple-nodes.d.ts +6 -0
  87. package/dist/src/pubsub/multiple-nodes.d.ts.map +1 -0
  88. package/dist/src/pubsub/multiple-nodes.js +350 -0
  89. package/dist/src/pubsub/multiple-nodes.js.map +1 -0
  90. package/dist/src/pubsub/two-nodes.d.ts +6 -0
  91. package/dist/src/pubsub/two-nodes.d.ts.map +1 -0
  92. package/dist/src/pubsub/two-nodes.js +217 -0
  93. package/dist/src/pubsub/two-nodes.js.map +1 -0
  94. package/dist/src/pubsub/utils.d.ts +6 -0
  95. package/dist/src/pubsub/utils.d.ts.map +1 -0
  96. package/dist/src/pubsub/utils.js +22 -0
  97. package/dist/src/pubsub/utils.js.map +1 -0
  98. package/dist/src/stream-muxer/base-test.d.ts +5 -0
  99. package/dist/src/stream-muxer/base-test.d.ts.map +1 -0
  100. package/dist/src/stream-muxer/base-test.js +153 -0
  101. package/dist/src/stream-muxer/base-test.js.map +1 -0
  102. package/dist/src/stream-muxer/close-test.d.ts +5 -0
  103. package/dist/src/stream-muxer/close-test.d.ts.map +1 -0
  104. package/dist/src/stream-muxer/close-test.js +269 -0
  105. package/dist/src/stream-muxer/close-test.js.map +1 -0
  106. package/dist/src/stream-muxer/index.d.ts +5 -0
  107. package/dist/src/stream-muxer/index.d.ts.map +1 -0
  108. package/dist/src/stream-muxer/index.js +13 -0
  109. package/dist/src/stream-muxer/index.js.map +1 -0
  110. package/dist/src/stream-muxer/mega-stress-test.d.ts +5 -0
  111. package/dist/src/stream-muxer/mega-stress-test.d.ts.map +1 -0
  112. package/dist/src/stream-muxer/mega-stress-test.js +11 -0
  113. package/dist/src/stream-muxer/mega-stress-test.js.map +1 -0
  114. package/dist/src/stream-muxer/spawner.d.ts +4 -0
  115. package/dist/src/stream-muxer/spawner.d.ts.map +1 -0
  116. package/dist/src/stream-muxer/spawner.js +36 -0
  117. package/dist/src/stream-muxer/spawner.js.map +1 -0
  118. package/dist/src/stream-muxer/stress-test.d.ts +5 -0
  119. package/dist/src/stream-muxer/stress-test.d.ts.map +1 -0
  120. package/dist/src/stream-muxer/stress-test.js +23 -0
  121. package/dist/src/stream-muxer/stress-test.js.map +1 -0
  122. package/dist/src/transport/dial-test.d.ts +5 -0
  123. package/dist/src/transport/dial-test.d.ts.map +1 -0
  124. package/dist/src/transport/dial-test.js +98 -0
  125. package/dist/src/transport/dial-test.js.map +1 -0
  126. package/dist/src/transport/filter-test.d.ts +5 -0
  127. package/dist/src/transport/filter-test.d.ts.map +1 -0
  128. package/dist/src/transport/filter-test.js +18 -0
  129. package/dist/src/transport/filter-test.js.map +1 -0
  130. package/dist/src/transport/index.d.ts +15 -0
  131. package/dist/src/transport/index.d.ts.map +1 -0
  132. package/dist/src/transport/index.js +11 -0
  133. package/dist/src/transport/index.js.map +1 -0
  134. package/dist/src/transport/listen-test.d.ts +5 -0
  135. package/dist/src/transport/listen-test.d.ts.map +1 -0
  136. package/dist/src/transport/listen-test.js +152 -0
  137. package/dist/src/transport/listen-test.js.map +1 -0
  138. package/package.json +69 -3
  139. package/src/connection/index.ts +182 -0
  140. package/src/connection-encryption/index.ts +97 -0
  141. package/src/connection-encryption/utils/index.ts +23 -0
  142. package/src/mocks/connection-encrypter.ts +113 -0
  143. package/src/mocks/connection-gater.ts +18 -0
  144. package/src/mocks/connection-manager.ts +211 -0
  145. package/src/mocks/connection.ts +215 -0
  146. package/src/mocks/duplex.ts +10 -0
  147. package/src/mocks/index.ts +12 -0
  148. package/src/mocks/metrics.ts +162 -0
  149. package/src/mocks/multiaddr-connection.ts +67 -0
  150. package/src/mocks/muxer.ts +445 -0
  151. package/src/mocks/peer-discovery.ts +60 -0
  152. package/src/mocks/registrar.ts +88 -0
  153. package/src/mocks/upgrader.ts +49 -0
  154. package/src/peer-discovery/index.ts +90 -0
  155. package/src/pubsub/api.ts +114 -0
  156. package/src/pubsub/connection-handlers.ts +413 -0
  157. package/src/pubsub/emit-self.ts +99 -0
  158. package/src/pubsub/index.ts +34 -0
  159. package/src/pubsub/messages.ts +59 -0
  160. package/src/pubsub/multiple-nodes.ts +440 -0
  161. package/src/pubsub/two-nodes.ts +273 -0
  162. package/src/pubsub/utils.ts +29 -0
  163. package/src/stream-muxer/base-test.ts +196 -0
  164. package/src/stream-muxer/close-test.ts +346 -0
  165. package/src/stream-muxer/index.ts +15 -0
  166. package/src/stream-muxer/mega-stress-test.ts +14 -0
  167. package/src/stream-muxer/spawner.ts +54 -0
  168. package/src/stream-muxer/stress-test.ts +27 -0
  169. package/src/transport/dial-test.ts +124 -0
  170. package/src/transport/filter-test.ts +25 -0
  171. package/src/transport/index.ts +25 -0
  172. package/src/transport/listen-test.ts +191 -0
@@ -0,0 +1,60 @@
1
+ import { EventEmitter } from '@libp2p/interface/events'
2
+ import { peerDiscovery } from '@libp2p/interface/peer-discovery'
3
+ import * as PeerIdFactory from '@libp2p/peer-id-factory'
4
+ import { multiaddr } from '@multiformats/multiaddr'
5
+ import type { PeerDiscovery, PeerDiscoveryEvents } from '@libp2p/interface/peer-discovery'
6
+ import type { PeerInfo } from '@libp2p/interface/peer-info'
7
+
8
+ interface MockDiscoveryInit {
9
+ discoveryDelay?: number
10
+ }
11
+
12
+ /**
13
+ * Emits 'peer' events on discovery.
14
+ */
15
+ export class MockDiscovery extends EventEmitter<PeerDiscoveryEvents> implements PeerDiscovery {
16
+ public readonly options: MockDiscoveryInit
17
+ private _isRunning: boolean
18
+ private _timer: any
19
+
20
+ constructor (init = {}) {
21
+ super()
22
+
23
+ this.options = init
24
+ this._isRunning = false
25
+ }
26
+
27
+ readonly [peerDiscovery] = this
28
+
29
+ start (): void {
30
+ this._isRunning = true
31
+ this._discoverPeer()
32
+ }
33
+
34
+ stop (): void {
35
+ clearTimeout(this._timer)
36
+ this._isRunning = false
37
+ }
38
+
39
+ isStarted (): boolean {
40
+ return this._isRunning
41
+ }
42
+
43
+ _discoverPeer (): void {
44
+ if (!this._isRunning) return
45
+
46
+ PeerIdFactory.createEd25519PeerId()
47
+ .then(peerId => {
48
+ this._timer = setTimeout(() => {
49
+ this.safeDispatchEvent<PeerInfo>('peer', {
50
+ detail: {
51
+ id: peerId,
52
+ multiaddrs: [multiaddr('/ip4/127.0.0.1/tcp/8000')],
53
+ protocols: []
54
+ }
55
+ })
56
+ }, this.options.discoveryDelay ?? 1000)
57
+ })
58
+ .catch(() => {})
59
+ }
60
+ }
@@ -0,0 +1,88 @@
1
+ import merge from 'merge-options'
2
+ import type { Connection } from '@libp2p/interface/connection'
3
+ import type { PeerId } from '@libp2p/interface/peer-id'
4
+ import type { Topology } from '@libp2p/interface/topology'
5
+ import type { IncomingStreamData, Registrar, StreamHandler, StreamHandlerOptions, StreamHandlerRecord } from '@libp2p/interface-internal/registrar'
6
+
7
+ export class MockRegistrar implements Registrar {
8
+ private readonly topologies = new Map<string, Array<{ id: string, topology: Topology }>>()
9
+ private readonly handlers = new Map<string, StreamHandlerRecord>()
10
+
11
+ getProtocols (): string[] {
12
+ return Array.from(this.handlers.keys()).sort()
13
+ }
14
+
15
+ async handle (protocol: string, handler: StreamHandler, opts?: StreamHandlerOptions): Promise<void> {
16
+ const options = merge.bind({ ignoreUndefined: true })({
17
+ maxInboundStreams: 1,
18
+ maxOutboundStreams: 1
19
+ }, opts)
20
+
21
+ if (this.handlers.has(protocol)) {
22
+ throw new Error(`Handler already registered for protocol ${protocol}`)
23
+ }
24
+
25
+ this.handlers.set(protocol, {
26
+ handler,
27
+ options
28
+ })
29
+ }
30
+
31
+ async unhandle (protocol: string): Promise<void> {
32
+ this.handlers.delete(protocol)
33
+ }
34
+
35
+ getHandler (protocol: string): StreamHandlerRecord {
36
+ const handler = this.handlers.get(protocol)
37
+
38
+ if (handler == null) {
39
+ throw new Error(`No handler registered for protocol ${protocol}`)
40
+ }
41
+
42
+ return handler
43
+ }
44
+
45
+ async register (protocol: string, topology: Topology): Promise<string> {
46
+ const id = `topology-id-${Math.random()}`
47
+ let topologies = this.topologies.get(protocol)
48
+
49
+ if (topologies == null) {
50
+ topologies = []
51
+ }
52
+
53
+ topologies.push({
54
+ id,
55
+ topology
56
+ })
57
+
58
+ this.topologies.set(protocol, topologies)
59
+
60
+ return id
61
+ }
62
+
63
+ unregister (id: string | string[]): void {
64
+ if (!Array.isArray(id)) {
65
+ id = [id]
66
+ }
67
+
68
+ id.forEach(id => this.topologies.delete(id))
69
+ }
70
+
71
+ getTopologies (protocol: string): Topology[] {
72
+ return (this.topologies.get(protocol) ?? []).map(t => t.topology)
73
+ }
74
+ }
75
+
76
+ export function mockRegistrar (): Registrar {
77
+ return new MockRegistrar()
78
+ }
79
+
80
+ export async function mockIncomingStreamEvent (protocol: string, conn: Connection, remotePeer: PeerId): Promise<IncomingStreamData> {
81
+ return {
82
+ ...await conn.newStream([protocol]),
83
+ // @ts-expect-error incomplete implementation
84
+ connection: {
85
+ remotePeer
86
+ }
87
+ }
88
+ }
@@ -0,0 +1,49 @@
1
+ import { mockConnection } from './connection.js'
2
+ import type { Libp2pEvents } from '@libp2p/interface'
3
+ import type { Connection, MultiaddrConnection } from '@libp2p/interface/connection'
4
+ import type { EventEmitter } from '@libp2p/interface/events'
5
+ import type { Registrar } from '@libp2p/interface-internal/registrar'
6
+ import type { Upgrader, UpgraderOptions } from '@libp2p/interface-internal/upgrader'
7
+
8
+ export interface MockUpgraderInit {
9
+ registrar?: Registrar
10
+ events?: EventEmitter<Libp2pEvents>
11
+ }
12
+
13
+ class MockUpgrader implements Upgrader {
14
+ private readonly registrar?: Registrar
15
+ private readonly events?: EventEmitter<Libp2pEvents>
16
+
17
+ constructor (init: MockUpgraderInit) {
18
+ this.registrar = init.registrar
19
+ this.events = init.events
20
+ }
21
+
22
+ async upgradeOutbound (multiaddrConnection: MultiaddrConnection, opts: UpgraderOptions = {}): Promise<Connection> {
23
+ const connection = mockConnection(multiaddrConnection, {
24
+ direction: 'outbound',
25
+ registrar: this.registrar,
26
+ ...opts
27
+ })
28
+
29
+ this.events?.safeDispatchEvent('connection:open', { detail: connection })
30
+
31
+ return connection
32
+ }
33
+
34
+ async upgradeInbound (multiaddrConnection: MultiaddrConnection, opts: UpgraderOptions = {}): Promise<Connection> {
35
+ const connection = mockConnection(multiaddrConnection, {
36
+ direction: 'inbound',
37
+ registrar: this.registrar,
38
+ ...opts
39
+ })
40
+
41
+ this.events?.safeDispatchEvent('connection:open', { detail: connection })
42
+
43
+ return connection
44
+ }
45
+ }
46
+
47
+ export function mockUpgrader (init: MockUpgraderInit = {}): Upgrader {
48
+ return new MockUpgrader(init)
49
+ }
@@ -0,0 +1,90 @@
1
+ import { start, stop } from '@libp2p/interface/startable'
2
+ import { isMultiaddr } from '@multiformats/multiaddr'
3
+ import { expect } from 'aegir/chai'
4
+ import delay from 'delay'
5
+ import pDefer from 'p-defer'
6
+ import type { TestSetup } from '../index.js'
7
+ import type { PeerDiscovery } from '@libp2p/interface/peer-discovery'
8
+
9
+ export default (common: TestSetup<PeerDiscovery>): void => {
10
+ describe('interface-peer-discovery compliance tests', () => {
11
+ let discovery: PeerDiscovery
12
+
13
+ beforeEach(async () => {
14
+ discovery = await common.setup()
15
+ })
16
+
17
+ afterEach('ensure discovery was stopped', async () => {
18
+ await stop(discovery)
19
+
20
+ await common.teardown()
21
+ })
22
+
23
+ it('can start the service', async () => {
24
+ await start(discovery)
25
+ })
26
+
27
+ it('can start and stop the service', async () => {
28
+ await start(discovery)
29
+ await stop(discovery)
30
+ })
31
+
32
+ it('should not fail to stop the service if it was not started', async () => {
33
+ await stop(discovery)
34
+ })
35
+
36
+ it('should not fail to start the service if it is already started', async () => {
37
+ await start(discovery)
38
+ await start(discovery)
39
+ })
40
+
41
+ it('should emit a peer event after start', async () => {
42
+ const defer = pDefer()
43
+
44
+ discovery.addEventListener('peer', (evt) => {
45
+ const { id, multiaddrs } = evt.detail
46
+ expect(id).to.exist()
47
+ expect(id)
48
+ .to.have.property('type')
49
+ .that.is.oneOf(['RSA', 'Ed25519', 'secp256k1'])
50
+ expect(multiaddrs).to.exist()
51
+
52
+ multiaddrs.forEach((m) => expect(isMultiaddr(m)).to.eql(true))
53
+
54
+ defer.resolve()
55
+ })
56
+
57
+ await start(discovery)
58
+
59
+ await defer.promise
60
+ })
61
+
62
+ it('should not receive a peer event before start', async () => {
63
+ discovery.addEventListener('peer', () => {
64
+ throw new Error('should not receive a peer event before start')
65
+ })
66
+
67
+ await delay(2000)
68
+ })
69
+
70
+ it('should not receive a peer event after stop', async () => {
71
+ const deferStart = pDefer()
72
+
73
+ discovery.addEventListener('peer', () => {
74
+ deferStart.resolve()
75
+ })
76
+
77
+ await start(discovery)
78
+
79
+ await deferStart.promise
80
+
81
+ await stop(discovery)
82
+
83
+ discovery.addEventListener('peer', () => {
84
+ throw new Error('should not receive a peer event after stop')
85
+ })
86
+
87
+ await delay(2000)
88
+ })
89
+ })
90
+ }
@@ -0,0 +1,114 @@
1
+ import { isStartable, start, stop } from '@libp2p/interface/startable'
2
+ import { expect } from 'aegir/chai'
3
+ import delay from 'delay'
4
+ import pDefer from 'p-defer'
5
+ import pWaitFor from 'p-wait-for'
6
+ import sinon from 'sinon'
7
+ import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
8
+ import { mockNetwork } from '../mocks/index.js'
9
+ import { createComponents } from './utils.js'
10
+ import type { PubSubArgs, PubSubComponents } from './index.js'
11
+ import type { TestSetup } from '../index.js'
12
+ import type { PubSub } from '@libp2p/interface/pubsub'
13
+
14
+ const topic = 'foo'
15
+ const data = uint8ArrayFromString('bar')
16
+
17
+ export default (common: TestSetup<PubSub, PubSubArgs>): void => {
18
+ describe('pubsub api', () => {
19
+ let pubsub: PubSub
20
+ let components: PubSubComponents
21
+
22
+ // Create pubsub router
23
+ beforeEach(async () => {
24
+ mockNetwork.reset()
25
+ components = await createComponents()
26
+
27
+ pubsub = components.pubsub = await common.setup({
28
+ components,
29
+ init: {
30
+ emitSelf: true
31
+ }
32
+ })
33
+ })
34
+
35
+ afterEach(async () => {
36
+ sinon.restore()
37
+ await stop(...Object.values(components))
38
+ await common.teardown()
39
+ mockNetwork.reset()
40
+ })
41
+
42
+ it('can start correctly', async () => {
43
+ if (!isStartable(pubsub)) {
44
+ return
45
+ }
46
+
47
+ sinon.spy(components.registrar, 'register')
48
+
49
+ await start(...Object.values(components))
50
+
51
+ expect(pubsub.isStarted()).to.equal(true)
52
+ expect(components.registrar.register).to.have.property('callCount', 1)
53
+ })
54
+
55
+ it('can stop correctly', async () => {
56
+ if (!isStartable(pubsub)) {
57
+ return
58
+ }
59
+
60
+ sinon.spy(components.registrar, 'unregister')
61
+
62
+ await start(...Object.values(components))
63
+ await stop(...Object.values(components))
64
+
65
+ expect(pubsub.isStarted()).to.equal(false)
66
+ expect(components.registrar.unregister).to.have.property('callCount', 1)
67
+ })
68
+
69
+ it('can subscribe and unsubscribe correctly', async () => {
70
+ const handler = (): void => {
71
+ throw new Error('a message should not be received')
72
+ }
73
+
74
+ await start(...Object.values(components))
75
+ pubsub.subscribe(topic)
76
+ pubsub.addEventListener('message', handler)
77
+
78
+ await pWaitFor(() => {
79
+ const topics = pubsub.getTopics()
80
+ return topics.length === 1 && topics[0] === topic
81
+ })
82
+
83
+ pubsub.removeEventListener('message', handler)
84
+ pubsub.unsubscribe(topic)
85
+
86
+ await pWaitFor(() => pubsub.getTopics().length === 0)
87
+
88
+ // Publish to guarantee the handler is not called
89
+ await pubsub.publish(topic, data)
90
+
91
+ // handlers are called async
92
+ await delay(100)
93
+
94
+ await stop(...Object.values(components))
95
+ })
96
+
97
+ it('can subscribe and publish correctly', async () => {
98
+ const defer = pDefer()
99
+
100
+ await start(...Object.values(components))
101
+
102
+ pubsub.subscribe(topic)
103
+ pubsub.addEventListener('message', (evt) => {
104
+ expect(evt).to.have.nested.property('detail.topic', topic)
105
+ expect(evt).to.have.deep.nested.property('detail.data', data)
106
+ defer.resolve()
107
+ })
108
+ await pubsub.publish(topic, data)
109
+ await defer.promise
110
+
111
+ await stop(...Object.values(components))
112
+ })
113
+ })
114
+ }