Skip to content

Commit

Permalink
chore: better logger (#1727)
Browse files Browse the repository at this point in the history
  • Loading branch information
mdjastrzebski authored Jan 8, 2025
1 parent f8a0d44 commit b4d5942
Show file tree
Hide file tree
Showing 8 changed files with 57 additions and 25 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
"typings/index.flow.js"
],
"dependencies": {
"chalk": "^4.1.2",
"jest-matcher-utils": "^29.7.0",
"pretty-format": "^29.7.0",
"redent": "^3.0.0"
Expand Down
28 changes: 13 additions & 15 deletions src/__tests__/render-debug.test.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
/* eslint-disable no-console */
import * as React from 'react';
import { Pressable, Text, TextInput, View } from 'react-native';
import stripAnsi from 'strip-ansi';
import { configure, fireEvent, render, screen } from '..';
import { logger } from '../helpers/logger';

const PLACEHOLDER_FRESHNESS = 'Add custom freshness';
const PLACEHOLDER_CHEF = 'Who inspected freshness?';
Expand All @@ -13,13 +13,11 @@ const DEFAULT_INPUT_CUSTOMER = 'What banana?';

const ignoreWarnings = ['Using debug("message") is deprecated'];

const realConsoleWarn = console.warn;

beforeEach(() => {
jest.spyOn(console, 'log').mockImplementation(() => {});
jest.spyOn(console, 'warn').mockImplementation((message) => {
if (!ignoreWarnings.some((warning) => message.includes(warning))) {
realConsoleWarn(message);
jest.spyOn(logger, 'info').mockImplementation(() => {});
jest.spyOn(logger, 'warn').mockImplementation((message) => {
if (!ignoreWarnings.some((warning) => `${message}`.includes(warning))) {
logger.warn(message);
}
});
});
Expand Down Expand Up @@ -99,12 +97,12 @@ test('debug', () => {
screen.debug('my custom message');
screen.debug({ message: 'another custom message' });

const mockCalls = jest.mocked(console.log).mock.calls;
const mockCalls = jest.mocked(logger.info).mock.calls;
expect(stripAnsi(mockCalls[0][0])).toMatchSnapshot();
expect(stripAnsi(mockCalls[1][0] + mockCalls[1][1])).toMatchSnapshot('with message');
expect(stripAnsi(mockCalls[2][0] + mockCalls[2][1])).toMatchSnapshot('another custom message');

const mockWarnCalls = jest.mocked(console.warn).mock.calls;
const mockWarnCalls = jest.mocked(logger.warn).mock.calls;
expect(mockWarnCalls[0]).toMatchInlineSnapshot(`
[
"Using debug("message") is deprecated and will be removed in future release, please use debug({ message: "message" }) instead.",
Expand All @@ -118,7 +116,7 @@ test('debug changing component', () => {

screen.debug();

const mockCalls = jest.mocked(console.log).mock.calls;
const mockCalls = jest.mocked(logger.info).mock.calls;
expect(stripAnsi(mockCalls[0][0])).toMatchSnapshot(
'bananaFresh button message should now be "fresh"',
);
Expand All @@ -128,7 +126,7 @@ test('debug with only children prop', () => {
render(<Banana />);
screen.debug({ mapProps: () => ({}) });

const mockCalls = jest.mocked(console.log).mock.calls;
const mockCalls = jest.mocked(logger.info).mock.calls;
expect(stripAnsi(mockCalls[0][0])).toMatchSnapshot();
});

Expand All @@ -146,7 +144,7 @@ test('debug with only prop whose value is bananaChef', () => {
},
});

const mockCalls = jest.mocked(console.log).mock.calls;
const mockCalls = jest.mocked(logger.info).mock.calls;
expect(stripAnsi(mockCalls[0][0])).toMatchSnapshot();
});

Expand All @@ -156,7 +154,7 @@ test('debug with only props from TextInput components', () => {
mapProps: (props, node) => (node.type === 'TextInput' ? props : {}),
});

const mockCalls = jest.mocked(console.log).mock.calls;
const mockCalls = jest.mocked(logger.info).mock.calls;
expect(stripAnsi(mockCalls[0][0])).toMatchSnapshot();
});

Expand All @@ -170,7 +168,7 @@ test('debug should use debugOptions from config when no option is specified', ()
);
screen.debug();

const mockCalls = jest.mocked(console.log).mock.calls;
const mockCalls = jest.mocked(logger.info).mock.calls;
expect(stripAnsi(mockCalls[0][0])).toMatchSnapshot();
});

Expand All @@ -191,6 +189,6 @@ test('debug should use given options over config debugOptions', () => {
);
screen.debug({ mapProps: (props) => props });

const mockCalls = jest.mocked(console.log).mock.calls;
const mockCalls = jest.mocked(logger.info).mock.calls;
expect(stripAnsi(mockCalls[0][0])).toMatchSnapshot();
});
7 changes: 3 additions & 4 deletions src/helpers/debug.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { ReactTestRendererJSON } from 'react-test-renderer';
import format, { FormatOptions } from './format';
import { logger } from './logger';

export type DebugOptions = {
message?: string;
Expand All @@ -17,10 +18,8 @@ export function debug(
const formatOptions = typeof options === 'object' ? { mapProps: options?.mapProps } : undefined;

if (message) {
// eslint-disable-next-line no-console
console.log(`${message}\n\n`, format(instance, formatOptions));
logger.info(`${message}\n\n`, format(instance, formatOptions));
} else {
// eslint-disable-next-line no-console
console.log(format(instance, formatOptions));
logger.info(format(instance, formatOptions));
}
}
32 changes: 32 additions & 0 deletions src/helpers/logger.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import * as nodeConsole from 'console';
import * as nodeUtil from 'util';
import chalk from 'chalk';
import redent from 'redent';

export const logger = {
debug(message: any, ...args: any[]) {
const output = formatMessage('●', message, ...args);
nodeConsole.debug(chalk.dim(output));
},

info(message: any, ...args: any[]) {
const output = formatMessage('●', message, ...args);
nodeConsole.info(output);
},

warn(message: any, ...args: any[]) {
const output = formatMessage('▲', message, ...args);
nodeConsole.warn(chalk.yellow(output));
},

error(message: any, ...args: any[]) {
const output = formatMessage('■', message, ...args);
nodeConsole.error(chalk.red(output));
},
};

function formatMessage(symbol: string, message: any, ...args: any[]) {
const formatted = nodeUtil.format(message, ...args);
const indented = redent(formatted, 4);
return ` ${symbol} ${indented.trimStart()}\n`;
}
3 changes: 2 additions & 1 deletion src/queries/__tests__/label-text.test.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as React from 'react';
import { View, Text, TextInput, Image, Pressable } from 'react-native';
import { render, screen } from '../..';
import { logger } from '../../helpers/logger';

const BUTTON_LABEL = 'cool button';
const BUTTON_HINT = 'click this button';
Expand Down Expand Up @@ -105,7 +106,7 @@ test('getAllByLabelText, queryAllByLabelText, findAllByLabelText with exact as f
describe('findBy options deprecations', () => {
let warnSpy: jest.SpyInstance;
beforeEach(() => {
warnSpy = jest.spyOn(console, 'warn').mockImplementation(() => {});
warnSpy = jest.spyOn(logger, 'warn').mockImplementation(() => {});
});
afterEach(() => {
warnSpy.mockRestore();
Expand Down
4 changes: 2 additions & 2 deletions src/queries/make-queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { ErrorWithStack } from '../helpers/errors';
import waitFor from '../wait-for';
import type { WaitForOptions } from '../wait-for';
import format from '../helpers/format';
import { logger } from '../helpers/logger';
import { screen } from '../screen';
import { defaultMapProps } from '../helpers/format-default';

Expand Down Expand Up @@ -69,8 +70,7 @@ function extractDeprecatedWaitForOptions(options?: WaitForOptions) {
deprecatedKeys.forEach((key) => {
const option = options[key];
if (option) {
// eslint-disable-next-line no-console
console.warn(
logger.warn(
`Use of option "${key}" in a findBy* query options (2nd parameter) is deprecated. Please pass this option in the waitForOptions (3rd parameter).
Example:
Expand Down
4 changes: 2 additions & 2 deletions src/render.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { addToCleanupQueue } from './cleanup';
import { getConfig } from './config';
import { getHostSelves } from './helpers/component-tree';
import { debug, DebugOptions } from './helpers/debug';
import { logger } from './helpers/logger';
import { validateStringsRenderedWithinText } from './helpers/string-validation';
import { renderWithAct } from './render-act';
import { setRenderResult } from './screen';
Expand Down Expand Up @@ -161,8 +162,7 @@ function makeDebug(instance: ReactTestInstance, renderer: ReactTestRenderer): De
: { ...defaultDebugOptions, ...options };

if (typeof options === 'string') {
// eslint-disable-next-line no-console
console.warn(
logger.warn(
'Using debug("message") is deprecated and will be removed in future release, please use debug({ message: "message" }) instead.',
);
}
Expand Down
3 changes: 2 additions & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2650,6 +2650,7 @@ __metadata:
"@types/react-test-renderer": "npm:^18.3.0"
babel-jest: "npm:^29.7.0"
babel-plugin-module-resolver: "npm:^5.0.2"
chalk: "npm:^4.1.2"
del-cli: "npm:^6.0.0"
eslint: "npm:^8.57.1"
eslint-plugin-prettier: "npm:^4.2.1"
Expand Down Expand Up @@ -3773,7 +3774,7 @@ __metadata:
languageName: node
linkType: hard

"chalk@npm:^4.0.0, chalk@npm:^4.1.0":
"chalk@npm:^4.0.0, chalk@npm:^4.1.0, chalk@npm:^4.1.2":
version: 4.1.2
resolution: "chalk@npm:4.1.2"
dependencies:
Expand Down

0 comments on commit b4d5942

Please sign in to comment.