/** * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * * @flow strict-local * @format */ const LOG_LEVELS = { trace: 0, info: 1, warn: 2, error: 3, }; describe('console.table(data, rows)', () => { let originalNativeLoggingHook; let logFn; beforeEach(() => { originalNativeLoggingHook = global.nativeLoggingHook; logFn = global.nativeLoggingHook = jest.fn(); }); afterEach(() => { global.nativeLoggingHook = originalNativeLoggingHook; }); it('should print the passed array as a Markdown table', () => { console.table([ {name: 'First', value: 500}, {name: 'Second', value: 600}, {name: 'Third', value: 700}, {name: 'Fourth', value: 800, extraValue: true}, ]); expect(logFn).toHaveBeenCalledTimes(1); expect(logFn.mock.lastCall).toEqual([ ` | (index) | name | value | extraValue | | ------- | -------- | ----- | ---------- | | 0 | 'First' | 500 | | | 1 | 'Second' | 600 | | | 2 | 'Third' | 700 | | | 3 | 'Fourth' | 800 | true |`, LOG_LEVELS.info, ]); }); it('should print the passed dictionary as a Markdown table', () => { console.table({ first: {name: 'First', value: 500}, second: {name: 'Second', value: 600}, third: {name: 'Third', value: 700}, fourth: {name: 'Fourth', value: 800, extraValue: true}, }); expect(logFn).toHaveBeenCalledTimes(1); expect(logFn.mock.lastCall).toEqual([ ` | (index) | name | value | extraValue | | ------- | -------- | ----- | ---------- | | first | 'First' | 500 | | | second | 'Second' | 600 | | | third | 'Third' | 700 | | | fourth | 'Fourth' | 800 | true |`, LOG_LEVELS.info, ]); }); it('should work with different types of values', () => { console.table([ { string: '', number: 0, boolean: true, function: () => {}, object: {a: 1, b: 2}, null: null, undefined: undefined, }, { string: 'a', number: 1, boolean: true, function: () => {}, object: {a: 1, b: 2}, null: null, undefined: undefined, }, { string: 'aa', number: 2, boolean: false, function: () => {}, object: {a: 1, b: 2}, null: null, undefined: undefined, }, { string: 'aaa', number: 3, boolean: false, function: () => {}, object: {a: 1, b: 2}, null: null, undefined: undefined, }, ]); expect(logFn).toHaveBeenCalledTimes(1); expect(logFn.mock.lastCall).toEqual([ ` | (index) | string | number | boolean | function | object | null | undefined | | ------- | ------ | ------ | ------- | -------- | ------ | ---- | --------- | | 0 | '' | 0 | true | ƒ | {…} | null | undefined | | 1 | 'a' | 1 | true | ƒ | {…} | null | undefined | | 2 | 'aa' | 2 | false | ƒ | {…} | null | undefined | | 3 | 'aaa' | 3 | false | ƒ | {…} | null | undefined |`, LOG_LEVELS.info, ]); }); it('should print the keys in all the objects', () => { console.table([ {name: 'foo'}, {name: 'bar', value: 1}, {value: 2, surname: 'baz'}, {address: 'other'}, ]); expect(logFn).toHaveBeenCalledTimes(1); expect(logFn.mock.lastCall).toEqual([ ` | (index) | name | value | surname | address | | ------- | ----- | ----- | ------- | ------- | | 0 | 'foo' | | | | | 1 | 'bar' | 1 | | | | 2 | | 2 | 'baz' | | | 3 | | | | 'other' |`, LOG_LEVELS.info, ]); }); it('should print an empty string for empty arrays', () => { console.table([]); expect(logFn).toHaveBeenCalledTimes(1); expect(logFn.mock.lastCall).toEqual([``, LOG_LEVELS.info]); }); it('should print an empty string for empty dictionaries', () => { console.table({}); expect(logFn).toHaveBeenCalledTimes(1); expect(logFn.mock.lastCall).toEqual([``, LOG_LEVELS.info]); }); // This test is currently failing it('should print an indices table for an array of empty objects', () => { console.table([{}, {}, {}, {}]); expect(logFn).toHaveBeenCalledTimes(1); expect(logFn.mock.lastCall).toEqual([ ` | (index) | | ------- | | 0 | | 1 | | 2 | | 3 |`, LOG_LEVELS.info, ]); }); it('should print an indices table for a dictionary of empty objects', () => { console.table({ first: {}, second: {}, third: {}, fourth: {}, }); expect(logFn).toHaveBeenCalledTimes(1); expect(logFn.mock.lastCall).toEqual([ ` | (index) | | ------- | | first | | second | | third | | fourth |`, LOG_LEVELS.info, ]); }); it('should not modify the logged value', () => { global.nativeLoggingHook = jest.fn(); const array = [ {name: 'First', value: 500}, {name: 'Second', value: 600}, {name: 'Third', value: 700}, {name: 'Fourth', value: 800, extraValue: true}, ]; const originalArrayValue = JSON.parse(JSON.stringify(array)); console.table(array); expect(array).toEqual(originalArrayValue); const object = { first: {name: 'First', value: 500}, second: {name: 'Second', value: 600}, third: {name: 'Third', value: 700}, fourth: {name: 'Fourth', value: 800, extraValue: true}, }; const originalObjectValue = JSON.parse(JSON.stringify(object)); console.table(object); expect(object).toEqual(originalObjectValue); }); it('should only print the selected columns, if specified (arrays)', () => { console.table( [ {first: 1, second: 2, third: 3}, {first: 4, second: 5}, {third: 7, fourth: 8}, {fifth: 9}, ], // $FlowExpectedError[extra-arg] ['first', 'fifth'], ); expect(logFn).toHaveBeenCalledTimes(1); expect(logFn.mock.lastCall).toEqual([ ` | (index) | first | fifth | | ------- | ----- | ----- | | 0 | 1 | | | 1 | 4 | | | 2 | | | | 3 | | 9 |`, LOG_LEVELS.info, ]); }); it('should only print the selected columns, if specified (dictionaries)', () => { console.table( { a: {first: 1, second: 2, third: 3}, b: {first: 4, second: 5}, c: {third: 7, fourth: 8}, d: {fifth: 9}, }, // $FlowExpectedError[extra-arg] ['first', 'fifth'], ); expect(logFn).toHaveBeenCalledTimes(1); expect(logFn.mock.lastCall).toEqual([ ` | (index) | first | fifth | | ------- | ----- | ----- | | a | 1 | | | b | 4 | | | c | | | | d | | 9 |`, LOG_LEVELS.info, ]); }); });