import {shallow} from 'enzyme'; import React from 'react'; import { DEFAULT_DASHBOARDS_CONTEXT, DashboardsContext, } from 'src/context/DashboardsContext'; import * as HashLib from 'src/lib/hashlib'; import * as ServicesLib from 'src/lib/services'; import * as WebSocketLib from 'src/lib/websocket'; import {DashboardsProvider} from 'src/providers/DashboardsProvider'; import { DashboardsFactory, DashboardsJSONFactory, } from 'tests/__fixtures__/dashboards'; import {FakeService, FakeWidget} from 'tests/__fixtures__/services'; describe('src/providers/DashboardsProvider', () => { describe('DashboardsProvider', () => { const Loader = (props) => LOADER; // eslint-disable-line no-unused-vars const Children = (props) => LOADER; // eslint-disable-line no-unused-vars let loadDashboards = null; let saveDashboards = null; let settings = null; beforeEach(() => { loadDashboards = jasmine.createSpy(); saveDashboards = jasmine.createSpy(); settings = { DEBUG: false, SERVICES: { [FakeService.kind]: FakeService, }, WIDGETS: { [FakeService.widget]: FakeWidget, }, WEBSOCKET: { url: '/backend/websocket', }, }; }); describe('constructor', () => { it('initializes the instance', () => { // Given const component = shallow( } loadDashboards={loadDashboards} saveDashboards={saveDashboards} settings={settings} > ); // Then expect(component.instance().webSocket).toBe(null); expect(component.instance().webSocketUnsubscriber).toBe(null); expect(component.instance().dashboardsHash).toBe(null); }); it('initializes the state', () => { // Given const component = shallow( } loadDashboards={loadDashboards} saveDashboards={saveDashboards} settings={settings} > ); // Then expect(component.state('currentDashboardId')).toEqual( DEFAULT_DASHBOARDS_CONTEXT.currentDashboardId ); expect(component.state('dashboards')).toEqual( DEFAULT_DASHBOARDS_CONTEXT.dashboards ); expect(component.state('isLoading')).toEqual( DEFAULT_DASHBOARDS_CONTEXT.isLoading ); expect(component.state('lastSaveTimestamp')).toEqual( DEFAULT_DASHBOARDS_CONTEXT.lastSaveTimestamp ); expect(component.state('lastSaveError')).toEqual( DEFAULT_DASHBOARDS_CONTEXT.lastSaveError ); expect(component.state('isSaving')).toEqual( DEFAULT_DASHBOARDS_CONTEXT.isSaving ); expect(component.state('isWebSocketConnected')).toEqual( DEFAULT_DASHBOARDS_CONTEXT.isWebSocketConnected ); expect(component.state('loadError')).toBe( DEFAULT_DASHBOARDS_CONTEXT.loadError ); }); }); describe('handleSaveError', () => { beforeEach(() => { spyOn(console, 'error'); }); it('handles a save error', () => { // Given const component = shallow( } loadDashboards={loadDashboards} saveDashboards={saveDashboards} settings={settings} > ); const error = new Error('FIAL'); // When const result = component.instance().handleSaveError(error); // Then expect(result).toEqual('FIAL'); expect(console.error).toHaveBeenCalledWith(jasmine.any(String), error); }); }); describe('onWebSocketStart', () => { it('handles websocket start event', () => { // Given const component = shallow( } loadDashboards={loadDashboards} saveDashboards={saveDashboards} settings={settings} > ); // When component.instance().onWebSocketStart(); // Then expect(component.state('isWebSocketConnected')).toBe(true); }); }); describe('onWebSocketStop', () => { it('handles websocket stop event', () => { // Given const component = shallow( } loadDashboards={loadDashboards} saveDashboards={saveDashboards} settings={settings} > ); component.setState({isWebSocketConnected: true}); // When component.instance().onWebSocketStop(); // Then expect(component.state('isWebSocketConnected')).toBe(false); }); }); describe('onWebSocketMessage', () => { let fakeDate = null; beforeEach(() => { fakeDate = new Date(1987, 9, 3, 8, 0, 0); jasmine.clock().install(); jasmine.clock().mockDate(fakeDate); }); afterEach(() => { jasmine.clock().uninstall(); }); it('handles a service notification for a single service', async () => { // Given const component = shallow( } loadDashboards={loadDashboards} saveDashboards={saveDashboards} settings={settings} > ); const dashboards = DashboardsFactory(); dashboards[0].services.forEach((service) => { spyOn(service, 'onMessage'); }); component.instance().setState({dashboards: dashboards}); const data = {spam: true}; // When await component.instance().onWebSocketMessage({ type: WebSocketLib.kWebSocketMsgTypeServiceNotification, kind: FakeService.kind, instance: 'fake_instance', data: data, }); // Then expect(dashboards[0].services[0].onMessage).toHaveBeenCalledWith(data); expect(dashboards[0].services[1].onMessage).not.toHaveBeenCalled(); }); it('handles a service notification for multiple services', async () => { // Given const component = shallow( } loadDashboards={loadDashboards} saveDashboards={saveDashboards} settings={settings} > ); const dashboards = DashboardsFactory(); dashboards[0].services.forEach((service) => { spyOn(service, 'onMessage'); }); component.instance().setState({dashboards: dashboards}); const data = {spam: true}; // When await component.instance().onWebSocketMessage({ type: WebSocketLib.kWebSocketMsgTypeServiceNotification, kind: FakeService.kind, data: data, }); // Then expect(dashboards[0].services[0].onMessage).toHaveBeenCalledWith(data); expect(dashboards[0].services[1].onMessage).toHaveBeenCalledWith(data); }); it('handles a state notification', async () => { // Given const component = shallow( } loadDashboards={loadDashboards} saveDashboards={saveDashboards} settings={settings} > ); const dashboards = DashboardsFactory(); const data = DashboardsJSONFactory(dashboards); spyOn(component.instance(), 'handleLoadedState').and.resolveTo(dashboards); // When await component.instance().onWebSocketMessage({ type: WebSocketLib.kWebSocketMsgTypeStateNotification, data: data, }); // Then expect(component.state('dashboards')).toEqual(dashboards); expect(component.state('lastSaveTimestamp')).toEqual(fakeDate); expect(component.instance().handleLoadedState).toHaveBeenCalledWith(data); }); it('does not handle a state notification if the dashboards hash did not change', async () => { // Given const component = shallow( } loadDashboards={loadDashboards} saveDashboards={saveDashboards} settings={settings} > ); const dashboards = DashboardsFactory(); const data = DashboardsJSONFactory(dashboards); component.instance().dashboardsHash = await HashLib.sha256( JSON.stringify(data) ); spyOn(component.instance(), 'handleLoadedState').and.resolveTo(dashboards); // When await component.instance().onWebSocketMessage({ type: WebSocketLib.kWebSocketMsgTypeStateNotification, data: data, }); // Then expect(component.state('dashboards')).not.toEqual(dashboards); expect(component.state('lastSaveTimestamp')).not.toEqual(fakeDate); expect(component.instance().handleLoadedState).not.toHaveBeenCalled(); }); }); describe('currentDashboard', () => { it('returns the current dashboard object', () => { // Given const component = shallow( } loadDashboards={loadDashboards} saveDashboards={saveDashboards} settings={settings} > ); const dashboards = DashboardsFactory(); component.setState({ dashboards: dashboards, currentDashboardId: 'testing', }); // When const result = component.instance().currentDashboard(); // Then expect(result).toEqual(dashboards[0]); }); }); describe('mutateCurrentDashboardServices', () => { it('returns the mutated current dashboard object', () => { // Given const component = shallow( } loadDashboards={loadDashboards} saveDashboards={saveDashboards} settings={settings} > ); const dashboards = DashboardsFactory(); dashboards.push({ id: 'testing2', name: 'Testing2', services: [ new FakeService({ instance: 'other_dashboard_instance', widgetComponent: FakeWidget, characteristics: { spam: true, }, layout: { x: 0, y: 0, w: 1, h: 1, }, }), ], }); component.setState({ dashboards: dashboards, currentDashboardId: 'testing', }); // When const result = component.instance().mutateCurrentDashboardServices( (services) => { return services.map((service) => { service.setCharacteristics({id: service.instance}); return service; }); } ); // Then expect(result.length).toEqual(2); expect(result[0].services[0].characteristics).toEqual({ id: result[0].services[0].instance, }); expect(result[0].services[1].characteristics).toEqual({ id: result[0].services[1].instance, }); expect(result[1].services[0].characteristics).toEqual({ spam: true, }); }); }); describe('serviceFromSpec', () => { let spec = null; beforeEach(() => { spec = { kind: 'FakeService', instance: 'fake_instance', characteristics: { spam: true, }, layout: { x: 0, y: 0, w: 1, h: 1, }, }; }); it('creates a dummy service is the service is uknown', () => { // Given settings.SERVICES = {}; const component = shallow( } loadDashboards={loadDashboards} saveDashboards={saveDashboards} settings={settings} > ); // When const result = component.instance().serviceFromSpec(spec); // Then expect(result).toBeInstanceOf(ServicesLib.DummyService); }); it('instantiates a service from the spec', () => { // Given const component = shallow( } loadDashboards={loadDashboards} saveDashboards={saveDashboards} settings={settings} > ); // When const result = component.instance().serviceFromSpec(spec); // Then expect(result).toBeInstanceOf(FakeService); expect(result.instance).toEqual(spec.instance); expect(result.characteristics).toEqual(spec.characteristics); expect(result.layout).toEqual(spec.layout); expect(result.widgetComponent).toEqual(FakeWidget); }); it('nullifies the widgetComponent if the widget is not known', () => { // Given settings.WIDGETS = {}; const component = shallow( } loadDashboards={loadDashboards} saveDashboards={saveDashboards} settings={settings} > ); // When const result = component.instance().serviceFromSpec(spec); // Then expect(result).toBeInstanceOf(FakeService); expect(result.widgetComponent).toBe(null); }); }); describe('saveDashboards', () => { let fakeDate = null; beforeEach(() => { saveDashboards = jasmine.createSpy().and.resolveTo('ok'); fakeDate = new Date(1987, 9, 3, 8, 0, 0); jasmine.clock().install(); jasmine.clock().mockDate(fakeDate); spyOn(console, 'error'); }); afterEach(() => { jasmine.clock().uninstall(); }); it('does not save the dashboards when dashboards hash did not change', async () => { // Given const component = shallow( } loadDashboards={loadDashboards} saveDashboards={saveDashboards} settings={settings} > ); component.setState({lastSaveError: 'FIAL'}); const dashboards = DashboardsFactory(); const data = DashboardsJSONFactory(dashboards); component.instance().dashboardsHash = await HashLib.sha256( JSON.stringify({dashboards: data}) ); // When await component.instance().saveDashboards(dashboards); // Then expect(saveDashboards).not.toHaveBeenCalled(); expect(component.state('lastSaveTimestamp')).not.toEqual(fakeDate); expect(component.state('lastSaveError')).toEqual('FIAL'); }); it('saves the dashboards', async () => { // Given const component = shallow( } loadDashboards={loadDashboards} saveDashboards={saveDashboards} settings={settings} > ); component.setState({lastSaveError: 'FIAL'}); const dashboards = DashboardsFactory(); // When await component.instance().saveDashboards(dashboards); // Then expect(saveDashboards).toHaveBeenCalled(); const savedDashboards = saveDashboards.calls.first().args[0]; expect(savedDashboards.dashboards.length).toEqual(1); expect(savedDashboards.dashboards[0].id).toEqual(dashboards[0].id); expect(savedDashboards.dashboards[0].name).toEqual(dashboards[0].name); expect(savedDashboards.dashboards[0].services.length).toEqual(2); expect(savedDashboards.dashboards[0].services[0]).toEqual( dashboards[0].services[0].toJSON() ); expect(savedDashboards.dashboards[0].services[1]).toEqual( dashboards[0].services[1].toJSON() ); expect(component.state('lastSaveTimestamp')).toEqual(fakeDate); expect(component.state('lastSaveError')).toBe(null); }); it('gracefully handles save error', async () => { // Given saveDashboards = jasmine.createSpy().and.rejectWith(new Error('FIAL')); const component = shallow( } loadDashboards={loadDashboards} saveDashboards={saveDashboards} settings={settings} > ); const dashboards = DashboardsFactory(); component.instance().dashboardsHash = 'spam'; component.setState({lastSaveTimestamp: fakeDate}); // When await component.instance().saveDashboards(dashboards); // Then expect(component.instance().dashboardsHash).toBe(null); expect(component.state('lastSaveTimestamp')).toBe(null); expect(component.state('lastSaveError')).toEqual('FIAL'); }); }); describe('nukeService', () => { it('stops and removes the specified service', () => { // Given const component = shallow( } loadDashboards={loadDashboards} saveDashboards={saveDashboards} settings={settings} > ); spyOn(component.instance(), 'saveDashboards'); const dashboards = DashboardsFactory(); const serviceToRemove = dashboards[0].services[0]; spyOn(serviceToRemove, 'stop'); component.setState({ dashboards: dashboards, currentDashboardId: dashboards[0].id, }); // When component.instance().nukeService('FakeService', 'fake_instance'); // Then const newDashboards = component.state('dashboards'); expect(newDashboards[0].services.length).toEqual(1); expect(newDashboards[0].services).not.toContain(serviceToRemove); expect(serviceToRemove.stop).toHaveBeenCalled(); expect(component.instance().saveDashboards).toHaveBeenCalledWith( newDashboards ); }); }); describe('saveServiceCharacteristics', () => { it('saves new characteristics for the specified service', () => { // Given const component = shallow( } loadDashboards={loadDashboards} saveDashboards={saveDashboards} settings={settings} > ); spyOn(component.instance(), 'saveDashboards'); const dashboards = DashboardsFactory(); const serviceToModify = dashboards[0].services[0]; spyOn(serviceToModify, 'setCharacteristics'); component.setState({ dashboards: dashboards, currentDashboardId: dashboards[0].id, }); const newCharacteristics = {spam: false}; // When component.instance().saveServiceCharacteristics( 'FakeService', 'fake_instance', newCharacteristics ); // Then const newDashboards = component.state('dashboards'); expect(newDashboards[0].services.length).toEqual(2); expect(serviceToModify.setCharacteristics).toHaveBeenCalledWith( newCharacteristics ); expect(component.instance().saveDashboards).toHaveBeenCalledWith( newDashboards ); }); }); describe('saveServiceLayout', () => { it('saves new characteristics for the specified service', () => { // Given const component = shallow( } loadDashboards={loadDashboards} saveDashboards={saveDashboards} settings={settings} > ); spyOn(component.instance(), 'saveDashboards'); const dashboards = DashboardsFactory(); const serviceToModify = dashboards[0].services[0]; spyOn(serviceToModify, 'setLayout'); component.setState({ dashboards: dashboards, currentDashboardId: dashboards[0].id, }); const newLayout = {x: 1, y: 1, w: 1, h: 1}; // When component.instance().saveServiceLayout('fake_instance', newLayout); // Then const newDashboards = component.state('dashboards'); expect(newDashboards[0].services.length).toEqual(2); expect(serviceToModify.setLayout).toHaveBeenCalledWith(newLayout); expect(component.instance().saveDashboards).toHaveBeenCalledWith( newDashboards ); }); }); describe('addService', () => { it('is a noop if no dashboard is selected', () => { // Given const component = shallow( } loadDashboards={loadDashboards} saveDashboards={saveDashboards} settings={settings} > ); spyOn(component.instance(), 'saveDashboards'); const dashboards = DashboardsFactory(); component.setState({dashboards: dashboards}); // When component.instance().addService('FakeService', {new: true}); // Then expect(component.state('dashboards')).toBe(dashboards); expect(component.instance().saveDashboards).not.toHaveBeenCalled(); }); it('adds a new service', () => { // Given const component = shallow( } loadDashboards={loadDashboards} saveDashboards={saveDashboards} settings={settings} > ); spyOn(component.instance(), 'saveDashboards'); const dashboards = DashboardsFactory(); component.setState({ dashboards: dashboards, currentDashboardId: dashboards[0].id, }); const newServiceCharacteristics = {new: true}; // When component.instance().addService( 'FakeService', newServiceCharacteristics ); // Then const newDashboards = component.state('dashboards'); expect(newDashboards[0].services.length).toEqual(3); expect(component.instance().saveDashboards).toHaveBeenCalledWith( newDashboards ); const newService = newDashboards[0].services[2]; expect(newService).toBeInstanceOf(FakeService); expect(newService.instance).toBeUUIDv4(); expect(newService.characteristics).toEqual(newServiceCharacteristics); expect(newService.layout).toEqual({x: 0, y: 2, w: 1, h: 1}); }); }); describe('handleLoadedState', () => { it('handles loaded state', async () => { // Given const component = shallow( } loadDashboards={loadDashboards} saveDashboards={saveDashboards} settings={settings} > ); spyOn(component.instance(), 'serviceFromSpec').and.returnValue( new ServicesLib.DummyService() ); const loadedState = {dashboards: DashboardsJSONFactory()}; const dashboardsHash = await HashLib.sha256( JSON.stringify(loadedState) ); // When const result = await component.instance().handleLoadedState( loadedState ); // Then expect(component.instance().dashboardsHash).toEqual(dashboardsHash); expect(result.length).toEqual(1); expect(result[0].id).toEqual(loadedState.dashboards[0].id); expect(result[0].name).toEqual(loadedState.dashboards[0].name); expect(result[0].services.length).toEqual( loadedState.dashboards[0].services.length ); expect(component.instance().serviceFromSpec.calls.count()).toEqual(2); expect(component.instance().serviceFromSpec).toHaveBeenCalledWith( loadedState.dashboards[0].services[0] ); expect(component.instance().serviceFromSpec).toHaveBeenCalledWith( loadedState.dashboards[0].services[1] ); }); }); describe('loadDashboards', () => { let fakeDate = null; let loadedDashboards = null; let loadedState = null; beforeEach(() => { loadedDashboards = DashboardsFactory(); loadedState = {dashboards: DashboardsJSONFactory(loadedDashboards)}; loadDashboards = jasmine.createSpy().and.resolveTo(loadedState); fakeDate = new Date(1987, 9, 3, 8, 0, 0); jasmine.clock().install(); jasmine.clock().mockDate(fakeDate); spyOn(console, 'error'); }); afterEach(() => { jasmine.clock().uninstall(); }); it('loads the dashboards', async () => { // Given const component = shallow( } loadDashboards={loadDashboards} saveDashboards={saveDashboards} settings={settings} > ); spyOn(component.instance(), 'handleLoadedState').and.resolveTo( loadedDashboards ); // When await component.instance().loadDashboards(); // Then expect(component.state('dashboards')).toEqual(loadedDashboards); expect(component.state('currentDashboardId')).toEqual( loadedDashboards[0].id ); expect(component.state('lastSaveTimestamp')).toEqual(fakeDate); expect(component.instance().handleLoadedState).toHaveBeenCalledWith( loadedState ); }); it('gracefully handles load error', async () => { // Given loadDashboards = jasmine.createSpy().and.rejectWith(new Error('FIAL')); const component = shallow( } loadDashboards={loadDashboards} saveDashboards={saveDashboards} settings={settings} > ); spyOn(component.instance(), 'handleLoadedState').and.resolveTo([]); spyOn(component.instance(), 'throwLoadError'); // When await component.instance().loadDashboards(); // Then expect(component.state('dashboards')).toEqual([]); expect(component.state('currentDashboardId')).toBe(null); expect(component.state('lastSaveTimestamp')).toBe(null); expect(component.state('loadError')).toEqual('FIAL'); expect(component.instance().handleLoadedState).not.toHaveBeenCalled(); expect(component.instance().throwLoadError).toHaveBeenCalledWith( component.state('loadError'), ); }); }); describe('setCurrentDashboardId', () => { it('sets the current dashboard id', () => { // Given const component = shallow( } loadDashboards={loadDashboards} saveDashboards={saveDashboards} settings={settings} > ); // When component.instance().setCurrentDashboardId('spam'); // Then expect(component.state('currentDashboardId')).toEqual('spam'); }); }); describe('addDashboard', () => { it('adds a dashboard', () => { // Given const component = shallow( } loadDashboards={loadDashboards} saveDashboards={saveDashboards} settings={settings} > ); spyOn(component.instance(), 'saveDashboards'); // When component.instance().addDashboard('New'); // Then const newDashboards = component.state('dashboards'); expect(newDashboards.length).toEqual(1); expect(newDashboards[0].name).toEqual('New'); expect(component.instance().saveDashboards).toHaveBeenCalledWith( newDashboards ); }); it('auto selects the first added dashboard', () => { // Given const component = shallow( } loadDashboards={loadDashboards} saveDashboards={saveDashboards} settings={settings} > ); component.setState({dashboards: []}); // When component.instance().addDashboard('New'); // Then expect(component.state('currentDashboardId')).toEqual( component.state('dashboards')[0].id ); }); it('does not auto select the other added dashboard', () => { // Given const component = shallow( } loadDashboards={loadDashboards} saveDashboards={saveDashboards} settings={settings} > ); const dashboards = DashboardsFactory(); component.setState({ dashboards: dashboards, currentDashboardId: 'testing', }); // When component.instance().addDashboard('New'); // Then expect(component.state('currentDashboardId')).toEqual('testing'); }); }); describe('throwLoadError', () => { it('throws the error as is if it is an Error', () => { // Given const error = new Error('FIAL'); const component = shallow( } loadDashboards={loadDashboards} saveDashboards={saveDashboards} settings={settings} > ); // When expect(() => component.instance().throwLoadError(error)).toThrow(error); }); it('wraps a string in an error and throws it', () => { // Given const component = shallow( } loadDashboards={loadDashboards} saveDashboards={saveDashboards} settings={settings} > ); // When expect(() => component.instance().throwLoadError('FIAL')).toThrowError( Error, 'FIAL', ); }); }); describe('componentDidMount', () => { let fakeHomeHubWebSocket = null; let mockWebSocketUnsubscriber = null; beforeEach(() => { fakeHomeHubWebSocket = jasmine.createSpyObj('HomeHubWebSocket', [ 'start', 'stop', 'addEventListener', 'removeEventListener', 'subscribe', ]); mockWebSocketUnsubscriber = jasmine.createSpy(); fakeHomeHubWebSocket.subscribe.and.returnValue( mockWebSocketUnsubscriber ); spyOn(WebSocketLib, 'HomeHubWebSocket').and.returnValue( fakeHomeHubWebSocket ); }); it('sets the isLoading state to true', () => { // Given const component = shallow( } loadDashboards={loadDashboards} saveDashboards={saveDashboards} settings={settings} > ); spyOn(component.instance(), 'loadDashboards'); // When component.instance().componentDidMount(); // Then expect(component.state('isLoading')).toBe(true); }); it('configures and starts the websocket connection', () => { // Given const component = shallow( } loadDashboards={loadDashboards} saveDashboards={saveDashboards} settings={settings} > ); spyOn(component.instance(), 'loadDashboards'); // When component.instance().componentDidMount(); // Then expect(component.instance().webSocket).toEqual(fakeHomeHubWebSocket); expect(WebSocketLib.HomeHubWebSocket).toHaveBeenCalledWith( settings.DEBUG, settings.WEBSOCKET ); expect(fakeHomeHubWebSocket.addEventListener).toHaveBeenCalledWith( 'start', component.instance().onWebSocketStart ); expect(fakeHomeHubWebSocket.addEventListener).toHaveBeenCalledWith( 'stop', component.instance().onWebSocketStop ); expect(component.instance().webSocketUnsubscriber).toEqual( mockWebSocketUnsubscriber ); expect(fakeHomeHubWebSocket.subscribe).toHaveBeenCalledWith( component.instance().onWebSocketMessage ); expect(fakeHomeHubWebSocket.start).toHaveBeenCalled(); }); it('configures and starts the websocket connection using custom connector', () => { // Given settings.CONNECTOR = jasmine.createSpy().and.returnValue( fakeHomeHubWebSocket ); const component = shallow( } loadDashboards={loadDashboards} saveDashboards={saveDashboards} settings={settings} > ); spyOn(component.instance(), 'loadDashboards'); // When component.instance().componentDidMount(); // Then expect(component.instance().webSocket).toEqual(fakeHomeHubWebSocket); expect(WebSocketLib.HomeHubWebSocket).not.toHaveBeenCalled(); expect(settings.CONNECTOR).toHaveBeenCalledWith( settings.DEBUG, settings.WEBSOCKET ); expect(fakeHomeHubWebSocket.addEventListener).toHaveBeenCalledWith( 'start', component.instance().onWebSocketStart ); expect(fakeHomeHubWebSocket.addEventListener).toHaveBeenCalledWith( 'stop', component.instance().onWebSocketStop ); expect(component.instance().webSocketUnsubscriber).toEqual( mockWebSocketUnsubscriber ); expect(fakeHomeHubWebSocket.subscribe).toHaveBeenCalledWith( component.instance().onWebSocketMessage ); expect(fakeHomeHubWebSocket.start).toHaveBeenCalled(); }); it('does not start the websocket in offline mode', () => { // Given settings.OFFLINE_MODE = true; const component = shallow( } loadDashboards={loadDashboards} saveDashboards={saveDashboards} settings={settings} > ); spyOn(component.instance(), 'loadDashboards'); // When component.instance().componentDidMount(); // Then expect(component.instance().webSocket).toEqual(fakeHomeHubWebSocket); expect(fakeHomeHubWebSocket.start).not.toHaveBeenCalled(); }); it('loads the dashboards', () => { // Given const component = shallow( } loadDashboards={loadDashboards} saveDashboards={saveDashboards} settings={settings} > ); spyOn(component.instance(), 'loadDashboards'); // When component.instance().componentDidMount(); // Then expect(component.instance().loadDashboards).toHaveBeenCalled(); }); }); describe('componentWillUnmount', () => { let fakeHomeHubWebSocket = null; let mockWebSocketUnsubscriber = null; beforeEach(() => { fakeHomeHubWebSocket = jasmine.createSpyObj('HomeHubWebSocket', [ 'start', 'stop', 'addEventListener', 'removeEventListener', 'subscribe', ]); mockWebSocketUnsubscriber = jasmine.createSpy(); }); it('unsubscribes from the websocket', () => { // Given const component = shallow( } loadDashboards={loadDashboards} saveDashboards={saveDashboards} settings={settings} > ); component.instance().webSocketUnsubscriber = mockWebSocketUnsubscriber; // When component.instance().componentWillUnmount(); // Then expect(component.instance().webSocketUnsubscriber).toBe(null); expect(mockWebSocketUnsubscriber).toHaveBeenCalled(); }); it('deconfigures and stops the websocket connection', () => { // Given const component = shallow( } loadDashboards={loadDashboards} saveDashboards={saveDashboards} settings={settings} > ); component.instance().webSocket = fakeHomeHubWebSocket; // When component.instance().componentWillUnmount(); // Then expect(fakeHomeHubWebSocket.removeEventListener).toHaveBeenCalledWith( 'start', component.instance().onWebSocketStart ); expect(fakeHomeHubWebSocket.removeEventListener).toHaveBeenCalledWith( 'stop', component.instance().onWebSocketStop ); expect(fakeHomeHubWebSocket.stop).toHaveBeenCalled(); }); }); describe('render', () => { it('configures and renders the DashboardsContext provider', () => { // Given const component = shallow( } loadDashboards={loadDashboards} saveDashboards={saveDashboards} settings={settings} > ); // When const provider = component.find(DashboardsContext.Provider); // Then expect(provider.exists()); expect(provider.prop('value')).toEqual({ currentDashboardId: component.state('currentDashboardId'), dashboards: component.state('dashboards'), nukeService: component.instance().nukeService, saveServiceCharacteristics: component.instance().saveServiceCharacteristics, saveServiceLayout: component.instance().saveServiceLayout, addService: component.instance().addService, isLoading: component.state('isLoading'), lastSaveTimestamp: component.state('lastSaveTimestamp'), lastSaveError: component.state('lastSaveError'), isSaving: component.state('isSaving'), isWebSocketConnected: component.state('isWebSocketConnected'), setCurrentDashboardId: component.instance().setCurrentDashboardId, dashboardsHash: component.instance().dashboardsHash, addDashboard: component.instance().addDashboard, loadError: component.state('loadError'), }); }); it('renders the Loader if it is loading dashboards', () => { // Given const component = shallow( } loadDashboards={loadDashboards} saveDashboards={saveDashboards} settings={settings} > ); component.setState({isLoading: true}); // Then expect(component.find(Loader).exists()).toBe(true); expect(component.find(Children).exists()).toBe(false); }); it('renders the Children if it is not loading', () => { // Given const component = shallow( } loadDashboards={loadDashboards} saveDashboards={saveDashboards} settings={settings} > ); component.setState({isLoading: false}); // Then expect(component.find(Loader).exists()).toBe(false); expect(component.find(Children).exists()).toBe(true); }); }); }); });