API Reference
Sentry Testkit consists of a very simple and strait-forward API using the following functions
Methods
Capture and assertions
reports()— captured errors and messagestransactions()— captured performance transactionslogs()— captured structured logsmetrics()— captured application metricsattachments()— captured event attachmentsfeedback()— captured user feedbackcheckIns()— captured cron monitor check-ins
Awaiting asynchronously-sent data
waitForReports(count, options)— and its siblingswaitForTransactions,waitForLogs,waitForMetrics,waitForAttachments,waitForFeedback,waitForCheckIns
Finding and filtering
findReport(error)findReportByMessage(message)findTransaction(name)reportsWithTag(key, value)— andtransactionsWithTag(key, value)isExist(error)getExceptionAt(index)
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.
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
})
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:
| Field | Type | Description |
|---|---|---|
level | string | trace | debug | info | warn | error | fatal |
message | string | The log body |
attributes | Object | Log attributes as plain values, e.g. { userId: 42 } |
timestamp | number | Epoch time in seconds |
traceId | string | The trace this log belongs to, if any |
severityNumber | number | The numeric severity, if any |
originalLog | Object | The 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:
| Field | Type | Description |
|---|---|---|
name | string | The metric name, e.g. api.requests |
type | string | counter | gauge | distribution |
value | number | The reported value |
unit | string | The unit, e.g. millisecond, if provided |
attributes | Object | Metric attributes as plain values, e.g. { endpoint: '/api/users' } |
timestamp | number | Epoch time in seconds |
traceId | string | The trace this metric belongs to, if any |
spanId | string | The span this metric was emitted from, if any |
originalMetric | Object | The 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:
| Field | Type | Description |
|---|---|---|
filename | string | The attachment's filename |
contentType | string | The declared content type, if any |
attachmentType | string | The Sentry attachment type, e.g. event.attachment, if any |
data | Uint8Array | The attachment bytes, exactly as sent |
text | string | The 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'] })
})
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:
| Field | Type | Description |
|---|---|---|
message | string | The feedback message |
name | string | The submitter's name, if provided |
contactEmail | string | The submitter's email, if provided |
url | string | The page the feedback was submitted from, if provided |
associatedEventId | string | The id of the error event this feedback is linked to, if any |
source | string | The feedback source, if provided |
replayId | string | The associated replay id, if any |
eventId | string | The feedback event's own id |
originalFeedback | Object | The 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:
| Field | Type | Description |
|---|---|---|
checkInId | string | The check-in id (used to correlate an in_progress with its ok/error) |
monitorSlug | string | The monitor's slug |
status | string | in_progress | ok | error |
duration | number | The check-in duration in seconds, for a finished check-in |
release | string | The release, if set |
environment | string | The environment, if set |
originalCheckIn | Object | The 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)
})
Calling reset() is very useful to run between tests, see more info and examples here