Skip to content

Commit 8926364

Browse files
rickhanloniiblakef
authored andcommitted
Refactor LogBox tests to spies (#46638)
Summary: Pull Request resolved: #46638 This is annoying, but in the next diff that fixes a bug I need to test using the default warning filter instead of a mock (really, all this mocking is terrible, idk why I did it this way). Unfortunately, in Jest you can't just reset mocks from `jest.mock`, `restoreMocks` only resets spies and not mocks (wild right). So in this diff I converted all the `jest.mock` calls to `jest.spyOn`. I also corrected some of the mocks that require `monitorEvent: 'warning',` like the warning filter sets. I also added a test that works without the fix. Changelog: [Internal] Reviewed By: javache Differential Revision: D63349615 fbshipit-source-id: 4f2a5a8800c8fe1a10e3613d3c2d0ed02fca773e
1 parent 094f036 commit 8926364

File tree

1 file changed

+91
-30
lines changed

1 file changed

+91
-30
lines changed

packages/react-native/Libraries/LogBox/__tests__/LogBox-test.js

Lines changed: 91 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
const LogBoxData = require('../Data/LogBoxData');
1515
const LogBox = require('../LogBox').default;
16+
const ExceptionsManager = require('../../Core/ExceptionsManager.js');
1617

1718
declare var console: any;
1819

@@ -34,15 +35,18 @@ describe('LogBox', () => {
3435

3536
beforeEach(() => {
3637
jest.resetModules();
38+
jest.restoreAllMocks();
3739
console.error = jest.fn();
38-
console.log = jest.fn();
3940
console.warn = jest.fn();
4041
});
4142

4243
afterEach(() => {
4344
LogBox.uninstall();
45+
// Reset ExceptionManager patching.
46+
if (console._errorOriginal) {
47+
console._errorOriginal = null;
48+
}
4449
console.error = error;
45-
console.log = log;
4650
console.warn = warn;
4751
});
4852

@@ -95,7 +99,7 @@ describe('LogBox', () => {
9599
});
96100

97101
it('registers warnings', () => {
98-
jest.mock('../Data/LogBoxData');
102+
jest.spyOn(LogBoxData, 'addLog');
99103

100104
LogBox.install();
101105

@@ -105,13 +109,14 @@ describe('LogBox', () => {
105109
});
106110

107111
it('reports a LogBox exception if we fail to add warnings', () => {
108-
jest.mock('../Data/LogBoxData');
109-
const mockError = new Error('Simulated error');
112+
jest.spyOn(LogBoxData, 'addLog');
113+
jest.spyOn(LogBoxData, 'reportLogBoxError');
110114

111115
// Picking a random implementation detail to simulate throwing.
112-
(LogBoxData.isMessageIgnored: any).mockImplementation(() => {
116+
jest.spyOn(LogBoxData, 'isMessageIgnored').mockImplementation(() => {
113117
throw mockError;
114118
});
119+
const mockError = new Error('Simulated error');
115120

116121
LogBox.install();
117122

@@ -123,7 +128,8 @@ describe('LogBox', () => {
123128
});
124129

125130
it('only registers errors beginning with "Warning: "', () => {
126-
jest.mock('../Data/LogBoxData');
131+
jest.spyOn(LogBoxData, 'addLog');
132+
jest.spyOn(LogBoxData, 'checkWarningFilter');
127133

128134
LogBox.install();
129135

@@ -133,7 +139,8 @@ describe('LogBox', () => {
133139
});
134140

135141
it('registers react errors with the formatting from filter', () => {
136-
jest.mock('../Data/LogBoxData');
142+
jest.spyOn(LogBoxData, 'addLog');
143+
jest.spyOn(LogBoxData, 'checkWarningFilter');
137144

138145
mockFilterResult({
139146
finalFormat: 'Custom format',
@@ -157,7 +164,8 @@ describe('LogBox', () => {
157164
});
158165

159166
it('registers errors with component stack as errors by default', () => {
160-
jest.mock('../Data/LogBoxData');
167+
jest.spyOn(LogBoxData, 'addLog');
168+
jest.spyOn(LogBoxData, 'checkWarningFilter');
161169

162170
mockFilterResult({});
163171

@@ -174,7 +182,8 @@ describe('LogBox', () => {
174182
});
175183

176184
it('registers errors with component stack as errors by default if not found in warning filter', () => {
177-
jest.mock('../Data/LogBoxData');
185+
jest.spyOn(LogBoxData, 'addLog');
186+
jest.spyOn(LogBoxData, 'checkWarningFilter');
178187

179188
mockFilterResult({
180189
monitorEvent: 'warning_unhandled',
@@ -193,10 +202,12 @@ describe('LogBox', () => {
193202
});
194203

195204
it('registers errors with component stack with legacy suppression as warning', () => {
196-
jest.mock('../Data/LogBoxData');
205+
jest.spyOn(LogBoxData, 'addLog');
206+
jest.spyOn(LogBoxData, 'checkWarningFilter');
197207

198208
mockFilterResult({
199209
suppressDialog_LEGACY: true,
210+
monitorEvent: 'warning',
200211
});
201212

202213
LogBox.install();
@@ -211,10 +222,12 @@ describe('LogBox', () => {
211222
});
212223

213224
it('registers errors with component stack and a forced dialog as fatals', () => {
214-
jest.mock('../Data/LogBoxData');
225+
jest.spyOn(LogBoxData, 'addLog');
226+
jest.spyOn(LogBoxData, 'checkWarningFilter');
215227

216228
mockFilterResult({
217229
forceDialogImmediately: true,
230+
monitorEvent: 'warning',
218231
});
219232

220233
LogBox.install();
@@ -229,7 +242,8 @@ describe('LogBox', () => {
229242
});
230243

231244
it('registers warning module errors with the formatting from filter', () => {
232-
jest.mock('../Data/LogBoxData');
245+
jest.spyOn(LogBoxData, 'addLog');
246+
jest.spyOn(LogBoxData, 'checkWarningFilter');
233247

234248
mockFilterResult({
235249
finalFormat: 'Custom format',
@@ -248,7 +262,8 @@ describe('LogBox', () => {
248262
});
249263

250264
it('registers warning module errors as errors by default', () => {
251-
jest.mock('../Data/LogBoxData');
265+
jest.spyOn(LogBoxData, 'addLog');
266+
jest.spyOn(LogBoxData, 'checkWarningFilter');
252267

253268
mockFilterResult({});
254269

@@ -262,10 +277,12 @@ describe('LogBox', () => {
262277
});
263278

264279
it('registers warning module errors with only legacy suppression as warning', () => {
265-
jest.mock('../Data/LogBoxData');
280+
jest.spyOn(LogBoxData, 'addLog');
281+
jest.spyOn(LogBoxData, 'checkWarningFilter');
266282

267283
mockFilterResult({
268284
suppressDialog_LEGACY: true,
285+
monitorEvent: 'warning',
269286
});
270287

271288
LogBox.install();
@@ -277,10 +294,12 @@ describe('LogBox', () => {
277294
});
278295

279296
it('registers warning module errors with a forced dialog as fatals', () => {
280-
jest.mock('../Data/LogBoxData');
297+
jest.spyOn(LogBoxData, 'addLog');
298+
jest.spyOn(LogBoxData, 'checkWarningFilter');
281299

282300
mockFilterResult({
283301
forceDialogImmediately: true,
302+
monitorEvent: 'warning',
284303
});
285304

286305
LogBox.install();
@@ -292,10 +311,12 @@ describe('LogBox', () => {
292311
});
293312

294313
it('ignores warning module errors that are suppressed completely', () => {
295-
jest.mock('../Data/LogBoxData');
314+
jest.spyOn(LogBoxData, 'addLog');
315+
jest.spyOn(LogBoxData, 'checkWarningFilter');
296316

297317
mockFilterResult({
298318
suppressCompletely: true,
319+
monitorEvent: 'warning',
299320
});
300321

301322
LogBox.install();
@@ -305,10 +326,11 @@ describe('LogBox', () => {
305326
});
306327

307328
it('ignores warning module errors that are pattern ignored', () => {
308-
jest.mock('../Data/LogBoxData');
329+
jest.spyOn(LogBoxData, 'checkWarningFilter');
330+
jest.spyOn(LogBoxData, 'isMessageIgnored').mockReturnValue(true);
331+
jest.spyOn(LogBoxData, 'addLog');
309332

310333
mockFilterResult({});
311-
(LogBoxData.isMessageIgnored: any).mockReturnValue(true);
312334

313335
LogBox.install();
314336

@@ -317,10 +339,11 @@ describe('LogBox', () => {
317339
});
318340

319341
it('ignores warning module errors that are from LogBox itself', () => {
320-
jest.mock('../Data/LogBoxData');
342+
jest.spyOn(LogBoxData, 'checkWarningFilter');
343+
jest.spyOn(LogBoxData, 'isLogBoxErrorMessage').mockReturnValue(true);
344+
jest.spyOn(LogBoxData, 'addLog');
321345

322346
mockFilterResult({});
323-
(LogBoxData.isLogBoxErrorMessage: any).mockReturnValue(true);
324347

325348
LogBox.install();
326349

@@ -329,8 +352,9 @@ describe('LogBox', () => {
329352
});
330353

331354
it('ignores logs that are pattern ignored"', () => {
332-
jest.mock('../Data/LogBoxData');
333-
(LogBoxData.isMessageIgnored: any).mockReturnValue(true);
355+
jest.spyOn(LogBoxData, 'checkWarningFilter');
356+
jest.spyOn(LogBoxData, 'isMessageIgnored').mockReturnValue(true);
357+
jest.spyOn(LogBoxData, 'addLog');
334358

335359
LogBox.install();
336360

@@ -339,8 +363,8 @@ describe('LogBox', () => {
339363
});
340364

341365
it('does not add logs that are from LogBox itself"', () => {
342-
jest.mock('../Data/LogBoxData');
343-
(LogBoxData.isLogBoxErrorMessage: any).mockReturnValue(true);
366+
jest.spyOn(LogBoxData, 'isLogBoxErrorMessage').mockReturnValue(true);
367+
jest.spyOn(LogBoxData, 'addLog');
344368

345369
LogBox.install();
346370

@@ -349,7 +373,7 @@ describe('LogBox', () => {
349373
});
350374

351375
it('ignores logs starting with "(ADVICE)"', () => {
352-
jest.mock('../Data/LogBoxData');
376+
jest.spyOn(LogBoxData, 'addLog');
353377

354378
LogBox.install();
355379

@@ -358,7 +382,7 @@ describe('LogBox', () => {
358382
});
359383

360384
it('does not ignore logs formatted to start with "(ADVICE)"', () => {
361-
jest.mock('../Data/LogBoxData');
385+
jest.spyOn(LogBoxData, 'addLog');
362386

363387
LogBox.install();
364388

@@ -376,7 +400,7 @@ describe('LogBox', () => {
376400
});
377401

378402
it('ignores console methods after uninstalling', () => {
379-
jest.mock('../Data/LogBoxData');
403+
jest.spyOn(LogBoxData, 'addLog');
380404

381405
LogBox.install();
382406
LogBox.uninstall();
@@ -389,7 +413,7 @@ describe('LogBox', () => {
389413
});
390414

391415
it('does not add logs after uninstalling', () => {
392-
jest.mock('../Data/LogBoxData');
416+
jest.spyOn(LogBoxData, 'addLog');
393417

394418
LogBox.install();
395419
LogBox.uninstall();
@@ -406,7 +430,7 @@ describe('LogBox', () => {
406430
});
407431

408432
it('does not add exceptions after uninstalling', () => {
409-
jest.mock('../Data/LogBoxData');
433+
jest.spyOn(LogBoxData, 'addException');
410434

411435
LogBox.install();
412436
LogBox.uninstall();
@@ -482,4 +506,41 @@ describe('LogBox', () => {
482506
'Custom: after installing for the second time',
483507
);
484508
});
509+
it('registers errors without component stack as errors by default, when ExceptionManager is registered first', () => {
510+
jest.spyOn(LogBoxData, 'checkWarningFilter');
511+
jest.spyOn(LogBoxData, 'addException');
512+
513+
ExceptionsManager.installConsoleErrorReporter();
514+
LogBox.install();
515+
516+
console.error('HIT');
517+
518+
// Errors without a component stack skip the warning filter and
519+
// fall through to the ExceptionManager, which are then reported
520+
// back to LogBox as non-fatal exceptions, in a convuluted dance
521+
// in the most legacy cruft way.
522+
expect(LogBoxData.addException).toBeCalledWith(
523+
expect.objectContaining({originalMessage: 'HIT'}),
524+
);
525+
expect(LogBoxData.checkWarningFilter).not.toBeCalled();
526+
});
527+
528+
it('registers errors without component stack as errors by default, when ExceptionManager is registered second', () => {
529+
jest.spyOn(LogBoxData, 'checkWarningFilter');
530+
jest.spyOn(LogBoxData, 'addException');
531+
532+
LogBox.install();
533+
ExceptionsManager.installConsoleErrorReporter();
534+
535+
console.error('HIT');
536+
537+
// Errors without a component stack skip the warning filter and
538+
// fall through to the ExceptionManager, which are then reported
539+
// back to LogBox as non-fatal exceptions, in a convuluted dance
540+
// in the most legacy cruft way.
541+
expect(LogBoxData.addException).toBeCalledWith(
542+
expect.objectContaining({originalMessage: 'HIT'}),
543+
);
544+
expect(LogBoxData.checkWarningFilter).not.toBeCalled();
545+
});
485546
});

0 commit comments

Comments
 (0)