@webex/plugin-meetings 3.0.0-beta.162 → 3.0.0-beta.164
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/dist/breakouts/breakout.js +7 -3
- package/dist/breakouts/breakout.js.map +1 -1
- package/dist/breakouts/events.js +31 -29
- package/dist/breakouts/events.js.map +1 -1
- package/dist/breakouts/index.js +4 -2
- package/dist/breakouts/index.js.map +1 -1
- package/dist/constants.js +2 -4
- package/dist/constants.js.map +1 -1
- package/dist/interpretation/index.js +1 -1
- package/dist/interpretation/siLanguage.js +1 -1
- package/dist/locus-info/index.js +33 -17
- package/dist/locus-info/index.js.map +1 -1
- package/dist/meeting/index.js +699 -682
- package/dist/meeting/index.js.map +1 -1
- package/dist/meeting/util.js +47 -25
- package/dist/meeting/util.js.map +1 -1
- package/dist/meeting-info/index.js +48 -7
- package/dist/meeting-info/index.js.map +1 -1
- package/dist/meeting-info/meeting-info-v2.js +24 -10
- package/dist/meeting-info/meeting-info-v2.js.map +1 -1
- package/dist/meetings/index.js +12 -9
- package/dist/meetings/index.js.map +1 -1
- package/dist/metrics/index.js +1 -487
- package/dist/metrics/index.js.map +1 -1
- package/dist/reconnection-manager/index.js +27 -17
- package/dist/reconnection-manager/index.js.map +1 -1
- package/dist/roap/request.js +20 -14
- package/dist/roap/request.js.map +1 -1
- package/dist/types/breakouts/events.d.ts +7 -1
- package/dist/types/constants.d.ts +0 -1
- package/dist/types/meeting/index.d.ts +31 -133
- package/dist/types/meeting-info/index.d.ts +6 -1
- package/dist/types/meetings/index.d.ts +1 -0
- package/dist/types/metrics/index.d.ts +4 -128
- package/package.json +19 -19
- package/src/breakouts/breakout.ts +10 -2
- package/src/breakouts/events.ts +51 -32
- package/src/breakouts/index.ts +9 -5
- package/src/constants.ts +0 -2
- package/src/locus-info/index.ts +35 -17
- package/src/meeting/index.ts +474 -536
- package/src/meeting/util.ts +42 -19
- package/src/meeting-info/index.ts +54 -8
- package/src/meeting-info/meeting-info-v2.ts +24 -9
- package/src/meetings/index.ts +11 -6
- package/src/metrics/index.ts +1 -506
- package/src/reconnection-manager/index.ts +27 -17
- package/src/roap/request.ts +21 -9
- package/test/unit/spec/breakouts/breakout.ts +4 -2
- package/test/unit/spec/breakouts/events.ts +24 -18
- package/test/unit/spec/locus-info/index.js +112 -0
- package/test/unit/spec/meeting/index.js +178 -145
- package/test/unit/spec/meeting/utils.js +93 -7
- package/test/unit/spec/meeting-info/index.js +181 -0
- package/test/unit/spec/meeting-info/meetinginfov2.js +68 -68
- package/test/unit/spec/meetings/index.js +35 -55
- package/test/unit/spec/metrics/index.js +1 -148
- package/test/unit/spec/reconnection-manager/index.js +51 -2
- package/test/unit/spec/roap/index.ts +8 -2
- package/test/unit/spec/roap/request.ts +43 -5
- package/dist/metrics/config.js +0 -335
- package/dist/metrics/config.js.map +0 -1
- package/dist/types/metrics/config.d.ts +0 -195
- package/src/metrics/config.ts +0 -534
|
@@ -17,14 +17,6 @@ import metrics from '@webex/plugin-meetings/src/metrics';
|
|
|
17
17
|
browserOnly(describe)('Meeting metrics', () => {
|
|
18
18
|
let webex, mockSubmitMetric, sandbox;
|
|
19
19
|
|
|
20
|
-
const geoHintInfo = {
|
|
21
|
-
clientAddress: '2001:0db8:0000:08d3:0000:0000:0070:0000',
|
|
22
|
-
clientRegion: 'US-WEST',
|
|
23
|
-
countryCode: 'US',
|
|
24
|
-
regionCode: 'US-WEST',
|
|
25
|
-
timezone: 'America/Los_Angeles',
|
|
26
|
-
};
|
|
27
|
-
|
|
28
20
|
beforeEach(() => {
|
|
29
21
|
sandbox = sinon.createSandbox();
|
|
30
22
|
mockSubmitMetric = sandbox.stub();
|
|
@@ -34,56 +26,15 @@ browserOnly(describe)('Meeting metrics', () => {
|
|
|
34
26
|
},
|
|
35
27
|
});
|
|
36
28
|
|
|
37
|
-
webex.version = '1.2.3';
|
|
38
|
-
webex.credentials.getOrgId = sinon.fake.returns('7890');
|
|
39
|
-
webex.credentials.config = {
|
|
40
|
-
_values: {
|
|
41
|
-
clientId: 'mock-client-id',
|
|
42
|
-
},
|
|
43
|
-
};
|
|
44
29
|
webex.config.metrics.type = ['behavioral'];
|
|
45
30
|
webex.internal.metrics.submitClientMetrics = mockSubmitMetric;
|
|
46
|
-
metrics.initialSetup(
|
|
31
|
+
metrics.initialSetup(webex);
|
|
47
32
|
});
|
|
48
33
|
|
|
49
34
|
afterEach(() => {
|
|
50
35
|
sandbox.restore();
|
|
51
36
|
});
|
|
52
37
|
|
|
53
|
-
describe('initPayload / initMediaPayload', () => {
|
|
54
|
-
it('should create payload with masked IPv4', () => {
|
|
55
|
-
geoHintInfo.clientAddress = '128.0.0.1';
|
|
56
|
-
webex.meetings = {
|
|
57
|
-
geoHintInfo,
|
|
58
|
-
};
|
|
59
|
-
metrics.initialSetup({}, webex);
|
|
60
|
-
const payload = metrics.initPayload('myMetric', {}, {clientType: 'TEAMS_CLIENT'});
|
|
61
|
-
|
|
62
|
-
assert(payload.origin.clientInfo.localNetworkPrefix === '128.0.0.0');
|
|
63
|
-
assert(payload.event.name === 'myMetric');
|
|
64
|
-
|
|
65
|
-
const payload2 = metrics.initMediaPayload('myMetric', {}, {clientType: 'TEAMS_CLIENT'});
|
|
66
|
-
|
|
67
|
-
assert(payload2.origin.clientInfo.localNetworkPrefix === '128.0.0.0');
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
it('should create payload with masked IPv6', () => {
|
|
71
|
-
geoHintInfo.clientAddress = '2001:0db8:0000:08d3:0000:0000:0070:0000';
|
|
72
|
-
webex.meetings = {
|
|
73
|
-
geoHintInfo,
|
|
74
|
-
};
|
|
75
|
-
metrics.initialSetup({}, webex);
|
|
76
|
-
const payload = metrics.initPayload('myIPv6Metric', {}, {clientType: 'TEAMS_CLIENT'});
|
|
77
|
-
|
|
78
|
-
assert(payload.origin.clientInfo.localNetworkPrefix === '2001:db8:0:8d3::');
|
|
79
|
-
assert(payload.event.name === 'myIPv6Metric');
|
|
80
|
-
|
|
81
|
-
const payload2 = metrics.initMediaPayload('myIPv6Metric', {}, {clientType: 'TEAMS_CLIENT'});
|
|
82
|
-
|
|
83
|
-
assert(payload2.origin.clientInfo.localNetworkPrefix === '2001:db8:0:8d3::');
|
|
84
|
-
});
|
|
85
|
-
});
|
|
86
|
-
|
|
87
38
|
describe('#sendBehavioralMetric', () => {
|
|
88
39
|
it('sends client metric via Metrics plugin', () => {
|
|
89
40
|
metrics.sendBehavioralMetric('myMetric');
|
|
@@ -108,102 +59,4 @@ browserOnly(describe)('Meeting metrics', () => {
|
|
|
108
59
|
});
|
|
109
60
|
});
|
|
110
61
|
});
|
|
111
|
-
|
|
112
|
-
describe('parseWebexApiError', () => {
|
|
113
|
-
it('returns the correct error data for meeting lookup info error', () => {
|
|
114
|
-
const err = {
|
|
115
|
-
body: {
|
|
116
|
-
code: 58400,
|
|
117
|
-
},
|
|
118
|
-
statusCode: 400,
|
|
119
|
-
};
|
|
120
|
-
const res = metrics.parseWebexApiError(err, false);
|
|
121
|
-
|
|
122
|
-
assert.deepEqual(res, {
|
|
123
|
-
shownToUser: false,
|
|
124
|
-
category: 'signaling',
|
|
125
|
-
errorDescription: 'MeetingInfoLookupError',
|
|
126
|
-
errorCode: 4100,
|
|
127
|
-
fatal: true,
|
|
128
|
-
name: 'other',
|
|
129
|
-
serviceErrorCode: 58400,
|
|
130
|
-
errorData: { error: { code: 58400 } },
|
|
131
|
-
httpCode: 400
|
|
132
|
-
});
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
it('returns the correct error data for access rights error error', () => {
|
|
136
|
-
const err = {
|
|
137
|
-
body: {
|
|
138
|
-
code: 403041,
|
|
139
|
-
},
|
|
140
|
-
statusCode: 400,
|
|
141
|
-
};
|
|
142
|
-
const res = metrics.parseWebexApiError(err, false);
|
|
143
|
-
|
|
144
|
-
assert.deepEqual(res, {
|
|
145
|
-
shownToUser: false,
|
|
146
|
-
"category": "expected",
|
|
147
|
-
"errorCode": 4005,
|
|
148
|
-
errorDescription: 'Moderator_Pin_Or_Guest_PIN_Required',
|
|
149
|
-
fatal: false,
|
|
150
|
-
name: 'other',
|
|
151
|
-
serviceErrorCode: 403041,
|
|
152
|
-
errorData: { error: { code: 403041 } },
|
|
153
|
-
httpCode: 400
|
|
154
|
-
});
|
|
155
|
-
});
|
|
156
|
-
|
|
157
|
-
it('returns default 4100 mapping for unknown error', () => {
|
|
158
|
-
const err = {
|
|
159
|
-
body: {
|
|
160
|
-
code: 123456,
|
|
161
|
-
},
|
|
162
|
-
};
|
|
163
|
-
const res = metrics.parseWebexApiError(err, false);
|
|
164
|
-
|
|
165
|
-
assert.deepEqual(res, {
|
|
166
|
-
shownToUser: false,
|
|
167
|
-
category: 'signaling',
|
|
168
|
-
errorDescription: 'MeetingInfoLookupError',
|
|
169
|
-
errorCode: 4100,
|
|
170
|
-
fatal: true,
|
|
171
|
-
name: 'other',
|
|
172
|
-
serviceErrorCode: 123456,
|
|
173
|
-
errorData: { error: { code: 123456 } },
|
|
174
|
-
});
|
|
175
|
-
});
|
|
176
|
-
});
|
|
177
|
-
|
|
178
|
-
describe('#generateErrorPayload', () => {
|
|
179
|
-
it('generates the correct payload for a valid error code', () => {
|
|
180
|
-
const errorCode = 4008;
|
|
181
|
-
const shownToUser = true;
|
|
182
|
-
const name = 'errorName';
|
|
183
|
-
const errBody = 'some error body';
|
|
184
|
-
const err = {
|
|
185
|
-
body: errBody,
|
|
186
|
-
statusCode: 404,
|
|
187
|
-
};
|
|
188
|
-
|
|
189
|
-
const payload = metrics.generateErrorPayload(
|
|
190
|
-
errorCode,
|
|
191
|
-
shownToUser,
|
|
192
|
-
name,
|
|
193
|
-
err
|
|
194
|
-
);
|
|
195
|
-
|
|
196
|
-
assert.deepEqual(payload, {
|
|
197
|
-
shownToUser,
|
|
198
|
-
category: 'expected',
|
|
199
|
-
errorDescription: 'NewLocusError',
|
|
200
|
-
errorCode,
|
|
201
|
-
fatal: true,
|
|
202
|
-
name,
|
|
203
|
-
errorData: {error: errBody},
|
|
204
|
-
serviceErrorCode: undefined,
|
|
205
|
-
httpCode: 404,
|
|
206
|
-
});
|
|
207
|
-
});
|
|
208
|
-
});
|
|
209
62
|
});
|
|
@@ -3,7 +3,6 @@ import chai from 'chai';
|
|
|
3
3
|
import chaiAsPromised from 'chai-as-promised';
|
|
4
4
|
import sinon from 'sinon';
|
|
5
5
|
import ReconnectionManager from '@webex/plugin-meetings/src/reconnection-manager';
|
|
6
|
-
import Metrics from '@webex/plugin-meetings/src/metrics';
|
|
7
6
|
|
|
8
7
|
const {assert} = chai;
|
|
9
8
|
|
|
@@ -16,7 +15,6 @@ describe('plugin-meetings', () => {
|
|
|
16
15
|
let fakeMeeting;
|
|
17
16
|
|
|
18
17
|
beforeEach(() => {
|
|
19
|
-
Metrics.postEvent = sinon.stub();
|
|
20
18
|
fakeMediaConnection = {
|
|
21
19
|
initiateOffer: sinon.stub().resolves({}),
|
|
22
20
|
reconnect: sinon.stub().resolves({}),
|
|
@@ -64,6 +62,11 @@ describe('plugin-meetings', () => {
|
|
|
64
62
|
getMeetingByType: sinon.stub().returns(true),
|
|
65
63
|
syncMeetings: sinon.stub().resolves({}),
|
|
66
64
|
},
|
|
65
|
+
internal: {
|
|
66
|
+
newMetrics: {
|
|
67
|
+
submitClientEvent: sinon.stub()
|
|
68
|
+
}
|
|
69
|
+
}
|
|
67
70
|
},
|
|
68
71
|
};
|
|
69
72
|
});
|
|
@@ -82,6 +85,23 @@ describe('plugin-meetings', () => {
|
|
|
82
85
|
credential: 'fake_turn_password',
|
|
83
86
|
},
|
|
84
87
|
]);
|
|
88
|
+
|
|
89
|
+
assert.calledWith(fakeMeeting.webex.internal.newMetrics.submitClientEvent, {
|
|
90
|
+
name: 'client.media.reconnecting',
|
|
91
|
+
options: {
|
|
92
|
+
meetingId: rm.meeting.id,
|
|
93
|
+
},
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
assert.calledWith(fakeMeeting.webex.internal.newMetrics.submitClientEvent, {
|
|
97
|
+
name: 'client.media.recovered',
|
|
98
|
+
payload: {
|
|
99
|
+
recoveredBy: 'new',
|
|
100
|
+
},
|
|
101
|
+
options: {
|
|
102
|
+
meetingId: rm.meeting.id,
|
|
103
|
+
},
|
|
104
|
+
});
|
|
85
105
|
});
|
|
86
106
|
|
|
87
107
|
it('does not clear previous requests and re-request media for non-multistream meetings', async () => {
|
|
@@ -107,6 +127,35 @@ describe('plugin-meetings', () => {
|
|
|
107
127
|
assert.calledOnce(fakeMeeting.mediaRequestManagers.audio.commit);
|
|
108
128
|
assert.calledOnce(fakeMeeting.mediaRequestManagers.video.commit);
|
|
109
129
|
});
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
it('sends the correct client event when reconnection fails', async () => {
|
|
133
|
+
sinon.stub(ReconnectionManager.prototype, 'executeReconnection').rejects();
|
|
134
|
+
fakeMeeting.isMultistream = true;
|
|
135
|
+
const rm = new ReconnectionManager(fakeMeeting);
|
|
136
|
+
|
|
137
|
+
try {
|
|
138
|
+
await rm.reconnect();
|
|
139
|
+
} catch (err) {
|
|
140
|
+
assert.calledWith(fakeMeeting.webex.internal.newMetrics.submitClientEvent, {
|
|
141
|
+
name: 'client.call.aborted',
|
|
142
|
+
payload: {
|
|
143
|
+
errors: [
|
|
144
|
+
{
|
|
145
|
+
category: 'expected',
|
|
146
|
+
errorCode: 2008,
|
|
147
|
+
fatal: true,
|
|
148
|
+
name: 'media-engine',
|
|
149
|
+
shownToUser: false,
|
|
150
|
+
},
|
|
151
|
+
],
|
|
152
|
+
},
|
|
153
|
+
options: {
|
|
154
|
+
meetingId: rm.meeting.id,
|
|
155
|
+
},
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
});
|
|
110
159
|
});
|
|
111
160
|
|
|
112
161
|
/**
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {assert} from '@webex/test-helper-chai';
|
|
2
2
|
import sinon from 'sinon';
|
|
3
3
|
import TurnDiscovery from '@webex/plugin-meetings/src/roap/turnDiscovery';
|
|
4
|
+
import MockWebex from '@webex/test-helper-mock-webex';
|
|
4
5
|
|
|
5
6
|
import RoapRequest from '@webex/plugin-meetings/src/roap/request';
|
|
6
7
|
import Roap from '@webex/plugin-meetings/src/roap/';
|
|
@@ -9,6 +10,8 @@ import Meeting from '@webex/plugin-meetings/src/meeting';
|
|
|
9
10
|
describe('Roap', () => {
|
|
10
11
|
describe('doTurnDiscovery', () => {
|
|
11
12
|
it('calls this.turnDiscovery.doTurnDiscovery() and forwards all the arguments', async () => {
|
|
13
|
+
const webex = new MockWebex({});
|
|
14
|
+
|
|
12
15
|
const RESULT = {something: 'some value'};
|
|
13
16
|
const meeting = {id: 'some meeting id'} as Meeting;
|
|
14
17
|
|
|
@@ -16,7 +19,7 @@ describe('Roap', () => {
|
|
|
16
19
|
.stub(TurnDiscovery.prototype, 'doTurnDiscovery')
|
|
17
20
|
.resolves(RESULT);
|
|
18
21
|
|
|
19
|
-
const roap = new Roap({}, {parent:
|
|
22
|
+
const roap = new Roap({}, {parent: webex});
|
|
20
23
|
|
|
21
24
|
// call with isReconnecting: true
|
|
22
25
|
const result = await roap.doTurnDiscovery(meeting, true);
|
|
@@ -40,7 +43,10 @@ describe('Roap', () => {
|
|
|
40
43
|
let sendRoapStub;
|
|
41
44
|
let meeting;
|
|
42
45
|
|
|
46
|
+
let webex;
|
|
47
|
+
|
|
43
48
|
beforeEach(() => {
|
|
49
|
+
webex = new MockWebex({});
|
|
44
50
|
meeting = {
|
|
45
51
|
id: 'some meeting id',
|
|
46
52
|
correlationId: 'correlation id',
|
|
@@ -77,7 +83,7 @@ describe('Roap', () => {
|
|
|
77
83
|
}reconnecting and TURN discovery is ${
|
|
78
84
|
turnDiscoverySkipped ? 'skipped' : 'not skipped'
|
|
79
85
|
}`, async () => {
|
|
80
|
-
const roap = new Roap({}, {parent:
|
|
86
|
+
const roap = new Roap({}, {parent: webex});
|
|
81
87
|
|
|
82
88
|
sinon.stub(roap.turnDiscovery, 'isSkipped').resolves(turnDiscoverySkipped);
|
|
83
89
|
|
|
@@ -3,7 +3,6 @@ import {assert} from '@webex/test-helper-chai';
|
|
|
3
3
|
import MockWebex from '@webex/test-helper-mock-webex';
|
|
4
4
|
import Meetings from '@webex/plugin-meetings';
|
|
5
5
|
import RoapRequest from '@webex/plugin-meetings/src/roap/request';
|
|
6
|
-
import Metrics from '@webex/plugin-meetings/src/metrics';
|
|
7
6
|
import {REACHABILITY} from '@webex/plugin-meetings/src/constants';
|
|
8
7
|
|
|
9
8
|
describe('plugin-meetings/roap', () => {
|
|
@@ -31,6 +30,9 @@ describe('plugin-meetings/roap', () => {
|
|
|
31
30
|
device: {
|
|
32
31
|
url: 'url',
|
|
33
32
|
},
|
|
33
|
+
newMetrics: {
|
|
34
|
+
submitClientEvent: sinon.stub()
|
|
35
|
+
},
|
|
34
36
|
};
|
|
35
37
|
|
|
36
38
|
// @ts-ignore
|
|
@@ -51,8 +53,6 @@ describe('plugin-meetings/roap', () => {
|
|
|
51
53
|
})
|
|
52
54
|
);
|
|
53
55
|
|
|
54
|
-
Metrics.postEvent = sinon.stub().returns();
|
|
55
|
-
|
|
56
56
|
await webex.boundedStorage.put(
|
|
57
57
|
REACHABILITY.namespace,
|
|
58
58
|
REACHABILITY.localStorageJoinCookie,
|
|
@@ -108,7 +108,7 @@ describe('plugin-meetings/roap', () => {
|
|
|
108
108
|
|
|
109
109
|
describe('sendRoap', () => {
|
|
110
110
|
it('includes joinCookie in the request correctly', async () => {
|
|
111
|
-
const locusMediaRequest = {
|
|
111
|
+
const locusMediaRequest = {send: sinon.stub().resolves({body: {locus: {}}})};
|
|
112
112
|
|
|
113
113
|
await roapRequest.sendRoap({
|
|
114
114
|
locusSelfUrl: locusUrl,
|
|
@@ -116,9 +116,24 @@ describe('plugin-meetings/roap', () => {
|
|
|
116
116
|
roapMessage: {
|
|
117
117
|
seq: 'seq',
|
|
118
118
|
},
|
|
119
|
+
meetingId: 'meeting-id',
|
|
119
120
|
locusMediaRequest,
|
|
120
121
|
});
|
|
121
122
|
|
|
123
|
+
assert.calledWith(webex.internal.newMetrics.submitClientEvent, {
|
|
124
|
+
name: 'client.locus.media.request',
|
|
125
|
+
options: {
|
|
126
|
+
meetingId: 'meeting-id',
|
|
127
|
+
},
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
assert.calledWith(webex.internal.newMetrics.submitClientEvent, {
|
|
131
|
+
name: 'client.locus.media.response',
|
|
132
|
+
options: {
|
|
133
|
+
meetingId: 'meeting-id',
|
|
134
|
+
},
|
|
135
|
+
});
|
|
136
|
+
|
|
122
137
|
const requestParams = locusMediaRequest.send.getCall(0).args[0];
|
|
123
138
|
assert.deepEqual(requestParams, {
|
|
124
139
|
type: 'RoapMessage',
|
|
@@ -130,9 +145,32 @@ describe('plugin-meetings/roap', () => {
|
|
|
130
145
|
roapMessage: {
|
|
131
146
|
seq: 'seq',
|
|
132
147
|
},
|
|
133
|
-
reachability: {clusterId:{udp:
|
|
148
|
+
reachability: {clusterId: {udp: 'test'}},
|
|
134
149
|
});
|
|
135
150
|
});
|
|
151
|
+
|
|
152
|
+
it('sends correct client event when fails', async () => {
|
|
153
|
+
const locusMediaRequest = {send: sinon.stub().rejects({code: 300, message: 'error'})};
|
|
154
|
+
try {
|
|
155
|
+
await roapRequest.sendRoap({
|
|
156
|
+
locusSelfUrl: locusUrl,
|
|
157
|
+
mediaId: 'mediaId',
|
|
158
|
+
roapMessage: {
|
|
159
|
+
seq: 'seq',
|
|
160
|
+
},
|
|
161
|
+
meetingId: 'meeting-id',
|
|
162
|
+
locusMediaRequest,
|
|
163
|
+
});
|
|
164
|
+
} catch (err) {
|
|
165
|
+
assert.calledWith(webex.internal.newMetrics.submitClientEvent, {
|
|
166
|
+
name: 'client.locus.media.response',
|
|
167
|
+
options: {
|
|
168
|
+
meetingId: 'meeting-id',
|
|
169
|
+
rawError: {code: 300, message: 'error'},
|
|
170
|
+
},
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
});
|
|
136
174
|
});
|
|
137
175
|
|
|
138
176
|
it('calls attachReachabilityData when sendRoap', async () => {
|