Skip to content

Commit c0982ff

Browse files
committed
add tests
1 parent 9f00186 commit c0982ff

File tree

3 files changed

+217
-1
lines changed

3 files changed

+217
-1
lines changed

packages/nuxt/src/runtime/plugins/sentry-cloudflare.server.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import type { NuxtRenderHTMLContext } from 'nuxt/app';
88
import { sentryCaptureErrorHook } from '../hooks/captureErrorHook';
99
import { updateRouteBeforeResponse } from '../hooks/updateRouteBeforeResponse';
1010
import { addSentryTracingMetaTags } from '../utils';
11-
import { getCfProperties, getCloudflareProperties, isEventType } from '../utils/event-type';
11+
import { getCfProperties, getCloudflareProperties, isEventType } from '../utils/event-type-check';
1212

1313
/**
1414
* Sentry Cloudflare Nitro plugin for when using the "cloudflare-pages" preset in Nuxt.
Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
import type { CfProperties } from '@cloudflare/workers-types';
2+
import { describe, expect, it, vi } from 'vitest';
3+
import {
4+
type CfEventType,
5+
getCfProperties,
6+
getCloudflareProperties,
7+
isEventType,
8+
} from '../../../src/runtime/utils/event-type-check';
9+
10+
describe('event-type-check', () => {
11+
const mockCfProperties: CfProperties = {
12+
colo: 'IMLND',
13+
country: 'IL',
14+
region: 'CoreRegion',
15+
timezone: 'ImagineLand/Core',
16+
city: 'Core',
17+
} as CfProperties;
18+
19+
const mockCloudflareProperties = {
20+
context: {
21+
waitUntil: vi.fn(),
22+
passThroughOnException: vi.fn(),
23+
props: { key: 'value' },
24+
},
25+
request: { url: 'https://example.com' },
26+
env: { API_KEY: 'test' },
27+
};
28+
29+
const createUnnestedCfEvent = (): CfEventType => ({
30+
protocol: 'https',
31+
host: 'example.com',
32+
method: 'GET',
33+
headers: { 'user-agent': 'test' },
34+
context: {
35+
cf: mockCfProperties,
36+
cloudflare: mockCloudflareProperties,
37+
},
38+
});
39+
40+
const createPlatformCfEvent = (): CfEventType => ({
41+
protocol: 'https',
42+
host: 'example.com',
43+
method: 'POST',
44+
headers: { 'content-type': 'application/json' },
45+
context: {
46+
_platform: {
47+
cf: mockCfProperties,
48+
cloudflare: mockCloudflareProperties,
49+
},
50+
},
51+
});
52+
53+
describe('isEventType', () => {
54+
describe('should return true for valid Cloudflare events', () => {
55+
it.each([
56+
['direct cf event', createUnnestedCfEvent()],
57+
['platform cf event', createPlatformCfEvent()],
58+
])('%s', (_, event) => {
59+
expect(isEventType(event)).toBe(true);
60+
});
61+
});
62+
63+
describe('should return false for invalid inputs', () => {
64+
it.each([
65+
['null', null],
66+
['undefined', undefined],
67+
['string', 'invalid'],
68+
['number', 123],
69+
['boolean', true],
70+
['array', []],
71+
['empty object', {}],
72+
])('%s', (_, input) => {
73+
expect(isEventType(input)).toBe(false);
74+
});
75+
});
76+
77+
describe('should return false for objects missing required properties', () => {
78+
const baseEvent = createUnnestedCfEvent();
79+
80+
it.each([
81+
['missing protocol', { ...baseEvent, protocol: undefined }],
82+
['missing host', { ...baseEvent, host: undefined }],
83+
['missing context', { ...baseEvent, context: undefined }],
84+
['null context', { ...baseEvent, context: null }],
85+
['context without cf', { ...baseEvent, context: { cloudflare: mockCloudflareProperties } }],
86+
['context without cloudflare', { ...baseEvent, context: { cf: mockCfProperties } }],
87+
['context with null cf', { ...baseEvent, context: { cf: null, cloudflare: mockCloudflareProperties } }],
88+
['context with null cloudflare', { ...baseEvent, context: { cf: mockCfProperties, cloudflare: null } }],
89+
[
90+
'cloudflare without context property',
91+
{
92+
...baseEvent,
93+
context: {
94+
cf: mockCfProperties,
95+
cloudflare: { request: {}, env: {} },
96+
},
97+
},
98+
],
99+
])('%s', (_, invalidEvent) => {
100+
expect(isEventType(invalidEvent)).toBe(false);
101+
});
102+
});
103+
104+
describe('should return false for platform events missing required properties', () => {
105+
const basePlatformEvent = createPlatformCfEvent();
106+
107+
it.each([
108+
[
109+
'platform without cf',
110+
{
111+
...basePlatformEvent,
112+
context: {
113+
_platform: {
114+
cloudflare: mockCloudflareProperties,
115+
},
116+
},
117+
},
118+
],
119+
[
120+
'platform without cloudflare',
121+
{
122+
...basePlatformEvent,
123+
context: {
124+
_platform: {
125+
cf: mockCfProperties,
126+
},
127+
},
128+
},
129+
],
130+
[
131+
'platform with null cf',
132+
{
133+
...basePlatformEvent,
134+
context: {
135+
_platform: {
136+
cf: null,
137+
cloudflare: mockCloudflareProperties,
138+
},
139+
},
140+
},
141+
],
142+
])('%s', (_, invalidEvent) => {
143+
expect(isEventType(invalidEvent)).toBe(false);
144+
});
145+
});
146+
});
147+
148+
describe('getCfProperties', () => {
149+
it.each([
150+
['direct cf event', createUnnestedCfEvent()],
151+
['platform cf event', createPlatformCfEvent()],
152+
])('should extract cf properties from %s', (_, event) => {
153+
const result = getCfProperties(event);
154+
expect(result).toEqual(mockCfProperties);
155+
expect(result.colo).toBe('IMLND');
156+
expect(result.country).toBe('IL');
157+
});
158+
159+
it('should return the same cf properties for both event types', () => {
160+
const directEvent = createUnnestedCfEvent();
161+
const platformEvent = createPlatformCfEvent();
162+
163+
const directCf = getCfProperties(directEvent);
164+
const platformCf = getCfProperties(platformEvent);
165+
166+
expect(directCf).toEqual(platformCf);
167+
});
168+
});
169+
170+
describe('getCloudflareProperties', () => {
171+
it.each([
172+
['direct cf event', createUnnestedCfEvent()],
173+
['platform cf event', createPlatformCfEvent()],
174+
])('should extract cloudflare properties from %s', (_, event) => {
175+
const result = getCloudflareProperties(event);
176+
expect(result).toEqual(mockCloudflareProperties);
177+
expect(result.context).toBeDefined();
178+
expect(result.request).toEqual({ url: 'https://example.com' });
179+
expect(result.env).toEqual({ API_KEY: 'test' });
180+
});
181+
182+
it('should return the same cloudflare properties for both event types', () => {
183+
const directEvent = createUnnestedCfEvent();
184+
const platformEvent = createPlatformCfEvent();
185+
186+
const directCloudflare = getCloudflareProperties(directEvent);
187+
const platformCloudflare = getCloudflareProperties(platformEvent);
188+
189+
expect(directCloudflare).toEqual(platformCloudflare);
190+
});
191+
});
192+
193+
describe('integration tests', () => {
194+
it('should work together for a complete workflow', () => {
195+
const event = createUnnestedCfEvent();
196+
197+
expect(isEventType(event)).toBe(true);
198+
199+
const cf = getCfProperties(event);
200+
const cloudflare = getCloudflareProperties(event);
201+
202+
expect(cf.country).toBe('IL');
203+
expect(cloudflare.request?.url).toBe('https://example.com');
204+
});
205+
206+
it('should handle both event structures consistently', () => {
207+
const events = [createUnnestedCfEvent(), createPlatformCfEvent()];
208+
209+
events.forEach(event => {
210+
expect(isEventType(event)).toBe(true);
211+
expect(getCfProperties(event)).toEqual(mockCfProperties);
212+
expect(getCloudflareProperties(event)).toEqual(mockCloudflareProperties);
213+
});
214+
});
215+
});
216+
});

0 commit comments

Comments
 (0)