diff --git a/src/isomorphic/ReactDebugTool.js b/src/isomorphic/ReactDebugTool.js index 4d2c2a3536..ea89a93641 100644 --- a/src/isomorphic/ReactDebugTool.js +++ b/src/isomorphic/ReactDebugTool.js @@ -70,6 +70,9 @@ var ReactDebugTool = { onUnmountComponent(internalInstance) { emitEvent('onUnmountComponent', internalInstance); }, + onTestEvent() { + emitEvent('onTestEvent'); + }, }; ReactDebugTool.addDevtool(ReactInvalidSetStateWarningDevTool); diff --git a/src/isomorphic/__tests__/ReactDebugTool-test.js b/src/isomorphic/__tests__/ReactDebugTool-test.js new file mode 100644 index 0000000000..bae09516f5 --- /dev/null +++ b/src/isomorphic/__tests__/ReactDebugTool-test.js @@ -0,0 +1,75 @@ +/** + * Copyright 2016-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @emails react-core + */ + +'use strict'; + +describe('ReactDebugTool', function() { + var ReactDebugTool; + + beforeEach(function() { + jest.resetModuleRegistry(); + ReactDebugTool = require('ReactDebugTool'); + }); + + it('should add and remove devtools', () => { + var handler1 = jasmine.createSpy('spy'); + var handler2 = jasmine.createSpy('spy'); + var devtool1 = {onTestEvent: handler1}; + var devtool2 = {onTestEvent: handler2}; + + ReactDebugTool.addDevtool(devtool1); + ReactDebugTool.onTestEvent(); + expect(handler1.calls.length).toBe(1); + expect(handler2.calls.length).toBe(0); + + ReactDebugTool.onTestEvent(); + expect(handler1.calls.length).toBe(2); + expect(handler2.calls.length).toBe(0); + + ReactDebugTool.addDevtool(devtool2); + ReactDebugTool.onTestEvent(); + expect(handler1.calls.length).toBe(3); + expect(handler2.calls.length).toBe(1); + + ReactDebugTool.onTestEvent(); + expect(handler1.calls.length).toBe(4); + expect(handler2.calls.length).toBe(2); + + ReactDebugTool.removeDevtool(devtool1); + ReactDebugTool.onTestEvent(); + expect(handler1.calls.length).toBe(4); + expect(handler2.calls.length).toBe(3); + + ReactDebugTool.removeDevtool(devtool2); + ReactDebugTool.onTestEvent(); + expect(handler1.calls.length).toBe(4); + expect(handler2.calls.length).toBe(3); + }); + + it('warns once when an error is thrown in devtool', () => { + spyOn(console, 'error'); + ReactDebugTool.addDevtool({ + onTestEvent() { + throw new Error('Hi.'); + }, + }); + + ReactDebugTool.onTestEvent(); + expect(console.error.calls.length).toBe(1); + expect(console.error.argsForCall[0][0]).toContain( + 'exception thrown by devtool while handling ' + + 'onTestEvent: Hi.' + ); + + ReactDebugTool.onTestEvent(); + expect(console.error.calls.length).toBe(1); + }); +}); diff --git a/src/renderers/dom/shared/ReactDOMDebugTool.js b/src/renderers/dom/shared/ReactDOMDebugTool.js index 9fcc3763fa..b90c122450 100644 --- a/src/renderers/dom/shared/ReactDOMDebugTool.js +++ b/src/renderers/dom/shared/ReactDOMDebugTool.js @@ -59,6 +59,9 @@ var ReactDOMDebugTool = { onDeleteValueForProperty(node, name) { emitEvent('onDeleteValueForProperty', node, name); }, + onTestEvent() { + emitEvent('onTestEvent'); + }, }; ReactDOMDebugTool.addDevtool(ReactDOMUnknownPropertyDevtool); diff --git a/src/renderers/dom/shared/__tests__/ReactDOMDebugTool-test.js b/src/renderers/dom/shared/__tests__/ReactDOMDebugTool-test.js new file mode 100644 index 0000000000..b4a94ec837 --- /dev/null +++ b/src/renderers/dom/shared/__tests__/ReactDOMDebugTool-test.js @@ -0,0 +1,75 @@ +/** + * Copyright 2016-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @emails react-core + */ + +'use strict'; + +describe('ReactDOMDebugTool', function() { + var ReactDOMDebugTool; + + beforeEach(function() { + jest.resetModuleRegistry(); + ReactDOMDebugTool = require('ReactDOMDebugTool'); + }); + + it('should add and remove devtools', () => { + var handler1 = jasmine.createSpy('spy'); + var handler2 = jasmine.createSpy('spy'); + var devtool1 = {onTestEvent: handler1}; + var devtool2 = {onTestEvent: handler2}; + + ReactDOMDebugTool.addDevtool(devtool1); + ReactDOMDebugTool.onTestEvent(); + expect(handler1.calls.length).toBe(1); + expect(handler2.calls.length).toBe(0); + + ReactDOMDebugTool.onTestEvent(); + expect(handler1.calls.length).toBe(2); + expect(handler2.calls.length).toBe(0); + + ReactDOMDebugTool.addDevtool(devtool2); + ReactDOMDebugTool.onTestEvent(); + expect(handler1.calls.length).toBe(3); + expect(handler2.calls.length).toBe(1); + + ReactDOMDebugTool.onTestEvent(); + expect(handler1.calls.length).toBe(4); + expect(handler2.calls.length).toBe(2); + + ReactDOMDebugTool.removeDevtool(devtool1); + ReactDOMDebugTool.onTestEvent(); + expect(handler1.calls.length).toBe(4); + expect(handler2.calls.length).toBe(3); + + ReactDOMDebugTool.removeDevtool(devtool2); + ReactDOMDebugTool.onTestEvent(); + expect(handler1.calls.length).toBe(4); + expect(handler2.calls.length).toBe(3); + }); + + it('warns once when an error is thrown in devtool', () => { + spyOn(console, 'error'); + ReactDOMDebugTool.addDevtool({ + onTestEvent() { + throw new Error('Hi.'); + }, + }); + + ReactDOMDebugTool.onTestEvent(); + expect(console.error.calls.length).toBe(1); + expect(console.error.argsForCall[0][0]).toContain( + 'exception thrown by devtool while handling ' + + 'onTestEvent: Hi.' + ); + + ReactDOMDebugTool.onTestEvent(); + expect(console.error.calls.length).toBe(1); + }); +});