Skip to content

Commit

Permalink
Seth - example refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
silesky committed Jul 4, 2023
1 parent 30b942f commit 8e2b8df
Show file tree
Hide file tree
Showing 12 changed files with 186 additions and 273 deletions.
22 changes: 6 additions & 16 deletions packages/node/src/__tests__/callback.test.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,10 @@
import {
createError,
createSuccess,
TestFetchClient,
} from './test-helpers/factories'
import { createTestAnalytics } from './test-helpers/create-test-analytics'
import { Context } from '../app/context'

describe('Callback behavior', () => {
const testClient = new TestFetchClient()
beforeEach(() => {
testClient.returnValue = createSuccess()
})

it('should handle success', async () => {
const ajs = createTestAnalytics({
maxEventsInBatch: 1,
customClient: testClient,
})
const ctx = await new Promise<Context>((resolve, reject) =>
ajs.track(
Expand All @@ -34,11 +23,12 @@ describe('Callback behavior', () => {
})

it('should handle errors', async () => {
testClient.returnValue = createError()
const ajs = createTestAnalytics({
maxEventsInBatch: 1,
customClient: testClient,
})
const ajs = createTestAnalytics(
{
maxEventsInBatch: 1,
},
{ withError: true }
)
const [err, ctx] = await new Promise<[any, Context]>((resolve) =>
ajs.track(
{
Expand Down
13 changes: 5 additions & 8 deletions packages/node/src/__tests__/disable.integration.test.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
import { createTestAnalytics } from './test-helpers/create-test-analytics'
import { createSuccess } from './test-helpers/factories'
import { TestFetchClient } from './test-helpers/test-fetch-client'

describe('disable', () => {
const mockSend: jest.Mock = jest.fn().mockResolvedValue(createSuccess())

const checkFetchClient = {
send: mockSend,
}
const customClient = new TestFetchClient()
const mockSend = jest.spyOn(customClient, 'send')

it('should dispatch callbacks and emit an http request, even if disabled', async () => {
const analytics = createTestAnalytics({
Expand All @@ -23,7 +20,7 @@ describe('disable', () => {
it('should call fetch if disabled is false', async () => {
const analytics = createTestAnalytics({
disable: false,
customClient: checkFetchClient,
customClient: customClient,
})
await new Promise((resolve) =>
analytics.track({ anonymousId: 'foo', event: 'bar' }, resolve)
Expand All @@ -33,7 +30,7 @@ describe('disable', () => {
it('should not call fetch if disabled is true', async () => {
const analytics = createTestAnalytics({
disable: true,
customClient: checkFetchClient,
customClient: customClient,
})
await new Promise((resolve) =>
analytics.track({ anonymousId: 'foo', event: 'bar' }, resolve)
Expand Down
29 changes: 12 additions & 17 deletions packages/node/src/__tests__/emitter.integration.test.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,8 @@
import {
createError,
createSuccess,
TestFetchClient,
} from './test-helpers/factories'
import { createTestAnalytics } from './test-helpers/create-test-analytics'
import { assertHttpRequestEmittedEvent } from './test-helpers/assert-shape'

describe('http_request', () => {
const testClient = new TestFetchClient()
it('emits an http_request event if success', async () => {
testClient.returnValue = createSuccess()
const analytics = createTestAnalytics()
const fn = jest.fn()
analytics.on('http_request', fn)
Expand All @@ -21,11 +14,12 @@ describe('http_request', () => {
})

it('emits an http_request event if error', async () => {
testClient.returnValue = createError()
const analytics = createTestAnalytics({
maxRetries: 0,
customClient: testClient,
})
const analytics = createTestAnalytics(
{
maxRetries: 0,
},
{ withError: true }
)
const fn = jest.fn()
analytics.on('http_request', fn)
await new Promise((resolve) =>
Expand All @@ -35,11 +29,12 @@ describe('http_request', () => {
})

it('if error, emits an http_request event on every retry', async () => {
testClient.returnValue = createError()
const analytics = createTestAnalytics({
maxRetries: 2,
customClient: testClient,
})
const analytics = createTestAnalytics(
{
maxRetries: 2,
},
{ withError: true }
)
const fn = jest.fn()
analytics.on('http_request', fn)
await new Promise((resolve) =>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { TestFetchClient } from './test-helpers/factories'
import { TestFetchClient } from './test-helpers/test-fetch-client'
import { performance as perf } from 'perf_hooks'
import { Analytics } from '../app/analytics-node'
import { sleep } from './test-helpers/sleep'
Expand All @@ -14,20 +14,20 @@ const testPlugin: Plugin = {
}

const testClient = new TestFetchClient()
const sendSpy = jest.spyOn(testClient, 'send')

describe('Ability for users to exit without losing events', () => {
let ajs!: Analytics
beforeEach(async () => {
testClient.reset()
ajs = new Analytics({
writeKey: 'abc123',
maxEventsInBatch: 1,
customClient: testClient,
})
})
const _helpers = {
getFetchCalls: (client = testClient) =>
client.calls.map(([url, request]) => ({
getFetchCalls: () =>
sendSpy.mock.calls.map(([url, request]) => ({
url,
method: request.method,
headers: request.headers,
Expand Down
13 changes: 8 additions & 5 deletions packages/node/src/__tests__/http-integration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ describe('Method Smoke Tests', () => {
let scope: nock.Scope
let ajs: Analytics
beforeEach(async () => {
ajs = createTestAnalytics()
ajs = createTestAnalytics({}, { useRealHTTPClient: true })
})

describe('Metadata', () => {
Expand Down Expand Up @@ -333,10 +333,13 @@ describe('Client: requestTimeout', () => {
})
it('should timeout immediately if request timeout is set to 0', async () => {
jest.useRealTimers()
const ajs = createTestAnalytics({
maxEventsInBatch: 1,
httpRequestTimeout: 0,
})
const ajs = createTestAnalytics(
{
maxEventsInBatch: 1,
httpRequestTimeout: 0,
},
{ useRealHTTPClient: true }
)
ajs.track({ event: 'foo', userId: 'foo', properties: { hello: 'world' } })
try {
await resolveCtx(ajs, 'track')
Expand Down
22 changes: 10 additions & 12 deletions packages/node/src/__tests__/integration.test.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
import { Plugin } from '../app/types'
import { resolveCtx } from './test-helpers/resolve-ctx'
import { testPlugin } from './test-helpers/test-plugin'
import { createError, TestFetchClient } from './test-helpers/factories'
import { createError } from './test-helpers/factories'
import { createTestAnalytics } from './test-helpers/create-test-analytics'
import { TestFetchClient } from './test-helpers/test-fetch-client'

const writeKey = 'foo'
jest.setTimeout(10000)
const timestamp = new Date()

const testClient = new TestFetchClient()

beforeEach(() => {
testClient.reset()
})
const sendSpy = jest.spyOn(testClient, 'send')

describe('Settings / Configuration Init', () => {
it('throws if no writeKey', () => {
Expand All @@ -32,7 +30,7 @@ describe('Settings / Configuration Init', () => {
const track = resolveCtx(analytics, 'track')
analytics.track({ event: 'foo', userId: 'sup' })
await track
expect(testClient.calls[0][0]).toBe('http://foo.com/bar')
expect(sendSpy.mock.calls[0][0]).toBe('http://foo.com/bar')
})

it('throws if host / path is bad', async () => {
Expand All @@ -52,15 +50,15 @@ describe('Error handling', () => {
expect(() => analytics.track({} as any)).toThrowError(/event/i)
})

it.only('should emit on an error', async () => {
const analytics = createTestAnalytics({
maxRetries: 0,
customClient: testClient,
})
testClient.returnValue = createError({
it('should emit on an error', async () => {
const err = createError({
statusText: 'Service Unavailable',
status: 503,
})
const analytics = createTestAnalytics({
maxRetries: 0,
customClient: new TestFetchClient({ response: err }),
})
try {
const promise = resolveCtx(analytics, 'track')
analytics.track({ event: 'foo', userId: 'sup' })
Expand Down
7 changes: 0 additions & 7 deletions packages/node/src/__tests__/plugins.test.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,6 @@
import { TestFetchClient } from './test-helpers/factories'
import { createTestAnalytics } from './test-helpers/create-test-analytics'

const testClient = new TestFetchClient()

describe('Plugins', () => {
beforeEach(() => {
testClient.reset()
})

describe('Initialize', () => {
it('loads analytics-node-next plugin', async () => {
const analytics = createTestAnalytics()
Expand Down
16 changes: 14 additions & 2 deletions packages/node/src/__tests__/test-helpers/create-test-analytics.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,20 @@
import { Analytics } from '../../app/analytics-node'
import { AnalyticsSettings } from '../../app/settings'
import { TestFetchClient, TestFetchClientOptions } from './test-fetch-client'

export const createTestAnalytics = (
settings: Partial<AnalyticsSettings> = {}
settings: Partial<AnalyticsSettings> = {},
{
withError,
useRealHTTPClient,
}: TestFetchClientOptions & { useRealHTTPClient?: boolean } = {}
) => {
return new Analytics({ writeKey: 'foo', flushInterval: 100, ...settings })
return new Analytics({
writeKey: 'foo',
flushInterval: 100,
...(useRealHTTPClient
? {}
: { customClient: new TestFetchClient({ withError }) }),
...settings,
})
}
40 changes: 0 additions & 40 deletions packages/node/src/__tests__/test-helpers/factories.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import { CustomHTTPClient } from '../../lib/customhttpclient'

export const createSuccess = (body?: any) => {
return Promise.resolve({
json: () => Promise.resolve(body),
Expand All @@ -17,41 +15,3 @@ export const createError = (overrides: Partial<Response> = {}) => {
...overrides,
}) as Promise<Response>
}

export class TestFetchClient implements CustomHTTPClient {
public callCount = 0

public calls = <any[]>[]
get lastCall() {
return this.calls.slice(-1)[0]
}

private _returnValue: any
set returnValue(value: any) {
this._returnValue = value
}

private _errorValue: any
set errorValue(value: any) {
this._errorValue = value
}

public reset() {
this.callCount = 0
this.calls = []
this._returnValue = null
this._errorValue = null
}

send = async (_resource: any, _options: any): Promise<Response> => {
this.calls.push([_resource, _options])
this.callCount++
if (this._errorValue) {
throw this._errorValue
}
if (this._returnValue) {
return this._returnValue
}
return createSuccess()
}
}
26 changes: 26 additions & 0 deletions packages/node/src/__tests__/test-helpers/test-fetch-client.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { CustomHTTPClient } from '../../lib/customhttpclient'
import { createError, createSuccess } from './factories'

export type TestFetchClientOptions = {
withError?: boolean
/** override response (if needed) */
response?: Response | Promise<Response>
}
/**
* Test client.
* Try not to use this directly -- use createTestAnalytics instead.
*/
export class TestFetchClient implements CustomHTTPClient {
private withError?: TestFetchClientOptions['withError']
private response?: TestFetchClientOptions['response']
constructor({ withError, response }: TestFetchClientOptions = {}) {
this.withError = withError
this.response = response
}
send(..._args: Parameters<CustomHTTPClient['send']>) {
if (this.response) {
return Promise.resolve(this.response)
}
return Promise.resolve(this.withError ? createError() : createSuccess())
}
}
Loading

0 comments on commit 8e2b8df

Please sign in to comment.