568 lines
17 KiB
JavaScript
568 lines
17 KiB
JavaScript
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 as read-only', () => {
|
|
// Given
|
|
fakeSettings.READ_ONLY = true;
|
|
|
|
// When
|
|
const component = shallow(
|
|
<StartMenu.ControlledStartMenu
|
|
hasDashboards={true}
|
|
offlineMode={false}
|
|
services={SERVICES}
|
|
settings={fakeSettings}
|
|
widgets={WIDGETS}
|
|
onAddDashboard={mockOnAddDashboard}
|
|
onAddService={mockOnAddService}
|
|
/>
|
|
);
|
|
|
|
// Then
|
|
expect(component.find('div[_hint="StartMenu"]').hasClass('read-only')).toBe(true);
|
|
expect(component.find('div[_hint="AddDashboard"]').exists()).toBe(false);
|
|
expect(component.find('div[_hint="Widgets"]').exists()).toBe(false);
|
|
});
|
|
|
|
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);
|
|
});
|
|
});
|
|
});
|