Skip to content

Commit bca376b

Browse files
authored
add network tests, expose signals (#1103)
1 parent e60f625 commit bca376b

File tree

7 files changed

+77
-13
lines changed

7 files changed

+77
-13
lines changed

packages/signals/signals-example/package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
{
22
"name": "@internal/signals-example",
3-
"version": "0.0.1",
43
"private": true,
54
"scripts": {
65
".": "yarn run -T turbo run --filter=@segment/signals-example...",

packages/signals/signals/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@segment/analytics-signals",
3-
"version": "0.0.1",
3+
"version": "0.0.0",
44
"main": "./dist/cjs/index.js",
55
"license": "MIT",
66
"repository": {

packages/signals/signals/src/core/signal-generators/__tests__/network.test.ts

Lines changed: 67 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,73 @@
1-
import { addFetchInterceptor, NetworkGenerator } from '../network'
1+
import {
2+
addFetchInterceptor,
3+
matchHostname,
4+
NetworkGenerator,
5+
containsJSONContent,
6+
} from '../network-gen'
27
import { SignalEmitter } from '../../emitter'
38
import { Response } from 'node-fetch'
49
import { sleep } from '@segment/analytics-core'
510

6-
describe('addFetchInterceptor', () => {
11+
describe(containsJSONContent, () => {
12+
it('should return true if headers contain application/json', () => {
13+
const headers = new Headers({ 'content-type': 'application/json' })
14+
expect(containsJSONContent(headers)).toBe(true)
15+
})
16+
it('should be case insensitive', () => {
17+
expect(containsJSONContent([['Content-Type', 'application/json']])).toBe(
18+
true
19+
)
20+
expect(
21+
containsJSONContent(new Headers({ 'Content-Type': 'application/json' }))
22+
).toBe(true)
23+
})
24+
25+
it('should return false if headers do not contain application/json', () => {
26+
const headers = new Headers({ 'content-type': 'text/html' })
27+
expect(containsJSONContent(headers)).toBe(false)
28+
expect(containsJSONContent(new Headers())).toBe(false)
29+
expect(containsJSONContent(undefined)).toBe(false)
30+
})
31+
})
32+
33+
describe(matchHostname, () => {
34+
const setHostname = (hostname: string) => {
35+
Object.defineProperty(window, 'location', {
36+
value: {
37+
...window.location,
38+
hostname: hostname,
39+
},
40+
writable: true,
41+
})
42+
}
43+
44+
beforeEach(() => {
45+
setHostname('example.com')
46+
})
47+
it('should only match first party domains', () => {
48+
expect(matchHostname('https://www.example.com')).toBe(true)
49+
expect(matchHostname('https://www.example.com/api/foo')).toBe(true)
50+
expect(matchHostname('https://www.foo.com')).toBe(false)
51+
expect(
52+
matchHostname('https://cdn.segment.com/v1/projects/1234/versions/1')
53+
).toBe(false)
54+
})
55+
56+
it('should work with subdomains', () => {
57+
setHostname('api.example.com')
58+
expect(matchHostname('https://api.example.com/foo')).toBe(true)
59+
expect(matchHostname('https://foo.com/foo')).toBe(false)
60+
expect(matchHostname('https://example.com/foo')).toBe(false)
61+
})
62+
63+
it('should always allow relative domains', () => {
64+
expect(matchHostname('/foo/bar')).toBe(true)
65+
expect(matchHostname('foo/bar')).toBe(true)
66+
expect(matchHostname('foo')).toBe(true)
67+
})
68+
})
69+
70+
describe(addFetchInterceptor, () => {
771
let origFetch: typeof window.fetch
872

973
beforeEach(() => {
@@ -32,7 +96,7 @@ describe('addFetchInterceptor', () => {
3296
})
3397
})
3498

35-
describe('NetworkGenerator', () => {
99+
describe(NetworkGenerator, () => {
36100
it('should register and emit signals on fetch requests and responses', async () => {
37101
const mockResponse = new Response(JSON.stringify({ data: 'test' }), {
38102
headers: { 'content-type': 'application/json' },

packages/signals/signals/src/core/signal-generators/network.ts renamed to packages/signals/signals/src/core/signal-generators/network-gen.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,27 +26,27 @@ export function addFetchInterceptor(
2626
}
2727
}
2828

29-
const matchHostname = (url: string): boolean => {
29+
export const matchHostname = (url: string): boolean => {
3030
const rIsAbs = new RegExp('^(?:[a-z+]+:)?//', 'i')
3131
if (!rIsAbs.test(url)) {
3232
// Relative URL will go to this host
3333
return true
3434
}
35-
return new URL(url).hostname?.includes(window.location.hostname) || false
35+
return new URL(url).hostname.includes(window.location.hostname)
3636
}
3737

3838
const normalizeHeaders = (headers: HeadersInit): Headers => {
3939
return headers instanceof Headers ? headers : new Headers(headers)
4040
}
4141

42-
const containsJSONContent = (headers: HeadersInit | undefined): boolean => {
42+
export const containsJSONContent = (
43+
headers: HeadersInit | undefined
44+
): boolean => {
4345
if (!headers) {
4446
return false
4547
}
4648
const normalizedHeaders = normalizeHeaders(headers)
47-
return (
48-
normalizedHeaders.get('content-type')?.includes('application/json') || false
49-
)
49+
return normalizedHeaders.get('content-type') === 'application/json'
5050
}
5151

5252
export class NetworkGenerator implements SignalGenerator {

packages/signals/signals/src/core/signals/signals.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { SignalsIngestClient } from '../client'
22
import { getSignalBuffer, SignalBuffer } from '../buffer'
33
import { SignalEmitter } from '../emitter'
4-
import { domGenerators } from '../signal-generators/dom-generators'
5-
import { NetworkGenerator } from '../signal-generators/network'
4+
import { domGenerators } from '../signal-generators/dom-gen'
5+
import { NetworkGenerator } from '../signal-generators/network-gen'
66
import {
77
SignalGenerator,
88
SignalGeneratorClass,

packages/signals/signals/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,5 @@ export type {
99
ProcessSignal,
1010
AnalyticsRuntimePublicApi,
1111
SignalsPluginSettingsConfig,
12+
Signal,
1213
} from './types'

0 commit comments

Comments
 (0)