Skip to main content

API Reference

Sentry Testkit consists of a very simple and strait-forward API using the following functions

Methods

Capture and assertions

Awaiting asynchronously-sent data

  • waitForReports(count, options) — and its siblings waitForTransactions, waitForLogs, waitForMetrics, waitForAttachments, waitForFeedback, waitForCheckIns

Finding and filtering

Utilities

What About Nodejs? - Of Course!

Sentry Testkit has full support in both @sentry/browser and @sentry/node (as well as other @sentry/<what-ever> clients) since they have the same API and lifecycle under the hood.

Raven-Testkit

The good old legacy raven-testkit documentation can be found here. It it still there to serve Raven which is the old legacy SDK of Sentry for JavaScript/Node.js platforms

Reference

reports()

Gets all existing reports.

Returns: Array - where each member of the array consists of Sentry's Report type.

See: You may refer to the definition of Report for further explanation and details.

For example

const waitForExpect = require('wait-for-expect')

test('reports example', async function() {
// Some scenario that will report the exceptions...

await waitForExpect(() => expect(testkit.reports().length).toBeGreaterThan(0))
const reports = testkit.reports()

// Do what ever you want with the reports list
})
info

Here we use wait-for-expect library to emphasize that sometimes we need to wait until the report is being sent as it is done asynchronously. You can also use the built-in waitForReports helper instead.

Each report also exposes evaluated feature flags as report.flags — an array of { flag, result } objects taken from the event's contexts.flags, or an empty array when no flags were attached:

expect(testkit.reports()[0].flags).toEqual([{ flag: 'new-checkout', result: true }])

Files sent with the event are exposed as report.attachments — see attachments() — and the array is empty when the event carried none.

waitForReports(count, options)

Waits until at least count reports have been captured. This replaces "sleep then assert" patterns and third-party polling helpers — Sentry transports are asynchronous, so reports may not be captured yet when your assertion runs.

Arguments

  • count: Number - the minimum number of reports to wait for
  • options: Object (optional) - { timeout: Number }, defaults to { timeout: 1000 } (milliseconds)

Returns: Promise<Array> - resolves with the captured reports once the count is reached; rejects with a descriptive error if the timeout elapses first.

For example

test('waitForReports example', async function() {
Sentry.captureException(new Error('sentry test kit is awesome!'))

const reports = await testkit.waitForReports(1)
expect(reports[0].error.message).toEqual('sentry test kit is awesome!')
})

Sibling helpers with the same signature exist for the other captured types: waitForTransactions(count, options), waitForLogs(count, options), waitForMetrics(count, options), waitForAttachments(count, options), waitForFeedback(count, options) and waitForCheckIns(count, options).

findReport(error)

Finds a report by a given error.

Uses Array.prototype.find under the hood

Arguments

  • error: Error - An error object to look for in the reports

Returns: Report | undefined - the report object if one found. undefined otherwise.

See: You may refer to the definition of Report for further explanation and details.

For example

test('findReport example', async function() {
const err = new Error('error to look for')

// Some faulty scenario that will report err

const report = testkit.findReport(err)
expect(report).toBeDefined()
})

findReportByMessage(message)

Finds a report by its message — either a captureMessage message or a captured error's message.

Arguments

  • message: String | RegExp - exact message to match, or a regular expression to test against

Returns: Report | undefined - the first matching report. undefined otherwise.

For example

test('findReportByMessage example', async function() {
Sentry.captureException(new Error('failed to fetch user 42'))
await testkit.waitForReports(1)

expect(testkit.findReportByMessage(/user \d+/)).toBeDefined()
})

findTransaction(name)

Finds a transaction by its name.

Arguments

  • name: String | RegExp - exact transaction name to match, or a regular expression to test against

Returns: Transaction | undefined - the first matching transaction. undefined otherwise.

For example

test('findTransaction example', async function() {
Sentry.startInactiveSpan({ op: 'transaction', name: 'checkout-flow' }).end()
await testkit.waitForTransactions(1)

expect(testkit.findTransaction(/^checkout/)).toBeDefined()
})

reportsWithTag(key, value)

Gets all reports carrying a given tag, optionally with a specific value.

Arguments

  • key: String - the tag key to look for
  • value: String (optional) - when provided, only reports whose tag equals this value are returned

Returns: Array - the matching reports (empty array when none match).

For example

test('reportsWithTag example', async function() {
Sentry.withScope(scope => {
scope.setTag('section', 'billing')
Sentry.captureException(new Error('tagged error'))
})
await testkit.waitForReports(1)

expect(testkit.reportsWithTag('section', 'billing')).toHaveLength(1)
})

A sibling helper with the same signature exists for transactions: transactionsWithTag(key, value).

isExist(error)

Checks whether a given error exist (i.e. has been reported)

Arguments

  • error: Error - An error object to look for in the reports

Returns: Boolean - true if the error exists. false otherwise.

For example

 test('isExist example', async function() {
const err = new Error('error to look for')
Sentry.captureException(err)
await waitForExpect(() => expect(testkit.reports()).toHaveLength(1))
expect(testkit.isExist(err)).toBe(true)
})

getExceptionAt(index)

Extracts the exception object of a report in a specific position.

Arguments

  • index : Number - index position of the report.

Returns: ReportError.

See: You may refer to the definition of ReportError for further explanation and details.

For example

test('getExceptionAt example', async function() {
Sentry.captureException(new Error('testing get exception at index 0'))
Sentry.captureException(new Error('testing get exception at index 1'))
await waitForExpect(() => expect(testkit.reports()).toHaveLength(2))
const { message } = testkit.getExceptionAt(1)
expect(message).toEqual('testing get exception at index 1')
})

transactions()

Gets all existing transactions.

Returns: Array - where each member of the array consists of a Transaction type.

See: You may refer to the definition of Transaction for further explanation and details.

For example

test('transactions example', async function() {
// Some scenario that will create a transaction...

await waitForExpect(() => expect(testkit.transactions().length).toBeGreaterThan(0))
const transactions = testkit.transactions()

// Do what ever you want with the transactions
})

logs()

Gets all captured structured logs (requires enableLogs: true in Sentry.init).

Returns: Array - where each member of the array consists of a Log type:

FieldTypeDescription
levelstringtrace | debug | info | warn | error | fatal
messagestringThe log body
attributesObjectLog attributes as plain values, e.g. { userId: 42 }
timestampnumberEpoch time in seconds
traceIdstringThe trace this log belongs to, if any
severityNumbernumberThe numeric severity, if any
originalLogObjectThe raw log item as sent by the SDK

For example

test('logs example', async function() {
Sentry.logger.info('user logged in', { userId: 42 })
await Sentry.flush()

const [log] = testkit.logs()
expect(log.level).toEqual('info')
expect(log.message).toEqual('user logged in')
expect(log.attributes.userId).toEqual(42)
})

metrics()

Gets all captured application metrics emitted via Sentry.metrics.count(...), Sentry.metrics.gauge(...) or Sentry.metrics.distribution(...) (Sentry SDK v10 and above).

Returns: Array - where each member of the array consists of a Metric type:

FieldTypeDescription
namestringThe metric name, e.g. api.requests
typestringcounter | gauge | distribution
valuenumberThe reported value
unitstringThe unit, e.g. millisecond, if provided
attributesObjectMetric attributes as plain values, e.g. { endpoint: '/api/users' }
timestampnumberEpoch time in seconds
traceIdstringThe trace this metric belongs to, if any
spanIdstringThe span this metric was emitted from, if any
originalMetricObjectThe raw metric item as sent by the SDK

Metrics are batched by the SDK, so flush before asserting on them.

For example

test('metrics example', async function() {
Sentry.metrics.count('api.requests', 1, { attributes: { endpoint: '/api/users' } })
await Sentry.flush()

const [metric] = testkit.metrics()
expect(metric.name).toEqual('api.requests')
expect(metric.type).toEqual('counter')
expect(metric.value).toEqual(1)
expect(metric.attributes.endpoint).toEqual('/api/users')
})

Alongside the attributes you set, the SDK enriches every metric with its own — sentry.release, sentry.environment, sentry.sdk.name and more — so assert on the specific attributes you care about rather than on the whole object.

attachments()

Gets all captured attachments — files sent with an event via scope.addAttachment(...) or the attachments capture option.

Returns: Array - where each member of the array consists of an Attachment type:

FieldTypeDescription
filenamestringThe attachment's filename
contentTypestringThe declared content type, if any
attachmentTypestringThe Sentry attachment type, e.g. event.attachment, if any
dataUint8ArrayThe attachment bytes, exactly as sent
textstringThe bytes decoded as UTF-8, for asserting on text attachments

Attachments travel in the same envelope as the event they belong to, so they are also exposed on that report as report.attachments:

test('attachments example', async function() {
Sentry.captureException(new Error('import failed'), {
attachments: [{ filename: 'import.csv', data: 'id,name\n1,jane', contentType: 'text/csv' }],
})

const [report] = await testkit.waitForReports(1)
expect(report.attachments).toHaveLength(1)
expect(report.attachments[0].filename).toEqual('import.csv')
expect(report.attachments[0].text).toEqual('id,name\n1,jane')
})

Use testkit.attachments() when you do not care which event an attachment belongs to:

test('scope attachment example', async function() {
Sentry.withScope(scope => {
scope.addAttachment({ filename: 'state.json', data: JSON.stringify({ cart: ['sku-1'] }) })
Sentry.captureException(new Error('checkout failed'))
})

const [attachment] = await testkit.waitForAttachments(1)
expect(JSON.parse(attachment.text)).toEqual({ cart: ['sku-1'] })
})
Binary attachments

data holds the exact bytes whenever the testkit receives them as bytes: transport mode (Node, browser and React) always does, and so does the network interceptor when your interceptor hands the request body over as a Buffer. The local server, Puppeteer and Playwright receive the request body as text, so a binary attachment such as a screenshot arrives UTF-8 decoded there. Assert on binary payloads in transport mode.

feedback()

Gets all captured user feedback submitted via Sentry.captureFeedback(...) or the feedback widget.

Returns: Array - where each member of the array consists of a FeedbackReport type:

FieldTypeDescription
messagestringThe feedback message
namestringThe submitter's name, if provided
contactEmailstringThe submitter's email, if provided
urlstringThe page the feedback was submitted from, if provided
associatedEventIdstringThe id of the error event this feedback is linked to, if any
sourcestringThe feedback source, if provided
replayIdstringThe associated replay id, if any
eventIdstringThe feedback event's own id
originalFeedbackObjectThe raw feedback event as sent by the SDK

For example

test('feedback example', async function() {
Sentry.captureFeedback({ message: 'the checkout page is confusing', email: 'jane@example.com' })

const [feedback] = await testkit.waitForFeedback(1)
expect(feedback.message).toEqual('the checkout page is confusing')
expect(feedback.contactEmail).toEqual('jane@example.com')
})

checkIns()

Gets all captured cron monitor check-ins reported via Sentry.captureCheckIn(...) or Sentry.withMonitor(...).

Returns: Array - where each member of the array consists of a CheckIn type:

FieldTypeDescription
checkInIdstringThe check-in id (used to correlate an in_progress with its ok/error)
monitorSlugstringThe monitor's slug
statusstringin_progress | ok | error
durationnumberThe check-in duration in seconds, for a finished check-in
releasestringThe release, if set
environmentstringThe environment, if set
originalCheckInObjectThe raw check-in payload as sent by the SDK

For example

test('check-in example', async function() {
const checkInId = Sentry.captureCheckIn({ monitorSlug: 'nightly-report', status: 'in_progress' })
Sentry.captureCheckIn({ checkInId, monitorSlug: 'nightly-report', status: 'ok', duration: 12.5 })

const checkIns = await testkit.waitForCheckIns(2)
expect(checkIns.map(c => c.status)).toEqual(['in_progress', 'ok'])
})

reset()

Resets the testkit state and clear all existing reports.

For example

test('reset example', async function() {
Sentry.captureException(new Error('Sentry test kit is awesome!'))
await waitForExpect(() => expect(testkit.reports()).toHaveLength(1))
expect(testkit.reports()).toHaveLength(1)
testkit.reset()
expect(testkit.reports()).toHaveLength(0)
})
tip

Calling reset() is very useful to run between tests, see more info and examples here