mockrtc 0.2.0 → 0.3.1
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/.github/workflows/ci.yml +2 -2
- package/dist/client/mockrtc-admin-request-builder.d.ts +7 -1
- package/dist/client/mockrtc-admin-request-builder.js +30 -0
- package/dist/client/mockrtc-admin-request-builder.js.map +1 -1
- package/dist/client/mockrtc-client.d.ts +8 -4
- package/dist/client/mockrtc-client.js +21 -9
- package/dist/client/mockrtc-client.js.map +1 -1
- package/dist/handling/handler-builder.d.ts +16 -9
- package/dist/handling/handler-builder.js +11 -1
- package/dist/handling/handler-builder.js.map +1 -1
- package/dist/handling/handler-step-definitions.d.ts +40 -23
- package/dist/handling/handler-step-definitions.js +61 -19
- package/dist/handling/handler-step-definitions.js.map +1 -1
- package/dist/handling/handler-steps.d.ts +11 -1
- package/dist/handling/handler-steps.js +33 -16
- package/dist/handling/handler-steps.js.map +1 -1
- package/dist/main-browser.d.ts +1 -0
- package/dist/main-browser.js +2 -1
- package/dist/main-browser.js.map +1 -1
- package/dist/main.d.ts +5 -3
- package/dist/main.js +2 -1
- package/dist/main.js.map +1 -1
- package/dist/matching/matcher-definitions.d.ts +51 -0
- package/dist/matching/matcher-definitions.js +94 -0
- package/dist/matching/matcher-definitions.js.map +1 -0
- package/dist/matching/matchers.d.ts +27 -0
- package/dist/matching/matchers.js +87 -0
- package/dist/matching/matchers.js.map +1 -0
- package/dist/mockrtc-base.d.ts +16 -0
- package/dist/mockrtc-base.js +19 -0
- package/dist/mockrtc-base.js.map +1 -0
- package/dist/mockrtc-peer.d.ts +9 -2
- package/dist/mockrtc.d.ts +62 -0
- package/dist/mockrtc.js.map +1 -1
- package/dist/rule-builder.d.ts +86 -0
- package/dist/rule-builder.js +113 -0
- package/dist/rule-builder.js.map +1 -0
- package/dist/server/mockrtc-admin-plugin.js +18 -1
- package/dist/server/mockrtc-admin-plugin.js.map +1 -1
- package/dist/server/mockrtc-server-peer.d.ts +1 -1
- package/dist/server/mockrtc-server-peer.js +19 -7
- package/dist/server/mockrtc-server-peer.js.map +1 -1
- package/dist/server/mockrtc-server.d.ts +12 -5
- package/dist/server/mockrtc-server.js +53 -18
- package/dist/server/mockrtc-server.js.map +1 -1
- package/dist/webrtc/datachannel-stream.d.ts +2 -0
- package/dist/webrtc/datachannel-stream.js +15 -1
- package/dist/webrtc/datachannel-stream.js.map +1 -1
- package/dist/webrtc/mediatrack-stream.d.ts +2 -0
- package/dist/webrtc/mediatrack-stream.js +15 -1
- package/dist/webrtc/mediatrack-stream.js.map +1 -1
- package/dist/webrtc/mockrtc-connection.js +1 -1
- package/dist/webrtc/mockrtc-connection.js.map +1 -1
- package/dist/webrtc/rtc-connection.d.ts +6 -2
- package/dist/webrtc/rtc-connection.js +21 -21
- package/dist/webrtc/rtc-connection.js.map +1 -1
- package/dist/webrtc-hooks.js +8 -2
- package/dist/webrtc-hooks.js.map +1 -1
- package/package.json +2 -2
- package/src/client/mockrtc-admin-request-builder.ts +49 -1
- package/src/client/mockrtc-client.ts +28 -10
- package/src/handling/handler-builder.ts +22 -10
- package/src/handling/handler-step-definitions.ts +81 -23
- package/src/handling/handler-steps.ts +42 -15
- package/src/main-browser.ts +1 -0
- package/src/main.ts +5 -1
- package/src/matching/matcher-definitions.ts +109 -0
- package/src/matching/matchers.ts +118 -0
- package/src/mockrtc-base.ts +49 -0
- package/src/mockrtc-peer.ts +9 -2
- package/src/mockrtc.ts +72 -0
- package/src/rule-builder.ts +142 -0
- package/src/server/mockrtc-admin-plugin.ts +41 -3
- package/src/server/mockrtc-server-peer.ts +28 -18
- package/src/server/mockrtc-server.ts +71 -15
- package/src/webrtc/datachannel-stream.ts +15 -1
- package/src/webrtc/mediatrack-stream.ts +15 -1
- package/src/webrtc/mockrtc-connection.ts +1 -1
- package/src/webrtc/rtc-connection.ts +37 -20
- package/src/webrtc-hooks.ts +8 -2
- package/test/integration/events.spec.ts +3 -1
- package/test/integration/matching.spec.ts +189 -0
- package/test/integration/proxy.spec.ts +4 -2
- package/test/integration/send-steps.spec.ts +51 -0
|
@@ -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):
|
|
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):
|
|
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():
|
|
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():
|
|
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():
|
|
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
|
-
|
|
95
|
+
* @category Steps
|
|
95
96
|
*/
|
|
96
|
-
waitForNextMessageOnChannel(channelLabel: string):
|
|
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):
|
|
115
|
-
send(channel: string | undefined, message: string | Buffer):
|
|
116
|
-
send(...args: [string | undefined, string | Buffer] | [string | Buffer]):
|
|
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));
|
|
@@ -20,76 +20,125 @@ export class WaitForDurationStepDefinition extends Serializable implements Handl
|
|
|
20
20
|
readonly type = 'wait-for-duration';
|
|
21
21
|
|
|
22
22
|
constructor(
|
|
23
|
-
|
|
23
|
+
public readonly durationMs: number
|
|
24
24
|
) {
|
|
25
25
|
super();
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
+
explain() {
|
|
29
|
+
return `wait for ${this.durationMs}ms`;
|
|
30
|
+
}
|
|
31
|
+
|
|
28
32
|
}
|
|
29
33
|
|
|
30
34
|
export class WaitForChannelStepDefinition extends Serializable implements HandlerStepDefinition {
|
|
31
35
|
|
|
32
|
-
readonly type = 'wait-for-channel';
|
|
36
|
+
readonly type = 'wait-for-rtc-data-channel';
|
|
33
37
|
|
|
34
38
|
constructor(
|
|
35
|
-
|
|
39
|
+
public readonly channelLabel?: string
|
|
36
40
|
) {
|
|
37
41
|
super();
|
|
38
42
|
}
|
|
43
|
+
|
|
44
|
+
explain() {
|
|
45
|
+
return `wait for an RTC channel${this.channelLabel ? ` labelled '${this.channelLabel}'` : ''}`;
|
|
46
|
+
}
|
|
47
|
+
|
|
39
48
|
}
|
|
40
49
|
|
|
41
50
|
export class WaitForMessageStepDefinition extends Serializable implements HandlerStepDefinition {
|
|
42
51
|
|
|
43
|
-
readonly type = 'wait-for-message';
|
|
52
|
+
readonly type = 'wait-for-rtc-message';
|
|
44
53
|
|
|
45
54
|
constructor(
|
|
46
|
-
|
|
55
|
+
public readonly channelLabel?: string
|
|
47
56
|
) {
|
|
48
57
|
super();
|
|
49
58
|
}
|
|
50
59
|
|
|
60
|
+
explain() {
|
|
61
|
+
return `wait for an RTC message${this.channelLabel ? ` on channel '${this.channelLabel}'` : ''}`;
|
|
62
|
+
}
|
|
63
|
+
|
|
51
64
|
}
|
|
52
65
|
|
|
53
66
|
export class WaitForTrackStepDefinition extends Serializable implements HandlerStepDefinition {
|
|
54
67
|
|
|
55
|
-
readonly type = 'wait-for-track';
|
|
68
|
+
readonly type = 'wait-for-rtc-track';
|
|
69
|
+
|
|
70
|
+
explain() {
|
|
71
|
+
return `wait for an RTC track`;
|
|
72
|
+
}
|
|
56
73
|
|
|
57
74
|
}
|
|
58
75
|
|
|
59
76
|
export class WaitForMediaStepDefinition extends Serializable implements HandlerStepDefinition {
|
|
60
77
|
|
|
61
|
-
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
|
+
}
|
|
62
99
|
|
|
63
100
|
}
|
|
64
101
|
|
|
65
102
|
export class SendStepDefinition extends Serializable implements HandlerStepDefinition {
|
|
66
103
|
|
|
67
|
-
readonly type = 'send-message';
|
|
104
|
+
readonly type = 'send-rtc-data-message';
|
|
68
105
|
|
|
69
106
|
constructor(
|
|
70
|
-
|
|
71
|
-
|
|
107
|
+
public readonly channelLabel: string | undefined,
|
|
108
|
+
public readonly message: string | Buffer
|
|
72
109
|
) {
|
|
73
110
|
super();
|
|
74
111
|
}
|
|
75
112
|
|
|
113
|
+
explain() {
|
|
114
|
+
return `send an RTC data message${this.channelLabel ? ` on channel '${this.channelLabel}'` : ''}`;
|
|
115
|
+
}
|
|
116
|
+
|
|
76
117
|
}
|
|
77
118
|
|
|
78
119
|
export class CloseStepDefinition extends Serializable implements HandlerStepDefinition {
|
|
79
120
|
|
|
80
|
-
readonly type = 'close-connection';
|
|
121
|
+
readonly type = 'close-rtc-connection';
|
|
122
|
+
|
|
123
|
+
explain() {
|
|
124
|
+
return `close the RTC connection`;
|
|
125
|
+
}
|
|
81
126
|
|
|
82
127
|
}
|
|
83
128
|
|
|
84
129
|
export class EchoStepDefinition extends Serializable implements HandlerStepDefinition {
|
|
85
130
|
|
|
86
|
-
readonly type = 'echo-
|
|
131
|
+
readonly type = 'echo-rtc';
|
|
132
|
+
|
|
133
|
+
explain() {
|
|
134
|
+
return `echo all RTC media & data`;
|
|
135
|
+
}
|
|
87
136
|
|
|
88
137
|
}
|
|
89
138
|
|
|
90
139
|
export class PeerProxyStepDefinition extends Serializable implements HandlerStepDefinition {
|
|
91
140
|
|
|
92
|
-
readonly type = 'peer-proxy';
|
|
141
|
+
readonly type = 'rtc-peer-proxy';
|
|
93
142
|
|
|
94
143
|
protected getAnswer: (offer: MockRTCSessionDescription) => Promise<RTCSessionDescriptionInit>;
|
|
95
144
|
|
|
@@ -111,6 +160,10 @@ export class PeerProxyStepDefinition extends Serializable implements HandlerStep
|
|
|
111
160
|
}
|
|
112
161
|
}
|
|
113
162
|
|
|
163
|
+
explain() {
|
|
164
|
+
return `proxy the RTC connection to the configured peer`;
|
|
165
|
+
}
|
|
166
|
+
|
|
114
167
|
serialize(channel: ClientServerChannel): {} {
|
|
115
168
|
channel.onRequest<
|
|
116
169
|
{ offer: MockRTCSessionDescription },
|
|
@@ -126,19 +179,24 @@ export class PeerProxyStepDefinition extends Serializable implements HandlerStep
|
|
|
126
179
|
|
|
127
180
|
export class DynamicProxyStepDefinition extends Serializable implements HandlerStepDefinition {
|
|
128
181
|
|
|
129
|
-
readonly type = 'dynamic-proxy';
|
|
182
|
+
readonly type = 'rtc-dynamic-proxy';
|
|
183
|
+
|
|
184
|
+
explain() {
|
|
185
|
+
return `proxy the RTC connection to a remote peer`;
|
|
186
|
+
}
|
|
130
187
|
|
|
131
188
|
}
|
|
132
189
|
|
|
133
190
|
export const StepDefinitionLookup = {
|
|
134
191
|
'wait-for-duration': WaitForDurationStepDefinition,
|
|
135
|
-
'wait-for-channel': WaitForChannelStepDefinition,
|
|
136
|
-
'wait-for-track': WaitForTrackStepDefinition,
|
|
137
|
-
'wait-for-media': WaitForMediaStepDefinition,
|
|
138
|
-
'wait-for-message': WaitForMessageStepDefinition,
|
|
139
|
-
'
|
|
140
|
-
'
|
|
141
|
-
'
|
|
142
|
-
'
|
|
143
|
-
'
|
|
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
|
|
144
202
|
};
|
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
EchoStepDefinition,
|
|
18
18
|
HandlerStepDefinition,
|
|
19
19
|
PeerProxyStepDefinition,
|
|
20
|
+
CreateChannelStepDefinition,
|
|
20
21
|
SendStepDefinition,
|
|
21
22
|
WaitForChannelStepDefinition,
|
|
22
23
|
WaitForDurationStepDefinition,
|
|
@@ -70,7 +71,7 @@ export class WaitForMessageStep extends WaitForMessageStepDefinition {
|
|
|
70
71
|
async handle(connection: MockRTCConnection): Promise<void> {
|
|
71
72
|
return new Promise<void>((resolve) => {
|
|
72
73
|
const messageReceived = () => {
|
|
73
|
-
connection.removeListener('channel-
|
|
74
|
+
connection.removeListener('channel-created', listenForMessage);
|
|
74
75
|
connection.channels.forEach((channel) => {
|
|
75
76
|
channel.removeListener('data', messageReceived);
|
|
76
77
|
channel.pause();
|
|
@@ -85,7 +86,7 @@ export class WaitForMessageStep extends WaitForMessageStepDefinition {
|
|
|
85
86
|
}
|
|
86
87
|
}
|
|
87
88
|
|
|
88
|
-
connection.on('channel-
|
|
89
|
+
connection.on('channel-created', listenForMessage);
|
|
89
90
|
connection.channels.forEach(listenForMessage);
|
|
90
91
|
});
|
|
91
92
|
}
|
|
@@ -108,7 +109,7 @@ export class WaitForMediaStep extends WaitForMediaStepDefinition {
|
|
|
108
109
|
async handle(connection: MockRTCConnection): Promise<void> {
|
|
109
110
|
return new Promise<void>((resolve) => {
|
|
110
111
|
const messageReceived = () => {
|
|
111
|
-
connection.removeListener('track-
|
|
112
|
+
connection.removeListener('track-created', listenForData);
|
|
112
113
|
connection.mediaTracks.forEach((track) => {
|
|
113
114
|
track.removeListener('data', messageReceived);
|
|
114
115
|
track.pause();
|
|
@@ -121,13 +122,24 @@ export class WaitForMediaStep extends WaitForMediaStepDefinition {
|
|
|
121
122
|
track.once('data', messageReceived);
|
|
122
123
|
}
|
|
123
124
|
|
|
124
|
-
connection.on('track-
|
|
125
|
+
connection.on('track-created', listenForData);
|
|
125
126
|
connection.mediaTracks.forEach(listenForData);
|
|
126
127
|
});
|
|
127
128
|
}
|
|
128
129
|
|
|
129
130
|
}
|
|
130
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
|
+
|
|
131
143
|
export class SendStep extends SendStepDefinition {
|
|
132
144
|
|
|
133
145
|
private matchesChannel(channel: DataChannelStream) {
|
|
@@ -149,6 +161,20 @@ export class SendStep extends SendStepDefinition {
|
|
|
149
161
|
);
|
|
150
162
|
}
|
|
151
163
|
|
|
164
|
+
static deserialize(data: {
|
|
165
|
+
channelLabel: string | undefined,
|
|
166
|
+
message: string | { type: 'Buffer', data: number[] }
|
|
167
|
+
}): SendStep {
|
|
168
|
+
return new SendStep(
|
|
169
|
+
data.channelLabel,
|
|
170
|
+
typeof data.message === 'string'
|
|
171
|
+
? data.message
|
|
172
|
+
// Buffers are serialized very roughly, so here we
|
|
173
|
+
// turn them back into real Buffer instances:
|
|
174
|
+
: Buffer.from(data.message.data)
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
|
|
152
178
|
}
|
|
153
179
|
|
|
154
180
|
export class CloseStep extends CloseStepDefinition {
|
|
@@ -166,8 +192,8 @@ export class EchoStep extends EchoStepDefinition {
|
|
|
166
192
|
stream.pipe(stream);
|
|
167
193
|
};
|
|
168
194
|
|
|
169
|
-
connection.on('channel-
|
|
170
|
-
connection.on('track-
|
|
195
|
+
connection.on('channel-created', echoContent);
|
|
196
|
+
connection.on('track-created', echoContent);
|
|
171
197
|
connection.channels.forEach(echoContent);
|
|
172
198
|
connection.mediaTracks.forEach(echoContent);
|
|
173
199
|
|
|
@@ -243,13 +269,14 @@ export class DynamicProxyStep extends DynamicProxyStepDefinition {
|
|
|
243
269
|
|
|
244
270
|
export const StepLookup: typeof StepDefinitionLookup = {
|
|
245
271
|
'wait-for-duration': WaitForDurationStep,
|
|
246
|
-
'wait-for-channel': WaitForChannelStep,
|
|
247
|
-
'wait-for-track': WaitForTrackStep,
|
|
248
|
-
'wait-for-media': WaitForMediaStep,
|
|
249
|
-
'wait-for-message': WaitForMessageStep,
|
|
250
|
-
'
|
|
251
|
-
'
|
|
252
|
-
'
|
|
253
|
-
'
|
|
254
|
-
'
|
|
272
|
+
'wait-for-rtc-data-channel': WaitForChannelStep,
|
|
273
|
+
'wait-for-rtc-track': WaitForTrackStep,
|
|
274
|
+
'wait-for-rtc-media': WaitForMediaStep,
|
|
275
|
+
'wait-for-rtc-message': WaitForMessageStep,
|
|
276
|
+
'create-rtc-data-channel': CreateChannelStep,
|
|
277
|
+
'send-rtc-data-message': SendStep,
|
|
278
|
+
'close-rtc-connection': CloseStep,
|
|
279
|
+
'echo-rtc': EchoStep,
|
|
280
|
+
'rtc-peer-proxy': PeerProxyStep,
|
|
281
|
+
'rtc-dynamic-proxy': DynamicProxyStep
|
|
255
282
|
};
|
package/src/main-browser.ts
CHANGED
|
@@ -11,6 +11,7 @@ import { MockRTCClient, MockRTCClientOptions } from "./client/mockrtc-client";
|
|
|
11
11
|
|
|
12
12
|
// Export the required structures to remotely build and send rules to the admin API:
|
|
13
13
|
export * as HandlerStepDefinitions from "./handling/handler-step-definitions";
|
|
14
|
+
export * as MatcherDefinitions from "./matching/matcher-definitions";
|
|
14
15
|
export { MockRTCAdminRequestBuilder } from "./client/mockrtc-admin-request-builder";
|
|
15
16
|
|
|
16
17
|
export type {
|
package/src/main.ts
CHANGED
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
MockRTCPeerBuilder,
|
|
10
10
|
MockRTCEvent,
|
|
11
11
|
MockRTCEventData,
|
|
12
|
+
MockRTCRuleDefinition,
|
|
12
13
|
MockRTCSessionDescription,
|
|
13
14
|
SelectedRTCCandidate,
|
|
14
15
|
TimingEvents
|
|
@@ -22,16 +23,18 @@ import { MockRTCClient, MockRTCClientOptions } from "./client/mockrtc-client";
|
|
|
22
23
|
|
|
23
24
|
// Export the required structures to remotely build and send rules to the admin API:
|
|
24
25
|
export * as HandlerStepDefinitions from "./handling/handler-step-definitions";
|
|
26
|
+
export * as MatcherDefinitions from "./matching/matcher-definitions";
|
|
25
27
|
export { MockRTCAdminRequestBuilder } from "./client/mockrtc-admin-request-builder";
|
|
26
28
|
|
|
27
29
|
// Re-export lots of types are used in various APIs (mostly to make TypeDoc happy):
|
|
28
30
|
export type { HandlerStep } from "./handling/handler-steps";
|
|
29
31
|
export type { MockRTCHandlerBuilder } from "./handling/handler-builder";
|
|
32
|
+
export type { MockRTCRuleBuilder, RuleHandlerBuilder } from "./rule-builder";
|
|
30
33
|
|
|
31
34
|
export type { MockRTCServerPeer } from "./server/mockrtc-server-peer";
|
|
32
35
|
export type { SessionData } from "./server/mockrtc-admin-plugin";
|
|
33
36
|
|
|
34
|
-
export type { RTCConnection } from "./webrtc/rtc-connection";
|
|
37
|
+
export type { RTCConnection, ParsedSDP } from "./webrtc/rtc-connection";
|
|
35
38
|
export type { MockRTCConnection } from "./webrtc/mockrtc-connection";
|
|
36
39
|
export type { DataChannelStream } from "./webrtc/datachannel-stream";
|
|
37
40
|
export type { MediaTrackStream } from "./webrtc/mediatrack-stream";
|
|
@@ -46,6 +49,7 @@ export type {
|
|
|
46
49
|
MockRTCAdminServer,
|
|
47
50
|
MockRTCEvent,
|
|
48
51
|
MockRTCEventData,
|
|
52
|
+
MockRTCRuleDefinition,
|
|
49
53
|
MockRTCSessionDescription,
|
|
50
54
|
SelectedRTCCandidate,
|
|
51
55
|
TimingEvents
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* SPDX-FileCopyrightText: 2022 Tim Perry <tim@httptoolkit.tech>
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import * as PluggableAdmin from 'mockttp/dist/pluggable-admin-api/pluggable-admin.browser';
|
|
7
|
+
|
|
8
|
+
export type Serializable = PluggableAdmin.Serialization.Serializable;
|
|
9
|
+
export const { Serializable } = PluggableAdmin.Serialization;
|
|
10
|
+
|
|
11
|
+
export interface MatcherDefinition extends Serializable {
|
|
12
|
+
readonly type: keyof typeof MatcherDefinitionLookup;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export class HasDataChannelMatcherDefinition extends Serializable implements MatcherDefinition {
|
|
16
|
+
readonly type = 'has-rtc-data-channel';
|
|
17
|
+
|
|
18
|
+
explain() {
|
|
19
|
+
return `with a data channel`;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export class HasVideoTrackMatcherDefinition extends Serializable implements MatcherDefinition {
|
|
24
|
+
readonly type = 'has-rtc-video-track';
|
|
25
|
+
|
|
26
|
+
explain() {
|
|
27
|
+
return `with a video track`;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export class HasAudioTrackMatcherDefinition extends Serializable implements MatcherDefinition {
|
|
32
|
+
readonly type = 'has-rtc-audio-track';
|
|
33
|
+
|
|
34
|
+
explain() {
|
|
35
|
+
return `with an audio track`;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export class HasMediaTrackMatcherDefinition extends Serializable implements MatcherDefinition {
|
|
40
|
+
readonly type = 'has-rtc-media-track';
|
|
41
|
+
|
|
42
|
+
explain() {
|
|
43
|
+
return `with any media track`;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export class HostnameMatcherDefinition extends Serializable implements MatcherDefinition {
|
|
48
|
+
|
|
49
|
+
readonly type = 'rtc-page-hostname';
|
|
50
|
+
|
|
51
|
+
constructor(
|
|
52
|
+
public readonly hostname: string
|
|
53
|
+
) {
|
|
54
|
+
super();
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
explain() {
|
|
58
|
+
return `from a page on ${this.hostname}`;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export class UrlRegexMatcherDefinition extends Serializable implements MatcherDefinition {
|
|
64
|
+
|
|
65
|
+
readonly type = 'rtc-page-regex';
|
|
66
|
+
|
|
67
|
+
readonly regexSource: string;
|
|
68
|
+
readonly regexFlags: string;
|
|
69
|
+
|
|
70
|
+
constructor(regex: RegExp) {
|
|
71
|
+
super();
|
|
72
|
+
this.regexSource = regex.source;
|
|
73
|
+
this.regexFlags = regex.flags;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
explain() {
|
|
77
|
+
return `from a page with URL matching /${this.regexSource}/${this.regexFlags}`;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export class UserAgentRegexMatcherDefinition extends Serializable implements MatcherDefinition {
|
|
83
|
+
|
|
84
|
+
readonly type = 'rtc-user-agent-regex';
|
|
85
|
+
|
|
86
|
+
readonly regexSource: string;
|
|
87
|
+
readonly regexFlags: string;
|
|
88
|
+
|
|
89
|
+
constructor(regex: RegExp) {
|
|
90
|
+
super();
|
|
91
|
+
this.regexSource = regex.source;
|
|
92
|
+
this.regexFlags = regex.flags;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
explain() {
|
|
96
|
+
return `from a user agent matching /${this.regexSource}/${this.regexFlags}`;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export const MatcherDefinitionLookup = {
|
|
102
|
+
'has-rtc-data-channel': HasDataChannelMatcherDefinition,
|
|
103
|
+
'has-rtc-video-track': HasVideoTrackMatcherDefinition,
|
|
104
|
+
'has-rtc-audio-track': HasAudioTrackMatcherDefinition,
|
|
105
|
+
'has-rtc-media-track': HasMediaTrackMatcherDefinition,
|
|
106
|
+
'rtc-page-hostname': HostnameMatcherDefinition,
|
|
107
|
+
'rtc-page-regex': UrlRegexMatcherDefinition,
|
|
108
|
+
'rtc-user-agent-regex': UserAgentRegexMatcherDefinition
|
|
109
|
+
};
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* SPDX-FileCopyrightText: 2022 Tim Perry <tim@httptoolkit.tech>
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { RTCConnection } from "../webrtc/rtc-connection";
|
|
7
|
+
import {
|
|
8
|
+
MatcherDefinition,
|
|
9
|
+
MatcherDefinitionLookup,
|
|
10
|
+
HasAudioTrackMatcherDefinition,
|
|
11
|
+
HasDataChannelMatcherDefinition,
|
|
12
|
+
HasMediaTrackMatcherDefinition,
|
|
13
|
+
HasVideoTrackMatcherDefinition,
|
|
14
|
+
HostnameMatcherDefinition,
|
|
15
|
+
UrlRegexMatcherDefinition,
|
|
16
|
+
UserAgentRegexMatcherDefinition
|
|
17
|
+
} from "./matcher-definitions";
|
|
18
|
+
|
|
19
|
+
export interface Matcher extends MatcherDefinition {
|
|
20
|
+
matches(connection: RTCConnection): boolean;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export class HasDataChannelMatcher extends HasDataChannelMatcherDefinition {
|
|
24
|
+
|
|
25
|
+
matches(connection: RTCConnection): boolean {
|
|
26
|
+
return [
|
|
27
|
+
...connection.getLocalDescription()!.parsedSdp.media,
|
|
28
|
+
...connection.getRemoteDescription()!.parsedSdp.media
|
|
29
|
+
].some(media => media.type === 'application');
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export class HasVideoTrackMatcher extends HasVideoTrackMatcherDefinition {
|
|
35
|
+
|
|
36
|
+
matches(connection: RTCConnection): boolean {
|
|
37
|
+
return [
|
|
38
|
+
...connection.getLocalDescription()!.parsedSdp.media,
|
|
39
|
+
...connection.getRemoteDescription()!.parsedSdp.media
|
|
40
|
+
].some(media => media.type === 'video');
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export class HasAudioTrackMatcher extends HasAudioTrackMatcherDefinition {
|
|
46
|
+
|
|
47
|
+
matches(connection: RTCConnection): boolean {
|
|
48
|
+
return [
|
|
49
|
+
...connection.getLocalDescription()!.parsedSdp.media,
|
|
50
|
+
...connection.getRemoteDescription()!.parsedSdp.media
|
|
51
|
+
].some(media => media.type === 'audio');
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export class HasMediaTrackMatcher extends HasMediaTrackMatcherDefinition {
|
|
57
|
+
|
|
58
|
+
matches(connection: RTCConnection): boolean {
|
|
59
|
+
return [
|
|
60
|
+
...connection.getLocalDescription()!.parsedSdp.media,
|
|
61
|
+
...connection.getRemoteDescription()!.parsedSdp.media
|
|
62
|
+
].some(media => media.type === 'video' || media.type === 'audio');
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const getConnectionSourceURL = (connection: RTCConnection): URL | undefined => {
|
|
68
|
+
const { sourceURL } = connection.metadata;
|
|
69
|
+
if (!sourceURL) return;
|
|
70
|
+
|
|
71
|
+
try {
|
|
72
|
+
return new URL(sourceURL);
|
|
73
|
+
} catch (e) {
|
|
74
|
+
console.warn('Unparseable RTC source URL:', e);
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
export class HostnameMatcher extends HostnameMatcherDefinition {
|
|
80
|
+
|
|
81
|
+
matches(connection: RTCConnection): boolean {
|
|
82
|
+
const url = getConnectionSourceURL(connection);
|
|
83
|
+
return url?.hostname === this.hostname;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export class UrlRegexMatcher extends UrlRegexMatcherDefinition {
|
|
89
|
+
|
|
90
|
+
matches(connection: RTCConnection): boolean {
|
|
91
|
+
const url = getConnectionSourceURL(connection);
|
|
92
|
+
return !!url?.toString().match(
|
|
93
|
+
new RegExp(this.regexSource, this.regexFlags)
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export class UserAgentRegexMatcher extends UserAgentRegexMatcherDefinition {
|
|
100
|
+
|
|
101
|
+
matches(connection: RTCConnection): boolean {
|
|
102
|
+
const userAgent = connection.metadata.userAgent;
|
|
103
|
+
return !!userAgent?.match(
|
|
104
|
+
new RegExp(this.regexSource, this.regexFlags)
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export const MatcherLookup: typeof MatcherDefinitionLookup = {
|
|
111
|
+
'has-rtc-data-channel': HasDataChannelMatcher,
|
|
112
|
+
'has-rtc-video-track': HasVideoTrackMatcher,
|
|
113
|
+
'has-rtc-audio-track': HasAudioTrackMatcher,
|
|
114
|
+
'has-rtc-media-track': HasMediaTrackMatcher,
|
|
115
|
+
'rtc-page-hostname': HostnameMatcher,
|
|
116
|
+
'rtc-page-regex': UrlRegexMatcher,
|
|
117
|
+
'rtc-user-agent-regex': UserAgentRegexMatcher
|
|
118
|
+
};
|