Files
react-native/Libraries/LogBox/Data/__tests__/LogBoxData-test.js
T
Rick Hanlon cc056907cf Clean up API for LogBoxLogParser
Summary:
This diff cleans up two functions from:

```
LogBoxLogData.add({args: ['A']});
LogBoxLogParser({args: ['A']});
```

to:

```
LogBoxLogData.add(['A']);
LogBoxLogParser.parseLog(['A']);
```

Changelog: [Internal]

Reviewed By: cpojer

Differential Revision: D18056462

fbshipit-source-id: be6108069fc24b1f25d1382ad31c314183c793f8
2019-10-22 14:13:20 -07:00

321 lines
9.0 KiB
JavaScript

/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @emails oncall+react_native
* @format
* @flow strict-local
*/
'use strict';
jest.mock('../../../Core/Devtools/parseErrorStack', () => {
return {__esModule: true, default: jest.fn(() => [])};
});
const LogBoxData = require('../LogBoxData');
const registry = () => {
const observer = jest.fn();
LogBoxData.observe(observer).unsubscribe();
return Array.from(observer.mock.calls[0][0]);
};
const filteredRegistry = () => {
const observer = jest.fn();
LogBoxData.observe(observer).unsubscribe();
return Array.from(observer.mock.calls[0][0]);
};
const observe = () => {
const observer = jest.fn();
return {
observer,
subscription: LogBoxData.observe(observer),
};
};
describe('LogBoxData', () => {
beforeEach(() => {
jest.resetModules();
});
it('adds and dismisses logs', () => {
LogBoxData.add(['A']);
expect(registry().length).toBe(1);
expect(registry()[0]).toBeDefined();
LogBoxData.dismiss(registry()[0]);
expect(registry().length).toBe(0);
expect(registry()[0]).toBeUndefined();
});
it('clears all logs', () => {
LogBoxData.add(['A']);
LogBoxData.add(['B']);
LogBoxData.add(['C']);
expect(registry().length).toBe(3);
LogBoxData.clear();
expect(registry().length).toBe(0);
});
it('keeps logs in chronological order', () => {
LogBoxData.add(['A']);
LogBoxData.add(['B']);
LogBoxData.add(['C']);
let logs = registry();
expect(logs.length).toBe(3);
expect(logs[0].category).toEqual('A');
expect(logs[1].category).toEqual('B');
expect(logs[2].category).toEqual('C');
LogBoxData.add(['A']);
// Expect `A` to be added to the end of the registry.
logs = registry();
expect(logs.length).toBe(4);
expect(logs[0].category).toEqual('A');
expect(logs[1].category).toEqual('B');
expect(logs[2].category).toEqual('C');
expect(logs[3].category).toEqual('A');
});
it('increments the count of previous log with matching category', () => {
LogBoxData.add(['A']);
LogBoxData.add(['B']);
let logs = registry();
expect(logs.length).toBe(2);
expect(logs[0].category).toEqual('A');
expect(logs[0].count).toBe(1);
expect(logs[1].category).toEqual('B');
expect(logs[1].count).toBe(1);
LogBoxData.add(['B']);
// Expect `B` to be rolled into the last log.
logs = registry();
expect(logs.length).toBe(2);
expect(logs[0].category).toEqual('A');
expect(logs[0].count).toBe(1);
expect(logs[1].category).toEqual('B');
expect(logs[1].count).toBe(2);
});
it('ignores logs matching patterns', () => {
LogBoxData.add(['A!']);
LogBoxData.add(['B?']);
LogBoxData.add(['C!']);
expect(filteredRegistry().length).toBe(3);
LogBoxData.addIgnorePatterns(['!']);
expect(filteredRegistry().length).toBe(1);
LogBoxData.addIgnorePatterns(['?']);
expect(filteredRegistry().length).toBe(0);
});
it('ignores logs matching regexs or pattern', () => {
LogBoxData.add(['There are 4 dogs']);
LogBoxData.add(['There are 3 cats']);
LogBoxData.add(['There are H cats']);
expect(filteredRegistry().length).toBe(3);
LogBoxData.addIgnorePatterns(['dogs']);
expect(filteredRegistry().length).toBe(2);
LogBoxData.addIgnorePatterns([/There are \d+ cats/]);
expect(filteredRegistry().length).toBe(1);
LogBoxData.addIgnorePatterns(['cats']);
expect(filteredRegistry().length).toBe(0);
});
it('ignores all logs when disabled', () => {
LogBoxData.add(['A!']);
LogBoxData.add(['B?']);
LogBoxData.add(['C!']);
expect(registry().length).toBe(3);
LogBoxData.setDisabled(true);
expect(registry().length).toBe(0);
LogBoxData.setDisabled(false);
expect(registry().length).toBe(3);
});
it('groups consecutive logs by format string categories', () => {
LogBoxData.add(['%s', 'A']);
expect(registry().length).toBe(1);
expect(registry()[0].count).toBe(1);
LogBoxData.add(['%s', 'B']);
expect(registry().length).toBe(1);
expect(registry()[0].count).toBe(2);
LogBoxData.add(['A']);
expect(registry().length).toBe(2);
expect(registry()[1].count).toBe(1);
LogBoxData.add(['B']);
expect(registry().length).toBe(3);
expect(registry()[2].count).toBe(1);
});
it('groups warnings with consideration for arguments', () => {
LogBoxData.add(['A', 'B']);
expect(registry().length).toBe(1);
expect(registry()[0].count).toBe(1);
LogBoxData.add(['A', 'B']);
expect(registry().length).toBe(1);
expect(registry()[0].count).toBe(2);
LogBoxData.add(['A', 'C']);
expect(registry().length).toBe(2);
expect(registry()[1].count).toBe(1);
LogBoxData.add(['%s', 'A', 'A']);
expect(registry().length).toBe(3);
expect(registry()[2].count).toBe(1);
LogBoxData.add(['%s', 'B', 'A']);
expect(registry().length).toBe(3);
expect(registry()[2].count).toBe(2);
LogBoxData.add(['%s', 'B', 'B']);
expect(registry().length).toBe(4);
expect(registry()[3].count).toBe(1);
});
it('ignores logs starting with "(ADVICE)"', () => {
LogBoxData.add(['(ADVICE) ...']);
expect(registry().length).toBe(0);
});
it('does not ignore logs formatted to start with "(ADVICE)"', () => {
LogBoxData.add(['%s ...', '(ADVICE)']);
expect(registry().length).toBe(1);
});
it('immediately updates new observers', () => {
const {observer: observerOne} = observe();
expect(observerOne.mock.calls.length).toBe(1);
const observerTwo = jest.fn();
LogBoxData.observe(observerTwo).unsubscribe();
expect(observerTwo.mock.calls.length).toBe(1);
expect(observerOne.mock.calls[0][0]).toEqual(observerTwo.mock.calls[0][0]);
});
it('sends batched updates asynchronously', () => {
const {observer} = observe();
expect(observer.mock.calls.length).toBe(1);
LogBoxData.add(['A']);
LogBoxData.add(['B']);
jest.runAllImmediates();
expect(observer.mock.calls.length).toBe(2);
// We expect observers to recieve the same Set object in sequential updates
// so that it doesn't break memoization for components observing state.
expect(observer.mock.calls[0][0]).toBe(observer.mock.calls[1][0]);
});
it('stops sending updates to unsubscribed observers', () => {
const {observer: observerOne, subscription} = observe();
subscription.unsubscribe();
expect(observerOne.mock.calls.length).toBe(1);
const observerTwo = jest.fn();
LogBoxData.observe(observerTwo).unsubscribe();
expect(observerTwo.mock.calls.length).toBe(1);
expect(observerOne.mock.calls[0][0]).toEqual(observerTwo.mock.calls[0][0]);
});
it('updates observers when a log is added or dismissed', () => {
const {observer} = observe();
expect(observer.mock.calls.length).toBe(1);
LogBoxData.add(['A']);
jest.runAllImmediates();
expect(observer.mock.calls.length).toBe(2);
const lastLog = Array.from(observer.mock.calls[1][0])[0];
LogBoxData.dismiss(lastLog);
jest.runAllImmediates();
expect(observer.mock.calls.length).toBe(3);
// Does nothing when category does not exist.
LogBoxData.dismiss(lastLog);
jest.runAllImmediates();
expect(observer.mock.calls.length).toBe(3);
});
it('updates observers when cleared', () => {
const {observer} = observe();
expect(observer.mock.calls.length).toBe(1);
LogBoxData.add(['A']);
jest.runAllImmediates();
expect(observer.mock.calls.length).toBe(2);
LogBoxData.clear();
jest.runAllImmediates();
expect(observer.mock.calls.length).toBe(3);
// Does nothing when already empty.
LogBoxData.clear();
jest.runAllImmediates();
expect(observer.mock.calls.length).toBe(3);
});
it('updates observers when an ignore pattern is added', () => {
const {observer} = observe();
expect(observer.mock.calls.length).toBe(1);
LogBoxData.addIgnorePatterns(['?']);
jest.runAllImmediates();
expect(observer.mock.calls.length).toBe(2);
LogBoxData.addIgnorePatterns(['!']);
jest.runAllImmediates();
expect(observer.mock.calls.length).toBe(3);
// Does nothing for an existing ignore pattern.
LogBoxData.addIgnorePatterns(['!']);
jest.runAllImmediates();
expect(observer.mock.calls.length).toBe(3);
});
it('updates observers when disabled or enabled', () => {
const {observer} = observe();
expect(observer.mock.calls.length).toBe(1);
LogBoxData.setDisabled(true);
jest.runAllImmediates();
expect(observer.mock.calls.length).toBe(2);
// Does nothing when already disabled.
LogBoxData.setDisabled(true);
jest.runAllImmediates();
expect(observer.mock.calls.length).toBe(2);
LogBoxData.setDisabled(false);
jest.runAllImmediates();
expect(observer.mock.calls.length).toBe(3);
// Does nothing when already enabled.
LogBoxData.setDisabled(false);
jest.runAllImmediates();
expect(observer.mock.calls.length).toBe(3);
});
});