mockrtc 0.1.0 → 0.3.0

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 (92) hide show
  1. package/.github/workflows/ci.yml +2 -2
  2. package/README.md +2 -2
  3. package/dist/client/mockrtc-admin-request-builder.d.ts +27 -0
  4. package/dist/client/mockrtc-admin-request-builder.js +201 -0
  5. package/dist/client/mockrtc-admin-request-builder.js.map +1 -0
  6. package/dist/client/mockrtc-client.d.ts +12 -4
  7. package/dist/client/mockrtc-client.js +38 -22
  8. package/dist/client/mockrtc-client.js.map +1 -1
  9. package/dist/client/mockrtc-remote-peer.d.ts +3 -2
  10. package/dist/client/mockrtc-remote-peer.js.map +1 -1
  11. package/dist/handling/handler-builder.d.ts +16 -9
  12. package/dist/handling/handler-builder.js +11 -1
  13. package/dist/handling/handler-builder.js.map +1 -1
  14. package/dist/handling/handler-step-definitions.d.ts +43 -25
  15. package/dist/handling/handler-step-definitions.js +61 -19
  16. package/dist/handling/handler-step-definitions.js.map +1 -1
  17. package/dist/handling/handler-steps.d.ts +4 -1
  18. package/dist/handling/handler-steps.js +27 -17
  19. package/dist/handling/handler-steps.js.map +1 -1
  20. package/dist/main-browser.d.ts +3 -0
  21. package/dist/main-browser.js +6 -1
  22. package/dist/main-browser.js.map +1 -1
  23. package/dist/main.d.ts +8 -5
  24. package/dist/main.js +6 -1
  25. package/dist/main.js.map +1 -1
  26. package/dist/matching/matcher-definitions.d.ts +51 -0
  27. package/dist/matching/matcher-definitions.js +94 -0
  28. package/dist/matching/matcher-definitions.js.map +1 -0
  29. package/dist/matching/matchers.d.ts +27 -0
  30. package/dist/matching/matchers.js +87 -0
  31. package/dist/matching/matchers.js.map +1 -0
  32. package/dist/mockrtc-base.d.ts +16 -0
  33. package/dist/mockrtc-base.js +19 -0
  34. package/dist/mockrtc-base.js.map +1 -0
  35. package/dist/mockrtc-peer.d.ts +44 -6
  36. package/dist/mockrtc.d.ts +200 -1
  37. package/dist/mockrtc.js +1 -0
  38. package/dist/mockrtc.js.map +1 -1
  39. package/dist/rule-builder.d.ts +86 -0
  40. package/dist/rule-builder.js +113 -0
  41. package/dist/rule-builder.js.map +1 -0
  42. package/dist/server/mockrtc-admin-plugin.d.ts +2 -2
  43. package/dist/server/mockrtc-admin-plugin.js +165 -3
  44. package/dist/server/mockrtc-admin-plugin.js.map +1 -1
  45. package/dist/server/mockrtc-server-peer.d.ts +8 -2
  46. package/dist/server/mockrtc-server-peer.js +119 -6
  47. package/dist/server/mockrtc-server-peer.js.map +1 -1
  48. package/dist/server/mockrtc-server.d.ts +20 -5
  49. package/dist/server/mockrtc-server.js +87 -14
  50. package/dist/server/mockrtc-server.js.map +1 -1
  51. package/dist/webrtc/datachannel-stream.d.ts +4 -0
  52. package/dist/webrtc/datachannel-stream.js +27 -1
  53. package/dist/webrtc/datachannel-stream.js.map +1 -1
  54. package/dist/webrtc/mediatrack-stream.d.ts +6 -0
  55. package/dist/webrtc/mediatrack-stream.js +28 -2
  56. package/dist/webrtc/mediatrack-stream.js.map +1 -1
  57. package/dist/webrtc/mockrtc-connection.d.ts +1 -1
  58. package/dist/webrtc/mockrtc-connection.js +77 -60
  59. package/dist/webrtc/mockrtc-connection.js.map +1 -1
  60. package/dist/webrtc/rtc-connection.d.ts +28 -5
  61. package/dist/webrtc/rtc-connection.js +62 -23
  62. package/dist/webrtc/rtc-connection.js.map +1 -1
  63. package/dist/webrtc-hooks.js +10 -2
  64. package/dist/webrtc-hooks.js.map +1 -1
  65. package/package.json +12 -6
  66. package/src/client/mockrtc-admin-request-builder.ts +232 -0
  67. package/src/client/mockrtc-client.ts +50 -28
  68. package/src/client/mockrtc-remote-peer.ts +9 -8
  69. package/src/handling/handler-builder.ts +22 -10
  70. package/src/handling/handler-step-definitions.ts +87 -27
  71. package/src/handling/handler-steps.ts +34 -20
  72. package/src/main-browser.ts +5 -0
  73. package/src/main.ts +23 -5
  74. package/src/matching/matcher-definitions.ts +109 -0
  75. package/src/matching/matchers.ts +118 -0
  76. package/src/mockrtc-base.ts +49 -0
  77. package/src/mockrtc-peer.ts +48 -6
  78. package/src/mockrtc.ts +235 -1
  79. package/src/rule-builder.ts +142 -0
  80. package/src/server/mockrtc-admin-plugin.ts +200 -9
  81. package/src/server/mockrtc-server-peer.ts +194 -7
  82. package/src/server/mockrtc-server.ts +136 -19
  83. package/src/webrtc/datachannel-stream.ts +31 -1
  84. package/src/webrtc/mediatrack-stream.ts +31 -4
  85. package/src/webrtc/mockrtc-connection.ts +22 -7
  86. package/src/webrtc/rtc-connection.ts +111 -29
  87. package/src/webrtc-hooks.ts +13 -4
  88. package/test/integration/events.spec.ts +538 -0
  89. package/test/integration/matching.spec.ts +257 -0
  90. package/test/integration/proxy.spec.ts +68 -1
  91. package/test/integration/send-steps.spec.ts +25 -0
  92. package/test/test-setup.ts +19 -0
@@ -3,7 +3,6 @@
3
3
  * SPDX-License-Identifier: Apache-2.0
4
4
  */
5
5
 
6
- import gql from 'graphql-tag';
7
6
 
8
7
  // Long-term, it'd be great to use the 'official' export path of mockttp/pluggable-admin, but
9
8
  // if we do so, then TypeScript <4.7 doesn't understand it here or downstream, so we get errors.
@@ -12,61 +11,69 @@ import gql from 'graphql-tag';
12
11
  import * as BrowserPluggableAdmin from 'mockttp/dist/pluggable-admin-api/pluggable-admin.browser';
13
12
  import type { PluggableAdmin } from 'mockttp';
14
13
 
15
- import { MockRTC, MockRTCOptions, MockRTCPeerBuilder } from "../mockrtc";
14
+ import { MockRTC, MockRTCEvent, MockRTCOptions, MockRTCRuleDefinition } from "../mockrtc";
15
+ import { MockRTCBase } from '../mockrtc-base';
16
16
 
17
- import type { MockRTCAdminPlugin } from "../server/mockrtc-admin-plugin";
18
17
  import type { MockRTCPeer } from '../mockrtc-peer';
19
18
  import { MockRTCRemotePeer } from './mockrtc-remote-peer';
20
- import { MockRTCHandlerBuilder } from '../handling/handler-builder';
19
+ import type { MockRTCAdminPlugin } from "../server/mockrtc-admin-plugin";
20
+ import { MockRTCAdminRequestBuilder } from './mockrtc-admin-request-builder';
21
21
  import { HandlerStepDefinition } from '../handling/handler-step-definitions';
22
+ import { MatcherDefinition } from '../matching/matcher-definitions';
22
23
 
23
24
  export type MockRTCClientOptions =
24
25
  PluggableAdmin.AdminClientOptions &
25
26
  MockRTCOptions;
26
27
 
27
- export class MockRTCClient implements MockRTC {
28
+ export class MockRTCClient extends MockRTCBase implements MockRTC {
28
29
 
29
30
  private adminClient: PluggableAdmin.AdminClient<{ webrtc: MockRTCAdminPlugin }>;
31
+ private requestBuilder: MockRTCAdminRequestBuilder;
30
32
 
31
33
  constructor(
32
34
  private options: MockRTCClientOptions = {}
33
35
  ) {
36
+ super();
37
+
34
38
  this.adminClient = new BrowserPluggableAdmin.AdminClient(options);
39
+ this.requestBuilder = new MockRTCAdminRequestBuilder();
35
40
  }
36
41
 
37
- buildPeer(): MockRTCPeerBuilder {
38
- return new MockRTCHandlerBuilder(this.buildPeerFromData);
42
+ getMatchingPeer(): MockRTCPeer {
43
+ return new MockRTCRemotePeer('matching-peer', this.adminClient);
39
44
  }
40
45
 
41
- private buildPeerFromData = async (handlerSteps: HandlerStepDefinition[]): Promise<MockRTCPeer> => {
46
+ async buildPeerFromDefinition(handlerSteps: HandlerStepDefinition[]): Promise<MockRTCPeer> {
42
47
  const { adminStream } = this.adminClient;
43
48
 
44
- const peerData = await this.adminClient.sendQuery<
45
- { createPeer: { peerId: string } },
46
- { peerId: string }
47
- >({
48
- query: gql`
49
- mutation CreatePeer($peerData: RTCHandlerData!) {
50
- createPeer(data: $peerData) {
51
- peerId
52
- }
53
- }
54
- `,
55
- variables: {
56
- peerData: {
57
- steps: handlerSteps.map(step =>
58
- BrowserPluggableAdmin.Serialization.serialize(step, adminStream)
59
- )
60
- }
61
- },
62
- transformResponse: ({ createPeer }) => createPeer
63
- });
49
+ const peerData = await this.adminClient.sendQuery(
50
+ this.requestBuilder.buildCreatePeerQuery(handlerSteps, adminStream)
51
+ );
64
52
 
65
53
  const { peerId } = peerData;
66
54
 
67
55
  return new MockRTCRemotePeer(peerId, this.adminClient);
68
56
  }
69
57
 
58
+ async addRuleFromDefinition(
59
+ matchers: MatcherDefinition[],
60
+ handlerSteps: HandlerStepDefinition[]
61
+ ) {
62
+ const { adminStream } = this.adminClient;
63
+
64
+ await this.adminClient.sendQuery(
65
+ this.requestBuilder.buildAddRuleQuery(matchers, handlerSteps, adminStream)
66
+ );
67
+ }
68
+
69
+ async setRulesFromDefinitions(rules: Array<MockRTCRuleDefinition>) {
70
+ const { adminStream } = this.adminClient;
71
+
72
+ await this.adminClient.sendQuery(
73
+ this.requestBuilder.buildSetRulesQuery(rules, adminStream)
74
+ );
75
+ }
76
+
70
77
  async start(): Promise<void> {
71
78
  await this.adminClient.start({
72
79
  webrtc: this.options
@@ -76,4 +83,19 @@ export class MockRTCClient implements MockRTC {
76
83
  async stop(): Promise<void> {
77
84
  await this.adminClient.stop();
78
85
  }
86
+
87
+ async on(event: MockRTCEvent, callback: any): Promise<void> {
88
+ const subscriptionRequest = this.requestBuilder.buildSubscriptionRequest(event);
89
+
90
+ if (!subscriptionRequest) {
91
+ // We just return an immediately promise if we don't recognize the event, which will quietly
92
+ // succeed but never call the corresponding callback (the same as the server and most event
93
+ // sources in the same kind of situation). This is what happens when the *client* doesn't
94
+ // recognize the event. Subscribe() below handles the unknown-to-server case.
95
+ console.warn(`Ignoring subscription for event unrecognized by MockRTC client: ${event}`);
96
+ return;
97
+ }
98
+
99
+ return this.adminClient.subscribe(subscriptionRequest, callback);
100
+ }
79
101
  }
@@ -6,6 +6,7 @@
6
6
  import { gql } from 'graphql-tag';
7
7
  import * as PluggableAdmin from 'mockttp/dist/pluggable-admin-api/pluggable-admin.browser';
8
8
 
9
+ import { MockRTCSessionDescription } from '../mockrtc';
9
10
  import {
10
11
  MockRTCPeer,
11
12
  MockRTCOfferParams,
@@ -83,7 +84,7 @@ export class MockRTCRemotePeer implements MockRTCPeer {
83
84
  }
84
85
 
85
86
  async answerOffer(
86
- offer: RTCSessionDescriptionInit,
87
+ offer: MockRTCSessionDescription,
87
88
  options?: AnswerOptions
88
89
  ): Promise<MockRTCAnswerParams> {
89
90
  return this.adminClient.sendQuery<
@@ -114,7 +115,7 @@ export class MockRTCRemotePeer implements MockRTCPeer {
114
115
  }
115
116
 
116
117
  async answerExternalOffer(
117
- offer: RTCSessionDescriptionInit,
118
+ offer: MockRTCSessionDescription,
118
119
  options?: AnswerOptions
119
120
  ): Promise<MockRTCExternalAnswerParams> {
120
121
  return this.adminClient.sendQuery<
@@ -211,10 +212,10 @@ class RemoteSessionApi implements MockRTCSession {
211
212
  public readonly sessionId: string
212
213
  ) {}
213
214
 
214
- createOffer(options?: OfferOptions): Promise<RTCSessionDescriptionInit> {
215
+ createOffer(options?: OfferOptions): Promise<MockRTCSessionDescription> {
215
216
  return this.adminClient.sendQuery<
216
217
  { createOffer: SessionData },
217
- RTCSessionDescriptionInit
218
+ MockRTCSessionDescription
218
219
  >({
219
220
  query: gql`
220
221
  mutation GetPeerRTCSessionOffer($peerId: ID!, $sessionId: ID!, $options: Raw) {
@@ -231,7 +232,7 @@ class RemoteSessionApi implements MockRTCSession {
231
232
  });
232
233
  }
233
234
 
234
- completeOffer(answer: RTCSessionDescriptionInit): Promise<void> {
235
+ completeOffer(answer: MockRTCSessionDescription): Promise<void> {
235
236
  return this.adminClient.sendQuery<void>({
236
237
  query: gql`
237
238
  mutation CompletePeerRTCOffer(
@@ -251,12 +252,12 @@ class RemoteSessionApi implements MockRTCSession {
251
252
  }
252
253
 
253
254
  answerOffer(
254
- offer: RTCSessionDescriptionInit,
255
+ offer: MockRTCSessionDescription,
255
256
  options?: AnswerOptions
256
- ): Promise<RTCSessionDescriptionInit> {
257
+ ): Promise<MockRTCSessionDescription> {
257
258
  return this.adminClient.sendQuery<
258
259
  { answerOffer: SessionData },
259
- RTCSessionDescriptionInit
260
+ MockRTCSessionDescription
260
261
  >({
261
262
  query: gql`
262
263
  mutation GetPeerRTCAnswer(
@@ -6,6 +6,7 @@
6
6
  import {
7
7
  type HandlerStepDefinition,
8
8
  PeerProxyStepDefinition,
9
+ CreateChannelStepDefinition,
9
10
  SendStepDefinition,
10
11
  DynamicProxyStepDefinition,
11
12
  WaitForChannelStepDefinition,
@@ -35,7 +36,7 @@ export class MockRTCHandlerBuilder<R> {
35
36
  *
36
37
  * @category Steps
37
38
  */
38
- sleep(duration: number): this {
39
+ sleep(duration: number): MockRTCHandlerBuilder<R> {
39
40
  this.handlerSteps.push(new WaitForDurationStepDefinition(duration));
40
41
  return this;
41
42
  }
@@ -45,7 +46,7 @@ export class MockRTCHandlerBuilder<R> {
45
46
  *
46
47
  * @category Steps
47
48
  */
48
- waitForChannel(channelLabel?: string): this {
49
+ waitForChannel(channelLabel?: string): MockRTCHandlerBuilder<R> {
49
50
  this.handlerSteps.push(new WaitForChannelStepDefinition(channelLabel));
50
51
  return this;
51
52
  }
@@ -55,7 +56,7 @@ export class MockRTCHandlerBuilder<R> {
55
56
  *
56
57
  * @category Steps
57
58
  */
58
- waitForTrack(): this {
59
+ waitForTrack(): MockRTCHandlerBuilder<R> {
59
60
  this.handlerSteps.push(new WaitForTrackStepDefinition());
60
61
  return this;
61
62
  }
@@ -68,7 +69,7 @@ export class MockRTCHandlerBuilder<R> {
68
69
  *
69
70
  * @category Steps
70
71
  */
71
- waitForNextMessage(): this {
72
+ waitForNextMessage(): MockRTCHandlerBuilder<R> {
72
73
  this.handlerSteps.push(new WaitForMessageStepDefinition());
73
74
  return this;
74
75
  }
@@ -80,7 +81,7 @@ export class MockRTCHandlerBuilder<R> {
80
81
  *
81
82
  * @category Steps
82
83
  */
83
- waitForNextMedia(): this {
84
+ waitForNextMedia(): MockRTCHandlerBuilder<R> {
84
85
  this.handlerSteps.push(new WaitForMediaStepDefinition());
85
86
  return this;
86
87
  }
@@ -91,13 +92,24 @@ export class MockRTCHandlerBuilder<R> {
91
92
  * This looks for new messages, ignoring any messages already consumed by
92
93
  * previous steps.
93
94
  *
94
- * @category Steps
95
+ * @category Steps
95
96
  */
96
- waitForNextMessageOnChannel(channelLabel: string): this {
97
+ waitForNextMessageOnChannel(channelLabel: string): MockRTCHandlerBuilder<R> {
97
98
  this.handlerSteps.push(new WaitForMessageStepDefinition(channelLabel));
98
99
  return this;
99
100
  }
100
101
 
102
+ /**
103
+ * Creates a new data channel with the given name, waiting until it opens
104
+ * before continuing.
105
+ *
106
+ * @category Steps
107
+ */
108
+ createDataChannel(channelLabel: string): MockRTCHandlerBuilder<R> {
109
+ this.handlerSteps.push(new CreateChannelStepDefinition(channelLabel));
110
+ return this;
111
+ }
112
+
101
113
  /**
102
114
  * Send a message or buffer on the connection's data channels.
103
115
  *
@@ -111,9 +123,9 @@ export class MockRTCHandlerBuilder<R> {
111
123
  *
112
124
  * @category Steps
113
125
  */
114
- send(message: string | Buffer): this;
115
- send(channel: string | undefined, message: string | Buffer): this;
116
- send(...args: [string | undefined, string | Buffer] | [string | Buffer]): this {
126
+ send(message: string | Buffer): MockRTCHandlerBuilder<R>;
127
+ send(channel: string | undefined, message: string | Buffer): MockRTCHandlerBuilder<R>;
128
+ send(...args: [string | undefined, string | Buffer] | [string | Buffer]): MockRTCHandlerBuilder<R> {
117
129
  if (args[1] !== undefined) {
118
130
  const [channel, message] = args as [string, string | Buffer];
119
131
  this.handlerSteps.push(new SendStepDefinition(channel, message));
@@ -5,6 +5,8 @@
5
5
 
6
6
  import * as PluggableAdmin from 'mockttp/dist/pluggable-admin-api/pluggable-admin.browser';
7
7
 
8
+ import { MockRTCSessionDescription } from '../mockrtc';
9
+
8
10
  export type Serializable = PluggableAdmin.Serialization.Serializable;
9
11
  export const { Serializable } = PluggableAdmin.Serialization;
10
12
  type ClientServerChannel = PluggableAdmin.Serialization.ClientServerChannel;
@@ -18,89 +20,138 @@ export class WaitForDurationStepDefinition extends Serializable implements Handl
18
20
  readonly type = 'wait-for-duration';
19
21
 
20
22
  constructor(
21
- protected durationMs: number
23
+ public readonly durationMs: number
22
24
  ) {
23
25
  super();
24
26
  }
25
27
 
28
+ explain() {
29
+ return `wait for ${this.durationMs}ms`;
30
+ }
31
+
26
32
  }
27
33
 
28
34
  export class WaitForChannelStepDefinition extends Serializable implements HandlerStepDefinition {
29
35
 
30
- readonly type = 'wait-for-channel';
36
+ readonly type = 'wait-for-rtc-data-channel';
31
37
 
32
38
  constructor(
33
- protected channelLabel?: string
39
+ public readonly channelLabel?: string
34
40
  ) {
35
41
  super();
36
42
  }
43
+
44
+ explain() {
45
+ return `wait for an RTC channel${this.channelLabel ? ` labelled '${this.channelLabel}'` : ''}`;
46
+ }
47
+
37
48
  }
38
49
 
39
50
  export class WaitForMessageStepDefinition extends Serializable implements HandlerStepDefinition {
40
51
 
41
- readonly type = 'wait-for-message';
52
+ readonly type = 'wait-for-rtc-message';
42
53
 
43
54
  constructor(
44
- protected channelLabel?: string
55
+ public readonly channelLabel?: string
45
56
  ) {
46
57
  super();
47
58
  }
48
59
 
60
+ explain() {
61
+ return `wait for an RTC message${this.channelLabel ? ` on channel '${this.channelLabel}'` : ''}`;
62
+ }
63
+
49
64
  }
50
65
 
51
66
  export class WaitForTrackStepDefinition extends Serializable implements HandlerStepDefinition {
52
67
 
53
- readonly type = 'wait-for-track';
68
+ readonly type = 'wait-for-rtc-track';
69
+
70
+ explain() {
71
+ return `wait for an RTC track`;
72
+ }
54
73
 
55
74
  }
56
75
 
57
76
  export class WaitForMediaStepDefinition extends Serializable implements HandlerStepDefinition {
58
77
 
59
- readonly type = 'wait-for-media';
78
+ readonly type = 'wait-for-rtc-media';
79
+
80
+ explain() {
81
+ return `wait for RTC media data`;
82
+ }
83
+
84
+ }
85
+
86
+ export class CreateChannelStepDefinition extends Serializable implements HandlerStepDefinition {
87
+
88
+ readonly type = 'create-rtc-data-channel';
89
+
90
+ constructor(
91
+ public readonly channelLabel: string
92
+ ) {
93
+ super();
94
+ }
95
+
96
+ explain() {
97
+ return `create an RTC data channel labelled '${this.channelLabel}'`;
98
+ }
60
99
 
61
100
  }
62
101
 
63
102
  export class SendStepDefinition extends Serializable implements HandlerStepDefinition {
64
103
 
65
- readonly type = 'send-message';
104
+ readonly type = 'send-rtc-data-message';
66
105
 
67
106
  constructor(
68
- protected channelLabel: string | undefined,
69
- protected message: string | Buffer
107
+ public readonly channelLabel: string | undefined,
108
+ public readonly message: string | Buffer
70
109
  ) {
71
110
  super();
72
111
  }
73
112
 
113
+ explain() {
114
+ return `send an RTC data message${this.channelLabel ? ` on channel '${this.channelLabel}'` : ''}`;
115
+ }
116
+
74
117
  }
75
118
 
76
119
  export class CloseStepDefinition extends Serializable implements HandlerStepDefinition {
77
120
 
78
- readonly type = 'close-connection';
121
+ readonly type = 'close-rtc-connection';
122
+
123
+ explain() {
124
+ return `close the RTC connection`;
125
+ }
79
126
 
80
127
  }
81
128
 
82
129
  export class EchoStepDefinition extends Serializable implements HandlerStepDefinition {
83
130
 
84
- readonly type = 'echo-channels';
131
+ readonly type = 'echo-rtc';
132
+
133
+ explain() {
134
+ return `echo all RTC media & data`;
135
+ }
85
136
 
86
137
  }
87
138
 
88
139
  export class PeerProxyStepDefinition extends Serializable implements HandlerStepDefinition {
89
140
 
90
- readonly type = 'peer-proxy';
141
+ readonly type = 'rtc-peer-proxy';
91
142
 
92
- protected getAnswer: (offer: RTCSessionDescriptionInit) => Promise<RTCSessionDescriptionInit>;
143
+ protected getAnswer: (offer: MockRTCSessionDescription) => Promise<RTCSessionDescriptionInit>;
93
144
 
94
145
  constructor(
95
146
  connectionTarget:
96
147
  | RTCPeerConnection
97
- | ((offer: RTCSessionDescriptionInit) => Promise<RTCSessionDescriptionInit>)
148
+ | ((offer: MockRTCSessionDescription) => Promise<RTCSessionDescriptionInit>)
98
149
  ) {
99
150
  super();
100
151
  if (connectionTarget instanceof Function) {
101
152
  this.getAnswer = connectionTarget;
102
153
  } else {
103
- this.getAnswer = async (offer: RTCSessionDescriptionInit) => {
154
+ this.getAnswer = async (offer: MockRTCSessionDescription) => {
104
155
  await connectionTarget.setRemoteDescription(offer);
105
156
  const answer = await connectionTarget.createAnswer();
106
157
  await connectionTarget.setLocalDescription(answer);
@@ -109,9 +160,13 @@ export class PeerProxyStepDefinition extends Serializable implements HandlerStep
109
160
  }
110
161
  }
111
162
 
163
+ explain() {
164
+ return `proxy the RTC connection to the configured peer`;
165
+ }
166
+
112
167
  serialize(channel: ClientServerChannel): {} {
113
168
  channel.onRequest<
114
- { offer: RTCSessionDescriptionInit },
169
+ { offer: MockRTCSessionDescription },
115
170
  { answer: RTCSessionDescriptionInit }
116
171
  >(async (msg) => {
117
172
  return { answer: await this.getAnswer(msg.offer) };
@@ -124,19 +179,24 @@ export class PeerProxyStepDefinition extends Serializable implements HandlerStep
124
179
 
125
180
  export class DynamicProxyStepDefinition extends Serializable implements HandlerStepDefinition {
126
181
 
127
- readonly type = 'dynamic-proxy';
182
+ readonly type = 'rtc-dynamic-proxy';
183
+
184
+ explain() {
185
+ return `proxy the RTC connection to a remote peer`;
186
+ }
128
187
 
129
188
  }
130
189
 
131
190
  export const StepDefinitionLookup = {
132
191
  'wait-for-duration': WaitForDurationStepDefinition,
133
- 'wait-for-channel': WaitForChannelStepDefinition,
134
- 'wait-for-track': WaitForTrackStepDefinition,
135
- 'wait-for-media': WaitForMediaStepDefinition,
136
- 'wait-for-message': WaitForMessageStepDefinition,
137
- 'send-message': SendStepDefinition,
138
- 'close-connection': CloseStepDefinition,
139
- 'echo-channels': EchoStepDefinition,
140
- 'peer-proxy': PeerProxyStepDefinition,
141
- 'dynamic-proxy': DynamicProxyStepDefinition
192
+ 'wait-for-rtc-data-channel': WaitForChannelStepDefinition,
193
+ 'wait-for-rtc-track': WaitForTrackStepDefinition,
194
+ 'wait-for-rtc-media': WaitForMediaStepDefinition,
195
+ 'wait-for-rtc-message': WaitForMessageStepDefinition,
196
+ 'create-rtc-data-channel': CreateChannelStepDefinition,
197
+ 'send-rtc-data-message': SendStepDefinition,
198
+ 'close-rtc-connection': CloseStepDefinition,
199
+ 'echo-rtc': EchoStepDefinition,
200
+ 'rtc-peer-proxy': PeerProxyStepDefinition,
201
+ 'rtc-dynamic-proxy': DynamicProxyStepDefinition
142
202
  };
@@ -5,6 +5,7 @@
5
5
 
6
6
  import { PluggableAdmin } from 'mockttp';
7
7
 
8
+ import { MockRTCSessionDescription } from '../mockrtc';
8
9
  import type { DataChannelStream } from '../webrtc/datachannel-stream';
9
10
  import type { MediaTrackStream } from '../webrtc/mediatrack-stream';
10
11
  import type { MockRTCConnection } from '../webrtc/mockrtc-connection';
@@ -16,6 +17,7 @@ import {
16
17
  EchoStepDefinition,
17
18
  HandlerStepDefinition,
18
19
  PeerProxyStepDefinition,
20
+ CreateChannelStepDefinition,
19
21
  SendStepDefinition,
20
22
  WaitForChannelStepDefinition,
21
23
  WaitForDurationStepDefinition,
@@ -69,7 +71,7 @@ export class WaitForMessageStep extends WaitForMessageStepDefinition {
69
71
  async handle(connection: MockRTCConnection): Promise<void> {
70
72
  return new Promise<void>((resolve) => {
71
73
  const messageReceived = () => {
72
- connection.removeListener('channel-open', listenForMessage);
74
+ connection.removeListener('channel-created', listenForMessage);
73
75
  connection.channels.forEach((channel) => {
74
76
  channel.removeListener('data', messageReceived);
75
77
  channel.pause();
@@ -84,7 +86,7 @@ export class WaitForMessageStep extends WaitForMessageStepDefinition {
84
86
  }
85
87
  }
86
88
 
87
- connection.on('channel-open', listenForMessage);
89
+ connection.on('channel-created', listenForMessage);
88
90
  connection.channels.forEach(listenForMessage);
89
91
  });
90
92
  }
@@ -107,7 +109,7 @@ export class WaitForMediaStep extends WaitForMediaStepDefinition {
107
109
  async handle(connection: MockRTCConnection): Promise<void> {
108
110
  return new Promise<void>((resolve) => {
109
111
  const messageReceived = () => {
110
- connection.removeListener('track-open', listenForData);
112
+ connection.removeListener('track-created', listenForData);
111
113
  connection.mediaTracks.forEach((track) => {
112
114
  track.removeListener('data', messageReceived);
113
115
  track.pause();
@@ -120,13 +122,24 @@ export class WaitForMediaStep extends WaitForMediaStepDefinition {
120
122
  track.once('data', messageReceived);
121
123
  }
122
124
 
123
- connection.on('track-open', listenForData);
125
+ connection.on('track-created', listenForData);
124
126
  connection.mediaTracks.forEach(listenForData);
125
127
  });
126
128
  }
127
129
 
128
130
  }
129
131
 
132
+ export class CreateChannelStep extends CreateChannelStepDefinition {
133
+
134
+ async handle(conn: MockRTCConnection): Promise<void> {
135
+ const channel = conn.createDataChannel(this.channelLabel);
136
+ return new Promise<void>((resolve) =>
137
+ channel.once('channel-open', resolve)
138
+ );
139
+ }
140
+
141
+ }
142
+
130
143
  export class SendStep extends SendStepDefinition {
131
144
 
132
145
  private matchesChannel(channel: DataChannelStream) {
@@ -165,8 +178,8 @@ export class EchoStep extends EchoStepDefinition {
165
178
  stream.pipe(stream);
166
179
  };
167
180
 
168
- connection.on('channel-open', echoContent);
169
- connection.on('track-open', echoContent);
181
+ connection.on('channel-created', echoContent);
182
+ connection.on('track-created', echoContent);
170
183
  connection.channels.forEach(echoContent);
171
184
  connection.mediaTracks.forEach(echoContent);
172
185
 
@@ -190,7 +203,7 @@ export class PeerProxyStep extends PeerProxyStepDefinition {
190
203
  );
191
204
  externalConn.setRemoteDescription(await this.getAnswer(externalOffer));
192
205
 
193
- connection.proxyTrafficTo(externalConn);
206
+ await connection.proxyTrafficTo(externalConn);
194
207
 
195
208
  // This step keeps running indefinitely, until the connection closes
196
209
  return new Promise<void>((resolve) => connection.on('connection-closed', resolve));
@@ -198,7 +211,7 @@ export class PeerProxyStep extends PeerProxyStepDefinition {
198
211
 
199
212
  serialize(channel: ClientServerChannel): {} {
200
213
  channel.onRequest<
201
- { offer: RTCSessionDescriptionInit },
214
+ { offer: MockRTCSessionDescription },
202
215
  { answer: RTCSessionDescriptionInit }
203
216
  >(async (msg) => {
204
217
  return { answer: await this.getAnswer(msg.offer) };
@@ -208,10 +221,10 @@ export class PeerProxyStep extends PeerProxyStepDefinition {
208
221
  }
209
222
 
210
223
  static deserialize(_data: {}, channel: ClientServerChannel): PeerProxyStep {
211
- return new PeerProxyStep(async (offer: RTCSessionDescriptionInit) => {
224
+ return new PeerProxyStep(async (offer: MockRTCSessionDescription) => {
212
225
  const response = await channel.request<
213
- { offer: RTCSessionDescriptionInit },
214
- { answer: RTCSessionDescriptionInit }
226
+ { offer: MockRTCSessionDescription },
227
+ { answer: MockRTCSessionDescription }
215
228
  >({ offer });
216
229
  return response.answer;
217
230
  });
@@ -242,13 +255,14 @@ export class DynamicProxyStep extends DynamicProxyStepDefinition {
242
255
 
243
256
  export const StepLookup: typeof StepDefinitionLookup = {
244
257
  'wait-for-duration': WaitForDurationStep,
245
- 'wait-for-channel': WaitForChannelStep,
246
- 'wait-for-track': WaitForTrackStep,
247
- 'wait-for-media': WaitForMediaStep,
248
- 'wait-for-message': WaitForMessageStep,
249
- 'send-message': SendStep,
250
- 'close-connection': CloseStep,
251
- 'echo-channels': EchoStep,
252
- 'peer-proxy': PeerProxyStep,
253
- 'dynamic-proxy': DynamicProxyStep
258
+ 'wait-for-rtc-data-channel': WaitForChannelStep,
259
+ 'wait-for-rtc-track': WaitForTrackStep,
260
+ 'wait-for-rtc-media': WaitForMediaStep,
261
+ 'wait-for-rtc-message': WaitForMessageStep,
262
+ 'create-rtc-data-channel': CreateChannelStep,
263
+ 'send-rtc-data-message': SendStep,
264
+ 'close-rtc-connection': CloseStep,
265
+ 'echo-rtc': EchoStep,
266
+ 'rtc-peer-proxy': PeerProxyStep,
267
+ 'rtc-dynamic-proxy': DynamicProxyStep
254
268
  };
@@ -9,6 +9,11 @@ import type {
9
9
  } from "./mockrtc";
10
10
  import { MockRTCClient, MockRTCClientOptions } from "./client/mockrtc-client";
11
11
 
12
+ // Export the required structures to remotely build and send rules to the admin API:
13
+ export * as HandlerStepDefinitions from "./handling/handler-step-definitions";
14
+ export * as MatcherDefinitions from "./matching/matcher-definitions";
15
+ export { MockRTCAdminRequestBuilder } from "./client/mockrtc-admin-request-builder";
16
+
12
17
  export type {
13
18
  MockRTC,
14
19
  MockRTCOptions