Skip to content

Commit 3bcbf7e

Browse files
committed
tests: added e2e tests for storage instrumentation
1 parent e85f173 commit 3bcbf7e

File tree

6 files changed

+422
-0
lines changed

6 files changed

+422
-0
lines changed

dev-packages/e2e-tests/test-applications/nuxt-3/nuxt.config.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,11 @@ export default defineNuxtConfig({
1111
},
1212
},
1313
},
14+
nitro: {
15+
storage: {
16+
'test-storage': {
17+
driver: 'memory',
18+
},
19+
},
20+
},
1421
});
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import { useStorage } from '#imports';
2+
import { defineEventHandler } from 'h3';
3+
4+
export default defineEventHandler(async _event => {
5+
const storage = useStorage('test-storage');
6+
7+
// Test all instrumented methods
8+
const results: Record<string, unknown> = {};
9+
10+
// Test setItem
11+
await storage.setItem('user:123', { name: 'John Doe', email: '[email protected]' });
12+
results.setItem = 'success';
13+
14+
// Test setItemRaw
15+
await storage.setItemRaw('raw:data', Buffer.from('raw data'));
16+
results.setItemRaw = 'success';
17+
18+
// Manually set batch items (setItems not supported by memory driver)
19+
await storage.setItem('batch:1', 'value1');
20+
await storage.setItem('batch:2', 'value2');
21+
22+
// Test hasItem
23+
const hasUser = await storage.hasItem('user:123');
24+
results.hasItem = hasUser;
25+
26+
// Test getItem
27+
const user = await storage.getItem('user:123');
28+
results.getItem = user;
29+
30+
// Test getItemRaw
31+
const rawData = await storage.getItemRaw('raw:data');
32+
results.getItemRaw = rawData?.toString();
33+
34+
// Test getKeys
35+
const keys = await storage.getKeys('batch:');
36+
results.getKeys = keys;
37+
38+
// Test removeItem
39+
await storage.removeItem('batch:1');
40+
results.removeItem = 'success';
41+
42+
// Test clear
43+
await storage.clear();
44+
results.clear = 'success';
45+
46+
// Verify clear worked
47+
const keysAfterClear = await storage.getKeys();
48+
results.keysAfterClear = keysAfterClear;
49+
50+
return {
51+
success: true,
52+
results,
53+
};
54+
});
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
import { expect, test } from '@playwright/test';
2+
import { waitForTransaction } from '@sentry-internal/test-utils';
3+
import { SEMANTIC_ATTRIBUTE_CACHE_HIT, SEMANTIC_ATTRIBUTE_CACHE_KEY } from '@sentry/core';
4+
import { SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '@sentry/nuxt';
5+
6+
test.describe('Storage Instrumentation', () => {
7+
const prefixKey = (key: string) => `test-storage:${key}`;
8+
9+
test('instruments all storage operations and creates spans with correct attributes', async ({ request }) => {
10+
const transactionPromise = waitForTransaction('nuxt-3', transactionEvent => {
11+
return transactionEvent.transaction?.includes('GET /api/storage-test') ?? false;
12+
});
13+
14+
const response = await request.get('/api/storage-test');
15+
expect(response.status()).toBe(200);
16+
17+
const transaction = await transactionPromise;
18+
19+
// Helper to find spans by operation
20+
const findSpansByOp = (op: string) => {
21+
return transaction.spans?.filter(span => span.data?.[SEMANTIC_ATTRIBUTE_SENTRY_OP] === op) || [];
22+
};
23+
24+
// Test setItem spans
25+
const setItemSpans = findSpansByOp('cache.set_item');
26+
expect(setItemSpans.length).toBeGreaterThanOrEqual(1);
27+
const setItemSpan = setItemSpans.find(span => span.data?.[SEMANTIC_ATTRIBUTE_CACHE_KEY] === prefixKey('user:123'));
28+
expect(setItemSpan).toBeDefined();
29+
expect(setItemSpan?.data).toMatchObject({
30+
[SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.set_item',
31+
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.cache.nuxt',
32+
[SEMANTIC_ATTRIBUTE_CACHE_KEY]: prefixKey('user:123'),
33+
'nuxt.storage.op': 'setItem',
34+
'nuxt.storage.mount': 'test-storage:',
35+
'nuxt.storage.driver': 'memory',
36+
});
37+
expect(setItemSpan?.description).toBe(prefixKey('user:123'));
38+
39+
// Test setItemRaw spans
40+
const setItemRawSpans = findSpansByOp('cache.set_item_raw');
41+
expect(setItemRawSpans.length).toBeGreaterThanOrEqual(1);
42+
const setItemRawSpan = setItemRawSpans.find(
43+
span => span.data?.[SEMANTIC_ATTRIBUTE_CACHE_KEY] === prefixKey('raw:data'),
44+
);
45+
expect(setItemRawSpan).toBeDefined();
46+
expect(setItemRawSpan?.data).toMatchObject({
47+
[SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.set_item_raw',
48+
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.cache.nuxt',
49+
[SEMANTIC_ATTRIBUTE_CACHE_KEY]: prefixKey('raw:data'),
50+
'nuxt.storage.op': 'setItemRaw',
51+
'nuxt.storage.mount': 'test-storage:',
52+
'nuxt.storage.driver': 'memory',
53+
});
54+
55+
// Test hasItem spans - should have cache hit attribute
56+
const hasItemSpans = findSpansByOp('cache.has_item');
57+
expect(hasItemSpans.length).toBeGreaterThanOrEqual(1);
58+
const hasItemSpan = hasItemSpans.find(span => span.data?.[SEMANTIC_ATTRIBUTE_CACHE_KEY] === prefixKey('user:123'));
59+
expect(hasItemSpan).toBeDefined();
60+
expect(hasItemSpan?.data).toMatchObject({
61+
[SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.has_item',
62+
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.cache.nuxt',
63+
[SEMANTIC_ATTRIBUTE_CACHE_KEY]: prefixKey('user:123'),
64+
[SEMANTIC_ATTRIBUTE_CACHE_HIT]: true,
65+
'nuxt.storage.op': 'hasItem',
66+
'nuxt.storage.mount': 'test-storage:',
67+
'nuxt.storage.driver': 'memory',
68+
});
69+
70+
// Test getItem spans - should have cache hit attribute
71+
const getItemSpans = findSpansByOp('cache.get_item');
72+
expect(getItemSpans.length).toBeGreaterThanOrEqual(1);
73+
const getItemSpan = getItemSpans.find(span => span.data?.[SEMANTIC_ATTRIBUTE_CACHE_KEY] === prefixKey('user:123'));
74+
expect(getItemSpan).toBeDefined();
75+
expect(getItemSpan?.data).toMatchObject({
76+
[SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.get_item',
77+
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.cache.nuxt',
78+
[SEMANTIC_ATTRIBUTE_CACHE_KEY]: prefixKey('user:123'),
79+
[SEMANTIC_ATTRIBUTE_CACHE_HIT]: true,
80+
'nuxt.storage.op': 'getItem',
81+
'nuxt.storage.mount': 'test-storage:',
82+
'nuxt.storage.driver': 'memory',
83+
});
84+
expect(getItemSpan?.description).toBe(prefixKey('user:123'));
85+
86+
// Test getItemRaw spans - should have cache hit attribute
87+
const getItemRawSpans = findSpansByOp('cache.get_item_raw');
88+
expect(getItemRawSpans.length).toBeGreaterThanOrEqual(1);
89+
const getItemRawSpan = getItemRawSpans.find(
90+
span => span.data?.[SEMANTIC_ATTRIBUTE_CACHE_KEY] === prefixKey('raw:data'),
91+
);
92+
expect(getItemRawSpan).toBeDefined();
93+
expect(getItemRawSpan?.data).toMatchObject({
94+
[SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.get_item_raw',
95+
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.cache.nuxt',
96+
[SEMANTIC_ATTRIBUTE_CACHE_KEY]: prefixKey('raw:data'),
97+
[SEMANTIC_ATTRIBUTE_CACHE_HIT]: true,
98+
'nuxt.storage.op': 'getItemRaw',
99+
'nuxt.storage.mount': 'test-storage:',
100+
'nuxt.storage.driver': 'memory',
101+
});
102+
103+
// Test getKeys spans
104+
const getKeysSpans = findSpansByOp('cache.get_keys');
105+
expect(getKeysSpans.length).toBeGreaterThanOrEqual(1);
106+
expect(getKeysSpans[0]?.data).toMatchObject({
107+
[SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.get_keys',
108+
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.cache.nuxt',
109+
'nuxt.storage.op': 'getKeys',
110+
'nuxt.storage.mount': 'test-storage:',
111+
'nuxt.storage.driver': 'memory',
112+
});
113+
114+
// Test removeItem spans
115+
const removeItemSpans = findSpansByOp('cache.remove_item');
116+
expect(removeItemSpans.length).toBeGreaterThanOrEqual(1);
117+
const removeItemSpan = removeItemSpans.find(
118+
span => span.data?.[SEMANTIC_ATTRIBUTE_CACHE_KEY] === prefixKey('batch:1'),
119+
);
120+
expect(removeItemSpan).toBeDefined();
121+
expect(removeItemSpan?.data).toMatchObject({
122+
[SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.remove_item',
123+
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.cache.nuxt',
124+
[SEMANTIC_ATTRIBUTE_CACHE_KEY]: prefixKey('batch:1'),
125+
'nuxt.storage.op': 'removeItem',
126+
'nuxt.storage.mount': 'test-storage:',
127+
'nuxt.storage.driver': 'memory',
128+
});
129+
130+
// Test clear spans
131+
const clearSpans = findSpansByOp('cache.clear');
132+
expect(clearSpans.length).toBeGreaterThanOrEqual(1);
133+
expect(clearSpans[0]?.data).toMatchObject({
134+
[SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.clear',
135+
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.cache.nuxt',
136+
'nuxt.storage.op': 'clear',
137+
'nuxt.storage.mount': 'test-storage:',
138+
'nuxt.storage.driver': 'memory',
139+
});
140+
141+
// Verify all spans have OK status
142+
const allStorageSpans = transaction.spans?.filter(
143+
span => span.data?.[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN] === 'auto.cache.nuxt',
144+
);
145+
expect(allStorageSpans?.length).toBeGreaterThan(0);
146+
allStorageSpans?.forEach(span => {
147+
expect(span.status).toBe('ok');
148+
});
149+
});
150+
});

dev-packages/e2e-tests/test-applications/nuxt-4/nuxt.config.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,11 @@ export default defineNuxtConfig({
2121
},
2222
},
2323
},
24+
nitro: {
25+
storage: {
26+
'test-storage': {
27+
driver: 'memory',
28+
},
29+
},
30+
},
2431
});
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import { useStorage } from '#imports';
2+
import { defineEventHandler } from 'h3';
3+
4+
export default defineEventHandler(async _event => {
5+
const storage = useStorage('test-storage');
6+
7+
// Test all instrumented methods
8+
const results: Record<string, unknown> = {};
9+
10+
// Test setItem
11+
await storage.setItem('user:123', { name: 'John Doe', email: '[email protected]' });
12+
results.setItem = 'success';
13+
14+
// Test setItemRaw
15+
await storage.setItemRaw('raw:data', Buffer.from('raw data'));
16+
results.setItemRaw = 'success';
17+
18+
// Manually set batch items (setItems not supported by memory driver)
19+
await storage.setItem('batch:1', 'value1');
20+
await storage.setItem('batch:2', 'value2');
21+
22+
// Test hasItem
23+
const hasUser = await storage.hasItem('user:123');
24+
results.hasItem = hasUser;
25+
26+
// Test getItem
27+
const user = await storage.getItem('user:123');
28+
results.getItem = user;
29+
30+
// Test getItemRaw
31+
const rawData = await storage.getItemRaw('raw:data');
32+
results.getItemRaw = rawData?.toString();
33+
34+
// Test getKeys
35+
const keys = await storage.getKeys('batch:');
36+
results.getKeys = keys;
37+
38+
// Test removeItem
39+
await storage.removeItem('batch:1');
40+
results.removeItem = 'success';
41+
42+
// Test clear
43+
await storage.clear();
44+
results.clear = 'success';
45+
46+
// Verify clear worked
47+
const keysAfterClear = await storage.getKeys();
48+
results.keysAfterClear = keysAfterClear;
49+
50+
return {
51+
success: true,
52+
results,
53+
};
54+
});

0 commit comments

Comments
 (0)