Skip to content

Commit a6249e0

Browse files
committed
fix tests
1 parent 152f47e commit a6249e0

File tree

3 files changed

+494
-338
lines changed

3 files changed

+494
-338
lines changed

packages/node/test/handlers.test.ts

+6-338
Original file line numberDiff line numberDiff line change
@@ -2,174 +2,15 @@ import * as sentryCore from '@sentry/core';
22
import * as sentryHub from '@sentry/hub';
33
import { Hub } from '@sentry/hub';
44
import { Transaction } from '@sentry/tracing';
5-
import { Baggage } from '@sentry/types';
5+
import { Baggage, Event } from '@sentry/types';
66
import { isBaggageEmpty, isBaggageMutable, SentryError } from '@sentry/utils';
77
import * as http from 'http';
8-
import * as net from 'net';
98

10-
import { Event, Request, User } from '../src';
119
import { NodeClient } from '../src/client';
12-
import {
13-
errorHandler,
14-
ExpressRequest,
15-
extractRequestData,
16-
parseRequest,
17-
requestHandler,
18-
tracingHandler,
19-
} from '../src/handlers';
10+
import { errorHandler, requestHandler, tracingHandler } from '../src/handlers';
2011
import * as SDK from '../src/sdk';
2112
import { getDefaultNodeClientOptions } from './helper/node-client-options';
2213

23-
describe('parseRequest', () => {
24-
let mockReq: { [key: string]: any };
25-
26-
beforeEach(() => {
27-
mockReq = {
28-
baseUrl: '/routerMountPath',
29-
body: 'foo',
30-
cookies: { test: 'test' },
31-
headers: {
32-
host: 'mattrobenolt.com',
33-
},
34-
method: 'POST',
35-
originalUrl: '/routerMountPath/subpath/specificValue?querystringKey=querystringValue',
36-
path: '/subpath/specificValue',
37-
query: {
38-
querystringKey: 'querystringValue',
39-
},
40-
route: {
41-
path: '/subpath/:parameterName',
42-
stack: [
43-
{
44-
name: 'parameterNameRouteHandler',
45-
},
46-
],
47-
},
48-
url: '/subpath/specificValue?querystringKey=querystringValue',
49-
user: {
50-
custom_property: 'foo',
51-
52-
id: 123,
53-
username: 'tobias',
54-
},
55-
};
56-
});
57-
58-
describe('parseRequest.user properties', () => {
59-
const DEFAULT_USER_KEYS = ['id', 'username', 'email'];
60-
const CUSTOM_USER_KEYS = ['custom_property'];
61-
62-
test('parseRequest.user only contains the default properties from the user', () => {
63-
const parsedRequest: Event = parseRequest({}, mockReq as ExpressRequest);
64-
expect(Object.keys(parsedRequest.user as User)).toEqual(DEFAULT_USER_KEYS);
65-
});
66-
67-
test('parseRequest.user only contains the custom properties specified in the options.user array', () => {
68-
const parsedRequest: Event = parseRequest({}, mockReq as ExpressRequest, {
69-
user: CUSTOM_USER_KEYS,
70-
});
71-
expect(Object.keys(parsedRequest.user as User)).toEqual(CUSTOM_USER_KEYS);
72-
});
73-
74-
test('parseRequest.user doesnt blow up when someone passes non-object value', () => {
75-
const parsedRequest: Event = parseRequest(
76-
{},
77-
{
78-
...mockReq,
79-
// @ts-ignore user is not assignable to object
80-
user: 'wat',
81-
},
82-
);
83-
expect(Object.keys(parsedRequest.user as User)).toEqual([]);
84-
});
85-
});
86-
87-
describe('parseRequest.ip property', () => {
88-
test('can be extracted from req.ip', () => {
89-
const parsedRequest: Event = parseRequest(
90-
{},
91-
{
92-
...mockReq,
93-
ip: '123',
94-
} as ExpressRequest,
95-
{
96-
ip: true,
97-
},
98-
);
99-
expect(parsedRequest.user!.ip_address).toEqual('123');
100-
});
101-
102-
test('can extract from req.connection.remoteAddress', () => {
103-
const parsedRequest: Event = parseRequest(
104-
{},
105-
{
106-
...mockReq,
107-
connection: {
108-
remoteAddress: '321',
109-
} as net.Socket,
110-
} as ExpressRequest,
111-
{
112-
ip: true,
113-
},
114-
);
115-
expect(parsedRequest.user!.ip_address).toEqual('321');
116-
});
117-
});
118-
119-
describe('parseRequest.request properties', () => {
120-
test('parseRequest.request only contains the default set of properties from the request', () => {
121-
const DEFAULT_REQUEST_PROPERTIES = ['cookies', 'data', 'headers', 'method', 'query_string', 'url'];
122-
const parsedRequest: Event = parseRequest({}, mockReq as ExpressRequest);
123-
expect(Object.keys(parsedRequest.request as Request)).toEqual(DEFAULT_REQUEST_PROPERTIES);
124-
});
125-
126-
test('parseRequest.request only contains the specified properties in the options.request array', () => {
127-
const INCLUDED_PROPERTIES = ['data', 'headers', 'query_string', 'url'];
128-
const parsedRequest: Event = parseRequest({}, mockReq as ExpressRequest, {
129-
request: INCLUDED_PROPERTIES,
130-
});
131-
expect(Object.keys(parsedRequest.request as Request)).toEqual(INCLUDED_PROPERTIES);
132-
});
133-
134-
test('parseRequest.request skips `body` property for GET and HEAD requests', () => {
135-
expect(parseRequest({}, mockReq as ExpressRequest, {}).request).toHaveProperty('data');
136-
expect(parseRequest({}, { ...mockReq, method: 'GET' } as ExpressRequest, {}).request).not.toHaveProperty('data');
137-
expect(parseRequest({}, { ...mockReq, method: 'HEAD' } as ExpressRequest, {}).request).not.toHaveProperty('data');
138-
});
139-
});
140-
141-
describe('parseRequest.transaction property', () => {
142-
test('extracts method and full route path by default`', () => {
143-
const parsedRequest: Event = parseRequest({}, mockReq as ExpressRequest);
144-
expect(parsedRequest.transaction).toEqual('POST /routerMountPath/subpath/:parameterName');
145-
});
146-
147-
test('extracts method and full path by default when mountpoint is `/`', () => {
148-
mockReq.originalUrl = mockReq.originalUrl.replace('/routerMountpath', '');
149-
mockReq.baseUrl = '';
150-
const parsedRequest: Event = parseRequest({}, mockReq as ExpressRequest);
151-
// "sub"path is the full path here, because there's no router mount path
152-
expect(parsedRequest.transaction).toEqual('POST /subpath/:parameterName');
153-
});
154-
155-
test('fallback to method and `originalUrl` if route is missing', () => {
156-
delete mockReq.route;
157-
const parsedRequest: Event = parseRequest({}, mockReq as ExpressRequest);
158-
expect(parsedRequest.transaction).toEqual('POST /routerMountPath/subpath/specificValue');
159-
});
160-
161-
test('can extract path only instead if configured', () => {
162-
const parsedRequest: Event = parseRequest({}, mockReq as ExpressRequest, { transaction: 'path' });
163-
expect(parsedRequest.transaction).toEqual('/routerMountPath/subpath/:parameterName');
164-
});
165-
166-
test('can extract handler name instead if configured', () => {
167-
const parsedRequest: Event = parseRequest({}, mockReq as ExpressRequest, { transaction: 'handler' });
168-
expect(parsedRequest.transaction).toEqual('parameterNameRouteHandler');
169-
});
170-
});
171-
});
172-
17314
describe('requestHandler', () => {
17415
const headers = { ears: 'furry', nose: 'wet', tongue: 'spotted', cookie: 'favorite=zukes' };
17516
const method = 'wagging';
@@ -270,7 +111,7 @@ describe('requestHandler', () => {
270111
});
271112
});
272113

273-
it('patches `res.end` when `flushTimeout` is specified', () => {
114+
it('patches `res.end` when `flushTimeout` is specified', done => {
274115
const flush = jest.spyOn(SDK, 'flush').mockResolvedValue(true);
275116

276117
const sentryRequestMiddleware = requestHandler({ flushTimeout: 1337 });
@@ -280,10 +121,11 @@ describe('requestHandler', () => {
280121
setImmediate(() => {
281122
expect(flush).toHaveBeenCalledWith(1337);
282123
expect(res.finished).toBe(true);
124+
done();
283125
});
284126
});
285127

286-
it('prevents errors thrown during `flush` from breaking the response', async () => {
128+
it('prevents errors thrown during `flush` from breaking the response', done => {
287129
jest.spyOn(SDK, 'flush').mockRejectedValue(new SentryError('HTTP Error (429)'));
288130

289131
const sentryRequestMiddleware = requestHandler({ flushTimeout: 1337 });
@@ -292,6 +134,7 @@ describe('requestHandler', () => {
292134

293135
setImmediate(() => {
294136
expect(res.finished).toBe(true);
137+
done();
295138
});
296139
});
297140
});
@@ -537,181 +380,6 @@ describe('tracingHandler', () => {
537380
});
538381
});
539382

540-
describe('extractRequestData()', () => {
541-
describe('default behaviour', () => {
542-
test('node', () => {
543-
expect(
544-
extractRequestData({
545-
headers: { host: 'example.com' },
546-
method: 'GET',
547-
secure: true,
548-
originalUrl: '/',
549-
}),
550-
).toEqual({
551-
cookies: {},
552-
headers: {
553-
host: 'example.com',
554-
},
555-
method: 'GET',
556-
query_string: null,
557-
url: 'https://example.com/',
558-
});
559-
});
560-
561-
test('degrades gracefully without request data', () => {
562-
expect(extractRequestData({})).toEqual({
563-
cookies: {},
564-
headers: {},
565-
method: undefined,
566-
query_string: null,
567-
url: 'http://<no host>',
568-
});
569-
});
570-
});
571-
572-
describe('cookies', () => {
573-
it('uses `req.cookies` if available', () => {
574-
expect(
575-
extractRequestData(
576-
{
577-
cookies: { foo: 'bar' },
578-
},
579-
['cookies'],
580-
),
581-
).toEqual({
582-
cookies: { foo: 'bar' },
583-
});
584-
});
585-
586-
it('parses the cookie header', () => {
587-
expect(
588-
extractRequestData(
589-
{
590-
headers: {
591-
cookie: 'foo=bar;',
592-
},
593-
},
594-
['cookies'],
595-
),
596-
).toEqual({
597-
cookies: { foo: 'bar' },
598-
});
599-
});
600-
601-
it('falls back if no cookies are defined', () => {
602-
expect(extractRequestData({}, ['cookies'])).toEqual({
603-
cookies: {},
604-
});
605-
});
606-
});
607-
608-
describe('data', () => {
609-
it('includes data from `req.body` if available', () => {
610-
expect(
611-
extractRequestData(
612-
{
613-
method: 'POST',
614-
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
615-
body: 'foo=bar',
616-
},
617-
['data'],
618-
),
619-
).toEqual({
620-
data: 'foo=bar',
621-
});
622-
});
623-
624-
it('encodes JSON body contents back to a string', () => {
625-
expect(
626-
extractRequestData(
627-
{
628-
method: 'POST',
629-
headers: { 'Content-Type': 'application/json' },
630-
body: { foo: 'bar' },
631-
},
632-
['data'],
633-
),
634-
).toEqual({
635-
data: '{"foo":"bar"}',
636-
});
637-
});
638-
});
639-
640-
describe('query_string', () => {
641-
it('parses the query parms from the url', () => {
642-
expect(
643-
extractRequestData(
644-
{
645-
headers: { host: 'example.com' },
646-
secure: true,
647-
originalUrl: '/?foo=bar',
648-
},
649-
['query_string'],
650-
),
651-
).toEqual({
652-
query_string: 'foo=bar',
653-
});
654-
});
655-
656-
it('gracefully degrades if url cannot be determined', () => {
657-
expect(extractRequestData({}, ['query_string'])).toEqual({
658-
query_string: null,
659-
});
660-
});
661-
});
662-
663-
describe('url', () => {
664-
test('express/koa', () => {
665-
expect(
666-
extractRequestData(
667-
{
668-
host: 'example.com',
669-
protocol: 'https',
670-
url: '/',
671-
},
672-
['url'],
673-
),
674-
).toEqual({
675-
url: 'https://example.com/',
676-
});
677-
});
678-
679-
test('node', () => {
680-
expect(
681-
extractRequestData(
682-
{
683-
headers: { host: 'example.com' },
684-
secure: true,
685-
originalUrl: '/',
686-
},
687-
['url'],
688-
),
689-
).toEqual({
690-
url: 'https://example.com/',
691-
});
692-
});
693-
});
694-
695-
describe('custom key', () => {
696-
it('includes the custom key if present', () => {
697-
expect(
698-
extractRequestData(
699-
{
700-
httpVersion: '1.1',
701-
},
702-
['httpVersion'],
703-
),
704-
).toEqual({
705-
httpVersion: '1.1',
706-
});
707-
});
708-
709-
it('gracefully degrades if the custom key is missing', () => {
710-
expect(extractRequestData({}, ['httpVersion'])).toEqual({});
711-
});
712-
});
713-
});
714-
715383
describe('errorHandler()', () => {
716384
const headers = { ears: 'furry', nose: 'wet', tongue: 'spotted', cookie: 'favorite=zukes' };
717385
const method = 'wagging';

0 commit comments

Comments
 (0)