Skip to content

Commit 4810a9b

Browse files
committed
add further warning & tests
1 parent 87fe76a commit 4810a9b

File tree

6 files changed

+206
-116
lines changed

6 files changed

+206
-116
lines changed

packages/replay/src/coreHandlers/util/networkUtils.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -74,14 +74,18 @@ export function getBodyString(body: unknown): [string | undefined, NetworkMetaWa
7474
if (body instanceof FormData) {
7575
return [_serializeFormData(body)];
7676
}
77+
78+
if (!body) {
79+
return [undefined];
80+
}
7781
} catch {
7882
__DEBUG_BUILD__ && logger.warn('[Replay] Failed to serialize body', body);
7983
return [undefined, 'BODY_PARSE_ERROR'];
8084
}
8185

8286
__DEBUG_BUILD__ && logger.info('[Replay] Skipping network body because of body type', body);
8387

84-
return [undefined];
88+
return [undefined, 'UNPARSEABLE_BODY_TYPE'];
8589
}
8690

8791
/** Merge a warning into an existing network request/response. */

packages/replay/src/coreHandlers/util/xhrUtils.ts

+7-2
Original file line numberDiff line numberDiff line change
@@ -171,12 +171,13 @@ function _getXhrResponseBody(xhr: XMLHttpRequest): [string | undefined, NetworkM
171171
* Blob
172172
* Document
173173
* POJO
174+
*
175+
* Exported only for tests.
174176
*/
175177
export function _parseXhrResponse(
176178
body: XMLHttpRequest['response'],
177179
responseType: XMLHttpRequest['responseType'],
178180
): [string | undefined, NetworkMetaWarning?] {
179-
logger.log(body, responseType, typeof body);
180181
try {
181182
if (typeof body === 'string') {
182183
return [body];
@@ -189,14 +190,18 @@ export function _parseXhrResponse(
189190
if (responseType === 'json' && body && typeof body === 'object') {
190191
return [JSON.stringify(body)];
191192
}
193+
194+
if (!body) {
195+
return [undefined];
196+
}
192197
} catch {
193198
__DEBUG_BUILD__ && logger.warn('[Replay] Failed to serialize body', body);
194199
return [undefined, 'BODY_PARSE_ERROR'];
195200
}
196201

197202
__DEBUG_BUILD__ && logger.info('[Replay] Skipping network body because of body type', body);
198203

199-
return [undefined];
204+
return [undefined, 'UNPARSEABLE_BODY_TYPE'];
200205
}
201206

202207
function _getBodySize(

packages/replay/src/types/request.ts

+6-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,12 @@ type JsonArray = unknown[];
33

44
export type NetworkBody = JsonObject | JsonArray | string;
55

6-
export type NetworkMetaWarning = 'MAYBE_JSON_TRUNCATED' | 'TEXT_TRUNCATED' | 'URL_SKIPPED' | 'BODY_PARSE_ERROR';
6+
export type NetworkMetaWarning =
7+
| 'MAYBE_JSON_TRUNCATED'
8+
| 'TEXT_TRUNCATED'
9+
| 'URL_SKIPPED'
10+
| 'BODY_PARSE_ERROR'
11+
| 'UNPARSEABLE_BODY_TYPE';
712

813
interface NetworkMeta {
914
warnings?: NetworkMetaWarning[];

packages/replay/test/unit/coreHandlers/util/fetchUtils.test.ts

+114-112
Original file line numberDiff line numberDiff line change
@@ -2,136 +2,138 @@ import { TextEncoder } from 'util';
22

33
import { _getResponseInfo } from '../../../../src/coreHandlers/util/fetchUtils';
44

5-
describe('_getResponseInfo', () => {
6-
it('works with captureDetails: false', async () => {
7-
const res = await _getResponseInfo(
8-
false,
9-
{
10-
networkCaptureBodies: true,
11-
textEncoder: new TextEncoder(),
12-
networkResponseHeaders: [],
13-
},
14-
undefined,
15-
undefined,
16-
);
5+
describe('Unit | coreHandlers | util | fetchUtils', () => {
6+
describe('_getResponseInfo', () => {
7+
it('works with captureDetails: false', async () => {
8+
const res = await _getResponseInfo(
9+
false,
10+
{
11+
networkCaptureBodies: true,
12+
textEncoder: new TextEncoder(),
13+
networkResponseHeaders: [],
14+
},
15+
undefined,
16+
undefined,
17+
);
1718

18-
expect(res).toEqual(undefined);
19-
});
19+
expect(res).toEqual(undefined);
20+
});
2021

21-
it('works with captureDetails: false & responseBodySize', async () => {
22-
const res = await _getResponseInfo(
23-
false,
24-
{
25-
networkCaptureBodies: true,
26-
textEncoder: new TextEncoder(),
27-
networkResponseHeaders: [],
28-
},
29-
undefined,
30-
123,
31-
);
22+
it('works with captureDetails: false & responseBodySize', async () => {
23+
const res = await _getResponseInfo(
24+
false,
25+
{
26+
networkCaptureBodies: true,
27+
textEncoder: new TextEncoder(),
28+
networkResponseHeaders: [],
29+
},
30+
undefined,
31+
123,
32+
);
3233

33-
expect(res).toEqual({
34-
headers: {},
35-
size: 123,
36-
_meta: {
37-
warnings: ['URL_SKIPPED'],
38-
},
34+
expect(res).toEqual({
35+
headers: {},
36+
size: 123,
37+
_meta: {
38+
warnings: ['URL_SKIPPED'],
39+
},
40+
});
3941
});
40-
});
4142

42-
it('works with text body', async () => {
43-
const response = {
44-
headers: {
45-
has: () => {
46-
return false;
47-
},
48-
get: () => {
49-
return undefined;
43+
it('works with text body', async () => {
44+
const response = {
45+
headers: {
46+
has: () => {
47+
return false;
48+
},
49+
get: () => {
50+
return undefined;
51+
},
5052
},
51-
},
52-
clone: () => response,
53-
text: () => Promise.resolve('text body'),
54-
} as unknown as Response;
53+
clone: () => response,
54+
text: () => Promise.resolve('text body'),
55+
} as unknown as Response;
5556

56-
const res = await _getResponseInfo(
57-
true,
58-
{
59-
networkCaptureBodies: true,
60-
textEncoder: new TextEncoder(),
61-
networkResponseHeaders: [],
62-
},
63-
response,
64-
undefined,
65-
);
57+
const res = await _getResponseInfo(
58+
true,
59+
{
60+
networkCaptureBodies: true,
61+
textEncoder: new TextEncoder(),
62+
networkResponseHeaders: [],
63+
},
64+
response,
65+
undefined,
66+
);
6667

67-
expect(res).toEqual({
68-
headers: {},
69-
size: 9,
70-
body: 'text body',
68+
expect(res).toEqual({
69+
headers: {},
70+
size: 9,
71+
body: 'text body',
72+
});
7173
});
72-
});
7374

74-
it('works with body that fails', async () => {
75-
const response = {
76-
headers: {
77-
has: () => {
78-
return false;
75+
it('works with body that fails', async () => {
76+
const response = {
77+
headers: {
78+
has: () => {
79+
return false;
80+
},
81+
get: () => {
82+
return undefined;
83+
},
7984
},
80-
get: () => {
81-
return undefined;
82-
},
83-
},
84-
clone: () => response,
85-
text: () => Promise.reject('cannot read'),
86-
} as unknown as Response;
85+
clone: () => response,
86+
text: () => Promise.reject('cannot read'),
87+
} as unknown as Response;
8788

88-
const res = await _getResponseInfo(
89-
true,
90-
{
91-
networkCaptureBodies: true,
92-
textEncoder: new TextEncoder(),
93-
networkResponseHeaders: [],
94-
},
95-
response,
96-
undefined,
97-
);
89+
const res = await _getResponseInfo(
90+
true,
91+
{
92+
networkCaptureBodies: true,
93+
textEncoder: new TextEncoder(),
94+
networkResponseHeaders: [],
95+
},
96+
response,
97+
undefined,
98+
);
9899

99-
expect(res).toEqual({
100-
_meta: { warnings: ['BODY_PARSE_ERROR'] },
101-
headers: {},
102-
size: undefined,
100+
expect(res).toEqual({
101+
_meta: { warnings: ['BODY_PARSE_ERROR'] },
102+
headers: {},
103+
size: undefined,
104+
});
103105
});
104-
});
105106

106-
it('works with body that times out', async () => {
107-
const response = {
108-
headers: {
109-
has: () => {
110-
return false;
111-
},
112-
get: () => {
113-
return undefined;
107+
it('works with body that times out', async () => {
108+
const response = {
109+
headers: {
110+
has: () => {
111+
return false;
112+
},
113+
get: () => {
114+
return undefined;
115+
},
114116
},
115-
},
116-
clone: () => response,
117-
text: () => new Promise(resolve => setTimeout(() => resolve('text body'), 1000)),
118-
} as unknown as Response;
117+
clone: () => response,
118+
text: () => new Promise(resolve => setTimeout(() => resolve('text body'), 1000)),
119+
} as unknown as Response;
119120

120-
const res = await _getResponseInfo(
121-
true,
122-
{
123-
networkCaptureBodies: true,
124-
textEncoder: new TextEncoder(),
125-
networkResponseHeaders: [],
126-
},
127-
response,
128-
undefined,
129-
);
121+
const res = await _getResponseInfo(
122+
true,
123+
{
124+
networkCaptureBodies: true,
125+
textEncoder: new TextEncoder(),
126+
networkResponseHeaders: [],
127+
},
128+
response,
129+
undefined,
130+
);
130131

131-
expect(res).toEqual({
132-
_meta: { warnings: ['BODY_PARSE_ERROR'] },
133-
headers: {},
134-
size: undefined,
132+
expect(res).toEqual({
133+
_meta: { warnings: ['BODY_PARSE_ERROR'] },
134+
headers: {},
135+
size: undefined,
136+
});
135137
});
136138
});
137139
});

packages/replay/test/unit/coreHandlers/util/networkUtils.test.ts

+36
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { NETWORK_BODY_MAX_SIZE } from '../../../../src/constants';
44
import {
55
buildNetworkRequestOrResponse,
66
getBodySize,
7+
getBodyString,
78
getFullUrl,
89
parseContentLengthHeader,
910
} from '../../../../src/coreHandlers/util/networkUtils';
@@ -248,4 +249,39 @@ describe('Unit | coreHandlers | util | networkUtils', () => {
248249
expect(actual).toBe(expected);
249250
});
250251
});
252+
253+
describe('getBodyString', () => {
254+
it('works with a string', () => {
255+
const actual = getBodyString('abc');
256+
expect(actual).toEqual(['abc']);
257+
});
258+
259+
it('works with URLSearchParams', () => {
260+
const body = new URLSearchParams();
261+
body.append('name', 'Anne');
262+
body.append('age', '32');
263+
const actual = getBodyString(body);
264+
expect(actual).toEqual(['name=Anne&age=32']);
265+
});
266+
267+
it('works with FormData', () => {
268+
const body = new FormData();
269+
body.append('name', 'Anne');
270+
body.append('age', '32');
271+
const actual = getBodyString(body);
272+
expect(actual).toEqual(['name=Anne&age=32']);
273+
});
274+
275+
it('works with empty data', () => {
276+
const body = undefined;
277+
const actual = getBodyString(body);
278+
expect(actual).toEqual([undefined]);
279+
});
280+
281+
it('works with other type of data', () => {
282+
const body = {};
283+
const actual = getBodyString(body);
284+
expect(actual).toEqual([undefined, 'UNPARSEABLE_BODY_TYPE']);
285+
});
286+
});
251287
});

0 commit comments

Comments
 (0)