Skip to content

Commit e57c9a5

Browse files
committed
test: Browser transports tests
1 parent a8b0287 commit e57c9a5

File tree

7 files changed

+186
-9
lines changed

7 files changed

+186
-9
lines changed

packages/browser/src/transports/base.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { SentryError } from '@sentry/core';
1+
import { DSN, SentryError } from '@sentry/core';
22
import {
33
DSNComponents,
44
SentryEvent,
@@ -12,16 +12,16 @@ export abstract class BaseTransport implements Transport {
1212
/**
1313
* @inheritDoc
1414
*/
15-
public endpointUrl: string;
15+
public url: string;
1616

1717
public constructor(public options: TransportOptions) {
18-
this.endpointUrl = this.composeEndpointUrl(options.dsn);
18+
this.url = this.composeUrl(new DSN(options.dsn));
1919
}
2020

2121
/**
2222
* @inheritDoc
2323
*/
24-
public composeEndpointUrl(dsn: DSNComponents): string {
24+
public composeUrl(dsn: DSNComponents): string {
2525
const auth = {
2626
sentry_key: dsn.user,
2727
sentry_secret: '',

packages/browser/src/transports/fetch.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,6 @@ export class FetchTransport extends BaseTransport {
2222
};
2323

2424
// TODO: Safe _window access
25-
return window.fetch(this.endpointUrl, defaultOptions);
25+
return window.fetch(this.url, defaultOptions);
2626
}
2727
}

packages/browser/src/transports/xhr.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ export class XHRTransport extends BaseTransport {
2323
reject(request);
2424
};
2525

26-
request.open('POST', this.endpointUrl);
26+
request.open('POST', this.url);
2727
request.send(serialize(event));
2828
});
2929
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { DSNComponents } from '@sentry/types';
2+
import { expect } from 'chai';
3+
import { BaseTransport } from '../../src/transports/base';
4+
5+
const testDSN = 'https://[email protected]/42';
6+
7+
class SimpleTransport extends BaseTransport {}
8+
// tslint:disable-next-line:max-classes-per-file
9+
class ComplexTransport extends BaseTransport {
10+
public composeUrl(dsn: DSNComponents): string {
11+
return `https://${dsn.host}/${dsn.user}`;
12+
}
13+
}
14+
15+
describe('BaseTransport', () => {
16+
it('doesnt provide send() implementation', async () => {
17+
const transport = new SimpleTransport({ dsn: testDSN });
18+
19+
try {
20+
await transport.send({});
21+
} catch (e) {
22+
expect(e.message).equal('Transport Class has to implement `send` method');
23+
}
24+
});
25+
26+
it('provides composeEndpointUrl() implementation', () => {
27+
const transport = new SimpleTransport({ dsn: testDSN });
28+
expect(transport.url).equal(
29+
'https://sentry.io/api/42/store/?sentry_key=123&sentry_version=7',
30+
);
31+
});
32+
33+
it('allows overriding composeEndpointUrl() implementation', () => {
34+
const transport = new ComplexTransport({ dsn: testDSN });
35+
expect(transport.url).equal('https://sentry.io/123');
36+
});
37+
});
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import { Transport } from '@sentry/types';
2+
import { expect } from 'chai';
3+
import { SinonStub, stub } from 'sinon';
4+
import { FetchTransport } from '../../src/transports/fetch';
5+
6+
const testDSN = 'https://[email protected]/42';
7+
const transportUrl =
8+
'https://sentry.io/api/42/store/?sentry_key=123&sentry_version=7';
9+
const payload = {
10+
event_id: '1337',
11+
message: 'Pickle Rick',
12+
user: {
13+
username: 'Morty',
14+
},
15+
};
16+
17+
let fetch: SinonStub;
18+
let transport: Transport;
19+
20+
describe('FetchTransport', () => {
21+
beforeEach(() => {
22+
fetch = stub(window, 'fetch');
23+
transport = new FetchTransport({ dsn: testDSN });
24+
});
25+
26+
afterEach(() => {
27+
fetch.restore();
28+
});
29+
30+
it('inherits composeEndpointUrl() implementation', () => {
31+
expect(transport.url).equal(transportUrl);
32+
});
33+
34+
describe('send()', async () => {
35+
it('sends a request to Sentry servers', async () => {
36+
const response = new Response('', {
37+
status: 200,
38+
});
39+
40+
fetch.returns(Promise.resolve(response));
41+
42+
return transport.send(payload).then(res => {
43+
expect(res.status).equal(200);
44+
expect(fetch.calledOnce).equal(true);
45+
expect(
46+
fetch.calledWith(transportUrl, {
47+
body: JSON.stringify(payload),
48+
keepalive: true,
49+
method: 'POST',
50+
referrerPolicy: 'origin',
51+
}),
52+
).equal(true);
53+
});
54+
});
55+
56+
it('rejects with non-200 status code', async () => {
57+
const response = new Response('', {
58+
status: 403,
59+
});
60+
61+
fetch.returns(Promise.reject(response));
62+
63+
return transport.send(payload).catch(res => {
64+
expect(res.status).equal(403);
65+
expect(fetch.calledOnce).equal(true);
66+
expect(
67+
fetch.calledWith(transportUrl, {
68+
body: JSON.stringify(payload),
69+
keepalive: true,
70+
method: 'POST',
71+
referrerPolicy: 'origin',
72+
}),
73+
).equal(true);
74+
});
75+
});
76+
});
77+
});
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import { Transport } from '@sentry/types';
2+
import { expect } from 'chai';
3+
import { fakeServer, SinonFakeServer } from 'sinon';
4+
import { XHRTransport } from '../../src/transports/xhr';
5+
6+
const testDSN = 'https://[email protected]/42';
7+
const transportUrl =
8+
'https://sentry.io/api/42/store/?sentry_key=123&sentry_version=7';
9+
const payload = {
10+
event_id: '1337',
11+
message: 'Pickle Rick',
12+
user: {
13+
username: 'Morty',
14+
},
15+
};
16+
17+
let server: SinonFakeServer;
18+
let transport: Transport;
19+
20+
describe('XHRTransport', () => {
21+
beforeEach(() => {
22+
server = fakeServer.create();
23+
server.respondImmediately = true;
24+
transport = new XHRTransport({ dsn: testDSN });
25+
});
26+
27+
afterEach(() => {
28+
server.restore();
29+
});
30+
31+
it('inherits composeEndpointUrl() implementation', () => {
32+
expect(transport.url).equal(transportUrl);
33+
});
34+
35+
describe('send()', async () => {
36+
it('sends a request to Sentry servers', async () => {
37+
server.respondWith('POST', transportUrl, [200, {}, '']);
38+
39+
return transport.send(payload).then(res => {
40+
expect(res.status).equal(200);
41+
42+
const request = server.requests[0];
43+
expect(server.requests.length).equal(1);
44+
expect(request.method).equal('POST');
45+
expect(JSON.parse(request.requestBody)).deep.equal(payload);
46+
});
47+
});
48+
49+
it('rejects with non-200 status code', async () => {
50+
server.respondWith('POST', transportUrl, [403, {}, '']);
51+
52+
return transport.send(payload).catch(res => {
53+
expect(res.status).equal(403);
54+
55+
const request = server.requests[0];
56+
expect(server.requests.length).equal(1);
57+
expect(request.method).equal('POST');
58+
expect(JSON.parse(request.requestBody)).deep.equal(payload);
59+
});
60+
});
61+
});
62+
});

packages/types/src/index.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -150,14 +150,15 @@ export interface Integration {
150150
install(): void;
151151
}
152152

153+
/** TODO */
153154
export interface TransportOptions {
154-
dsn: DSNComponents;
155+
dsn: DSNLike;
155156
}
156157

157158
/** TODO */
158159
export interface Transport {
159-
endpointUrl: string;
160-
composeEndpointUrl(dsn: DSNComponents): string;
160+
url: string;
161+
composeUrl(dsn: DSNComponents): string;
161162
send(event: SentryEvent): Promise<Response | XMLHttpRequest>;
162163
}
163164

0 commit comments

Comments
 (0)