diff --git a/lib/src/components/ComponentRegistry.test.tsx b/lib/src/components/ComponentRegistry.test.tsx index a9e64b4e607..b46d50aa357 100644 --- a/lib/src/components/ComponentRegistry.test.tsx +++ b/lib/src/components/ComponentRegistry.test.tsx @@ -1,13 +1,17 @@ import { ComponentRegistry } from './ComponentRegistry'; import { Store } from './Store'; -import { mock, instance, verify, anyFunction } from 'ts-mockito'; +import { mock, instance, verify, anyFunction, when, anyString, anything } from 'ts-mockito'; import { ComponentWrapper } from './ComponentWrapper'; import { ComponentEventsObserver } from '../events/ComponentEventsObserver'; import { AppRegistryService } from '../adapters/AppRegistryService'; +import * as React from 'react'; import { ComponentProvider } from 'react-native'; const DummyComponent = () => null; +class MyComponent extends React.Component { +} + describe('ComponentRegistry', () => { let mockedStore: Store; let mockedComponentEventsObserver: ComponentEventsObserver; @@ -48,4 +52,19 @@ describe('ComponentRegistry', () => { uut.registerComponent('example.MyComponent.name', generator); expect(generator).toHaveBeenCalledTimes(0); }); + + it('should create ComponentWrapper only once', () => { + jest.spyOn(uut, 'wrapComponent'); + let _store: Record = {}; + when(mockedStore.hasRegisteredWrappedComponent(anyString())).thenCall(name => name in _store); + when(mockedStore.getComponentClassForName(anyString())).thenCall(name => _store[name]); + when(mockedStore.setComponentClassForName(anyString(), anything())).thenCall((name, component) => _store[name] = component); + when(mockedComponentWrapper.wrap).thenReturn(() => MyComponent); + + const generator: ComponentProvider = () => DummyComponent; + uut.registerComponent('example.MyComponent.name', generator); + uut.registerComponent('example.MyComponent.name', generator); + + expect(uut.wrapComponent).toHaveBeenCalledTimes(1); + }); }); diff --git a/lib/src/components/ComponentRegistry.ts b/lib/src/components/ComponentRegistry.ts index a0c188550e6..2d862ec4d10 100644 --- a/lib/src/components/ComponentRegistry.ts +++ b/lib/src/components/ComponentRegistry.ts @@ -11,7 +11,6 @@ export class ComponentRegistry { private componentWrapper: ComponentWrapper, private appRegistryService: AppRegistryService ) {} - registerComponent( componentName: string | number, componentProvider: ComponentProvider, @@ -19,25 +18,30 @@ export class ComponentRegistry { ReduxProvider?: any, reduxStore?: any ): ComponentProvider { - const NavigationComponent = () => { - if (this.store.hasRegisteredWrappedComponent(componentName)) { - return this.store.getWrappedComponent(componentName); - } else { - const wrappedComponent = this.componentWrapper.wrap( - componentName.toString(), - componentProvider, - this.store, - this.componentEventsObserver, - concreteComponentProvider, - ReduxProvider, - reduxStore - ); - this.store.setWrappedComponent(componentName, wrappedComponent); - return wrappedComponent; - } - }; - this.store.setComponentClassForName(componentName.toString(), NavigationComponent); + const NavigationComponent = this.store.hasRegisteredWrappedComponent(componentName) ? + this.store.getComponentClassForName(componentName)! : + this.wrapComponent(componentName, componentProvider, concreteComponentProvider, ReduxProvider, reduxStore); this.appRegistryService.registerComponent(componentName.toString(), NavigationComponent); return NavigationComponent; } + + wrapComponent( + componentName: string | number, + componentProvider: ComponentProvider, + concreteComponentProvider?: ComponentProvider, + ReduxProvider?: any, + reduxStore?: any + ): ComponentProvider { + const NavigationComponent = () => this.componentWrapper.wrap( + componentName.toString(), + componentProvider, + this.store, + this.componentEventsObserver, + concreteComponentProvider, + ReduxProvider, + reduxStore + ); + this.store.setComponentClassForName(componentName.toString(), NavigationComponent); + return NavigationComponent; + } } diff --git a/lib/src/components/ComponentWrapper.test.tsx b/lib/src/components/ComponentWrapper.test.tsx index fdc333d601a..2d6cbcebeaa 100644 --- a/lib/src/components/ComponentWrapper.test.tsx +++ b/lib/src/components/ComponentWrapper.test.tsx @@ -172,7 +172,7 @@ describe('ComponentWrapper', () => { const componentGenerator = jest.fn(() => MyComponent); uut.wrap(componentName, componentGenerator, store, componentEventsObserver); - expect(componentGenerator.mock.calls.length).toBe(1); + expect(componentGenerator).toHaveBeenCalledTimes(1); }); describe(`register with redux store`, () => { diff --git a/lib/src/components/Store.ts b/lib/src/components/Store.ts index 884bfc8a2cc..b39cdde8775 100644 --- a/lib/src/components/Store.ts +++ b/lib/src/components/Store.ts @@ -1,4 +1,3 @@ -import * as React from 'react'; import { ComponentProvider } from 'react-native'; import { IWrappedComponent } from './ComponentWrapper'; @@ -6,7 +5,6 @@ export class Store { private componentsByName: Record = {}; private propsById: Record = {}; private componentsInstancesById: Record = {}; - private wrappedComponents: Record> = {}; updateProps(componentId: string, props: any) { this.propsById[componentId] = props; @@ -33,6 +31,10 @@ export class Store { return this.componentsByName[componentName.toString()]; } + hasRegisteredWrappedComponent(componentName: string | number): boolean { + return componentName in this.componentsByName; + } + setComponentInstance(id: string, component: IWrappedComponent): void { this.componentsInstancesById[id] = component; } @@ -40,16 +42,4 @@ export class Store { getComponentInstance(id: string): IWrappedComponent { return this.componentsInstancesById[id]; } - - setWrappedComponent(componentName: string | number, wrappedComponent: React.ComponentClass): void { - this.wrappedComponents[componentName] = wrappedComponent; - } - - hasRegisteredWrappedComponent(componentName: string | number): boolean { - return componentName in this.wrappedComponents; - } - - getWrappedComponent(componentName: string | number): React.ComponentClass { - return this.wrappedComponents[componentName]; - } }