/* eslint-disable no-unused-vars */ import {shallow} from 'enzyme'; import React from 'react'; import {withContext} from 'shallow-with-context'; import {ServiceContainer} from 'src/containers/ServiceContainer'; import {DEFAULT_DASHBOARDS_CONTEXT} from 'src/context/DashboardsContext'; import {DummyService, ServiceState} from 'src/lib/services'; import {DashboardsFactory} from 'tests/__fixtures__/dashboards'; describe('src/containers/ServiceContainer', () => { const ServiceContainerWithContext = withContext( ServiceContainer, DEFAULT_DASHBOARDS_CONTEXT ); let context = null; beforeEach(() => { context = { ...DEFAULT_DASHBOARDS_CONTEXT, nukeService: jasmine.createSpy(), saveServiceCharacteristics: jasmine.createSpy(), saveServiceLayout: jasmine.createSpy(), addService: jasmine.createSpy(), setCurrentDashboardId: jasmine.createSpy(), addDashboard: jasmine.createSpy(), dashboards: DashboardsFactory(), }; }); describe('constructor', () => { it('initializes the state', () => { // Given const component = shallow( {(props) => It works!} , { context: context, } ); // Then expect(component.state('serviceState')).toBe(null); expect(component.state('showSettingsModal')).toBe(false); expect(component.state('nextCharacteristics')).toBe(null); }); }); describe('service', () => { it('looks up the bound service instance', () => { // Given const component = shallow( {(props) => It works!} , { context: context, } ); // When const service = component.instance().service(); // Then expect(service).toEqual(context.dashboards[0].services[0]); }); }); describe('setServiceState', () => { it('initializes new state object if the current state is `null`', () => { // Given const component = shallow( {(props) => It works!} , { context: context, } ); // When component.instance().setServiceState({data: {spam: true}}, {}); // Then expect(component.state('serviceState')).toBeInstanceOf(ServiceState); expect(component.state('serviceState').data()).toEqual({spam: true}); }); it('initializes new state object if reset is requested', () => { // Given const component = shallow( {(props) => It works!} , { context: context, } ); const oldState = new ServiceState({data: {spam: false}}); component.setState({serviceState: oldState}); // When component.instance().setServiceState( {data: {spam: true}}, {reset: true} ); // Then expect(component.state('serviceState')).not.toBe(oldState); }); it('updates the existing state object with new payload', () => { // Given const component = shallow( {(props) => It works!} , { context: context, } ); const oldState = new ServiceState({data: {spam: false}}); component.setState({serviceState: oldState}); // When component.instance().setServiceState({data: {spam: true}}, {}); // Then expect(component.state('serviceState')).not.toBe(oldState); expect(component.state('serviceState').data()).toEqual({spam: true}); }); }); it('allows setting next characteristics', () => { // Given const component = shallow( {(props) => It works!} , { context: context, } ); // When component.instance().setNextCharacteristics({spam: true}); // Then expect(component.state('nextCharacteristics')).toEqual({spam: true}); }); describe('setNextCharacteristicsFromService', () => { it('resets the next characteristics if the service is null', () => { // Given const component = shallow( {(props) => It works!} , { context: context, } ); component.setState({nextCharacteristics: {spam: false}}); // When component.instance().setNextCharacteristicsFromService(null); // Then expect(component.state('nextCharacteristics')).toBe(null); }); it('resets the next characteristics if the service has no widget', () => { // Given const component = shallow( {(props) => It works!} , { context: context, } ); component.setState({nextCharacteristics: {spam: false}}); const service = context.dashboards[0].services[0]; service.widgetComponent = null; // When component.instance().setNextCharacteristicsFromService(service); // Then expect(component.state('nextCharacteristics')).toBe(null); }); it('resets the next characteristics if the service is dummy', () => { // Given const component = shallow( {(props) => It works!} , { context: context, } ); component.setState({nextCharacteristics: {spam: false}}); const service = new DummyService(); // When component.instance().setNextCharacteristicsFromService(service); // Then expect(component.state('nextCharacteristics')).toBe(null); }); it('sets the next characteristics from the service characteristics', () => { // Given const component = shallow( {(props) => It works!} , { context: context, } ); const service = context.dashboards[0].services[0]; // When component.instance().setNextCharacteristicsFromService(service); // Then expect(component.state('nextCharacteristics')).toEqual( service.characteristics ); }); }); describe('showHideSettingsModal', () => { it('sets next characteristics from the service when modal is to be shown', () => { // Givem const component = shallow( {(props) => It works!} , { context: context, } ); spyOn(component.instance(), 'setNextCharacteristicsFromService'); // When component.instance().showHideSettingsModal(true); // Then expect(component.instance().setNextCharacteristicsFromService).toHaveBeenCalledWith( context.dashboards[0].services[0] ); }); it('resets next characteristics when modal is to be hidden', () => { // Given const component = shallow( {(props) => It works!} , { context: context, } ); spyOn(component.instance(), 'setNextCharacteristicsFromService'); // When component.instance().showHideSettingsModal(false); // Then expect(component.instance().setNextCharacteristicsFromService).toHaveBeenCalledWith( null ); }); it('updates the state with new visibility flag', () => { // Given const component = shallow( {(props) => It works!} , { context: context, } ); spyOn(component.instance(), 'setNextCharacteristicsFromService'); // When component.instance().showHideSettingsModal(true); // Then expect(component.state('showSettingsModal')).toBe(true); }); }); describe('onSettingsButtonClick', () => { it('requests the settings modal to be shown', () => { // Given const component = shallow( {(props) => It works!} , { context: context, } ); spyOn(component.instance(), 'showHideSettingsModal'); // When component.instance().onSettingsButtonClick(); // Then expect(component.instance().showHideSettingsModal).toHaveBeenCalledWith( true ); }); }); describe('onSettingsModalClose', () => { it('requests the settings modal to be hidden', () => { // Given const component = shallow( {(props) => It works!} , { context: context, } ); spyOn(component.instance(), 'showHideSettingsModal'); // When component.instance().onSettingsModalClose(); // Then expect(component.instance().showHideSettingsModal).toHaveBeenCalledWith( false ); }); }); describe('onSettingsModalSaveButtonClick', () => { it('requests the next characteristics to be saved', () => { // Given const component = shallow( {(props) => It works!} , { context: context, } ); component.setState({nextCharacteristics: {spam: true}}); // When component.instance().onSettingsModalSaveButtonClick(); // Then expect(context.saveServiceCharacteristics).toHaveBeenCalledWith( 'FakeService', 'fake_instance', {spam: true} ); }); it('closes the settings modal', () => { // Given const component = shallow( {(props) => It works!} , { context: context, } ); spyOn(component.instance(), 'onSettingsModalClose'); // When component.instance().onSettingsModalSaveButtonClick(); // Then expect(component.instance().onSettingsModalClose).toHaveBeenCalled(); }); }); describe('onSettingsModalNukeButtonClick', () => { it('requests the service to be nuked', () => { // Given const component = shallow( {(props) => It works!} , { context: context, } ); // When component.instance().onSettingsModalNukeButtonClick(); // Then expect(context.nukeService).toHaveBeenCalledWith( 'FakeService', 'fake_instance' ); }); it('closes the settings modal', () => { // Given const component = shallow( {(props) => It works!} , { context: context, } ); spyOn(component.instance(), 'onSettingsModalClose'); // When component.instance().onSettingsModalNukeButtonClick(); // Then expect(component.instance().onSettingsModalClose).toHaveBeenCalled(); }); }); describe('onAppearancePopupColorChange', () => { it('requests the updated characteristics to be saved', () => { // Given const component = shallow( {(props) => It works!} , { context: context, } ); // When component.instance().onAppearancePopupColorChange('red'); // Then expect(context.saveServiceCharacteristics).toHaveBeenCalledWith( 'FakeService', 'fake_instance', { spam: true, appearance: { color: 'red', }, } ); }); }); describe('onServiceRestartButtonClick', () => { it('requests the updated characteristics to be saved', () => { // Given const component = shallow( {(props) => It works!} , { context: context, } ); const service = context.dashboards[0].services[0]; spyOn(service, 'restart'); // When component.instance().onServiceRestartButtonClick(); // Then expect(service.restart).toHaveBeenCalled(); }); }); describe('unsubscribeIfNeeded', () => { it('calls the unsubscribe callback', () => { // Given const component = shallow( {(props) => It works!} , { context: context, } ); component.instance().serviceUnsubscribe = jasmine.createSpy(); // When component.instance().unsubscribeIfNeeded(); // Then expect(component.instance().serviceUnsubscribe).toHaveBeenCalled(); }); }); describe('componentDidMount', () => { it('is a noop if the service is null', () => { // Given const component = shallow( {(props) => It works!} , { context: context, } ); spyOn(component.instance(), 'setServiceState'); spyOn(component.instance(), 'unsubscribeIfNeeded'); spyOn(component.instance(), 'service').and.returnValue(null); // When component.instance().componentDidMount(); // Then expect(component.instance().setServiceState).not.toHaveBeenCalled(); expect(component.instance().unsubscribeIfNeeded).not.toHaveBeenCalled(); expect(component.instance().serviceUnsubscribe).toBe(null); }); it('is a noop if the service has no widget', () => { // Given const component = shallow( {(props) => It works!} , { context: context, } ); spyOn(component.instance(), 'setServiceState'); spyOn(component.instance(), 'unsubscribeIfNeeded'); context.dashboards[0].services[0].widgetComponent = null; // When component.instance().componentDidMount(); // Then expect(component.instance().setServiceState).not.toHaveBeenCalled(); expect(component.instance().unsubscribeIfNeeded).not.toHaveBeenCalled(); expect(component.instance().serviceUnsubscribe).toBe(null); }); it('is a noop if the service is dummy', () => { // Given const component = shallow( {(props) => It works!} , { context: context, } ); spyOn(component.instance(), 'setServiceState'); spyOn(component.instance(), 'unsubscribeIfNeeded'); spyOn(component.instance(), 'service').and.returnValue( new DummyService() ); // When component.instance().componentDidMount(); // Then expect(component.instance().setServiceState).not.toHaveBeenCalled(); expect(component.instance().unsubscribeIfNeeded).not.toHaveBeenCalled(); expect(component.instance().serviceUnsubscribe).toBe(null); }); it('sets itself up for the service', () => { // Given const component = shallow( {(props) => It works!} , { context: context, } ); spyOn(component.instance(), 'setServiceState'); spyOn(component.instance(), 'unsubscribeIfNeeded'); const service = context.dashboards[0].services[0]; spyOn(service, 'start'); const initialState = new ServiceState({data: {initial: true}}); spyOn(service, 'initialState').and.returnValue(initialState); const fakeUnsubscribe = jasmine.createSpy(); spyOn(service, 'subscribe').and.returnValue(fakeUnsubscribe); // When component.instance().componentDidMount(); // Then expect(component.instance().setServiceState).toHaveBeenCalledWith( initialState, true ); expect(service.start).toHaveBeenCalled(); expect(component.instance().unsubscribeIfNeeded).toHaveBeenCalled(); expect(service.subscribe).toHaveBeenCalledWith( component.instance().setServiceState ); expect(component.instance().serviceUnsubscribe).toEqual(fakeUnsubscribe); }); }); describe('componentWillUnmount', () => { it('unsubscribes from the service', () => { // Given const component = shallow( {(props) => It works!} , { context: context, } ); const mockUnsubscribeIfNeeded = jasmine.createSpy(); component.instance().unsubscribeIfNeeded = mockUnsubscribeIfNeeded; // When component.unmount(); // Then expect(mockUnsubscribeIfNeeded).toHaveBeenCalled(); }); }); describe('render', () => { let childrenFunc = null; beforeEach(() => { childrenFunc = jasmine.createSpy(); childrenFunc.returnValue = It works!; }); it('calls the children func with props', () => { // Given const component = shallow( {childrenFunc} , { context: context, } ); const serviceState = new ServiceState({data: {spam: true}}); component.setState({ serviceState: serviceState, showSettingsModal: true, nextCharacteristics: {eggs: true}, }); // Then expect(childrenFunc).toHaveBeenCalledWith({ hasSettingsView: true, service: context.dashboards[0].services[0], serviceState: serviceState, setServiceState: component.instance().setServiceState, settingsViewProps: { kind: 'FakeService', instance: 'fake_instance', nextCharacteristics: {eggs: true}, setNextCharacteristics: component.instance().setNextCharacteristics, }, showSettingsModal: true, onAppearancePopupColorChange: component.instance().onAppearancePopupColorChange, onServiceRestartButtonClick: component.instance().onServiceRestartButtonClick, onSettingsButtonClick: component.instance().onSettingsButtonClick, onSettingsModalClose: component.instance().onSettingsModalClose, onSettingsModalNukeButtonClick: component.instance().onSettingsModalNukeButtonClick, onSettingsModalSaveButtonClick: component.instance().onSettingsModalSaveButtonClick, }); }); it('disables settings view if the service is dummy', () => { // Given const service = context.dashboards[0].services[0]; spyOn(service, 'isDummy').and.returnValue(true); const component = shallow( {childrenFunc} , { context: context, } ); // Then expect(childrenFunc).toHaveBeenCalledWith(jasmine.objectContaining({ hasSettingsView: false, })); }); it('disables settings view if the service has no widget', () => { // Given const service = context.dashboards[0].services[0]; service.widgetComponent = null; const component = shallow( {childrenFunc} , { context: context, } ); // Then expect(childrenFunc).toHaveBeenCalledWith(jasmine.objectContaining({ hasSettingsView: false, })); }); it('disables settings view if the service widget has no settings view', () => { // Given const service = context.dashboards[0].services[0]; const oldSettingsView = service.widgetComponent.settingsView; service.widgetComponent.settingsView = undefined; const component = shallow( {childrenFunc} , { context: context, } ); // Then expect(childrenFunc).toHaveBeenCalledWith(jasmine.objectContaining({ hasSettingsView: false, })); // After service.widgetComponent.settingsView = oldSettingsView; }); }); });