|
1 | 1 | import { UserTraits } from '../types'; |
2 | | -import { chunk, allSettled, deepCompare, getURL } from '../util'; |
| 2 | +import { |
| 3 | + chunk, |
| 4 | + allSettled, |
| 5 | + deepCompare, |
| 6 | + getURL, |
| 7 | + validateApiHost, |
| 8 | +} from '../util'; |
3 | 9 |
|
4 | 10 | describe('#chunk', () => { |
5 | 11 | it('handles empty array', () => { |
@@ -210,3 +216,39 @@ describe('getURL function', () => { |
210 | 216 | ); |
211 | 217 | }); |
212 | 218 | }); |
| 219 | + |
| 220 | +describe('validateApiHost', () => { |
| 221 | + it('accepts a bare hostname', () => { |
| 222 | + expect(validateApiHost('api.segment.io')).toBe(true); |
| 223 | + }); |
| 224 | + |
| 225 | + it('accepts hostname with path (normal Segment format)', () => { |
| 226 | + expect(validateApiHost('api.segment.io/v1')).toBe(true); |
| 227 | + expect(validateApiHost('events.eu1.segmentapis.com')).toBe(true); |
| 228 | + }); |
| 229 | + |
| 230 | + it('accepts hostname with port', () => { |
| 231 | + expect(validateApiHost('api.segment.io:443/v1')).toBe(true); |
| 232 | + }); |
| 233 | + |
| 234 | + it('rejects values with a scheme', () => { |
| 235 | + expect(validateApiHost('https://api.segment.io/v1')).toBe(false); |
| 236 | + expect(validateApiHost('http://api.segment.io/v1')).toBe(false); |
| 237 | + }); |
| 238 | + |
| 239 | + it('rejects values with credentials', () => { |
| 240 | + expect(validateApiHost('user:pass@api.segment.io')).toBe(false); |
| 241 | + }); |
| 242 | + |
| 243 | + it('rejects values with a query string', () => { |
| 244 | + expect(validateApiHost('attacker.com/collect?x=')).toBe(false); |
| 245 | + }); |
| 246 | + |
| 247 | + it('rejects values with a fragment', () => { |
| 248 | + expect(validateApiHost('attacker.com/path#fragment')).toBe(false); |
| 249 | + }); |
| 250 | + |
| 251 | + it('rejects empty string', () => { |
| 252 | + expect(validateApiHost('')).toBe(false); |
| 253 | + }); |
| 254 | +}); |
0 commit comments