390 lines
12 KiB
JavaScript
390 lines
12 KiB
JavaScript
|
import {FatalError, Widget} from '@bthlabs/homehub-components';
|
||
|
import {ServiceState} from '@bthlabs/homehub-core';
|
||
|
import {DateTime} from 'luxon';
|
||
|
import {shallow} from 'enzyme';
|
||
|
import React from 'react';
|
||
|
import {Form} from 'react-bootstrap';
|
||
|
|
||
|
import {IFormicariumService} from 'src/IFormicariumService';
|
||
|
import * as IFormicariumWidgetView from 'src/IFormicariumWidgetView';
|
||
|
|
||
|
import {IFormicariumDataFactory} from 'tests/__fixtures__/iformicarium';
|
||
|
|
||
|
describe('src/widgets/IFormicariumWidgetView', () => {
|
||
|
describe('IFormicariumWidgetSettingsView', () => {
|
||
|
let fakeNextCharacteristics = null;
|
||
|
let mockSetNextCharacteristics = null;
|
||
|
|
||
|
beforeEach(() => {
|
||
|
fakeNextCharacteristics = {
|
||
|
mqtt: '',
|
||
|
name: '',
|
||
|
topic: '',
|
||
|
};
|
||
|
mockSetNextCharacteristics = jasmine.createSpy();
|
||
|
});
|
||
|
|
||
|
it('calls the setNextCharacteristics callback when mqtt input changes', () => {
|
||
|
// Given
|
||
|
const component = shallow(
|
||
|
<IFormicariumWidgetView.IFormicariumWidgetSettingsView
|
||
|
nextCharacteristics={fakeNextCharacteristics}
|
||
|
setNextCharacteristics={mockSetNextCharacteristics}
|
||
|
/>
|
||
|
);
|
||
|
|
||
|
// When
|
||
|
component.find(Form.Control).at(0).simulate('change', {
|
||
|
target: {value: 'thisisntright.local'},
|
||
|
});
|
||
|
|
||
|
// Then
|
||
|
expect(mockSetNextCharacteristics).toHaveBeenCalledWith({
|
||
|
...fakeNextCharacteristics,
|
||
|
mqtt: 'thisisntright.local',
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('calls the setNextCharacteristics callback when name input changes', () => {
|
||
|
// Given
|
||
|
const component = shallow(
|
||
|
<IFormicariumWidgetView.IFormicariumWidgetSettingsView
|
||
|
nextCharacteristics={fakeNextCharacteristics}
|
||
|
setNextCharacteristics={mockSetNextCharacteristics}
|
||
|
/>
|
||
|
);
|
||
|
|
||
|
// When
|
||
|
component.find(Form.Control).at(1).simulate('change', {
|
||
|
target: {value: 'iformicarium'},
|
||
|
});
|
||
|
|
||
|
// Then
|
||
|
expect(mockSetNextCharacteristics).toHaveBeenCalledWith({
|
||
|
...fakeNextCharacteristics,
|
||
|
name: 'iformicarium',
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('calls the setNextCharacteristics callback when topic input changes', () => {
|
||
|
// Given
|
||
|
const component = shallow(
|
||
|
<IFormicariumWidgetView.IFormicariumWidgetSettingsView
|
||
|
nextCharacteristics={fakeNextCharacteristics}
|
||
|
setNextCharacteristics={mockSetNextCharacteristics}
|
||
|
/>
|
||
|
);
|
||
|
|
||
|
// When
|
||
|
component.find(Form.Control).at(2).simulate('change', {
|
||
|
target: {value: 'iformicarium'},
|
||
|
});
|
||
|
|
||
|
// Then
|
||
|
expect(mockSetNextCharacteristics).toHaveBeenCalledWith({
|
||
|
...fakeNextCharacteristics,
|
||
|
topic: 'iformicarium',
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('renders empty when nextCharacteristics is empty', () => {
|
||
|
// Given
|
||
|
fakeNextCharacteristics = null;
|
||
|
const component = shallow(
|
||
|
<IFormicariumWidgetView.IFormicariumWidgetSettingsView
|
||
|
nextCharacteristics={fakeNextCharacteristics}
|
||
|
setNextCharacteristics={mockSetNextCharacteristics}
|
||
|
/>
|
||
|
);
|
||
|
|
||
|
// Then
|
||
|
expect(component.isEmptyRender()).toBe(true);
|
||
|
});
|
||
|
|
||
|
it('configures and renders the city input', () => {
|
||
|
// Given
|
||
|
fakeNextCharacteristics = {
|
||
|
...fakeNextCharacteristics,
|
||
|
mqtt: 'thisisntright.local',
|
||
|
name: 'iformicarium',
|
||
|
topic: 'iformicarium',
|
||
|
};
|
||
|
const component = shallow(
|
||
|
<IFormicariumWidgetView.IFormicariumWidgetSettingsView
|
||
|
nextCharacteristics={fakeNextCharacteristics}
|
||
|
setNextCharacteristics={mockSetNextCharacteristics}
|
||
|
/>
|
||
|
);
|
||
|
|
||
|
// When
|
||
|
const input = component.find(Form.Control).at(0);
|
||
|
|
||
|
// Then
|
||
|
expect(input.exists()).toBe(true);
|
||
|
expect(input.prop('value')).toEqual(fakeNextCharacteristics.mqtt);
|
||
|
});
|
||
|
|
||
|
it('configures and renders the name input', () => {
|
||
|
// Given
|
||
|
fakeNextCharacteristics = {
|
||
|
...fakeNextCharacteristics,
|
||
|
mqtt: 'thisisntright.local',
|
||
|
name: 'iformicarium',
|
||
|
topic: 'iformicarium',
|
||
|
};
|
||
|
const component = shallow(
|
||
|
<IFormicariumWidgetView.IFormicariumWidgetSettingsView
|
||
|
nextCharacteristics={fakeNextCharacteristics}
|
||
|
setNextCharacteristics={mockSetNextCharacteristics}
|
||
|
/>
|
||
|
);
|
||
|
|
||
|
// When
|
||
|
const input = component.find(Form.Control).at(1);
|
||
|
|
||
|
// Then
|
||
|
expect(input.exists()).toBe(true);
|
||
|
expect(input.prop('value')).toEqual(fakeNextCharacteristics.name);
|
||
|
});
|
||
|
|
||
|
it('configures and renders the topic input', () => {
|
||
|
// Given
|
||
|
fakeNextCharacteristics = {
|
||
|
...fakeNextCharacteristics,
|
||
|
mqtt: 'thisisntright.local',
|
||
|
name: 'iformicarium',
|
||
|
topic: 'iformicarium',
|
||
|
};
|
||
|
const component = shallow(
|
||
|
<IFormicariumWidgetView.IFormicariumWidgetSettingsView
|
||
|
nextCharacteristics={fakeNextCharacteristics}
|
||
|
setNextCharacteristics={mockSetNextCharacteristics}
|
||
|
/>
|
||
|
);
|
||
|
|
||
|
// When
|
||
|
const input = component.find(Form.Control).at(2);
|
||
|
|
||
|
// Then
|
||
|
expect(input.exists()).toBe(true);
|
||
|
expect(input.prop('value')).toEqual(fakeNextCharacteristics.topic);
|
||
|
});
|
||
|
});
|
||
|
|
||
|
describe('IFormicariumWidgetView', () => {
|
||
|
let fakeAppearance = null;
|
||
|
let fakeDateTime = null;
|
||
|
let fakeService = null;
|
||
|
let fakeServiceState = null;
|
||
|
let fakeData = null;
|
||
|
|
||
|
beforeEach(() => {
|
||
|
fakeAppearance = {color: 'red'};
|
||
|
fakeDateTime = DateTime.local(1987, 10, 3, 8, 0, 0);
|
||
|
fakeService = new IFormicariumService({
|
||
|
instance: 'testing',
|
||
|
layout: {x: 0, y: 0, h: 1, w: 1},
|
||
|
});
|
||
|
fakeData = IFormicariumDataFactory();
|
||
|
fakeServiceState = new ServiceState({
|
||
|
data: fakeData,
|
||
|
});
|
||
|
|
||
|
spyOn(DateTime, 'fromSeconds').and.returnValue(fakeDateTime);
|
||
|
spyOn(fakeDateTime, 'toLocaleString').and.returnValue(
|
||
|
'Formatted DateTime'
|
||
|
);
|
||
|
});
|
||
|
|
||
|
it('defines the widget attributes', () => {
|
||
|
// Then
|
||
|
expect(IFormicariumWidgetView.IFormicariumWidgetView.defaultLayout).toEqual({
|
||
|
h: jasmine.any(Number),
|
||
|
w: jasmine.any(Number),
|
||
|
});
|
||
|
expect(IFormicariumWidgetView.IFormicariumWidgetView.icon).toBeDefined();
|
||
|
expect(IFormicariumWidgetView.IFormicariumWidgetView.layoutConstraints).toEqual({
|
||
|
minH: jasmine.any(Number),
|
||
|
minW: jasmine.any(Number),
|
||
|
});
|
||
|
expect(IFormicariumWidgetView.IFormicariumWidgetView.settingsView).toEqual(
|
||
|
IFormicariumWidgetView.IFormicariumWidgetSettingsView
|
||
|
);
|
||
|
expect(IFormicariumWidgetView.IFormicariumWidgetView.title).toEqual('iFormicarium');
|
||
|
});
|
||
|
|
||
|
it('renders empty when service state is null', () => {
|
||
|
// Given
|
||
|
fakeServiceState = null;
|
||
|
const component = shallow(
|
||
|
<IFormicariumWidgetView.IFormicariumWidgetView
|
||
|
appearance={fakeAppearance}
|
||
|
service={fakeService}
|
||
|
serviceState={fakeServiceState}
|
||
|
/>
|
||
|
);
|
||
|
|
||
|
// Then
|
||
|
expect(component.isEmptyRender()).toBe(true);
|
||
|
});
|
||
|
|
||
|
it('configures and renders the Widget', () => {
|
||
|
// Given
|
||
|
const component = shallow(
|
||
|
<IFormicariumWidgetView.IFormicariumWidgetView
|
||
|
appearance={fakeAppearance}
|
||
|
service={fakeService}
|
||
|
serviceState={fakeServiceState}
|
||
|
/>
|
||
|
);
|
||
|
|
||
|
// When
|
||
|
const widget = component.find(Widget).at(0);
|
||
|
|
||
|
// Then
|
||
|
expect(widget.exists()).toBe(true);
|
||
|
expect(widget.prop('appearance')).toEqual(fakeAppearance);
|
||
|
});
|
||
|
|
||
|
it('renders the loader when state is loading', () => {
|
||
|
// Given
|
||
|
spyOn(fakeServiceState, 'isLoading').and.returnValue(true);
|
||
|
const component = shallow(
|
||
|
<IFormicariumWidgetView.IFormicariumWidgetView
|
||
|
appearance={fakeAppearance}
|
||
|
service={fakeService}
|
||
|
serviceState={fakeServiceState}
|
||
|
/>
|
||
|
);
|
||
|
|
||
|
// When
|
||
|
const loader = component.find('Icon[_hint="Loader"]').at(0);
|
||
|
|
||
|
// Then
|
||
|
expect(loader.exists()).toBe(true);
|
||
|
expect(loader.prop('icon')).toBeDefined();
|
||
|
});
|
||
|
|
||
|
it('does not render the loader when state is not loading', () => {
|
||
|
// Given
|
||
|
const component = shallow(
|
||
|
<IFormicariumWidgetView.IFormicariumWidgetView
|
||
|
appearance={fakeAppearance}
|
||
|
service={fakeService}
|
||
|
serviceState={fakeServiceState}
|
||
|
/>
|
||
|
);
|
||
|
|
||
|
// When
|
||
|
const loader = component.find('Icon[_hint="Loader"]').at(0);
|
||
|
|
||
|
// Then
|
||
|
expect(loader.exists()).toBe(false);
|
||
|
});
|
||
|
|
||
|
it('does not compute and render instance info when service state has no data', () => {
|
||
|
// Given
|
||
|
spyOn(fakeServiceState, 'hasData').and.returnValue(false);
|
||
|
const component = shallow(
|
||
|
<IFormicariumWidgetView.IFormicariumWidgetView
|
||
|
appearance={fakeAppearance}
|
||
|
service={fakeService}
|
||
|
serviceState={fakeServiceState}
|
||
|
/>
|
||
|
);
|
||
|
|
||
|
// When
|
||
|
const instanceInfo = component.find('div[_hint="InstanceInfo"]').at(0);
|
||
|
|
||
|
// Then
|
||
|
expect(instanceInfo.exists()).toBe(false);
|
||
|
});
|
||
|
|
||
|
it('computes and renders instance info when service state has data', () => {
|
||
|
// Given
|
||
|
const component = shallow(
|
||
|
<IFormicariumWidgetView.IFormicariumWidgetView
|
||
|
appearance={fakeAppearance}
|
||
|
service={fakeService}
|
||
|
serviceState={fakeServiceState}
|
||
|
/>
|
||
|
);
|
||
|
|
||
|
// When
|
||
|
const instanceInfo = component.find('div[_hint="InstanceInfo"]').at(0);
|
||
|
|
||
|
// Then
|
||
|
expect(instanceInfo.exists()).toBe(true);
|
||
|
|
||
|
const instanceName = component.find('h5[_hint="InstanceName"]').at(0);
|
||
|
expect(instanceName.exists()).toBe(true);
|
||
|
expect(instanceName.text()).toEqual(fakeData.name);
|
||
|
|
||
|
const instanceMetrics = component.find('div[_hint="InstanceMetrics"]').at(0);
|
||
|
expect(instanceMetrics.exists()).toBe(true);
|
||
|
|
||
|
const instanceDHTMetric = instanceMetrics.find('div[_hint="InstanceDHTMetric"]').at(0);
|
||
|
expect(instanceDHTMetric.exists()).toBe(true);
|
||
|
expect(instanceDHTMetric.find('p').at(0).text()).toEqual(
|
||
|
fakeData.dht['0'].name
|
||
|
);
|
||
|
expect(instanceDHTMetric.find('p').at(1).text()).toContain(
|
||
|
`Temp: ${fakeData.dht['0'].temp}`
|
||
|
);
|
||
|
expect(instanceDHTMetric.find('p').at(2).text()).toEqual(
|
||
|
`Humi: ${fakeData.dht['0'].humi}%`
|
||
|
);
|
||
|
|
||
|
const instanceFanMetric = instanceMetrics.find('div[_hint="InstanceFanMetric"]').at(0);
|
||
|
expect(instanceFanMetric.exists()).toBe(true);
|
||
|
expect(instanceFanMetric.find('p').at(1).text()).toEqual('25%');
|
||
|
|
||
|
const lastUpdate = component.find('small[_hint="LastUpdate"]').at(0);
|
||
|
expect(lastUpdate.exists()).toBe(true);
|
||
|
expect(lastUpdate.text()).toContain('Formatted DateTime');
|
||
|
|
||
|
expect(DateTime.fromSeconds).toHaveBeenCalledWith(fakeData.dt);
|
||
|
expect(fakeDateTime.toLocaleString).toHaveBeenCalledWith(
|
||
|
DateTime.TIME_SIMPLE
|
||
|
);
|
||
|
});
|
||
|
|
||
|
it('does not render FatalError if service state has no fatal error', () => {
|
||
|
// Given
|
||
|
const component = shallow(
|
||
|
<IFormicariumWidgetView.IFormicariumWidgetView
|
||
|
appearance={fakeAppearance}
|
||
|
service={fakeService}
|
||
|
serviceState={fakeServiceState}
|
||
|
/>
|
||
|
);
|
||
|
|
||
|
// When
|
||
|
const fatalError = component.find(FatalError).at(0);
|
||
|
|
||
|
// Then
|
||
|
expect(fatalError.exists()).toBe(false);
|
||
|
});
|
||
|
|
||
|
it('configures and renders FatalError if service state has fatal error', () => {
|
||
|
// Given
|
||
|
spyOn(fakeServiceState, 'hasFatalError').and.returnValue(true);
|
||
|
const component = shallow(
|
||
|
<IFormicariumWidgetView.IFormicariumWidgetView
|
||
|
appearance={fakeAppearance}
|
||
|
service={fakeService}
|
||
|
serviceState={fakeServiceState}
|
||
|
/>
|
||
|
);
|
||
|
|
||
|
// When
|
||
|
const fatalError = component.find(FatalError).at(0);
|
||
|
|
||
|
// Then
|
||
|
expect(fatalError.exists()).toBe(true);
|
||
|
expect(fatalError.prop('service')).toEqual(fakeService);
|
||
|
expect(fatalError.prop('serviceState')).toEqual(fakeServiceState);
|
||
|
});
|
||
|
});
|
||
|
});
|