Skip to content

Commit c4aceeb

Browse files
committed
refactor(utm): add tests for UTM validation
1 parent e6a179f commit c4aceeb

File tree

1 file changed

+174
-0
lines changed

1 file changed

+174
-0
lines changed

test/utils/utm.test.ts

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
import { validateUtmParams, sanitizeUtmParams } from '../../src/utils/utm/utm';
2+
3+
describe('UTM Utils', () => {
4+
describe('validateUtmParams', () => {
5+
it('should return true for undefined or null utm', () => {
6+
expect(validateUtmParams(undefined)).toBe(true);
7+
expect(validateUtmParams(null as any)).toBe(true);
8+
});
9+
10+
it('should return true for empty object', () => {
11+
expect(validateUtmParams({})).toBe(true);
12+
});
13+
14+
it('should return false for non-object types', () => {
15+
expect(validateUtmParams('string' as any)).toBe(false);
16+
expect(validateUtmParams(123 as any)).toBe(false);
17+
expect(validateUtmParams(true as any)).toBe(false);
18+
expect(validateUtmParams([] as any)).toBe(false);
19+
});
20+
21+
it('should return false for invalid UTM keys', () => {
22+
expect(validateUtmParams({ invalidKey: 'value' } as any)).toBe(false);
23+
expect(validateUtmParams({ source: 'google', invalidKey: 'value' } as any)).toBe(false);
24+
});
25+
26+
it('should return true for valid UTM keys', () => {
27+
expect(validateUtmParams({ source: 'google' })).toBe(true);
28+
expect(validateUtmParams({ medium: 'cpc' })).toBe(true);
29+
expect(validateUtmParams({ campaign: 'spring_2025' })).toBe(true);
30+
expect(validateUtmParams({ content: 'ad_variant_a' })).toBe(true);
31+
expect(validateUtmParams({ term: 'error_tracker' })).toBe(true);
32+
});
33+
34+
it('should return true for multiple valid UTM keys', () => {
35+
const validUtm = {
36+
source: 'google',
37+
medium: 'cpc',
38+
campaign: 'spring_2025_launch',
39+
content: 'ad_variant_a',
40+
term: 'error_tracker',
41+
};
42+
expect(validateUtmParams(validUtm)).toBe(true);
43+
});
44+
45+
it('should return false for non-string values', () => {
46+
expect(validateUtmParams({ source: 123 } as any)).toBe(false);
47+
expect(validateUtmParams({ source: true } as any)).toBe(false);
48+
expect(validateUtmParams({ source: {} } as any)).toBe(false);
49+
expect(validateUtmParams({ source: [] } as any)).toBe(false);
50+
});
51+
52+
it('should return false for empty string values', () => {
53+
expect(validateUtmParams({ source: '' })).toBe(false);
54+
});
55+
56+
it('should return false for values that are too long', () => {
57+
const longValue = 'a'.repeat(201);
58+
expect(validateUtmParams({ source: longValue })).toBe(false);
59+
});
60+
61+
it('should return true for values at maximum length', () => {
62+
const maxLengthValue = 'a'.repeat(200);
63+
expect(validateUtmParams({ source: maxLengthValue })).toBe(true);
64+
});
65+
66+
it('should return false for values with invalid characters', () => {
67+
expect(validateUtmParams({ source: 'google@example' })).toBe(false);
68+
expect(validateUtmParams({ source: 'google#hash' })).toBe(false);
69+
expect(validateUtmParams({ source: 'google$money' })).toBe(false);
70+
expect(validateUtmParams({ source: 'google%percent' })).toBe(false);
71+
});
72+
73+
it('should return true for values with valid characters', () => {
74+
expect(validateUtmParams({ source: 'google-ads' })).toBe(true);
75+
expect(validateUtmParams({ source: 'google_ads' })).toBe(true);
76+
expect(validateUtmParams({ source: 'google.com' })).toBe(true);
77+
expect(validateUtmParams({ source: 'Google Ads 123' })).toBe(true);
78+
});
79+
80+
it('should handle undefined and null values in object', () => {
81+
expect(validateUtmParams({ source: 'google', medium: undefined })).toBe(true);
82+
expect(validateUtmParams({ source: 'google', medium: null as any })).toBe(true);
83+
});
84+
});
85+
86+
describe('sanitizeUtmParams', () => {
87+
it('should return undefined for undefined or null utm', () => {
88+
expect(sanitizeUtmParams(undefined)).toBeUndefined();
89+
expect(sanitizeUtmParams(null as any)).toBeUndefined();
90+
});
91+
92+
it('should return undefined for empty object', () => {
93+
expect(sanitizeUtmParams({})).toBeUndefined();
94+
});
95+
96+
it('should filter out invalid keys', () => {
97+
const input = { source: 'google', invalidKey: 'value' } as any;
98+
const result = sanitizeUtmParams(input);
99+
expect(result).toEqual({ source: 'google' });
100+
});
101+
102+
it('should sanitize values by removing invalid characters', () => {
103+
const input = { source: 'google@#$%ads' };
104+
const result = sanitizeUtmParams(input);
105+
expect(result).toEqual({ source: 'googleads' });
106+
});
107+
108+
it('should trim whitespace', () => {
109+
const input = { source: ' google ads ' };
110+
const result = sanitizeUtmParams(input);
111+
expect(result).toEqual({ source: 'google ads' });
112+
});
113+
114+
it('should limit length to 200 characters', () => {
115+
const longValue = 'a'.repeat(250);
116+
const input = { source: longValue };
117+
const result = sanitizeUtmParams(input);
118+
expect(result?.source).toHaveLength(200);
119+
});
120+
121+
it('should preserve valid characters', () => {
122+
const input = {
123+
source: 'google-ads',
124+
medium: 'cpc_campaign',
125+
campaign: 'spring.2025',
126+
content: 'Ad Variant 123',
127+
term: 'error_tracker-tool',
128+
};
129+
const result = sanitizeUtmParams(input);
130+
expect(result).toEqual(input);
131+
});
132+
133+
it('should remove entries with empty values after sanitization', () => {
134+
const input = { source: '@#$%', medium: 'cpc' };
135+
const result = sanitizeUtmParams(input);
136+
expect(result).toEqual({ medium: 'cpc' });
137+
});
138+
139+
it('should return undefined if all values become empty after sanitization', () => {
140+
const input = { source: '@#$%', medium: '!@#$' };
141+
const result = sanitizeUtmParams(input);
142+
expect(result).toBeUndefined();
143+
});
144+
145+
it('should handle non-string values by filtering them out', () => {
146+
const input = { source: 'google', medium: 123, campaign: true } as any;
147+
const result = sanitizeUtmParams(input);
148+
expect(result).toEqual({ source: 'google' });
149+
});
150+
151+
it('should handle null and undefined values', () => {
152+
const input = { source: 'google', medium: null as any, campaign: undefined };
153+
const result = sanitizeUtmParams(input);
154+
expect(result).toEqual({ source: 'google' });
155+
});
156+
157+
it('should handle complex sanitization case', () => {
158+
const input = {
159+
source: ' Google@Ads#Campaign ',
160+
medium: 'cpc$paid%search',
161+
campaign: 'spring_2025-launch.campaign',
162+
content: '!@#$%',
163+
term: 'error tracker tool',
164+
};
165+
const result = sanitizeUtmParams(input);
166+
expect(result).toEqual({
167+
source: 'GoogleAdsCampaign',
168+
medium: 'cpcpaidsearch',
169+
campaign: 'spring_2025-launch.campaign',
170+
term: 'error tracker tool',
171+
});
172+
});
173+
});
174+
});

0 commit comments

Comments
 (0)