Skip to content

Commit

Permalink
Revert "Use collectAsyncCalls with promise"
Browse files Browse the repository at this point in the history
This reverts commit 1568036.
amortemousque committed Nov 26, 2024

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
1 parent 1568036 commit ff85ce8
Showing 6 changed files with 140 additions and 127 deletions.
76 changes: 43 additions & 33 deletions packages/core/src/domain/error/trackRuntimeError.spec.ts
Original file line number Diff line number Diff line change
@@ -31,16 +31,17 @@ describe('trackRuntimeError', () => {
window.onerror = originalOnErrorHandler
})

it('should collect unhandled error', async () => {
it('should collect unhandled error', (done) => {
setTimeout(() => {
throw new Error(ERROR_MESSAGE)
})

await collectAsyncCalls(onErrorSpy, 1)
expect(notifyError).toHaveBeenCalledOnceWith(jasmine.objectContaining({ message: ERROR_MESSAGE }))
collectAsyncCalls(onErrorSpy, 1, () => {
expect(notifyError).toHaveBeenCalledOnceWith(jasmine.objectContaining({ message: ERROR_MESSAGE }))
done()
})
})

it('should collect unhandled rejection', async () => {
it('should collect unhandled rejection', (done) => {
if (!('onunhandledrejection' in window)) {
pending('onunhandledrejection not supported')
}
@@ -51,8 +52,10 @@ describe('trackRuntimeError', () => {
void Promise.reject(new Error(ERROR_MESSAGE))
})

await collectAsyncCalls(onUnhandledrejectionSpy, 1)
expect(notifyError).toHaveBeenCalledOnceWith(jasmine.objectContaining({ message: ERROR_MESSAGE }))
collectAsyncCalls(onUnhandledrejectionSpy, 1, () => {
expect(notifyError).toHaveBeenCalledOnceWith(jasmine.objectContaining({ message: ERROR_MESSAGE }))
done()
})
})
})

@@ -79,50 +82,55 @@ describe('instrumentOnError', () => {
stopCollectingUnhandledError()
})

it('should call original error handler', async () => {
it('should call original error handler', (done) => {
setTimeout(() => {
throw new Error(ERROR_MESSAGE)
})

await collectAsyncCalls(onErrorSpy, 1)
expect(onErrorSpy).toHaveBeenCalled()
collectAsyncCalls(onErrorSpy, 1, () => {
expect(onErrorSpy).toHaveBeenCalled()
done()
})
})

it('should notify unhandled error instance', async () => {
it('should notify unhandled error instance', (done) => {
const error = new Error(ERROR_MESSAGE)
setTimeout(() => {
throw error
})

await collectAsyncCalls(onErrorSpy, 1)
expect(onErrorSpy).toHaveBeenCalled()
const [stack, originalError] = callbackSpy.calls.mostRecent().args
expect(originalError).toBe(error)
expect(stack).toBeDefined()
collectAsyncCalls(onErrorSpy, 1, () => {
const [stack, originalError] = callbackSpy.calls.mostRecent().args
expect(originalError).toBe(error)
expect(stack).toBeDefined()
done()
})
})

it('should notify unhandled string', async () => {
it('should notify unhandled string', (done) => {
const error = 'foo' as any
setTimeout(() => {
// eslint-disable-next-line no-throw-literal
throw error
})
await collectAsyncCalls(onErrorSpy, 1)
const [stack, originalError] = callbackSpy.calls.mostRecent().args
expect(originalError).toBe(error)
expect(stack).toBeDefined()
collectAsyncCalls(onErrorSpy, 1, () => {
const [stack, originalError] = callbackSpy.calls.mostRecent().args
expect(originalError).toBe(error)
expect(stack).toBeDefined()
done()
})
})

it('should notify unhandled object', async () => {
it('should notify unhandled object', (done) => {
const error = { a: 'foo' } as any
setTimeout(() => {
// eslint-disable-next-line no-throw-literal
throw error
})
await collectAsyncCalls(onErrorSpy, 1)
const [stack, originalError] = callbackSpy.calls.mostRecent().args
expect(originalError).toBe(error)
expect(stack).toBeDefined()
collectAsyncCalls(onErrorSpy, 1, () => {
const [stack, originalError] = callbackSpy.calls.mostRecent().args
expect(originalError).toBe(error)
expect(stack).toBeDefined()
done()
})
})

describe('uncaught exception handling', () => {
@@ -156,16 +164,18 @@ describe('instrumentOnError', () => {
})

describe('should handle direct onerror calls', () => {
it('with objects', async () => {
it('with objects', (done) => {
const error = { foo: 'bar' } as any
setTimeout(() => {
window.onerror!(error)
})

await collectAsyncCalls(onErrorSpy, 1)
const [stack, originalError] = callbackSpy.calls.mostRecent().args
expect(originalError).toBe(error)
expect(stack).toBeDefined()
collectAsyncCalls(onErrorSpy, 1, () => {
const [stack, originalError] = callbackSpy.calls.mostRecent().args
expect(originalError).toBe(error)
expect(stack).toBeDefined()
done()
})
})

describe('with undefined arguments', () => {
4 changes: 2 additions & 2 deletions packages/core/src/transport/httpRequest.spec.ts
Original file line number Diff line number Diff line change
@@ -70,7 +70,7 @@ describe('httpRequest', () => {
})
})

it('should use retry strategy', async () => {
it('should use retry strategy', (done) => {
if (!interceptor.isFetchKeepAliveSupported()) {
pending('no fetch keepalive support')
}
@@ -90,7 +90,7 @@ describe('httpRequest', () => {

request.send({ data: '{"foo":"bar1"}\n{"foo":"bar2"}', bytesCount: 10 })

await collectAsyncCalls(fetchSpy, 2)
collectAsyncCalls(fetchSpy, 2, () => done())
})
})

41 changes: 19 additions & 22 deletions packages/core/test/collectAsyncCalls.ts
Original file line number Diff line number Diff line change
@@ -2,32 +2,29 @@ import { getCurrentJasmineSpec } from './getCurrentJasmineSpec'

export function collectAsyncCalls<F extends jasmine.Func>(
spy: jasmine.Spy<F>,
expectedCallsCount: number
): Promise<jasmine.Calls<F>> {
return new Promise((resolve, reject) => {
const currentSpec = getCurrentJasmineSpec()
if (!currentSpec) {
reject(new Error('collectAsyncCalls should be called within jasmine code'))
return
}
expectedCallsCount: number,
callback: (calls: jasmine.Calls<F>) => void
) {
const currentSpec = getCurrentJasmineSpec()
if (!currentSpec) {
throw new Error('collectAsyncCalls should be called within jasmine code')
}

const checkCalls = () => {
if (spy.calls.count() === expectedCallsCount) {
spy.and.callFake(extraCallDetected as F)
callback(spy.calls)
} else if (spy.calls.count() > expectedCallsCount) {
extraCallDetected()
} else {
spy.and.callFake((() => {
if (spy.calls.count() === expectedCallsCount) {
spy.and.callFake(extraCallDetected as F)
resolve(spy.calls)
} else if (spy.calls.count() > expectedCallsCount) {
extraCallDetected()
callback(spy.calls)
}
}

checkCalls()

spy.and.callFake((() => {
checkCalls()
}) as F)
}

function extraCallDetected() {
reject(new Error(`Unexpected extra call for spec '${currentSpec!.fullName}'`))
}
})
function extraCallDetected() {
fail(`Unexpected extra call for spec '${currentSpec!.fullName}'`)
}
}
4 changes: 3 additions & 1 deletion packages/rum/src/boot/startRecording.spec.ts
Original file line number Diff line number Diff line change
@@ -252,7 +252,9 @@ describe('startRecording', () => {
}

async function readSentRequests(expectedSentRequestCount: number) {
const calls = await collectAsyncCalls(requestSendSpy, expectedSentRequestCount)
const calls = await new Promise<jasmine.Calls<HttpRequest['sendOnExit']>>((resolve) =>
collectAsyncCalls(requestSendSpy, expectedSentRequestCount, resolve)
)
return Promise.all(calls.all().map((call) => readReplayPayload(call.args[0])))
}
})
138 changes: 71 additions & 67 deletions packages/rum/src/domain/record/record.spec.ts
Original file line number Diff line number Diff line change
@@ -40,7 +40,7 @@ describe('record', () => {
})
})

it('captures stylesheet rules', async () => {
it('captures stylesheet rules', (done) => {
const styleElement = appendElement('<style></style>') as HTMLStyleElement

startRecording()
@@ -59,88 +59,92 @@ describe('record', () => {
styleSheet.insertRule('body { color: #ccc; }')
}, 10)

await collectAsyncCalls(emitSpy, recordsPerFullSnapshot() + 6)
collectAsyncCalls(emitSpy, recordsPerFullSnapshot() + 6, () => {
const records = getEmittedRecords()
let i = 0

const records = getEmittedRecords()
let i = 0
expect(records[i++].type).toEqual(RecordType.Meta)
expect(records[i++].type).toEqual(RecordType.Focus)
expect(records[i++].type).toEqual(RecordType.FullSnapshot)

expect(records[i++].type).toEqual(RecordType.Meta)
expect(records[i++].type).toEqual(RecordType.Focus)
expect(records[i++].type).toEqual(RecordType.FullSnapshot)
if (window.visualViewport) {
expect(records[i++].type).toEqual(RecordType.VisualViewport)
}

if (window.visualViewport) {
expect(records[i++].type).toEqual(RecordType.VisualViewport)
}
expect(records[i].type).toEqual(RecordType.IncrementalSnapshot)
expect((records[i++] as BrowserIncrementalSnapshotRecord).data).toEqual(
jasmine.objectContaining({
source: IncrementalSource.StyleSheetRule,
adds: [{ rule: 'body { background: #000; }', index: undefined }],
})
)
expect(records[i].type).toEqual(RecordType.IncrementalSnapshot)
expect((records[i++] as BrowserIncrementalSnapshotRecord).data).toEqual(
jasmine.objectContaining({
source: IncrementalSource.StyleSheetRule,
adds: [{ rule: 'body { background: #111; }', index: undefined }],
})
)
expect(records[i].type).toEqual(RecordType.IncrementalSnapshot)
expect((records[i++] as BrowserIncrementalSnapshotRecord).data).toEqual(
jasmine.objectContaining({
source: IncrementalSource.StyleSheetRule,
removes: [{ index: 0 }],
})
)
expect(records[i].type).toEqual(RecordType.IncrementalSnapshot)
expect((records[i++] as BrowserIncrementalSnapshotRecord).data).toEqual(
jasmine.objectContaining({
source: IncrementalSource.StyleSheetRule,
adds: [{ rule: 'body { color: #fff; }', index: undefined }],
})
)
expect(records[i].type).toEqual(RecordType.IncrementalSnapshot)
expect((records[i++] as BrowserIncrementalSnapshotRecord).data).toEqual(
jasmine.objectContaining({
source: IncrementalSource.StyleSheetRule,
removes: [{ index: 0 }],
})
)
expect(records[i].type).toEqual(RecordType.IncrementalSnapshot)
expect((records[i++] as BrowserIncrementalSnapshotRecord).data).toEqual(
jasmine.objectContaining({
source: IncrementalSource.StyleSheetRule,
adds: [{ rule: 'body { color: #ccc; }', index: undefined }],
})
)

expect(records[i].type).toEqual(RecordType.IncrementalSnapshot)
expect((records[i++] as BrowserIncrementalSnapshotRecord).data).toEqual(
jasmine.objectContaining({
source: IncrementalSource.StyleSheetRule,
adds: [{ rule: 'body { background: #000; }', index: undefined }],
})
)
expect(records[i].type).toEqual(RecordType.IncrementalSnapshot)
expect((records[i++] as BrowserIncrementalSnapshotRecord).data).toEqual(
jasmine.objectContaining({
source: IncrementalSource.StyleSheetRule,
adds: [{ rule: 'body { background: #111; }', index: undefined }],
})
)
expect(records[i].type).toEqual(RecordType.IncrementalSnapshot)
expect((records[i++] as BrowserIncrementalSnapshotRecord).data).toEqual(
jasmine.objectContaining({
source: IncrementalSource.StyleSheetRule,
removes: [{ index: 0 }],
})
)
expect(records[i].type).toEqual(RecordType.IncrementalSnapshot)
expect((records[i++] as BrowserIncrementalSnapshotRecord).data).toEqual(
jasmine.objectContaining({
source: IncrementalSource.StyleSheetRule,
adds: [{ rule: 'body { color: #fff; }', index: undefined }],
})
)
expect(records[i].type).toEqual(RecordType.IncrementalSnapshot)
expect((records[i++] as BrowserIncrementalSnapshotRecord).data).toEqual(
jasmine.objectContaining({
source: IncrementalSource.StyleSheetRule,
removes: [{ index: 0 }],
})
)
expect(records[i].type).toEqual(RecordType.IncrementalSnapshot)
expect((records[i++] as BrowserIncrementalSnapshotRecord).data).toEqual(
jasmine.objectContaining({
source: IncrementalSource.StyleSheetRule,
adds: [{ rule: 'body { color: #ccc; }', index: undefined }],
})
)
done()
})
})

it('flushes pending mutation records before taking a full snapshot', async () => {
it('flushes pending mutation records before taking a full snapshot', (done) => {
startRecording()

appendElement('<hr/>')

// trigger full snapshot by starting a new view
newView()

await collectAsyncCalls(emitSpy, 1 + 2 * recordsPerFullSnapshot())
collectAsyncCalls(emitSpy, 1 + 2 * recordsPerFullSnapshot(), () => {
const records = getEmittedRecords()
let i = 0

const records = getEmittedRecords()
let i = 0
expect(records[i++].type).toEqual(RecordType.Meta)
expect(records[i++].type).toEqual(RecordType.Focus)
expect(records[i++].type).toEqual(RecordType.FullSnapshot)

expect(records[i++].type).toEqual(RecordType.Meta)
expect(records[i++].type).toEqual(RecordType.Focus)
expect(records[i++].type).toEqual(RecordType.FullSnapshot)
if (window.visualViewport) {
expect(records[i++].type).toEqual(RecordType.VisualViewport)
}
expect(records[i].type).toEqual(RecordType.IncrementalSnapshot)
expect((records[i++] as BrowserIncrementalSnapshotRecord).data.source).toEqual(IncrementalSource.Mutation)
expect(records[i++].type).toEqual(RecordType.Meta)
expect(records[i++].type).toEqual(RecordType.Focus)
expect(records[i++].type).toEqual(RecordType.FullSnapshot)

if (window.visualViewport) {
expect(records[i++].type).toEqual(RecordType.VisualViewport)
}
expect(records[i].type).toEqual(RecordType.IncrementalSnapshot)
expect((records[i++] as BrowserIncrementalSnapshotRecord).data.source).toEqual(IncrementalSource.Mutation)
expect(records[i++].type).toEqual(RecordType.Meta)
expect(records[i++].type).toEqual(RecordType.Focus)
expect(records[i++].type).toEqual(RecordType.FullSnapshot)
done()
})
})

describe('Shadow dom', () => {
4 changes: 2 additions & 2 deletions packages/rum/src/domain/record/trackers/trackMutation.spec.ts
Original file line number Diff line number Diff line change
@@ -92,15 +92,15 @@ describe('trackMutation', () => {
})
})

it('processes mutations asynchronously', async () => {
it('processes mutations asynchronously', (done) => {
serializeDocumentWithDefaults()
const { mutationCallbackSpy } = startMutationCollection()

appendElement('<div></div>', sandbox)

expect(mutationCallbackSpy).not.toHaveBeenCalled()

await collectAsyncCalls(mutationCallbackSpy, 1)
collectAsyncCalls(mutationCallbackSpy, 1, () => done())
})

it('does not emit a mutation when a node is appended to a unknown node', () => {

0 comments on commit ff85ce8

Please sign in to comment.