Release 1.3.0

This commit is contained in:
2021-08-26 12:33:15 +02:00
commit 9bb72f0207
1148 changed files with 92133 additions and 0 deletions

View File

@@ -0,0 +1,35 @@
import {shallow} from 'enzyme';
import React from 'react';
import {Button, Modal} from 'src/components';
import * as AboutModal from 'src/main/components/AboutModal';
describe('src/main/components/AboutModal', () => {
describe('AboutModal', () => {
it('configures and renders the about modal', () => {
// Given
const mockOnClose = jasmine.createSpy();
const component = shallow(
<AboutModal.AboutModal
build={123}
show={true}
version='1.0'
onClose={mockOnClose}
/>
);
// Then
const modal = component.find(Modal);
expect(modal.exists()).toBe(true);
expect(modal.prop('show')).toBe(true);
expect(modal.prop('onClose')).toEqual(mockOnClose);
const versionLine = component.find('p.text-muted');
expect(versionLine.text()).toMatch('v1.0-123');
const button = component.find(Button).at(0);
expect(button.exists()).toBe(true);
expect(button.prop('onClick')).toEqual(mockOnClose);
});
});
});

View File

@@ -0,0 +1,123 @@
import {shallow} from 'enzyme';
import React from 'react';
import {Button, Form, Modal} from 'src/components';
import * as AddDashboardModal from 'src/main/components/AddDashboardModal';
describe('src/main/components/AddDashboardModal', () => {
describe('AddDashboardModal', () => {
let mockOnClose = null;
let mockOnSave = null;
beforeEach(() => {
mockOnClose = jasmine.createSpy();
mockOnSave = jasmine.createSpy();
});
it('closes the modal when it hides', async () => {
// Given
const component = shallow(
<AddDashboardModal.AddDashboardModal
show={true}
onClose={mockOnClose}
onSave={mockOnSave}
/>
);
// When
component.find(Form.Control).at(0).simulate(
'change', {target: {value: 'spam'}}
);
const modal = component.find(Modal).at(0);
await modal.invoke('onHide')();
// Then
expect(component.find(Form.Control).at(0).prop('value')).toEqual('');
expect(mockOnClose).toHaveBeenCalled();
});
it('configures and renders the name input', () => {
// Given
const component = shallow(
<AddDashboardModal.AddDashboardModal
show={true}
onClose={mockOnClose}
onSave={mockOnSave}
/>
);
// When
const nameInput = component.find(Form.Control).at(0);
// Then
expect(nameInput.exists()).toBe(true);
expect(nameInput.prop('value')).toEqual('');
});
it('updates the state when name input changes', () => {
// Given
const component = shallow(
<AddDashboardModal.AddDashboardModal
show={true}
onClose={mockOnClose}
onSave={mockOnSave}
/>
);
// When
component.find(Form.Control).at(0).simulate(
'change', {target: {value: 'spam'}}
);
// Then
const nameInput = component.find(Form.Control).at(0);
expect(nameInput.prop('value')).toEqual('spam');
});
it('closes the modal when cancel button is clicked', () => {
// Given
const component = shallow(
<AddDashboardModal.AddDashboardModal
show={true}
onClose={mockOnClose}
onSave={mockOnSave}
/>
);
// When
component.find(Form.Control).at(0).simulate(
'change', {target: {value: 'spam'}}
);
component.find(Button).at(0).simulate('click');
// Then
const nameInput = component.find(Form.Control).at(0);
expect(nameInput.prop('value')).toEqual('');
expect(mockOnClose).toHaveBeenCalled();
});
it('saves and closes the modal when the save button is clicked', () => {
// Given
const component = shallow(
<AddDashboardModal.AddDashboardModal
show={true}
onClose={mockOnClose}
onSave={mockOnSave}
/>
);
// When
component.find(Form.Control).at(0).simulate(
'change', {target: {value: 'spam'}}
);
component.find(Button).at(1).simulate('click');
// Then
const nameInput = component.find(Form.Control).at(0);
expect(nameInput.prop('value')).toEqual('');
expect(mockOnSave).toHaveBeenCalledWith('spam');
expect(mockOnClose).toHaveBeenCalled();
});
});
});

View File

@@ -0,0 +1,18 @@
import {shallow} from 'enzyme';
import React from 'react';
import * as AppLoader from 'src/main/components/AppLoader';
describe('src/main/components/AppLoader', () => {
describe('AppLoader', () => {
it('allows passing an arbitrary class name', () => {
// Given
const component = shallow(
<AppLoader.AppLoader className="test" />
);
// Then
expect(component.hasClass('test')).toBe(true);
});
});
});

View File

@@ -0,0 +1,55 @@
import {shallow} from 'enzyme';
import React from 'react';
import {DynamicGridLayout} from 'src/components';
import * as Dashboard from 'src/main/components/Dashboard';
describe('src/main/components/Dashboard', () => {
describe('Dashboard', () => {
let layout = null;
let mockOnGridLayoutChange = null;
beforeEach(() => {
layout = [{i: 'test', x: 0, y: 0, w: 1, h: 1}];
mockOnGridLayoutChange = jasmine.createSpy();
});
it('configures and renders the DynamicGridLayout', () => {
// Given
const component = shallow(
<Dashboard.Dashboard
layout={layout}
onGridLayoutChange={mockOnGridLayoutChange}
>
<span key="test">It works!</span>
</Dashboard.Dashboard>
);
// Then
const dynamicGridLayout = component.find(DynamicGridLayout).at(0);
expect(dynamicGridLayout.exists()).toBe(true);
expect(dynamicGridLayout.prop('cols')).toEqual(12);
expect(dynamicGridLayout.prop('layout')).toEqual(layout);
expect(dynamicGridLayout.prop('rowHeight')).toEqual(30);
expect(dynamicGridLayout.prop('onLayoutChange')).toEqual(
mockOnGridLayoutChange
);
});
it('renders the children', () => {
// Given
const children = <span key="test">It works!</span>;
const component = shallow(
<Dashboard.Dashboard
layout={layout}
onGridLayoutChange={mockOnGridLayoutChange}
>
{children}
</Dashboard.Dashboard>
);
// Then
expect(component.contains(children)).toBe(true);
});
});
});

View File

@@ -0,0 +1,531 @@
import Popup from '@bthlabs/react-custom-popup';
import {shallow} from 'enzyme';
import React from 'react';
import {AppearancePopup, WidgetSettingsModal} from 'src/main/components';
import * as DashboardItem from 'src/main/components/DashboardItem';
describe('src/main/components/DashboardItem', () => {
describe('DashboardItem', () => {
let fakeServiceState = null;
let mockOnAppearancePopupColorChange = null;
let mockOnServiceRestartButtonClick = null;
let mockOnSettingsButtonClick = null;
let mockOnSettingsModalClose = null;
let mockOnSettingsModalNukeButtonClick = null;
let mockOnSettingsModalSaveButtonClick = null;
beforeEach(() => {
fakeServiceState = jasmine.createSpyObj('ServiceState', ['isLoading']);
fakeServiceState.isLoading.and.returnValue(false);
mockOnAppearancePopupColorChange = jasmine.createSpy();
mockOnServiceRestartButtonClick = jasmine.createSpy();
mockOnSettingsButtonClick = jasmine.createSpy();
mockOnSettingsModalClose = jasmine.createSpy();
mockOnSettingsModalNukeButtonClick = jasmine.createSpy();
mockOnSettingsModalSaveButtonClick = jasmine.createSpy();
});
it('renders the children', () => {
// Given
const children = <span>It works!</span>;
const component = shallow(
<DashboardItem.DashboardItem
hasSettingsView={false}
serviceState={fakeServiceState}
settingsView={null}
settingsViewProps={{}}
showSettingsModal={false}
onAppearancePopupColorChange={mockOnAppearancePopupColorChange}
onServiceRestartButtonClick={mockOnServiceRestartButtonClick}
onSettingsButtonClick={mockOnSettingsButtonClick}
onSettingsModalClose={mockOnSettingsModalClose}
onSettingsModalNukeButtonClick={mockOnSettingsModalNukeButtonClick}
onSettingsModalSaveButtonClick={mockOnSettingsModalSaveButtonClick}
>
{children}
</DashboardItem.DashboardItem>
);
// Then
expect(component.contains(children)).toBe(true);
});
it('renders the draggable handle', () => {
// Given
const component = shallow(
<DashboardItem.DashboardItem
hasSettingsView={false}
serviceState={fakeServiceState}
settingsView={null}
settingsViewProps={{}}
showSettingsModal={false}
onAppearancePopupColorChange={mockOnAppearancePopupColorChange}
onServiceRestartButtonClick={mockOnServiceRestartButtonClick}
onSettingsButtonClick={mockOnSettingsButtonClick}
onSettingsModalClose={mockOnSettingsModalClose}
onSettingsModalNukeButtonClick={mockOnSettingsModalNukeButtonClick}
onSettingsModalSaveButtonClick={mockOnSettingsModalSaveButtonClick}
>
<span>It works!</span>
</DashboardItem.DashboardItem>
);
// Then
expect(component.find('.draggable-handle').exists()).toBe(true);
});
it('does not render the restart toolbar item if serviceState is null', () => {
// Given
const component = shallow(
<DashboardItem.DashboardItem
hasSettingsView={false}
serviceState={null}
settingsView={null}
settingsViewProps={{}}
showSettingsModal={false}
onAppearancePopupColorChange={mockOnAppearancePopupColorChange}
onServiceRestartButtonClick={mockOnServiceRestartButtonClick}
onSettingsButtonClick={mockOnSettingsButtonClick}
onSettingsModalClose={mockOnSettingsModalClose}
onSettingsModalNukeButtonClick={mockOnSettingsModalNukeButtonClick}
onSettingsModalSaveButtonClick={mockOnSettingsModalSaveButtonClick}
>
<span>It works!</span>
</DashboardItem.DashboardItem>
);
// Then
expect(component.find('WidgetToolbarItem[_hint="Restart"]').exists()).toBe(
false
);
});
it('does not render the restart toolbar item if service state is loading', () => {
// Given
fakeServiceState.isLoading.and.returnValue(true);
const component = shallow(
<DashboardItem.DashboardItem
hasSettingsView={false}
serviceState={fakeServiceState}
settingsView={null}
settingsViewProps={{}}
showSettingsModal={false}
onAppearancePopupColorChange={mockOnAppearancePopupColorChange}
onServiceRestartButtonClick={mockOnServiceRestartButtonClick}
onSettingsButtonClick={mockOnSettingsButtonClick}
onSettingsModalClose={mockOnSettingsModalClose}
onSettingsModalNukeButtonClick={mockOnSettingsModalNukeButtonClick}
onSettingsModalSaveButtonClick={mockOnSettingsModalSaveButtonClick}
>
<span>It works!</span>
</DashboardItem.DashboardItem>
);
// Then
expect(component.find('WidgetToolbarItem[_hint="Restart"]').exists()).toBe(
false
);
});
it('configures and renders the restart toolbar item', () => {
// Given
const component = shallow(
<DashboardItem.DashboardItem
hasSettingsView={false}
serviceState={fakeServiceState}
settingsView={null}
settingsViewProps={{}}
showSettingsModal={false}
onAppearancePopupColorChange={mockOnAppearancePopupColorChange}
onServiceRestartButtonClick={mockOnServiceRestartButtonClick}
onSettingsButtonClick={mockOnSettingsButtonClick}
onSettingsModalClose={mockOnSettingsModalClose}
onSettingsModalNukeButtonClick={mockOnSettingsModalNukeButtonClick}
onSettingsModalSaveButtonClick={mockOnSettingsModalSaveButtonClick}
>
<span>It works!</span>
</DashboardItem.DashboardItem>
);
// When
const restartItem = component.find('WidgetToolbarItem[_hint="Restart"]');
// Then
expect(restartItem.exists()).toBe(true);
expect(restartItem.prop('onClick')).toEqual(
mockOnServiceRestartButtonClick
);
});
it('configures and renders the appearance toolbar item', () => {
// Given
const component = shallow(
<DashboardItem.DashboardItem
hasSettingsView={false}
serviceState={fakeServiceState}
settingsView={null}
settingsViewProps={{}}
showSettingsModal={false}
onAppearancePopupColorChange={mockOnAppearancePopupColorChange}
onServiceRestartButtonClick={mockOnServiceRestartButtonClick}
onSettingsButtonClick={mockOnSettingsButtonClick}
onSettingsModalClose={mockOnSettingsModalClose}
onSettingsModalNukeButtonClick={mockOnSettingsModalNukeButtonClick}
onSettingsModalSaveButtonClick={mockOnSettingsModalSaveButtonClick}
>
<span>It works!</span>
</DashboardItem.DashboardItem>
);
// When
const appearanceItem = component.find(
'WidgetToolbarItem[_hint="Appearance"]'
);
// Then
expect(appearanceItem.exists()).toBe(true);
});
it('displays the appearance popup when appearance toolbar item is clicked', () => {
// Given
const component = shallow(
<DashboardItem.DashboardItem
hasSettingsView={false}
serviceState={fakeServiceState}
settingsView={null}
settingsViewProps={{}}
showSettingsModal={false}
onAppearancePopupColorChange={mockOnAppearancePopupColorChange}
onServiceRestartButtonClick={mockOnServiceRestartButtonClick}
onSettingsButtonClick={mockOnSettingsButtonClick}
onSettingsModalClose={mockOnSettingsModalClose}
onSettingsModalNukeButtonClick={mockOnSettingsModalNukeButtonClick}
onSettingsModalSaveButtonClick={mockOnSettingsModalSaveButtonClick}
>
<span>It works!</span>
</DashboardItem.DashboardItem>
);
// When
component.find('WidgetToolbarItem[_hint="Appearance"]').simulate(
'click'
);
// Then
const popup = component.find(Popup).at(0);
expect(popup.prop('visible')).toBe(true);
});
it('does not render the settings toolbar item if hasSettingsView is false', () => {
// Given
const component = shallow(
<DashboardItem.DashboardItem
hasSettingsView={false}
serviceState={fakeServiceState}
settingsView={null}
settingsViewProps={{}}
showSettingsModal={false}
onAppearancePopupColorChange={mockOnAppearancePopupColorChange}
onServiceRestartButtonClick={mockOnServiceRestartButtonClick}
onSettingsButtonClick={mockOnSettingsButtonClick}
onSettingsModalClose={mockOnSettingsModalClose}
onSettingsModalNukeButtonClick={mockOnSettingsModalNukeButtonClick}
onSettingsModalSaveButtonClick={mockOnSettingsModalSaveButtonClick}
>
<span>It works!</span>
</DashboardItem.DashboardItem>
);
// Then
expect(component.find('WidgetToolbarItem[_hint="Settings"]').exists()).toBe(
false
);
});
it('configures and renders the settings toolbar item', () => {
// Given
const component = shallow(
<DashboardItem.DashboardItem
hasSettingsView={true}
serviceState={fakeServiceState}
settingsView={<span>Settings</span>}
settingsViewProps={{}}
showSettingsModal={false}
onAppearancePopupColorChange={mockOnAppearancePopupColorChange}
onServiceRestartButtonClick={mockOnServiceRestartButtonClick}
onSettingsButtonClick={mockOnSettingsButtonClick}
onSettingsModalClose={mockOnSettingsModalClose}
onSettingsModalNukeButtonClick={mockOnSettingsModalNukeButtonClick}
onSettingsModalSaveButtonClick={mockOnSettingsModalSaveButtonClick}
>
<span>It works!</span>
</DashboardItem.DashboardItem>
);
// When
const settingsItem = component.find(
'WidgetToolbarItem[_hint="Settings"]'
);
// Then
expect(settingsItem.exists()).toBe(true);
expect(settingsItem.prop('onClick')).toEqual(mockOnSettingsButtonClick);
});
it('does not render the delete toolbar item if hasSettingsView is true', () => {
// Given
const component = shallow(
<DashboardItem.DashboardItem
hasSettingsView={true}
serviceState={fakeServiceState}
settingsView={<span>Settings</span>}
settingsViewProps={{}}
showSettingsModal={false}
onAppearancePopupColorChange={mockOnAppearancePopupColorChange}
onServiceRestartButtonClick={mockOnServiceRestartButtonClick}
onSettingsButtonClick={mockOnSettingsButtonClick}
onSettingsModalClose={mockOnSettingsModalClose}
onSettingsModalNukeButtonClick={mockOnSettingsModalNukeButtonClick}
onSettingsModalSaveButtonClick={mockOnSettingsModalSaveButtonClick}
>
<span>It works!</span>
</DashboardItem.DashboardItem>
);
// Then
expect(component.find('WidgetToolbarItem[_hint="Delete"]').exists()).toBe(
false
);
});
it('configures and renders the delete toolbar item', () => {
// Given
const component = shallow(
<DashboardItem.DashboardItem
hasSettingsView={false}
serviceState={fakeServiceState}
settingsView={null}
settingsViewProps={{}}
showSettingsModal={false}
onAppearancePopupColorChange={mockOnAppearancePopupColorChange}
onServiceRestartButtonClick={mockOnServiceRestartButtonClick}
onSettingsButtonClick={mockOnSettingsButtonClick}
onSettingsModalClose={mockOnSettingsModalClose}
onSettingsModalNukeButtonClick={mockOnSettingsModalNukeButtonClick}
onSettingsModalSaveButtonClick={mockOnSettingsModalSaveButtonClick}
>
<span>It works!</span>
</DashboardItem.DashboardItem>
);
// When
const deleteItem = component.find(
'WidgetToolbarItem[_hint="Delete"]'
);
// Then
expect(deleteItem.exists()).toBe(true);
expect(deleteItem.prop('onClick')).toEqual(
mockOnSettingsModalNukeButtonClick
);
});
it('does not render the WidgetSettingsModal if hasSettingsView is false', () => {
// Given
const component = shallow(
<DashboardItem.DashboardItem
hasSettingsView={false}
serviceState={fakeServiceState}
settingsView={null}
settingsViewProps={{}}
showSettingsModal={false}
onAppearancePopupColorChange={mockOnAppearancePopupColorChange}
onServiceRestartButtonClick={mockOnServiceRestartButtonClick}
onSettingsButtonClick={mockOnSettingsButtonClick}
onSettingsModalClose={mockOnSettingsModalClose}
onSettingsModalNukeButtonClick={mockOnSettingsModalNukeButtonClick}
onSettingsModalSaveButtonClick={mockOnSettingsModalSaveButtonClick}
>
<span>It works!</span>
</DashboardItem.DashboardItem>
);
// When
const widgetSettingsModal = component.find(WidgetSettingsModal).at(0);
// Then
expect(widgetSettingsModal.exists()).toBe(false);
});
it('configures and renders the WidgetSettingsModal', () => {
// Given
const settingsView = <span>Settings</span>;
const settingsViewProps = {spam: true};
const component = shallow(
<DashboardItem.DashboardItem
hasSettingsView={true}
serviceState={fakeServiceState}
settingsView={settingsView}
settingsViewProps={settingsViewProps}
showSettingsModal={true}
onAppearancePopupColorChange={mockOnAppearancePopupColorChange}
onServiceRestartButtonClick={mockOnServiceRestartButtonClick}
onSettingsButtonClick={mockOnSettingsButtonClick}
onSettingsModalClose={mockOnSettingsModalClose}
onSettingsModalNukeButtonClick={mockOnSettingsModalNukeButtonClick}
onSettingsModalSaveButtonClick={mockOnSettingsModalSaveButtonClick}
>
<span>It works!</span>
</DashboardItem.DashboardItem>
);
// When
const widgetSettingsModal = component.find(WidgetSettingsModal).at(0);
// Then
expect(widgetSettingsModal.exists()).toBe(true);
expect(widgetSettingsModal.prop('buttons').length).toEqual(1);
expect(widgetSettingsModal.prop('settingsView')).toEqual(settingsView);
expect(widgetSettingsModal.prop('settingsViewProps')).toEqual(
settingsViewProps
);
expect(widgetSettingsModal.prop('show')).toBe(true);
expect(widgetSettingsModal.prop('onClose')).toEqual(
mockOnSettingsModalClose
);
expect(widgetSettingsModal.prop('onCancelButtonClick')).toEqual(
mockOnSettingsModalClose
);
expect(widgetSettingsModal.prop('onSaveButtonClick')).toEqual(
mockOnSettingsModalSaveButtonClick
);
const nukeButtonComponent = shallow(
widgetSettingsModal.prop('buttons')[0]
);
expect(nukeButtonComponent.isEmptyRender()).toBe(false);
expect(nukeButtonComponent.prop('onClick')).toEqual(
mockOnSettingsModalNukeButtonClick
);
});
it('configures and renders the appearance popup wrapper', () => {
// Given
const component = shallow(
<DashboardItem.DashboardItem
hasSettingsView={true}
serviceState={fakeServiceState}
settingsView={<span>Settings</span>}
settingsViewProps={{}}
showSettingsModal={false}
onAppearancePopupColorChange={mockOnAppearancePopupColorChange}
onServiceRestartButtonClick={mockOnServiceRestartButtonClick}
onSettingsButtonClick={mockOnSettingsButtonClick}
onSettingsModalClose={mockOnSettingsModalClose}
onSettingsModalNukeButtonClick={mockOnSettingsModalNukeButtonClick}
onSettingsModalSaveButtonClick={mockOnSettingsModalSaveButtonClick}
>
<span>It works!</span>
</DashboardItem.DashboardItem>
);
// When
const popup = component.find(Popup).at(0);
// Then
expect(popup.exists()).toBe(true);
expect(popup.prop('visible')).toBe(false);
});
it('hides the appearance popup wrapper when the overlay is clicked', () => {
// Given
const component = shallow(
<DashboardItem.DashboardItem
hasSettingsView={true}
serviceState={fakeServiceState}
settingsView={<span>Settings</span>}
settingsViewProps={{}}
showSettingsModal={false}
onAppearancePopupColorChange={mockOnAppearancePopupColorChange}
onServiceRestartButtonClick={mockOnServiceRestartButtonClick}
onSettingsButtonClick={mockOnSettingsButtonClick}
onSettingsModalClose={mockOnSettingsModalClose}
onSettingsModalNukeButtonClick={mockOnSettingsModalNukeButtonClick}
onSettingsModalSaveButtonClick={mockOnSettingsModalSaveButtonClick}
>
<span>It works!</span>
</DashboardItem.DashboardItem>
);
// When
component.find('WidgetToolbarItem[_hint="Appearance"]').simulate(
'click'
);
component.find(Popup).at(0).invoke('onOverlayClick')();
// Then
const popup = component.find(Popup).at(0);
expect(popup.prop('visible')).toBe(false);
});
it('configures and renders the appearance popup view', () => {
// Given
const component = shallow(
<DashboardItem.DashboardItem
hasSettingsView={true}
serviceState={fakeServiceState}
settingsView={<span>Settings</span>}
settingsViewProps={{}}
showSettingsModal={false}
onAppearancePopupColorChange={mockOnAppearancePopupColorChange}
onServiceRestartButtonClick={mockOnServiceRestartButtonClick}
onSettingsButtonClick={mockOnSettingsButtonClick}
onSettingsModalClose={mockOnSettingsModalClose}
onSettingsModalNukeButtonClick={mockOnSettingsModalNukeButtonClick}
onSettingsModalSaveButtonClick={mockOnSettingsModalSaveButtonClick}
>
<span>It works!</span>
</DashboardItem.DashboardItem>
);
// When
const popupView = component.find(AppearancePopup).at(0);
// Then
expect(popupView.exists()).toBe(true);
});
it('handles the AppearancePopup color change', () => {
// Given
const component = shallow(
<DashboardItem.DashboardItem
hasSettingsView={true}
serviceState={fakeServiceState}
settingsView={<span>Settings</span>}
settingsViewProps={{}}
showSettingsModal={false}
onAppearancePopupColorChange={mockOnAppearancePopupColorChange}
onServiceRestartButtonClick={mockOnServiceRestartButtonClick}
onSettingsButtonClick={mockOnSettingsButtonClick}
onSettingsModalClose={mockOnSettingsModalClose}
onSettingsModalNukeButtonClick={mockOnSettingsModalNukeButtonClick}
onSettingsModalSaveButtonClick={mockOnSettingsModalSaveButtonClick}
>
<span>It works!</span>
</DashboardItem.DashboardItem>
);
// When
component.find('WidgetToolbarItem[_hint="Appearance"]').simulate(
'click'
);
component.find(AppearancePopup).at(0).invoke('onColorChange')('red');
// Then
expect(component.find(Popup).at(0).prop('visible')).toBe(false);
expect(mockOnAppearancePopupColorChange).toHaveBeenCalledWith('red');
});
});
});

View File

@@ -0,0 +1,23 @@
import {shallow} from 'enzyme';
import React from 'react';
import * as DummyWidget from 'src/main/components/DummyWidget';
import {UptimeService} from 'src/services/uptime';
describe('src/main/components/DummyWidget', () => {
describe('DummyWidget', () => {
it('renders the service information', () => {
// Given
const service = new UptimeService({instance: 'testing'});
const component = shallow(
<DummyWidget.DummyWidget service={service} />
);
// When
const code = component.find('code').at(0);
// Then
expect(code.text()).toEqual(`${service.widget} (${service.instance})`);
});
});
});

View File

@@ -0,0 +1,544 @@
import {
kServiceOfflineWeather, kServiceTime, kServiceUptime, kServiceWeather,
kWidgetUptime, kWidgetWeather,
} from '@bthlabs/homehub-core';
import {Icon, IconBasicGear} from '@bthlabs/homehub-icons';
import Popup from '@bthlabs/react-custom-popup';
import {shallow} from 'enzyme';
import React from 'react';
import {AboutModal} from 'src/main/components/AboutModal';
import * as StartMenu from 'src/main/components/StartMenu';
import {SERVICES} from 'src/services';
import {WIDGETS} from 'src/widgets';
import {SettingsFactory} from 'tests/__fixtures__/settings';
describe('src/main/components/StartMenu', () => {
describe('ControlledStartMenu', () => {
let mockOnAddDashboard = null;
let mockOnAddService = null;
let fakeSettings = null;
beforeEach(() => {
mockOnAddService = jasmine.createSpy();
mockOnAddDashboard = jasmine.createSpy();
fakeSettings = SettingsFactory();
});
it('renders the start button', () => {
// Given
const component = shallow(
<StartMenu.ControlledStartMenu
hasDashboards={true}
offlineMode={false}
services={SERVICES}
settings={fakeSettings}
widgets={WIDGETS}
onAddDashboard={mockOnAddDashboard}
onAddService={mockOnAddService}
/>
);
// When
const startButton = component.find('a[_hint="StartButton"]').at(0);
// Then
expect(startButton.exists()).toBe(true);
});
it('displays the start menu popup when the start button is clicked', () => {
// Given
const component = shallow(
<StartMenu.ControlledStartMenu
hasDashboards={true}
offlineMode={false}
services={SERVICES}
settings={fakeSettings}
widgets={WIDGETS}
onAddDashboard={mockOnAddDashboard}
onAddService={mockOnAddService}
/>
);
// When
component.find('a[_hint="StartButton"]').at(0).simulate('click');
// Then
const popup = component.find(Popup).at(0);
expect(popup.prop('visible')).toBe(true);
});
it('configures and renders the start menu popup', () => {
// Given
const component = shallow(
<StartMenu.ControlledStartMenu
hasDashboards={true}
offlineMode={false}
services={SERVICES}
settings={fakeSettings}
widgets={WIDGETS}
onAddDashboard={mockOnAddDashboard}
onAddService={mockOnAddService}
/>
);
// When
const popup = component.find(Popup).at(0);
// Then
expect(popup.exists()).toBe(true);
expect(popup.prop('visible')).toBe(false);
});
it('hides the start menu popup when the overlay is clicked', () => {
// Given
const component = shallow(
<StartMenu.ControlledStartMenu
hasDashboards={true}
offlineMode={false}
services={SERVICES}
settings={fakeSettings}
widgets={WIDGETS}
onAddDashboard={mockOnAddDashboard}
onAddService={mockOnAddService}
/>
);
// When
component.find('a[_hint="StartButton"]').at(0).simulate('click');
component.find(Popup).at(0).invoke('onOverlayClick')();
// Then
const popup = component.find(Popup).at(0);
expect(popup.prop('visible')).toBe(false);
});
it('renders the start menu view', () => {
// Given
const component = shallow(
<StartMenu.ControlledStartMenu
hasDashboards={true}
offlineMode={false}
services={SERVICES}
settings={fakeSettings}
widgets={WIDGETS}
onAddDashboard={mockOnAddDashboard}
onAddService={mockOnAddService}
/>
);
// When
const startMenu = component.find('div[_hint="StartMenu"]').at(0);
// Then
expect(startMenu.exists()).toBe(true);
});
it('hides the start menu popup when the start menu is clicked', () => {
// Given
const component = shallow(
<StartMenu.ControlledStartMenu
hasDashboards={true}
offlineMode={false}
services={SERVICES}
settings={fakeSettings}
widgets={WIDGETS}
onAddDashboard={mockOnAddDashboard}
onAddService={mockOnAddService}
/>
);
// When
component.find('a[_hint="StartButton"]').at(0).simulate('click');
component.find('div[_hint="StartMenu"]').at(0).simulate('click');
// Then
const popup = component.find(Popup).at(0);
expect(popup.prop('visible')).toBe(false);
});
it('renders the about toolbar item', () => {
// Given
const component = shallow(
<StartMenu.ControlledStartMenu
hasDashboards={true}
offlineMode={false}
services={SERVICES}
settings={fakeSettings}
widgets={WIDGETS}
onAddDashboard={mockOnAddDashboard}
onAddService={mockOnAddService}
/>
);
// When
const aboutItem = component.find('div[_hint="About"]').at(0);
// Then
expect(aboutItem.exists()).toBe(true);
});
it('displays the about modal when the about toolbar item is clicked', () => {
// Given
const component = shallow(
<StartMenu.ControlledStartMenu
hasDashboards={true}
offlineMode={false}
services={SERVICES}
settings={fakeSettings}
widgets={WIDGETS}
onAddDashboard={mockOnAddDashboard}
onAddService={mockOnAddService}
/>
);
// When
component.find('div[_hint="About"]').at(0).simulate('click');
// Then
const aboutModal = component.find(AboutModal).at(0);
expect(aboutModal.prop('show')).toBe(true);
});
it('configures and renders the add dashboard toolbar item', () => {
// Given
const component = shallow(
<StartMenu.ControlledStartMenu
hasDashboards={true}
offlineMode={false}
services={SERVICES}
settings={fakeSettings}
widgets={WIDGETS}
onAddDashboard={mockOnAddDashboard}
onAddService={mockOnAddService}
/>
);
// When
const addDashboardItem = component.find('div[_hint="AddDashboard"]').at(0);
// Then
expect(addDashboardItem.exists()).toBe(true);
expect(addDashboardItem.prop('onClick')).toEqual(mockOnAddDashboard);
});
it('renders the reload toolbar item', () => {
// Given
const component = shallow(
<StartMenu.ControlledStartMenu
hasDashboards={true}
offlineMode={false}
services={SERVICES}
settings={fakeSettings}
widgets={WIDGETS}
onAddDashboard={mockOnAddDashboard}
onAddService={mockOnAddService}
/>
);
// When
const addDashboardItem = component.find('div[_hint="Reload"]').at(0);
// Then
expect(addDashboardItem.exists()).toBe(true);
});
xit('reloads the page when the reload button is clicked', () => {
// Given
spyOn(window.location, 'reload');
const component = shallow(
<StartMenu.ControlledStartMenu
hasDashboards={true}
offlineMode={false}
services={SERVICES}
settings={fakeSettings}
widgets={WIDGETS}
onAddDashboard={mockOnAddDashboard}
onAddService={mockOnAddService}
/>
);
// When
component.find('div[_hint="Reload"]').at(0).simulate('click');
// Then
expect(window.location.reload).toHaveBeenCalled();
});
describe('Widgets', () => {
let fakeServices = null;
let fakeWidgets = null;
beforeEach(() => {
fakeServices = {
[kServiceOfflineWeather]: SERVICES.kServiceOfflineWeather,
[kServiceTime]: SERVICES.kServiceTime,
[kServiceUptime]: SERVICES.kServiceUptime,
[kServiceWeather]: SERVICES.kServiceWeather,
};
fakeWidgets = {
[kWidgetUptime]: WIDGETS.kWidgetUptime,
[kWidgetWeather]: WIDGETS.kWidgetWeather,
};
});
it('renders the list of widgets available in online mode', () => {
// Given
const component = shallow(
<StartMenu.ControlledStartMenu
hasDashboards={true}
offlineMode={false}
services={fakeServices}
settings={fakeSettings}
widgets={fakeWidgets}
onAddDashboard={mockOnAddDashboard}
onAddService={mockOnAddService}
/>
);
// When
const widgets = component.find('div[_hint="Widgets"]').at(0);
// Then
const serviceKeys = widgets.find('div[_hint="Widget"]').map((wrapper) => {
return wrapper.prop('data-service');
});
expect(serviceKeys.length).toEqual(3);
expect(serviceKeys).not.toContain(kServiceOfflineWeather);
expect(serviceKeys).toContain(kServiceTime);
expect(serviceKeys).toContain(kServiceUptime);
expect(serviceKeys).toContain(kServiceWeather);
});
it('renders the list of widgets available in offline mode', () => {
// Given
const component = shallow(
<StartMenu.ControlledStartMenu
hasDashboards={true}
offlineMode={true}
services={fakeServices}
settings={fakeSettings}
widgets={fakeWidgets}
onAddDashboard={mockOnAddDashboard}
onAddService={mockOnAddService}
/>
);
// When
const widgets = component.find('div[_hint="Widgets"]').at(0);
// Then
const serviceKeys = widgets.find('div[_hint="Widget"]').map((wrapper) => {
return wrapper.prop('data-service');
});
expect(serviceKeys.length).toEqual(2);
expect(serviceKeys).toContain(kServiceOfflineWeather);
expect(serviceKeys).toContain(kServiceTime);
expect(serviceKeys).not.toContain(kServiceUptime);
expect(serviceKeys).not.toContain(kServiceWeather);
});
it('configures and renders a widget item for a known widget', () => {
// Given
const component = shallow(
<StartMenu.ControlledStartMenu
hasDashboards={true}
offlineMode={false}
services={fakeServices}
settings={fakeSettings}
widgets={fakeWidgets}
onAddDashboard={mockOnAddDashboard}
onAddService={mockOnAddService}
/>
);
// When
const widgetItem = component.find(
`div[data-service="${kServiceWeather}"]`
).at(
0
);
const icon = widgetItem.find(Icon).at(0);
const title = widgetItem.find('p').at(0);
// Then
expect(widgetItem.hasClass('disabled')).toBe(false);
expect(icon.prop('icon')).toEqual(fakeWidgets[kWidgetWeather].icon);
expect(title.text()).toEqual(fakeWidgets[kWidgetWeather].title);
});
it('configures and renders a widget item for an unknown widget', () => {
// Given
const component = shallow(
<StartMenu.ControlledStartMenu
hasDashboards={true}
offlineMode={false}
services={fakeServices}
settings={fakeSettings}
widgets={fakeWidgets}
onAddDashboard={mockOnAddDashboard}
onAddService={mockOnAddService}
/>
);
// When
const widgetItem = component.find(
`div[data-service="${kServiceTime}"]`
).at(
0
);
const icon = widgetItem.find(Icon).at(0);
const title = widgetItem.find('p').at(0);
// Then
expect(icon.prop('icon')).toEqual(IconBasicGear);
expect(title.text()).toEqual('Unnamed Widget');
});
it('renders widgets as disabled if it has no dashboards', () => {
// Given
const component = shallow(
<StartMenu.ControlledStartMenu
hasDashboards={false}
offlineMode={false}
services={fakeServices}
settings={fakeSettings}
widgets={fakeWidgets}
onAddDashboard={mockOnAddDashboard}
onAddService={mockOnAddService}
/>
);
// When
const widgetItem = component.find(
`div[data-service="${kServiceWeather}"]`
).at(
0
);
// Then
expect(widgetItem.hasClass('disabled')).toBe(true);
});
it('handles a widget item click', () => {
// Given
const mockEventPreventDefault = jasmine.createSpy();
const mockEventStopPropagation = jasmine.createSpy();
const component = shallow(
<StartMenu.ControlledStartMenu
hasDashboards={true}
offlineMode={false}
services={fakeServices}
settings={fakeSettings}
widgets={fakeWidgets}
onAddDashboard={mockOnAddDashboard}
onAddService={mockOnAddService}
/>
);
// When
const widgetItem = component.find(
`div[data-service="${kServiceTime}"]`
).at(
0
);
widgetItem.simulate('click', {
currentTarget: {
dataset: {service: kServiceTime},
},
preventDefault: mockEventPreventDefault,
stopPropagation: mockEventStopPropagation,
});
// Then
expect(mockOnAddService).toHaveBeenCalledWith(kServiceTime);
expect(mockEventPreventDefault).not.toHaveBeenCalled();
expect(mockEventStopPropagation).not.toHaveBeenCalled();
});
it('cancels the event when it does not have dashboards', () => {
// Given
const mockEventPreventDefault = jasmine.createSpy();
const mockEventStopPropagation = jasmine.createSpy();
const component = shallow(
<StartMenu.ControlledStartMenu
hasDashboards={false}
offlineMode={false}
services={fakeServices}
settings={fakeSettings}
widgets={fakeWidgets}
onAddDashboard={mockOnAddDashboard}
onAddService={mockOnAddService}
/>
);
// When
const widgetItem = component.find(
`div[data-service="${kServiceTime}"]`
).at(
0
);
widgetItem.simulate('click', {
currentTarget: {
dataset: {service: kServiceTime},
},
preventDefault: mockEventPreventDefault,
stopPropagation: mockEventStopPropagation,
});
// Then
expect(mockOnAddService).not.toHaveBeenCalled();
expect(mockEventPreventDefault).toHaveBeenCalled();
expect(mockEventStopPropagation).toHaveBeenCalled();
});
});
it('configures and renders the about modal', () => {
// Given
const component = shallow(
<StartMenu.ControlledStartMenu
hasDashboards={true}
offlineMode={false}
services={SERVICES}
settings={fakeSettings}
widgets={WIDGETS}
onAddDashboard={mockOnAddDashboard}
onAddService={mockOnAddService}
/>
);
// When
const aboutModal = component.find(AboutModal).at(0);
// Then
expect(aboutModal.exists()).toBe(true);
expect(aboutModal.prop('build')).toEqual(123);
expect(aboutModal.prop('show')).toBe(false);
expect(aboutModal.prop('version')).toEqual('1.0');
});
it('displays the about modal when it closes', () => {
// Given
const component = shallow(
<StartMenu.ControlledStartMenu
hasDashboards={true}
offlineMode={false}
services={SERVICES}
settings={fakeSettings}
widgets={WIDGETS}
onAddDashboard={mockOnAddDashboard}
onAddService={mockOnAddService}
/>
);
// When
component.find('div[_hint="About"]').at(0).simulate('click');
component.find(AboutModal).at(0).invoke('onClose')();
// Then
const aboutModal = component.find(AboutModal).at(0);
expect(aboutModal.prop('show')).toBe(false);
});
});
});

View File

@@ -0,0 +1,273 @@
import {shallow} from 'enzyme';
import React from 'react';
import {StartMenu} from 'src/main/components/StartMenu';
import * as Taskbar from 'src/main/components/Taskbar';
import {SERVICES} from 'src/services';
import {WIDGETS} from 'src/widgets';
import {DashboardsFactory} from 'tests/__fixtures__/dashboards';
describe('src/main/components/Taskbar', () => {
describe('Taskbar', () => {
let mockOnAddDashboard = null;
let mockOnAddService = null;
let mockOnSelectDashboard = null;
let fakeDashboards = null;
let fakeSavingState = null;
let fakeWebSocketState = null;
beforeEach(() => {
mockOnAddDashboard = jasmine.createSpy();
mockOnAddService = jasmine.createSpy();
mockOnSelectDashboard = jasmine.createSpy();
fakeDashboards = DashboardsFactory();
fakeSavingState = {
isSaving: false,
lastSaveError: null,
lastSaveTimestamp: new Date(1987, 9, 3, 8, 0, 0),
};
fakeWebSocketState = {
isWebSocketConnected: true,
};
});
it('configures and renders the start menu', () => {
// Given
const component = shallow(
<Taskbar.Taskbar
currentDashboardId="testing"
dashboards={fakeDashboards}
offlineMode={false}
savingState={fakeSavingState}
services={SERVICES}
webSocketState={fakeWebSocketState}
widgets={WIDGETS}
onAddDashboard={mockOnAddDashboard}
onAddService={mockOnAddService}
/>
);
// When
const startMenu = component.find(StartMenu).at(0);
// Then
expect(startMenu.exists()).toBe(true);
expect(startMenu.prop('offlineMode')).toBe(false);
expect(startMenu.prop('services')).toEqual(SERVICES);
expect(startMenu.prop('widgets')).toEqual(WIDGETS);
expect(startMenu.prop('onAddDashboard')).toEqual(mockOnAddDashboard);
expect(startMenu.prop('onAddService')).toEqual(mockOnAddService);
});
it('configures renders the dashboard buttons', () => {
// Given
const component = shallow(
<Taskbar.Taskbar
currentDashboardId="testing"
dashboards={fakeDashboards}
offlineMode={false}
savingState={fakeSavingState}
services={SERVICES}
webSocketState={fakeWebSocketState}
widgets={WIDGETS}
onAddDashboard={mockOnAddDashboard}
onAddService={mockOnAddService}
/>
);
// When
const dashboardButtons = component.find('a[_hint="Dashboard"]');
// Then
expect(dashboardButtons.length).toEqual(2);
const dashboardButton = dashboardButtons.at(0);
expect(dashboardButton.hasClass('active')).toBe(true);
expect(dashboardButton.prop('data-dashboard')).toEqual(
fakeDashboards[0].id
);
expect(dashboardButton.text()).toEqual(fakeDashboards[0].name);
expect(dashboardButtons.at(1).hasClass('active')).toBe(false);
});
it('selects a dashboard when its button is clicked', () => {
// Given
const component = shallow(
<Taskbar.Taskbar
currentDashboardId="testing"
dashboards={fakeDashboards}
offlineMode={false}
savingState={fakeSavingState}
services={SERVICES}
webSocketState={fakeWebSocketState}
widgets={WIDGETS}
onAddDashboard={mockOnAddDashboard}
onAddService={mockOnAddService}
onSelectDashboard={mockOnSelectDashboard}
/>
);
// When
component.find('a[_hint="Dashboard"]').at(0).simulate('click', {
currentTarget: {
dataset: {dashboard: fakeDashboards[0].id},
},
});
// Then
expect(mockOnSelectDashboard).toHaveBeenCalledWith(fakeDashboards[0].id);
});
it('does not render websocket status in offline mode', () => {
// Given
const component = shallow(
<Taskbar.Taskbar
currentDashboardId="testing"
dashboards={fakeDashboards}
offlineMode={true}
savingState={fakeSavingState}
services={SERVICES}
webSocketState={fakeWebSocketState}
widgets={WIDGETS}
onAddDashboard={mockOnAddDashboard}
onAddService={mockOnAddService}
onSelectDashboard={mockOnSelectDashboard}
/>
);
// Then
expect(component.find('Icon[_hint="WebSocketConnected"]').exists()).toBe(
false
);
expect(component.find('Icon[_hint="WebSocketNotConnected"]').exists()).toBe(
false
);
});
it('renders the websocket connection status when websocket is connected', () => {
// Given
const component = shallow(
<Taskbar.Taskbar
currentDashboardId="testing"
dashboards={fakeDashboards}
offlineMode={false}
savingState={fakeSavingState}
services={SERVICES}
webSocketState={fakeWebSocketState}
widgets={WIDGETS}
onAddDashboard={mockOnAddDashboard}
onAddService={mockOnAddService}
onSelectDashboard={mockOnSelectDashboard}
/>
);
// Then
expect(component.find('Icon[_hint="WebSocketConnected"]').exists()).toBe(
true
);
expect(component.find('Icon[_hint="WebSocketNotConnected"]').exists()).toBe(
false
);
});
it('renders the websocket connection status when websocket is not connected', () => {
// Given
fakeWebSocketState.isWebSocketConnected = false;
const component = shallow(
<Taskbar.Taskbar
currentDashboardId="testing"
dashboards={fakeDashboards}
offlineMode={false}
savingState={fakeSavingState}
services={SERVICES}
webSocketState={fakeWebSocketState}
widgets={WIDGETS}
onAddDashboard={mockOnAddDashboard}
onAddService={mockOnAddService}
onSelectDashboard={mockOnSelectDashboard}
/>
);
// Then
expect(component.find('Icon[_hint="WebSocketConnected"]').exists()).toBe(
false
);
expect(component.find('Icon[_hint="WebSocketNotConnected"]').exists()).toBe(
true
);
});
it('renders the saving status when it is saving', () => {
// Given
fakeSavingState.isSaving = true;
const component = shallow(
<Taskbar.Taskbar
currentDashboardId="testing"
dashboards={fakeDashboards}
offlineMode={false}
savingState={fakeSavingState}
services={SERVICES}
webSocketState={fakeWebSocketState}
widgets={WIDGETS}
onAddDashboard={mockOnAddDashboard}
onAddService={mockOnAddService}
onSelectDashboard={mockOnSelectDashboard}
/>
);
// Then
expect(component.find('Icon[_hint="IsSaving"]').exists()).toBe(true);
expect(component.find('Icon[_hint="SaveError"]').exists()).toBe(false);
expect(component.find('Icon[_hint="SaveOK"]').exists()).toBe(false);
});
it('renders the saving status when last save was an error', () => {
// Given
fakeSavingState.lastSaveError = 'FIAL';
const component = shallow(
<Taskbar.Taskbar
currentDashboardId="testing"
dashboards={fakeDashboards}
offlineMode={false}
savingState={fakeSavingState}
services={SERVICES}
webSocketState={fakeWebSocketState}
widgets={WIDGETS}
onAddDashboard={mockOnAddDashboard}
onAddService={mockOnAddService}
onSelectDashboard={mockOnSelectDashboard}
/>
);
// Then
expect(component.find('Icon[_hint="IsSaving"]').exists()).toBe(false);
expect(component.find('Icon[_hint="SaveError"]').exists()).toBe(true);
expect(component.find('Icon[_hint="SaveOK"]').exists()).toBe(false);
});
it('renders the saving status when last save was OK', () => {
// Given
const component = shallow(
<Taskbar.Taskbar
currentDashboardId="testing"
dashboards={fakeDashboards}
offlineMode={false}
savingState={fakeSavingState}
services={SERVICES}
webSocketState={fakeWebSocketState}
widgets={WIDGETS}
onAddDashboard={mockOnAddDashboard}
onAddService={mockOnAddService}
onSelectDashboard={mockOnSelectDashboard}
/>
);
// Then
expect(component.find('Icon[_hint="IsSaving"]').exists()).toBe(false);
expect(component.find('Icon[_hint="SaveError"]').exists()).toBe(false);
expect(component.find('Icon[_hint="SaveOK"]').exists()).toBe(true);
});
});
});

View File

@@ -0,0 +1,133 @@
import {shallow} from 'enzyme';
import React from 'react';
import {Button, Modal} from 'src/components';
import * as WidgetSettingsModal from 'src/main/components/WidgetSettingsModal';
describe('src/main/components/WidgetSettingsModal', () => {
describe('WidgetSettingsModal', () => {
let mockOnCancelButtonClick = null;
let mockOnClose = null;
let mockOnSaveButtonClick = null;
let fakeSettingsView = null;
let fakeSettingsViewProps = null;
beforeEach(() => {
mockOnCancelButtonClick = jasmine.createSpy();
mockOnClose = jasmine.createSpy();
mockOnSaveButtonClick = jasmine.createSpy();
fakeSettingsView = jasmine.createSpy().and.returnValue(
<span>Settings</span>
);
fakeSettingsView.displayName = 'FakeSettingsView';
fakeSettingsViewProps = {spam: true};
});
it('configures and renders the modal', () => {
// Given
const component = shallow(
<WidgetSettingsModal.WidgetSettingsModal
buttons={[]}
settingsView={fakeSettingsView}
settingsViewProps={fakeSettingsViewProps}
show={false}
onCancelButtonClick={mockOnCancelButtonClick}
onClose={mockOnClose}
onSaveButtonClick={mockOnSaveButtonClick}
/>
);
// When
const modal = component.find(Modal).at(0);
// Then
expect(modal.exists()).toBe(true);
expect(modal.prop('show')).toBe(false);
expect(modal.prop('onHide')).toEqual(mockOnClose);
});
it('configures and renders the settings view', () => {
// Given
const component = shallow(
<WidgetSettingsModal.WidgetSettingsModal
buttons={[]}
settingsView={fakeSettingsView}
settingsViewProps={fakeSettingsViewProps}
show={false}
onCancelButtonClick={mockOnCancelButtonClick}
onClose={mockOnClose}
onSaveButtonClick={mockOnSaveButtonClick}
/>
);
// When
const settingsView = component.find(fakeSettingsView).at(0);
// Then
expect(settingsView.props()).toEqual(fakeSettingsViewProps);
});
it('renders the additional buttons', () => {
// Given
const button = <Button key="testing">Test</Button>;
const component = shallow(
<WidgetSettingsModal.WidgetSettingsModal
buttons={[button]}
settingsView={fakeSettingsView}
settingsViewProps={fakeSettingsViewProps}
show={false}
onCancelButtonClick={mockOnCancelButtonClick}
onClose={mockOnClose}
onSaveButtonClick={mockOnSaveButtonClick}
/>
);
// Then
expect(component.contains(button)).toBe(true);
});
it('configures and renders the cancel button', () => {
// Given
const component = shallow(
<WidgetSettingsModal.WidgetSettingsModal
buttons={[]}
settingsView={fakeSettingsView}
settingsViewProps={fakeSettingsViewProps}
show={false}
onCancelButtonClick={mockOnCancelButtonClick}
onClose={mockOnClose}
onSaveButtonClick={mockOnSaveButtonClick}
/>
);
// When
const button = component.find('Button[_hint="Cancel"]').at(0);
// Then
expect(button.exists()).toBe(true);
expect(button.prop('onClick')).toEqual(mockOnCancelButtonClick);
});
it('configures and renders the save button', () => {
// Given
const component = shallow(
<WidgetSettingsModal.WidgetSettingsModal
buttons={[]}
settingsView={fakeSettingsView}
settingsViewProps={fakeSettingsViewProps}
show={false}
onCancelButtonClick={mockOnCancelButtonClick}
onClose={mockOnClose}
onSaveButtonClick={mockOnSaveButtonClick}
/>
);
// When
const button = component.find('Button[_hint="Save"]').at(0);
// Then
expect(button.exists()).toBe(true);
expect(button.prop('onClick')).toEqual(mockOnSaveButtonClick);
});
});
});

View File

@@ -0,0 +1,98 @@
import {shallow} from 'enzyme';
import React from 'react';
import * as WidgetToolbar from 'src/main/components/WidgetToolbar';
describe('src/main/components/WidgetToolbar', () => {
describe('WidgetToolbar', () => {
it('allows passing an arbitrary class name', () => {
// Given
const component = shallow(
<WidgetToolbar.WidgetToolbar className="test">
<span>It works!</span>
</WidgetToolbar.WidgetToolbar>
);
// Then
expect(component.hasClass('test')).toBe(true);
});
it('renders a right-side toolbar', () => {
// Given
const component = shallow(
<WidgetToolbar.WidgetToolbar right>
<span>It works!</span>
</WidgetToolbar.WidgetToolbar>
);
// Then
expect(component.hasClass('left')).toBe(false);
expect(component.hasClass('right')).toBe(true);
});
it('renders a left-side toolbar', () => {
// Given
const component = shallow(
<WidgetToolbar.WidgetToolbar>
<span>It works!</span>
</WidgetToolbar.WidgetToolbar>
);
// Then
expect(component.hasClass('left')).toBe(true);
expect(component.hasClass('right')).toBe(false);
});
it('renders the children', () => {
// Given
const children = <span>It works!</span>;
const component = shallow(
<WidgetToolbar.WidgetToolbar right>
{children}
</WidgetToolbar.WidgetToolbar>
);
// Then
expect(component.contains(children)).toBe(true);
});
});
describe('WidgetToolbar.Item', () => {
it('allows passing an arbitrary class name', () => {
// Given
const component = shallow(
<WidgetToolbar.WidgetToolbar.Item className="test">
<span>It works!</span>
</WidgetToolbar.WidgetToolbar.Item>
);
// Then
expect(component.hasClass('test')).toBe(true);
});
it('renders a danger item', () => {
// Given
const component = shallow(
<WidgetToolbar.WidgetToolbar.Item danger>
<span>It works!</span>
</WidgetToolbar.WidgetToolbar.Item>
);
// Then
expect(component.hasClass('danger')).toBe(true);
});
it('renders the children', () => {
// Given
const children = <span>It works!</span>;
const component = shallow(
<WidgetToolbar.WidgetToolbar.Item>
{children}
</WidgetToolbar.WidgetToolbar.Item>
);
// Then
expect(component.contains(children)).toBe(true);
});
});
});

View File

@@ -0,0 +1,170 @@
import {
DashboardsContext, ServiceContainer, ServiceState,
} from '@bthlabs/homehub-core';
import {mount} from 'enzyme';
import React from 'react';
import {Dashboard, DashboardItem, DummyWidget} from 'src/main/components';
import * as DashboardContainer from 'src/main/containers/DashboardContainer';
import {DashboardsContextFactory} from 'tests/__fixtures__/dashboardsContext';
import {FakeWidget} from 'tests/__fixtures__/services';
import {SettingsFactory} from 'tests/__fixtures__/settings';
describe('src/main/containers/DashboardContainer', () => {
describe('ControlledDashboardContainer', () => {
let fakeDashboardsContext = null;
let fakeSettings = null;
beforeEach(() => {
fakeDashboardsContext = DashboardsContextFactory();
fakeSettings = SettingsFactory();
});
it('handles grid layout change', () => {
// Given
const component = mount(
<DashboardsContext.Provider value={fakeDashboardsContext}>
<DashboardContainer.ControlledDashboardContainer
settings={fakeSettings}
/>
</DashboardsContext.Provider>
);
// When
const dashboard = component.find(Dashboard).at(0);
dashboard.invoke('onGridLayoutChange')([
{i: 'fake_instance', x: 0, y: 0, w: 1, h: 1},
{i: 'other_fake_instance', x: 1, y: 1, w: 1, h: 1},
]);
// Then
expect(fakeDashboardsContext.saveServiceLayout).toHaveBeenCalledWith(
'fake_instance', {x: 0, y: 0, w: 1, h: 1}
);
expect(fakeDashboardsContext.saveServiceLayout).toHaveBeenCalledWith(
'other_fake_instance', {x: 1, y: 1, w: 1, h: 1}
);
});
it('configures and renders the dashboard', () => {
// Given
const component = mount(
<DashboardsContext.Provider value={fakeDashboardsContext}>
<DashboardContainer.ControlledDashboardContainer
settings={fakeSettings}
/>
</DashboardsContext.Provider>
);
const expectedLayout = [
{i: 'fake_instance', x: 0, y: 0, w: 1, h: 1, minW: 1, minH: 1},
{i: 'other_fake_instance', x: 0, y: 1, w: 1, h: 1},
];
// When
const dashboard = component.find(Dashboard).at(0);
// Then
expect(dashboard.exists()).toBe(true);
expect(dashboard.prop('layout')).toEqual(expectedLayout);
});
it('configures and render a ServiceContainer for services', () => {
// Given
const component = mount(
<DashboardsContext.Provider value={fakeDashboardsContext}>
<DashboardContainer.ControlledDashboardContainer
settings={fakeSettings}
/>
</DashboardsContext.Provider>
);
// When
const serviceContainers = component.find(ServiceContainer);
// Then
expect(serviceContainers.length).toEqual(2);
const serviceContainer = serviceContainers.at(0);
expect(serviceContainer.prop('instance')).toEqual(
fakeDashboardsContext.dashboards[0].services[0].instance
);
expect(serviceContainer.prop('kind')).toEqual(
fakeDashboardsContext.dashboards[0].services[0].kind
);
});
it('configures and renders a DashboardItem for services', () => {
// Given
const component = mount(
<DashboardsContext.Provider value={fakeDashboardsContext}>
<DashboardContainer.ControlledDashboardContainer
settings={fakeSettings}
/>
</DashboardsContext.Provider>
);
// When
const dashboardItems = component.find(DashboardItem);
// Then
expect(dashboardItems.length).toEqual(2);
const dashboardItem = dashboardItems.at(0);
expect(dashboardItem.prop('settingsView')).toEqual(
FakeWidget.settingsView
);
expect(dashboardItem.prop('settingsViewProps').settings).toEqual(
fakeSettings
);
expect(dashboardItems.at(1).prop('settingsView')).not.toBeDefined();
});
it('configures and renders a widget for services', () => {
// Given
const component = mount(
<DashboardsContext.Provider value={fakeDashboardsContext}>
<DashboardContainer.ControlledDashboardContainer
settings={fakeSettings}
/>
</DashboardsContext.Provider>
);
// When
const widget = component.find(FakeWidget).at(0);
// Then
expect(widget.exists()).toBe(true);
expect(widget.prop('appearance')).toEqual(
fakeDashboardsContext.dashboards[0].services[0].characteristics.appearance
);
expect(widget.prop('service')).toEqual(
fakeDashboardsContext.dashboards[0].services[0]
);
expect(widget.prop('serviceState')).toBeInstanceOf(ServiceState);
expect(widget.prop('setServiceState')).toBeDefined();
});
it('renders a DummyWidget for service with unknown widget', () => {
// Given
const component = mount(
<DashboardsContext.Provider value={fakeDashboardsContext}>
<DashboardContainer.ControlledDashboardContainer
settings={fakeSettings}
/>
</DashboardsContext.Provider>
);
// When
const widget = component.find(DummyWidget).at(0);
// Then
expect(widget.exists()).toBe(true);
expect(widget.prop('service')).toEqual(
fakeDashboardsContext.dashboards[0].services[1]
);
});
});
});

View File

@@ -0,0 +1,270 @@
import {DashboardsContext} from '@bthlabs/homehub-core';
import {RangoAppContext} from '@bthlabs/rango';
import {mount} from 'enzyme';
import React from 'react';
import {
AddDashboardModal, Taskbar, WidgetSettingsModal,
} from 'src/main/components';
import * as TaskbarContainer from 'src/main/containers/TaskbarContainer';
import {DashboardsContextFactory} from 'tests/__fixtures__/dashboardsContext';
import {
FakeService, FakeServiceWithoutSettings, FakeWidget,
} from 'tests/__fixtures__/services';
import {SettingsFactory} from 'tests/__fixtures__/settings';
describe('src/main/containers/TaskbarContainer', () => {
describe('TaskbarContainer', () => {
let fakeDashboardsContext = null;
let fakeSettings = null;
let fakeRangoAppContext = null;
beforeEach(() => {
fakeDashboardsContext = DashboardsContextFactory();
fakeSettings = SettingsFactory();
fakeRangoAppContext = {settings: fakeSettings};
});
it('configures the WidgetSettingsModal to show settings view for added service', () => {
// Given
const component = mount(
<RangoAppContext.Provider value={fakeRangoAppContext}>
<DashboardsContext.Provider value={fakeDashboardsContext}>
<TaskbarContainer.TaskbarContainer />
</DashboardsContext.Provider>
</RangoAppContext.Provider>
);
// When
component.find(Taskbar).at(0).invoke('onAddService')(FakeService.kind);
component.setProps({});
// Then
const widgetSettingsModal = component.find(WidgetSettingsModal).at(0);
expect(widgetSettingsModal.prop('settingsView')).toEqual(
FakeWidget.settingsView
);
expect(widgetSettingsModal.prop('settingsViewProps')).toEqual({
nextCharacteristics: FakeService.emptyCharacteristics(),
settings: fakeSettings,
setNextCharacteristics: jasmine.any(Function),
});
expect(fakeDashboardsContext.addService).not.toHaveBeenCalled();
});
it('immediately adds a service that does not use settings view', () => {
// Given
const component = mount(
<RangoAppContext.Provider value={fakeRangoAppContext}>
<DashboardsContext.Provider value={fakeDashboardsContext}>
<TaskbarContainer.TaskbarContainer />
</DashboardsContext.Provider>
</RangoAppContext.Provider>
);
// When
component.find(Taskbar).at(0).invoke('onAddService')(
FakeServiceWithoutSettings.kind
);
component.setProps({});
// Then
expect(fakeDashboardsContext.addService).toHaveBeenCalledWith(
FakeServiceWithoutSettings.kind,
FakeServiceWithoutSettings.emptyCharacteristics()
);
});
it('handles the WidgetSettingsModal being closed', () => {
// Given
const component = mount(
<RangoAppContext.Provider value={fakeRangoAppContext}>
<DashboardsContext.Provider value={fakeDashboardsContext}>
<TaskbarContainer.TaskbarContainer />
</DashboardsContext.Provider>
</RangoAppContext.Provider>
);
// When
component.find(Taskbar).at(0).invoke('onAddService')(FakeService.kind);
component.setProps({});
component.find(WidgetSettingsModal).at(0).invoke('onClose')();
component.setProps({});
// Then
const widgetSettingsModal = component.find(WidgetSettingsModal).at(0);
expect(widgetSettingsModal.prop('settingsView')).toBe(null);
expect(widgetSettingsModal.prop('settingsViewProps')).toEqual({});
});
it('handles the WidgetSettingsModal save button click', () => {
// Given
const component = mount(
<RangoAppContext.Provider value={fakeRangoAppContext}>
<DashboardsContext.Provider value={fakeDashboardsContext}>
<TaskbarContainer.TaskbarContainer />
</DashboardsContext.Provider>
</RangoAppContext.Provider>
);
// When
component.find(Taskbar).at(0).invoke('onAddService')(FakeService.kind);
component.setProps({});
component.find(WidgetSettingsModal).at(0).invoke('onSaveButtonClick')();
component.setProps({});
// Then
expect(fakeDashboardsContext.addService).toHaveBeenCalledWith(
FakeService.kind,
FakeService.emptyCharacteristics()
);
});
it('displays the AddDashboardModal when add dashboard button is clicked', () => {
// Given
const component = mount(
<RangoAppContext.Provider value={fakeRangoAppContext}>
<DashboardsContext.Provider value={fakeDashboardsContext}>
<TaskbarContainer.TaskbarContainer />
</DashboardsContext.Provider>
</RangoAppContext.Provider>
);
// When
component.find(Taskbar).at(0).invoke('onAddDashboard')();
// Then
const addDashboardModal = component.find(AddDashboardModal).at(0);
expect(addDashboardModal.prop('show')).toBe(true);
});
it('hides the AddDashboardModal when it is closed', () => {
// Given
const component = mount(
<RangoAppContext.Provider value={fakeRangoAppContext}>
<DashboardsContext.Provider value={fakeDashboardsContext}>
<TaskbarContainer.TaskbarContainer />
</DashboardsContext.Provider>
</RangoAppContext.Provider>
);
// When
component.find(Taskbar).at(0).invoke('onAddDashboard')();
component.find(AddDashboardModal).at(0).invoke('onClose')();
// Then
const addDashboardModal = component.find(AddDashboardModal).at(0);
expect(addDashboardModal.prop('show')).toBe(false);
});
it('handles the AddDashboardModal save button click', () => {
// Given
const component = mount(
<RangoAppContext.Provider value={fakeRangoAppContext}>
<DashboardsContext.Provider value={fakeDashboardsContext}>
<TaskbarContainer.TaskbarContainer />
</DashboardsContext.Provider>
</RangoAppContext.Provider>
);
// When
component.find(AddDashboardModal).at(0).invoke('onSave')('Testing2');
// Then
expect(fakeDashboardsContext.addDashboard).toHaveBeenCalledWith(
'Testing2'
);
});
it('sets a selected dashboard as current', () => {
// Given
const component = mount(
<RangoAppContext.Provider value={fakeRangoAppContext}>
<DashboardsContext.Provider value={fakeDashboardsContext}>
<TaskbarContainer.TaskbarContainer />
</DashboardsContext.Provider>
</RangoAppContext.Provider>
);
// When
component.find(Taskbar).at(0).invoke('onSelectDashboard')('testing2');
// Then
expect(fakeDashboardsContext.setCurrentDashboardId).toHaveBeenCalledWith(
'testing2'
);
});
it('configures and renders the Taskbar', () => {
// Given
const component = mount(
<RangoAppContext.Provider value={fakeRangoAppContext}>
<DashboardsContext.Provider value={fakeDashboardsContext}>
<TaskbarContainer.TaskbarContainer />
</DashboardsContext.Provider>
</RangoAppContext.Provider>
);
// When
const taskbar = component.find(Taskbar).at(0);
// Then
expect(taskbar.exists()).toBe(true);
expect(taskbar.prop('currentDashboardId')).toEqual(
fakeDashboardsContext.currentDashboardId
);
expect(taskbar.prop('dashboards')).toEqual(
fakeDashboardsContext.dashboards
);
expect(taskbar.prop('offlineMode')).toEqual(fakeSettings.OFFLINE_MODE);
expect(taskbar.prop('savingState')).toEqual({
isSaving: false,
lastSaveError: null,
lastSaveTimestamp: null,
});
expect(taskbar.prop('services')).toEqual(fakeSettings.SERVICES);
expect(taskbar.prop('webSocketState')).toEqual({
isWebSocketConnected: false,
});
expect(taskbar.prop('widgets')).toEqual(fakeSettings.WIDGETS);
});
it('configures and renders the WidgetSettingsModal', () => {
// Given
const component = mount(
<RangoAppContext.Provider value={fakeRangoAppContext}>
<DashboardsContext.Provider value={fakeDashboardsContext}>
<TaskbarContainer.TaskbarContainer />
</DashboardsContext.Provider>
</RangoAppContext.Provider>
);
// When
const widgetSettingsModal = component.find(WidgetSettingsModal).at(0);
// Then
expect(widgetSettingsModal.exists()).toBe(true);
expect(widgetSettingsModal.prop('show')).toBe(true);
});
it('configures and renders the AddDashboardModal', () => {
// Given
const component = mount(
<RangoAppContext.Provider value={fakeRangoAppContext}>
<DashboardsContext.Provider value={fakeDashboardsContext}>
<TaskbarContainer.TaskbarContainer />
</DashboardsContext.Provider>
</RangoAppContext.Provider>
);
// When
const addDashboardModal = component.find(AddDashboardModal).at(0);
// Then
expect(addDashboardModal.exists()).toBe(true);
});
});
});

View File

@@ -0,0 +1,147 @@
import * as HomeHubCore from '@bthlabs/homehub-core';
import * as StateDataSource from 'src/main/dataSources/StateDataSource';
describe('src/lib/main/dataSources/StateDataSource', () => {
beforeEach(() => {
spyOn(HomeHubCore.API.State, 'get');
spyOn(HomeHubCore.API.State, 'save');
spyOn(HomeHubCore.LocalStorage, 'getItem');
spyOn(HomeHubCore.LocalStorage, 'setItem');
});
afterEach(() => {
StateDataSource.setOfflineMode(false);
});
describe('loadState', () => {
it('throws an error if API call in online mode returns an error', async () => {
// Given
StateDataSource.setOfflineMode(false);
HomeHubCore.API.State.get.and.resolveTo({
error: 'FIAL',
});
// When
let result = null;
try {
await StateDataSource.loadState();
} catch (error) {
result = error;
}
// Then
expect(result).toEqual('FIAL');
});
it('returns state loaded from the API in online mode', async () => {
// Given
StateDataSource.setOfflineMode(false);
const data = {dashboards: []};
HomeHubCore.API.State.get.and.resolveTo({
data: data,
});
// When
const result = await StateDataSource.loadState();
// Then
expect(result).toEqual(data);
expect(HomeHubCore.API.State.get).toHaveBeenCalled();
expect(HomeHubCore.LocalStorage.getItem).not.toHaveBeenCalled();
});
it('returns state loaded from local storage in offline mode', async () => {
// Given
StateDataSource.setOfflineMode(true);
const data = {dashboards: []};
HomeHubCore.LocalStorage.getItem.and.returnValue(JSON.stringify(data));
// When
const result = await StateDataSource.loadState();
// Then
expect(result).toEqual(data);
expect(HomeHubCore.API.State.get).not.toHaveBeenCalled();
expect(HomeHubCore.LocalStorage.getItem).toHaveBeenCalledWith('state');
});
it('returns initial state if it is missing in local storage in offline mode', async () => {
// Given
StateDataSource.setOfflineMode(true);
HomeHubCore.LocalStorage.getItem.and.returnValue(null);
// When
const result = await StateDataSource.loadState();
// Then
expect(result.dashboards.length).toEqual(1);
});
});
describe('doSaveState', () => {
let fakeState = null;
beforeEach(() => {
fakeState = {
dashboards: [
{
id: 'testing',
name: 'Testing',
services: [],
},
],
};
});
it('throws an error if API call in online mode returns an error', async () => {
// Given
StateDataSource.setOfflineMode(false);
HomeHubCore.API.State.save.and.resolveTo({
error: 'FIAL',
});
// When
let result = null;
try {
result = await StateDataSource.doSaveState(fakeState);
} catch (error) {
result = error;
}
// Then
expect(result).toEqual('FIAL');
});
it('returns the result of the API call in online mode', async () => {
// Given
StateDataSource.setOfflineMode(false);
HomeHubCore.API.State.save.and.resolveTo({
data: true,
});
// When
const result = await StateDataSource.doSaveState(fakeState);
// Then
expect(result).toBe(true);
expect(HomeHubCore.API.State.save).toHaveBeenCalledWith(fakeState);
expect(HomeHubCore.LocalStorage.setItem).not.toHaveBeenCalled();
});
it('returns the result of local storage save operation in offline mode', async () => {
// Given
StateDataSource.setOfflineMode(true);
// When
const result = await StateDataSource.doSaveState(fakeState);
// Then
expect(result).toBe(true);
expect(HomeHubCore.API.State.save).not.toHaveBeenCalled();
expect(HomeHubCore.LocalStorage.setItem).toHaveBeenCalledWith(
'state', JSON.stringify(fakeState)
);
});
});
});

View File

@@ -0,0 +1,101 @@
import {DashboardsProvider} from '@bthlabs/homehub-core';
import {shallow} from 'enzyme';
import React from 'react';
import {DashboardContainer, TaskbarContainer} from 'src/main/containers';
import {StateDataSource} from 'src/main/dataSources';
import * as AppView from 'src/main/views/AppView';
import {SettingsFactory} from 'tests/__fixtures__/settings';
describe('src/main/views/AppView', () => {
describe('AppView', () => {
let fakeActions = null;
let fakeSetings = null;
beforeEach(() => {
fakeActions = {
setDocumentTitle: jasmine.createSpy(),
};
fakeSetings = SettingsFactory();
});
describe('componentDidMount', () => {
it('calls the setDocumentTitle action', () => {
// Given
const component = shallow(
<AppView.AppView
actions={fakeActions}
settings={fakeSetings}
/>
);
// When
component.instance().componentDidMount();
// Then
expect(fakeActions.setDocumentTitle).toHaveBeenCalledWith(
jasmine.any(String)
);
});
});
describe('render', () => {
it('configures and renders the DashboardsProvider', () => {
// Given
const component = shallow(
<AppView.AppView
actions={fakeActions}
settings={fakeSetings}
/>
);
// When
const dashboardsProvider = component.find(DashboardsProvider).at(0);
// Then
expect(dashboardsProvider.exists()).toBe(true);
expect(dashboardsProvider.prop('loader')).toBeDefined();
expect(dashboardsProvider.prop('loadDashboards')).toEqual(
StateDataSource.loadState
);
expect(dashboardsProvider.prop('saveDashboards')).toEqual(
StateDataSource.saveState
);
expect(dashboardsProvider.prop('settings')).toEqual(fakeSetings);
});
it('configures and renders the DashboardContainer', () => {
// Given
const component = shallow(
<AppView.AppView
actions={fakeActions}
settings={fakeSetings}
/>
);
// When
const dashboardContainer = component.find(DashboardContainer).at(0);
// Then
expect(dashboardContainer.exists()).toBe(true);
});
it('configures and renders the TaskbarContainer', () => {
// Given
const component = shallow(
<AppView.AppView
actions={fakeActions}
settings={fakeSetings}
/>
);
// When
const taskbarContainer = component.find(TaskbarContainer).at(0);
// Then
expect(taskbarContainer.exists()).toBe(true);
});
});
});
});

View File

@@ -0,0 +1,86 @@
import {shallow} from 'enzyme';
import React from 'react';
import * as ErrorBoundaryView from 'src/main/views/ErrorBoundaryView';
describe('src/main/views/ErrorBoundaryView', () => {
describe('ErrorBoundaryView', () => {
let fakeError = null;
beforeEach(() => {
fakeError = new Error('FIAL');
});
describe('constructor', () => {
it('initializes the state', () => {
// Given
const component = shallow(
<ErrorBoundaryView.ErrorBoundaryView>
<span>It works!</span>
</ErrorBoundaryView.ErrorBoundaryView>
);
// Then
expect(component.state('error')).toBe(null);
});
});
describe('componentDidCatch', () => {
it('updates the state with error', () => {
// Given
const component = shallow(
<ErrorBoundaryView.ErrorBoundaryView>
<span>It works!</span>
</ErrorBoundaryView.ErrorBoundaryView>
);
// When
component.instance().componentDidCatch(fakeError);
// Then
expect(component.state('error')).toEqual(fakeError);
});
});
describe('render', () => {
let fakeChildren = null;
beforeEach(() => {
fakeChildren = <span>It works!</span>;
});
it('renders the children when error is null', () => {
// Given
const component = shallow(
<ErrorBoundaryView.ErrorBoundaryView>
{fakeChildren}
</ErrorBoundaryView.ErrorBoundaryView>
);
// When
component.setState({error: null});
// Then
expect(component.contains(fakeChildren)).toBe(true);
expect(component.contains('.ErrorBoundaryView')).toBe(false);
});
it('renders the error view when error is not null', () => {
// Given
const component = shallow(
<ErrorBoundaryView.ErrorBoundaryView>
{fakeChildren}
</ErrorBoundaryView.ErrorBoundaryView>
);
// When
component.setState({error: fakeError});
// Then
expect(component.contains(fakeChildren)).toBe(false);
expect(component.hasClass('ErrorBoundaryView')).toBe(true);
expect(component.find('p').at(1).text()).toMatch(fakeError.message);
});
});
});
});