Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion packages/core/src/integrations/consola.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,13 +123,20 @@ export interface ConsolaLogObject {
/**
* The raw arguments passed to the log method.
*
* When `message` is not provided, these args are typically formatted into the final message.
* These args are typically formatted into the final `message`. In Consola reporters, `message` is not provided.
*
* @example
* ```ts
* consola.info('Hello', 'world', { user: 'john' });
* // args = ['Hello', 'world', { user: 'john' }]
* ```
*
* @example
* ```ts
* // `message` is a reserved property in Consola
* consola.log({ message: 'Hello' });
* // args = ['Hello']
* ```
*/
args?: unknown[];

Expand Down
246 changes: 73 additions & 173 deletions packages/core/test/lib/integrations/consola.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,14 @@ vi.mock('../../../src/logs/internal', () => ({
_INTERNAL_flushLogsBuffer: vi.fn(),
}));

vi.mock('../../../src/logs/utils', async actual => ({
formatConsoleArgs: vi.fn(((await actual()) as any).formatConsoleArgs),
}));
vi.mock('../../../src/logs/utils', async importOriginal => {
// eslint-disable-next-line @typescript-eslint/consistent-type-imports
const actual: typeof import('../../../src/logs/utils') = await importOriginal();
return {
...actual,
formatConsoleArgs: vi.fn(actual.formatConsoleArgs),
};
});

vi.mock('../../../src/currentScopes', () => ({
getClient: vi.fn(),
Expand All @@ -22,6 +27,7 @@ vi.mock('../../../src/currentScopes', () => ({

describe('createConsolaReporter', () => {
let mockClient: TestClient;
let sentryReporter: ReturnType<typeof createConsolaReporter>;

beforeEach(() => {
vi.clearAllMocks();
Expand All @@ -34,12 +40,11 @@ describe('createConsolaReporter', () => {
normalizeMaxBreadth: 1000,
});

const mockScope = {
getClient: vi.fn().mockReturnValue(mockClient),
};

vi.mocked(getClient).mockReturnValue(mockClient);
vi.mocked(getCurrentScope).mockReturnValue(mockScope as any);
vi.mocked(getCurrentScope).mockReturnValue({
getClient: vi.fn().mockReturnValue(mockClient),
} as any);
sentryReporter = createConsolaReporter();
});

afterEach(() => {
Expand All @@ -56,126 +61,7 @@ describe('createConsolaReporter', () => {
});
});

describe('log capturing', () => {
let sentryReporter: any;

beforeEach(() => {
sentryReporter = createConsolaReporter();
});

it('should capture error logs', () => {
const logObj = {
type: 'error',
level: 0,
message: 'This is an error',
tag: 'test',
date: new Date('2023-01-01T00:00:00.000Z'),
};

sentryReporter.log(logObj);

expect(_INTERNAL_captureLog).toHaveBeenCalledWith({
level: 'error',
message: 'This is an error',
attributes: {
'sentry.origin': 'auto.log.consola',
'consola.tag': 'test',
'consola.type': 'error',
'consola.level': 0,
},
});
});

it('should capture warn logs', () => {
const logObj = {
type: 'warn',
message: 'This is a warning',
};

sentryReporter.log(logObj);

expect(_INTERNAL_captureLog).toHaveBeenCalledWith({
level: 'warn',
message: 'This is a warning',
attributes: {
'sentry.origin': 'auto.log.consola',
'consola.type': 'warn',
},
});
});

it('should capture info logs', () => {
const logObj = {
type: 'info',
message: 'This is info',
};

sentryReporter.log(logObj);

expect(_INTERNAL_captureLog).toHaveBeenCalledWith({
level: 'info',
message: 'This is info',
attributes: {
'sentry.origin': 'auto.log.consola',
'consola.type': 'info',
},
});
});

it('should capture debug logs', () => {
const logObj = {
type: 'debug',
message: 'Debug message',
};

sentryReporter.log(logObj);

expect(_INTERNAL_captureLog).toHaveBeenCalledWith({
level: 'debug',
message: 'Debug message',
attributes: {
'sentry.origin': 'auto.log.consola',
'consola.type': 'debug',
},
});
});

it('should capture trace logs', () => {
const logObj = {
type: 'trace',
message: 'Trace message',
};

sentryReporter.log(logObj);

expect(_INTERNAL_captureLog).toHaveBeenCalledWith({
level: 'trace',
message: 'Trace message',
attributes: {
'sentry.origin': 'auto.log.consola',
'consola.type': 'trace',
},
});
});

it('should capture fatal logs', () => {
const logObj = {
type: 'fatal',
message: 'Fatal error',
};

sentryReporter.log(logObj);

expect(_INTERNAL_captureLog).toHaveBeenCalledWith({
level: 'fatal',
message: 'Fatal error',
attributes: {
'sentry.origin': 'auto.log.consola',
'consola.type': 'fatal',
},
});
});

describe('message and args handling', () => {
it('should format message from args when message is not provided', () => {
const logObj = {
type: 'info',
Expand Down Expand Up @@ -215,53 +101,67 @@ describe('createConsolaReporter', () => {
},
});
});
});

it('should map consola levels to sentry levels when type is not provided', () => {
const logObj = {
level: 0, // Fatal level
message: 'Fatal message',
};

sentryReporter.log(logObj);

expect(_INTERNAL_captureLog).toHaveBeenCalledWith({
level: 'fatal',
message: 'Fatal message',
attributes: {
'sentry.origin': 'auto.log.consola',
'consola.level': 0,
},
});
describe('level mapping', () => {
it.each([
['error', 'error'],
['warn', 'warn'],
['info', 'info'],
['debug', 'debug'],
['trace', 'trace'],
['fatal', 'fatal'],
] as const)('maps type "%s" to Sentry level "%s"', (type, expectedLevel) => {
sentryReporter.log({ type, args: [`${type} message`] });

expect(_INTERNAL_captureLog).toHaveBeenCalledWith(
expect.objectContaining({
level: expectedLevel,
message: `${type} message`,
attributes: expect.objectContaining({ 'consola.type': type, 'sentry.origin': 'auto.log.consola' }),
}),
);
});

it('should map various consola types correctly', () => {
const testCases = [
{ type: 'success', expectedLevel: 'info' },
{ type: 'fail', expectedLevel: 'error' },
{ type: 'ready', expectedLevel: 'info' },
{ type: 'start', expectedLevel: 'info' },
{ type: 'verbose', expectedLevel: 'debug' },
{ type: 'log', expectedLevel: 'info' },
{ type: 'silent', expectedLevel: 'trace' },
];

testCases.forEach(({ type, expectedLevel }) => {
vi.clearAllMocks();

sentryReporter.log({
type,
message: `Test ${type} message`,
});

expect(_INTERNAL_captureLog).toHaveBeenCalledWith({
it.each([
['success', 'info'],
['fail', 'error'],
['ready', 'info'],
['start', 'info'],
['verbose', 'debug'],
['log', 'info'],
['silent', 'trace'],
] as const)('maps consola type "%s" to Sentry level "%s"', (type, expectedLevel) => {
sentryReporter.log({ type, args: [`Test ${type}`] });

expect(_INTERNAL_captureLog).toHaveBeenCalledWith(
expect.objectContaining({
level: expectedLevel,
message: `Test ${type} message`,
attributes: {
'sentry.origin': 'auto.log.consola',
message: `Test ${type}`,
attributes: expect.objectContaining({
'consola.type': type,
},
});
'sentry.origin': 'auto.log.consola',
}),
}),
);
});

it('uses level number when type is missing', () => {
sentryReporter.log({
level: 0, // Fatal level
args: ['Fatal message'],
});

expect(_INTERNAL_captureLog).toHaveBeenCalledWith(
expect.objectContaining({
level: 'fatal',
message: 'Fatal message',
attributes: expect.objectContaining({
'consola.level': 0,
'sentry.origin': 'auto.log.consola',
}),
}),
);
});
});

Expand All @@ -274,21 +174,21 @@ describe('createConsolaReporter', () => {
// Should capture error
filteredReporter.log({
type: 'error',
message: 'Error message',
args: ['Error message'],
});
expect(_INTERNAL_captureLog).toHaveBeenCalledTimes(1);

// Should capture warn
filteredReporter.log({
type: 'warn',
message: 'Warn message',
args: ['Warn message'],
});
expect(_INTERNAL_captureLog).toHaveBeenCalledTimes(2);

// Should not capture info
filteredReporter.log({
type: 'info',
message: 'Info message',
args: ['Info message'],
});
expect(_INTERNAL_captureLog).toHaveBeenCalledTimes(2);
});
Expand All @@ -300,7 +200,7 @@ describe('createConsolaReporter', () => {
['trace', 'debug', 'info', 'warn', 'error', 'fatal'].forEach(type => {
defaultReporter.log({
type,
message: `${type} message`,
args: [`${type} message`],
});
});

Expand Down
Loading