import { DATA_ENDPOINT } from '../src/constants.js'
import CrashReporter from '../src/crash-reporter.js'
import { describe, expect, it, vi, beforeEach, afterEach } from 'vitest'
import * as bstackLogger from '../src/bstackLogger.js'
vi.mock('fetch')
const bstackLoggerSpy = vi.spyOn(bstackLogger.BStackLogger, 'logToFile')
bstackLoggerSpy.mockImplementation(() => {})
describe('CrashReporter', () => {
afterEach(() => {
vi.resetAllMocks()
delete process.env.CREDENTIALS_FOR_CRASH_REPORTING
delete process.env.userConfigForReporting
})
describe('uploadCrashReport', () => {
it ('should return if creds are not valid', () => {
process.env.CREDENTIALS_FOR_CRASH_REPORTING = 'some invalid credentials'
expect(() => {
CrashReporter.uploadCrashReport('some exception', 'some stack')
}).not.toThrow()
})
it('should return if no username or key', () => {
process.env.CREDENTIALS_FOR_CRASH_REPORTING = '{}'
expect(() => {
CrashReporter.uploadCrashReport('some exception', 'some stack')
}).not.toThrow()
})
describe('valid credentials', () => {
beforeEach(() => {
process.env.CREDENTIALS_FOR_CRASH_REPORTING = JSON.stringify({ 'username': 'user', 'password': 'password' })
process.env.userConfigForReporting = JSON.stringify({})
})
it('should not raise any exception', () => {
vi.mocked(fetch).mockReturnValueOnce(Promise.resolve(Response.json({ status: 'success' })))
expect(() => CrashReporter.uploadCrashReport('some exception', 'some stack')).not.toThrow()
expect(vi.mocked(fetch).mock.calls[0][1]?.method).toEqual('POST')
})
it('should send empty config if fetching config fails', () => {
vi.mocked(fetch).mockReturnValueOnce(Promise.resolve(Response.json({ status: 'success' })))
const url = `${DATA_ENDPOINT}/api/v1/analytics`
expect(() => CrashReporter.uploadCrashReport('some exception', 'some stack')).not.toThrow()
expect(fetch).toHaveBeenCalledWith(url, expect.objectContaining({
method: 'POST',
body: expect.stringContaining('"config":{}}')
}))
})
it('should not raise error if request fails', () => {
vi.mocked(fetch).mockReturnValueOnce(Promise.resolve(Response.json({ status: 'failed' })))
expect(() => CrashReporter.uploadCrashReport('some exception', 'some stack')).not.toThrow()
expect(vi.mocked(fetch).mock.calls[0][1]?.method).toEqual('POST')
})
})
})
describe('filterPII', () => {
it('should delete user key from L1', () => {
const userConfig = {
'framework': 'some framework',
'user': 'some user',
'key': 'key',
'some_other_keys': 'value',
capabilities: {},
services: []
}
const filteredConfig = CrashReporter.filterPII(userConfig)
expect(filteredConfig).toEqual({
'framework': 'some framework',
'some_other_keys': 'value',
capabilities: {},
services: []
})
})
it('should delete user key from testObservabilityOptions', () => {
const userConfig = {
'framework': 'some framework',
'user': 'some user',
'key': 'key',
capabilities: {},
services: [
['browserstack', {
testObservabilityOptions: {
user: 'username',
key: 'access-key',
},
}]
]
}
const filteredConfig = CrashReporter.filterPII(userConfig)
expect(filteredConfig).toEqual({
'framework': 'some framework',
capabilities: {},
services: [
['browserstack', {
testObservabilityOptions: {
},
}]
]
})
})
it('should delete user key from browserstack service options', () => {
const userConfig = {
'framework': 'some framework',
'user': 'some user',
'key': 'key',
capabilities: {},
services: [
['browserstack', {
user: 'username',
key: 'access-key',
}]
]
}
const filteredConfig = CrashReporter.filterPII(userConfig as any)
expect(filteredConfig).toEqual({
'framework': 'some framework',
capabilities: {},
services: [
['browserstack', {}]
]
})
})
})
})