-
-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Expand file tree
/
Copy pathsdk.test.ts
More file actions
165 lines (147 loc) · 5.73 KB
/
sdk.test.ts
File metadata and controls
165 lines (147 loc) · 5.73 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
import type { Event, EventProcessor } from '@sentry/core';
import * as SentryNode from '@sentry/node';
import { getGlobalScope, Scope, SDK_VERSION } from '@sentry/node';
import { beforeEach, describe, expect, it, vi } from 'vitest';
import { init } from '../../src/server';
import { clientSourceMapErrorFilter, lowQualityTransactionsFilter } from '../../src/server/sdk';
const nodeInit = vi.spyOn(SentryNode, 'init');
describe('Nuxt Server SDK', () => {
describe('init', () => {
beforeEach(() => {
vi.clearAllMocks();
});
it('Adds Nuxt metadata to the SDK options', () => {
expect(nodeInit).not.toHaveBeenCalled();
init({
dsn: 'https://public@dsn.ingest.sentry.io/1337',
});
const expectedMetadata = {
_metadata: {
sdk: {
name: 'sentry.javascript.nuxt',
version: SDK_VERSION,
packages: [
{ name: 'npm:@sentry/nuxt', version: SDK_VERSION },
{ name: 'npm:@sentry/node', version: SDK_VERSION },
],
},
},
};
expect(nodeInit).toHaveBeenCalledTimes(1);
expect(nodeInit).toHaveBeenLastCalledWith(expect.objectContaining(expectedMetadata));
});
it('returns client from init', () => {
expect(init({})).not.toBeUndefined();
});
describe('lowQualityTransactionsFilter', () => {
const options = { debug: false };
const filter = lowQualityTransactionsFilter(options);
describe('filters out low quality transactions', () => {
it.each([
'GET /_nuxt/some_asset.js',
'GET _nuxt/some_asset.js',
'GET /icons/favicon.ico',
'GET /assets/logo.png',
'GET /icons/zones/forest.svg',
])('filters out low quality transaction: (%s)', transaction => {
const event = { type: 'transaction' as const, transaction };
expect(filter(event, {})).toBeNull();
});
});
describe('keeps high quality transactions', () => {
// Nuxt parametrizes routes sometimes in a special way - especially catchAll o.O
it.each(['GET /', 'POST /_server', 'GET /catchAll/:id(.*)*', 'GET /article/:slug()', 'GET /user/:id'])(
'does not filter out route transactions (%s)',
transaction => {
const event = { type: 'transaction' as const, transaction };
expect(filter(event, {})).toEqual(event);
},
);
});
it('does not filter non-transaction events', () => {
const event = { type: 'error' as const, transaction: 'GET /assets/image.png' } as unknown as Event;
expect(filter(event, {})).toEqual(event);
});
it('handles events without transaction property', () => {
const event = { type: 'transaction' as const };
expect(filter(event, {})).toEqual(event);
});
});
it('registers an event processor', async () => {
let passedEventProcessors: EventProcessor[] = [];
const addEventProcessor = vi
.spyOn(getGlobalScope(), 'addEventProcessor')
.mockImplementation((eventProcessor: EventProcessor) => {
passedEventProcessors = [...passedEventProcessors, eventProcessor];
return new Scope();
});
init({
dsn: 'https://public@dsn.ingest.sentry.io/1337',
});
expect(addEventProcessor).toHaveBeenCalledTimes(2);
expect(passedEventProcessors[0]?.id).toEqual('NuxtLowQualityTransactionsFilter');
expect(passedEventProcessors[1]?.id).toEqual('NuxtClientSourceMapErrorFilter');
});
});
describe('clientSourceMapErrorFilter', () => {
const options = { debug: false };
const filter = clientSourceMapErrorFilter(options);
describe('filters out errors', () => {
it.each([
[
'source map errors with leading /',
{
exception: { values: [{ value: "ENOENT: no such file or directory, open '/path/to/_nuxt/file.js.map'" }] },
},
],
[
'source map errors without leading /',
{ exception: { values: [{ value: "ENOENT: no such file or directory, open 'path/to/_nuxt/file.js.map'" }] } },
],
[
'source map errors with long path',
{
exception: {
values: [
{
value:
"ENOENT: no such file or directory, open 'path/to/public/_nuxt/public/long/long/path/file.js.map'",
},
],
},
},
],
])('filters out %s', (_, event) => {
// @ts-expect-error Event type is not correct in tests
expect(filter(event)).toBeNull();
});
});
describe('does not filter out errors', () => {
it.each([
['other errors', { exception: { values: [{ value: 'Some other error' }] } }],
['events with no exceptions', {}],
[
'events without _nuxt in path',
{
exception: { values: [{ value: "ENOENT: no such file or directory, open '/path/to/other/file.js.map'" }] },
},
],
[
'source map errors with different casing',
{
exception: { values: [{ value: "ENOENT: No Such file or directory, open '/path/to/_nuxt/file.js.map'" }] },
},
],
[
'non-source-map file',
{ exception: { values: [{ value: "ENOENT: no such file or directory, open '/path/to/_nuxt/file.js'" }] } },
],
['events with no exception values', { exception: { values: [] } }],
['events with null exception value', { exception: { values: [null] } }],
])('does not filter out %s', (_, event) => {
// @ts-expect-error Event type is not correct in tests
expect(filter(event)).toEqual(event);
});
});
});
});