|
1 | 1 | import { beforeEach, describe, expect, it, test, vi } from 'vitest'; |
2 | | -import { DEBUG_BUILD } from '../../../src/debug-build'; |
3 | 2 | import { debug } from '../../../src/utils/debug-logger'; |
4 | 3 | import { dsnToString, extractOrgIdFromClient, extractOrgIdFromDsnHost, makeDsn } from '../../../src/utils/dsn'; |
5 | 4 | import { getDefaultTestClientOptions, TestClient } from '../../mocks/client'; |
6 | 5 |
|
7 | | -function testIf(condition: boolean) { |
8 | | - return condition ? test : test.skip; |
9 | | -} |
| 6 | +let mockDebugBuild = true; |
| 7 | + |
| 8 | +vi.mock('../../../src/debug-build', () => ({ |
| 9 | + get DEBUG_BUILD() { |
| 10 | + return mockDebugBuild; |
| 11 | + }, |
| 12 | +})); |
10 | 13 |
|
11 | 14 | const loggerErrorSpy = vi.spyOn(debug, 'error').mockImplementation(() => {}); |
12 | 15 | const consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => {}); |
13 | 16 |
|
14 | 17 | describe('Dsn', () => { |
15 | 18 | beforeEach(() => { |
16 | 19 | vi.clearAllMocks(); |
| 20 | + mockDebugBuild = true; |
17 | 21 | }); |
18 | 22 |
|
19 | 23 | describe('fromComponents', () => { |
@@ -51,7 +55,7 @@ describe('Dsn', () => { |
51 | 55 | expect(dsn?.projectId).toBe('123'); |
52 | 56 | }); |
53 | 57 |
|
54 | | - testIf(DEBUG_BUILD)('returns `undefined` for missing components', () => { |
| 58 | + it('returns `undefined` for missing components', () => { |
55 | 59 | expect( |
56 | 60 | makeDsn({ |
57 | 61 | host: '', |
@@ -88,7 +92,7 @@ describe('Dsn', () => { |
88 | 92 | expect(loggerErrorSpy).toHaveBeenCalledTimes(4); |
89 | 93 | }); |
90 | 94 |
|
91 | | - testIf(DEBUG_BUILD)('returns `undefined` if components are invalid', () => { |
| 95 | + it('returns `undefined` if components are invalid', () => { |
92 | 96 | expect( |
93 | 97 | makeDsn({ |
94 | 98 | host: 'sentry.io', |
@@ -167,20 +171,61 @@ describe('Dsn', () => { |
167 | 171 | expect(dsn?.projectId).toBe('321'); |
168 | 172 | }); |
169 | 173 |
|
170 | | - testIf(DEBUG_BUILD)('returns undefined when provided invalid Dsn', () => { |
| 174 | + test('with IPv4 hostname', () => { |
| 175 | + const dsn = makeDsn('https://abc@192.168.1.1/123'); |
| 176 | + expect(dsn?.protocol).toBe('https'); |
| 177 | + expect(dsn?.publicKey).toBe('abc'); |
| 178 | + expect(dsn?.pass).toBe(''); |
| 179 | + expect(dsn?.host).toBe('192.168.1.1'); |
| 180 | + expect(dsn?.port).toBe(''); |
| 181 | + expect(dsn?.path).toBe(''); |
| 182 | + expect(dsn?.projectId).toBe('123'); |
| 183 | + }); |
| 184 | + |
| 185 | + test.each([ |
| 186 | + '[2001:db8::1]', |
| 187 | + '[::1]', // loopback |
| 188 | + '[::ffff:192.0.2.1]', // IPv4-mapped IPv6 (contains dots) |
| 189 | + '[fe80::1]', // link-local |
| 190 | + '[2001:db8:85a3::8a2e:370:7334]', // compressed in middle |
| 191 | + '[2001:db8::]', // trailing zeros compressed |
| 192 | + '[2001:0db8:0000:0000:0000:0000:0000:0001]', // full form with leading zeros |
| 193 | + '[fe80::1%eth0]', // zone identifier with interface name (contains percent sign) |
| 194 | + '[fe80::1%25eth0]', // zone identifier URL-encoded (percent as %25) |
| 195 | + '[fe80::a:b:c:d%en0]', // zone identifier with different interface |
| 196 | + ])('with IPv6 hostname %s', hostname => { |
| 197 | + const dsn = makeDsn(`https://abc@${hostname}/123`); |
| 198 | + expect(dsn?.protocol).toBe('https'); |
| 199 | + expect(dsn?.publicKey).toBe('abc'); |
| 200 | + expect(dsn?.pass).toBe(''); |
| 201 | + expect(dsn?.host).toBe(hostname); |
| 202 | + expect(dsn?.port).toBe(''); |
| 203 | + expect(dsn?.path).toBe(''); |
| 204 | + expect(dsn?.projectId).toBe('123'); |
| 205 | + }); |
| 206 | + |
| 207 | + test('skips validation for non-debug builds', () => { |
| 208 | + mockDebugBuild = false; |
| 209 | + const dsn = makeDsn('httx://abc@192.168.1.1/123'); |
| 210 | + expect(dsn?.protocol).toBe('httx'); |
| 211 | + expect(dsn?.publicKey).toBe('abc'); |
| 212 | + expect(dsn?.pass).toBe(''); |
| 213 | + }); |
| 214 | + |
| 215 | + it('returns undefined when provided invalid Dsn', () => { |
171 | 216 | expect(makeDsn('some@random.dsn')).toBeUndefined(); |
172 | 217 | expect(consoleErrorSpy).toHaveBeenCalledTimes(1); |
173 | 218 | }); |
174 | 219 |
|
175 | | - testIf(DEBUG_BUILD)('returns undefined if mandatory fields are missing', () => { |
| 220 | + it('returns undefined if mandatory fields are missing', () => { |
176 | 221 | expect(makeDsn('://abc@sentry.io/123')).toBeUndefined(); |
177 | 222 | expect(makeDsn('https://@sentry.io/123')).toBeUndefined(); |
178 | 223 | expect(makeDsn('https://abc@123')).toBeUndefined(); |
179 | 224 | expect(makeDsn('https://abc@sentry.io/')).toBeUndefined(); |
180 | 225 | expect(consoleErrorSpy).toHaveBeenCalledTimes(4); |
181 | 226 | }); |
182 | 227 |
|
183 | | - testIf(DEBUG_BUILD)('returns undefined if fields are invalid', () => { |
| 228 | + it('returns undefined if fields are invalid', () => { |
184 | 229 | expect(makeDsn('httpx://abc@sentry.io/123')).toBeUndefined(); |
185 | 230 | expect(makeDsn('httpx://abc@sentry.io:xxx/123')).toBeUndefined(); |
186 | 231 | expect(makeDsn('http://abc@sentry.io/abc')).toBeUndefined(); |
|
0 commit comments