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 'src/components'; import * as WeatherWidgetView from 'src/widgets/WeatherWidgetView'; import {FakeService} from 'tests/__fixtures__/services'; import {SettingsFactory} from 'tests/__fixtures__/settings'; import {WeatherFactory} from 'tests/__fixtures__/weather'; describe('src/widgets/WeatherWidgetView', () => { describe('WeatherWidgetSettingsView', () => { let fakeNextCharacteristics = null; let fakeSettings = null; let mockSetNextCharacteristics = null; beforeEach(() => { fakeNextCharacteristics = { city: '', units: '', apiKey: '', }; fakeSettings = SettingsFactory(); mockSetNextCharacteristics = jasmine.createSpy(); }); it('calls the setNextCharacteristics callback when city input changes', () => { // Given const component = shallow( ); // When component.find(Form.Control).at(0).simulate('change', { target: {value: 'Wroclaw,PL'}, }); // Then expect(mockSetNextCharacteristics).toHaveBeenCalledWith({ ...fakeNextCharacteristics, city: 'Wroclaw,PL', }); }); it('calls the setNextCharacteristics callback when units input changes', () => { // Given const component = shallow( ); // When component.find(Form.Control).at(1).simulate('change', { target: {value: 'imperial'}, }); // Then expect(mockSetNextCharacteristics).toHaveBeenCalledWith({ ...fakeNextCharacteristics, units: 'imperial', }); }); it('calls the setNextCharacteristics callback when API key input changes', () => { // Given const component = shallow( ); // When component.find(Form.Control).at(2).simulate('change', { target: {value: 'thisisntright'}, }); // Then expect(mockSetNextCharacteristics).toHaveBeenCalledWith({ ...fakeNextCharacteristics, apiKey: 'thisisntright', }); }); it('renders empty when nextCharacteristics is empty', () => { // Given fakeNextCharacteristics = null; const component = shallow( ); // Then expect(component.isEmptyRender()).toBe(true); }); it('configures and renders the city input', () => { // Given fakeNextCharacteristics = { ...fakeNextCharacteristics, city: 'Wroclaw,PL', units: 'metric', apiKey: 'thisisntright', }; const component = shallow( ); // When const input = component.find(Form.Control).at(0); // Then expect(input.exists()).toBe(true); expect(input.prop('value')).toEqual(fakeNextCharacteristics.city); }); it('configures and renders the units input', () => { // Given fakeNextCharacteristics = { ...fakeNextCharacteristics, city: 'Wroclaw,PL', units: 'metric', apiKey: 'thisisntright', }; const component = shallow( ); // When const input = component.find(Form.Control).at(1); // Then expect(input.exists()).toBe(true); expect(input.prop('value')).toEqual(fakeNextCharacteristics.units); }); it('configures and renders the API key input', () => { // Given fakeNextCharacteristics = { ...fakeNextCharacteristics, city: 'Wroclaw,PL', units: 'metric', apiKey: 'thisisntright', }; const component = shallow( ); // When const input = component.find(Form.Control).at(2); // Then expect(input.exists()).toBe(true); expect(input.prop('value')).toEqual(fakeNextCharacteristics.apiKey); }); it('does not render the API key input if it is missing in characteristics', () => { // Given fakeNextCharacteristics = { city: 'Wroclaw,PL', units: 'metric', }; const component = shallow( ); // When const input = component.find(Form.Control).at(2); // Then expect(input.exists()).toBe(false); }); }); describe('WeatherWidgetView', () => { let fakeAppearance = null; let fakeDateTime = null; let fakeService = null; let fakeServiceState = null; let fakeWeather = null; beforeEach(() => { fakeAppearance = {color: 'red'}; fakeDateTime = DateTime.local(1987, 10, 3, 8, 0, 0); fakeService = new FakeService({ instance: 'testing', layout: {x: 0, y: 0, h: 1, w: 1}, }); fakeWeather = WeatherFactory(); fakeServiceState = new ServiceState({ data: fakeWeather, }); spyOn(DateTime, 'fromSeconds').and.returnValue(fakeDateTime); spyOn(fakeDateTime, 'toLocaleString').and.returnValue( 'Formatted DateTime' ); }); it('defines the widget attributes', () => { // Then expect(WeatherWidgetView.WeatherWidgetView.defaultLayout).toEqual({ h: jasmine.any(Number), w: jasmine.any(Number), }); expect(WeatherWidgetView.WeatherWidgetView.icon).toBeDefined(); expect(WeatherWidgetView.WeatherWidgetView.layoutConstraints).toEqual({ minH: jasmine.any(Number), minW: jasmine.any(Number), }); expect(WeatherWidgetView.WeatherWidgetView.settingsView).toEqual( WeatherWidgetView.WeatherWidgetSettingsView ); expect(WeatherWidgetView.WeatherWidgetView.title).toEqual('Weather'); }); it('renders empty when service state is null', () => { // Given fakeServiceState = null; const component = shallow( ); // Then expect(component.isEmptyRender()).toBe(true); }); it('configures and renders the Widget', () => { // Given const component = shallow( ); // When const widget = component.find(Widget).at(0); // Then expect(widget.exists()).toBe(true); expect(widget.prop('appearance')).toEqual(fakeAppearance); expect(widget.prop('instance')).toEqual(fakeService.instance); expect(widget.prop('kind')).toEqual(fakeService.kind); expect(widget.prop('layout')).toEqual(fakeService.layout); }); it('renders the loader when state is loading', () => { // Given spyOn(fakeServiceState, 'isLoading').and.returnValue(true); const component = shallow( ); // 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( ); // When const loader = component.find('Icon[_hint="Loader"]').at(0); // Then expect(loader.exists()).toBe(false); }); it('does not compute and render weather info when service state has no data', () => { // Given spyOn(fakeServiceState, 'hasData').and.returnValue(false); const component = shallow( ); // When const weatherInfo = component.find('div[_hint="WeatherInfo"]').at(0); // Then expect(weatherInfo.exists()).toBe(false); }); it('computes and renders weather info when service state has data', () => { // Given const component = shallow( ); // When const weatherInfo = component.find('div[_hint="WeatherInfo"]').at(0); // Then expect(weatherInfo.exists()).toBe(true); const weatherIcon = component.find('Icon[_hint="WeatherIcon"]').at(0); expect(weatherIcon.exists()).toBe(true); expect(weatherIcon.prop('icon')).toBeDefined(); const weatherName = component.find('h5[_hint="WeatherName"]').at(0); expect(weatherName.exists()).toBe(true); expect(weatherName.text()).toEqual(fakeWeather.name); const weatherDescription = component.find('h6[_hint="WeatherDescription"]').at(0); expect(weatherDescription.exists()).toBe(true); expect(weatherDescription.text()).toEqual( fakeWeather.weather[0].description ); const weatherTemp = component.find('h5[_hint="WeatherTemp"]').at(0); expect(weatherTemp.exists()).toBe(true); expect(weatherTemp.text()).toEqual( `${Math.round(fakeWeather.main.temp)}°` ); const weatherTempRange = component.find('h6[_hint="WeatherTempRange"]').at(0); expect(weatherTempRange.exists()).toBe(true); expect(weatherTempRange.text()).toContain( `${Math.round(fakeWeather.main.temp_min)}°` ); expect(weatherTempRange.text()).toContain( `${Math.round(fakeWeather.main.temp_max)}°` ); const lastUpdate = component.find('small[_hint="LastUpdate"]').at(0); expect(lastUpdate.exists()).toBe(true); expect(lastUpdate.text()).toContain('Formatted DateTime'); expect(DateTime.fromSeconds).toHaveBeenCalledWith(fakeWeather.dt); expect(fakeDateTime.toLocaleString).toHaveBeenCalledWith( DateTime.TIME_SIMPLE ); }); it('does not render FatalError if service state has no fatal error', () => { // Given const component = shallow( ); // 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( ); // 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); }); }); });