Skip to content

Commit 92f9aeb

Browse files
committed
test(node): Document Node integration tests.
1 parent 37b14bf commit 92f9aeb

File tree

3 files changed

+90
-1
lines changed

3 files changed

+90
-1
lines changed
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# Integration Tests for Sentry Node.JS SDK
2+
3+
## Structure
4+
5+
```
6+
suites/
7+
|---- public-api/
8+
|---- captureMessage/
9+
|---- test.ts [assertions]
10+
|---- scenario.ts [Sentry initialization and test subject]
11+
|---- customTest/
12+
|---- test.ts [assertions]
13+
|---- scenario_1.ts [optional extra test scenario]
14+
|---- scenario_2.ts [optional extra test scenario]
15+
|---- server_with_mongo.ts [optional custom server]
16+
|---- server_with_postgres.ts [optional custom server]
17+
utils/
18+
|---- defaults/
19+
|---- server.ts [default Express server configuration]
20+
```
21+
22+
The tests are grouped by their scopes, such as `public-api` or `tracing`. In every group of tests, there are multiple folders containing test scenarios and assertions.
23+
24+
Tests run on Express servers (a server instance per test). By default, a simple server template inside `utils/defaults/server.ts` is used. Every server instance runs on a different port.
25+
26+
A custom server configuration can be used, supplying a script that exports a valid express server instance as default. `runServer` utility function accepts an optional `serverPath` argument for this purpose.
27+
28+
`scenario.ts` contains the initialization logic and the test subject. By default, `{TEST_DIR}/scenario.ts` is used, but `runServer` also accepts an optional `scenarioPath` argument for non-standard usage.
29+
30+
`test.ts` is required for each test case, and contains the server runner logic, request interceptors for Sentry requests, and assertions. Test server, interceptors and assertions are all run on the same Jest thread.
31+
32+
### Utilities
33+
34+
`utils/` contains helpers and Sentry-specific assertions that can be used in (`test.ts`).
35+
36+
## Running Tests Locally
37+
38+
Tests can be run locally using the latest version of Chromium with:
39+
40+
`yarn test`
41+
42+
To run tests with Jest's watch mode:
43+
44+
`yarn test:jest`
45+
46+
To filter tests by their title:
47+
48+
`yarn test -t "set different properties of a scope"`
49+
50+
You can refer to [Jest documentation](https://jestjs.io/docs/cli) for other CLI options.

packages/node-integration-tests/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111
"lint:eslint": "eslint . --cache --cache-location '../../eslintcache/' --format stylish",
1212
"lint:prettier": "prettier --check \"{suites,utils}/**/*.ts\"",
1313
"type-check": "tsc",
14-
"test": "jest --detectOpenHandles --runInBand --forceExit"
14+
"test": "jest --detectOpenHandles --runInBand --forceExit",
15+
"test:watch": "yarn test --watch"
1516
},
1617
"dependencies": {
1718
"express": "^4.17.3",

packages/node-integration-tests/utils/index.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ import nock from 'nock';
55
import * as path from 'path';
66
import { getPortPromise } from 'portfinder';
77

8+
/**
9+
* Asserts against a Sentry Event ignoring non-deterministic properties
10+
*
11+
* @param {Record<string, unknown>} actual
12+
* @param {Record<string, unknown>} expected
13+
*/
814
const assertSentryEvent = (actual: Record<string, unknown>, expected: Record<string, unknown>): void => {
915
expect(actual).toMatchObject({
1016
event_id: expect.any(String),
@@ -13,6 +19,12 @@ const assertSentryEvent = (actual: Record<string, unknown>, expected: Record<str
1319
});
1420
};
1521

22+
/**
23+
* Asserts against a Sentry Transaction ignoring non-deterministic properties
24+
*
25+
* @param {Record<string, unknown>} actual
26+
* @param {Record<string, unknown>} expected
27+
*/
1628
const assertSentryTransaction = (actual: Record<string, unknown>, expected: Record<string, unknown>): void => {
1729
expect(actual).toMatchObject({
1830
event_id: expect.any(String),
@@ -24,10 +36,22 @@ const assertSentryTransaction = (actual: Record<string, unknown>, expected: Reco
2436
});
2537
};
2638

39+
/**
40+
* Parses response body containing an Envelope
41+
*
42+
* @param {string} body
43+
* @return {*} {Array<Record<string, unknown>>}
44+
*/
2745
const parseEnvelope = (body: string): Array<Record<string, unknown>> => {
2846
return body.split('\n').map(e => JSON.parse(e));
2947
};
3048

49+
/**
50+
* Intercepts and extracts a request containing a Sentry Event
51+
*
52+
* @param {string} url
53+
* @return {*} {Promise<Record<string, unknown>>}
54+
*/
3155
const getEventRequest = async (url: string): Promise<Record<string, unknown>> => {
3256
return new Promise(resolve => {
3357
nock('https://dsn.ingest.sentry.io')
@@ -41,6 +65,12 @@ const getEventRequest = async (url: string): Promise<Record<string, unknown>> =>
4165
});
4266
};
4367

68+
/**
69+
* Intercepts and extracts a request containing a Sentry Envelope
70+
*
71+
* @param {string} url
72+
* @return {*} {Promise<Array<Record<string, unknown>>>}
73+
*/
4474
const getEnvelopeRequest = async (url: string): Promise<Array<Record<string, unknown>>> => {
4575
return new Promise(resolve => {
4676
nock('https://dsn.ingest.sentry.io')
@@ -55,6 +85,14 @@ const getEnvelopeRequest = async (url: string): Promise<Array<Record<string, unk
5585
});
5686
};
5787

88+
/**
89+
* Runs a test server
90+
*
91+
* @param {string} testDir
92+
* @param {string} [serverPath]
93+
* @param {string} [scenarioPath]
94+
* @return {*} {Promise<string>}
95+
*/
5896
async function runServer(testDir: string, serverPath?: string, scenarioPath?: string): Promise<string> {
5997
const port = await getPortPromise();
6098
const url = `http://localhost:${port}/test`;

0 commit comments

Comments
 (0)