From 3412edb843876283700e6ae00f981b22aa5159f0 Mon Sep 17 00:00:00 2001 From: Adam Mills Date: Tue, 21 Nov 2017 00:46:36 -0500 Subject: [PATCH] Compute state display tests (#643) * Move computeDomain and format functions to js * Add tests for computeStateDisplay * Always recalculate state display * Remove LANGUAGE from hassUtils object * Move AppLocalizeBehavior import to mixins * Import mixins to state-card-display * Safety check on computeStateDisplay * Don't store computed domains on stateObj * Integration tests for state-card-display * Include extractDomain code in polymer repo * Remove util function null checking * Dont render test element without hass and stateObj * Revert "Don't store computed domains on stateObj" This reverts commit e3509d71823ff5e42a4dcf4849a98c5bb6cb391c. * Revert "Always recalculate state display" This reverts commit 27c24e2694ee6f7c147782532268b3a67998d49b. --- js/common/util/compute_domain.js | 7 + js/common/util/compute_state_display.js | 59 ++++++ js/common/util/format_date.js | 19 ++ js/common/util/format_date_time.js | 22 +++ js/common/util/format_time.js | 19 ++ js/util.js | 15 ++ src/components/ha-cards.html | 2 + src/home-assistant.html | 1 - src/state-summary/state-card-display.html | 55 +----- src/util/hass-mixins.html | 2 + src/util/hass-util.html | 82 -------- .../common/util/attribute_class_names_test.js | 8 +- test-mocha/common/util/compute_domain.js | 12 ++ .../common/util/compute_state_display.js | 184 ++++++++++++++++++ test-mocha/common/util/format_date.js | 20 ++ test-mocha/common/util/format_date_time.js | 20 ++ test-mocha/common/util/format_time.js | 20 ++ test/index.html | 2 + test/state-card-display-test.html | 64 ++++++ test/state-info-test.html | 4 - 20 files changed, 476 insertions(+), 141 deletions(-) create mode 100644 js/common/util/compute_domain.js create mode 100644 js/common/util/compute_state_display.js create mode 100644 js/common/util/format_date.js create mode 100644 js/common/util/format_date_time.js create mode 100644 js/common/util/format_time.js create mode 100644 test-mocha/common/util/compute_domain.js create mode 100644 test-mocha/common/util/compute_state_display.js create mode 100644 test-mocha/common/util/format_date.js create mode 100644 test-mocha/common/util/format_date_time.js create mode 100644 test-mocha/common/util/format_time.js create mode 100644 test/state-card-display-test.html diff --git a/js/common/util/compute_domain.js b/js/common/util/compute_domain.js new file mode 100644 index 0000000000..58faa51be7 --- /dev/null +++ b/js/common/util/compute_domain.js @@ -0,0 +1,7 @@ +export default function computeDomain(stateObj) { + if (!stateObj._domain) { + stateObj._domain = stateObj.entity_id.substr(0, stateObj.entity_id.indexOf('.')); + } + + return stateObj._domain; +} diff --git a/js/common/util/compute_state_display.js b/js/common/util/compute_state_display.js new file mode 100644 index 0000000000..a43175de4a --- /dev/null +++ b/js/common/util/compute_state_display.js @@ -0,0 +1,59 @@ +import computeDomain from './compute_domain'; +import formatDateTime from './format_date_time'; +import formatDate from './format_date'; +import formatTime from './format_time'; + +export default function computeStateDisplay(haLocalize, stateObj, language) { + if (!stateObj._stateDisplay) { + const domain = computeDomain(stateObj); + if (domain === 'binary_sensor') { + // Try device class translation, then default binary sensor translation + if (stateObj.attributes.device_class) { + stateObj._stateDisplay = + haLocalize(`state.${domain}.${stateObj.attributes.device_class}`, stateObj.state); + } + if (!stateObj._stateDisplay) { + stateObj._stateDisplay = haLocalize(`state.${domain}.default`, stateObj.state); + } + } else if (stateObj.attributes.unit_of_measurement) { + stateObj._stateDisplay = stateObj.state + ' ' + stateObj.attributes.unit_of_measurement; + } else if (domain === 'input_datetime') { + let date; + if (!stateObj.attributes.has_time) { + date = new Date( + stateObj.attributes.year, + stateObj.attributes.month - 1, + stateObj.attributes.day + ); + stateObj._stateDisplay = formatDate(date, language); + } else if (!stateObj.attributes.has_date) { + date = new Date( + 1970, 0, 1, + stateObj.attributes.hour, + stateObj.attributes.minute + ); + stateObj._stateDisplay = formatTime(date, language); + } else { + date = new Date( + stateObj.attributes.year, stateObj.attributes.month - 1, + stateObj.attributes.day, stateObj.attributes.hour, + stateObj.attributes.minute + ); + stateObj._stateDisplay = formatDateTime(date, language); + } + } else if (domain === 'zwave') { + if (['initializing', 'dead'].includes(stateObj.state)) { + stateObj._stateDisplay = haLocalize('state.zwave.query_stage', stateObj.state, 'query_stage', stateObj.attributes.query_stage); + } else { + stateObj._stateDisplay = haLocalize('state.zwave.default', stateObj.state); + } + } else { + stateObj._stateDisplay = haLocalize(`state.${domain}`, stateObj.state); + } + // Fall back to default or raw state if nothing else matches. + stateObj._stateDisplay = stateObj._stateDisplay + || haLocalize('state.default', stateObj.state) || stateObj.state; + } + + return stateObj._stateDisplay; +} diff --git a/js/common/util/format_date.js b/js/common/util/format_date.js new file mode 100644 index 0000000000..006e736f88 --- /dev/null +++ b/js/common/util/format_date.js @@ -0,0 +1,19 @@ +// Check for support of native locale string options +function toLocaleDateStringSupportsOptions() { + try { + new Date().toLocaleDateString('i'); + } catch (e) { + return e.name === 'RangeError'; + } + return false; +} + +export default (toLocaleDateStringSupportsOptions() ? + function (dateObj, locales) { + return dateObj.toLocaleDateString( + locales, + { year: 'numeric', month: 'long', day: 'numeric' }, + ); + } : function (dateObj, locales) { // eslint-disable-line no-unused-vars + return window.fecha.format(dateObj, 'mediumDate'); + }); diff --git a/js/common/util/format_date_time.js b/js/common/util/format_date_time.js new file mode 100644 index 0000000000..f695511b86 --- /dev/null +++ b/js/common/util/format_date_time.js @@ -0,0 +1,22 @@ +// Check for support of native locale string options +function toLocaleStringSupportsOptions() { + try { + new Date().toLocaleString('i'); + } catch (e) { + return e.name === 'RangeError'; + } + return false; +} + +export default (toLocaleStringSupportsOptions() ? + function (dateObj, locales) { + return dateObj.toLocaleString(locales, { + year: 'numeric', + month: 'long', + day: 'numeric', + hour: 'numeric', + minute: '2-digit', + }); + } : function (dateObj, locales) { // eslint-disable-line no-unused-vars + return window.fecha.format(dateObj, 'haDateTime'); + }); diff --git a/js/common/util/format_time.js b/js/common/util/format_time.js new file mode 100644 index 0000000000..5ff05a67da --- /dev/null +++ b/js/common/util/format_time.js @@ -0,0 +1,19 @@ +// Check for support of native locale string options +function toLocaleTimeStringSupportsOptions() { + try { + new Date().toLocaleTimeString('i'); + } catch (e) { + return e.name === 'RangeError'; + } + return false; +} + +export default (toLocaleTimeStringSupportsOptions() ? + function (dateObj, locales) { + return dateObj.toLocaleTimeString( + locales, + { hour: 'numeric', minute: '2-digit' } + ); + } : function (dateObj, locales) { // eslint-disable-line no-unused-vars + return window.fecha.format(dateObj, 'shortTime'); + }); diff --git a/js/util.js b/js/util.js index 621f7e0019..eb97c013ac 100644 --- a/js/util.js +++ b/js/util.js @@ -7,7 +7,22 @@ */ import attributeClassNames from './common/util/attribute_class_names'; +import computeDomain from './common/util/compute_domain'; +import computeStateDisplay from './common/util/compute_state_display'; +import formatDate from './common/util/format_date'; +import formatDateTime from './common/util/format_date_time'; +import formatTime from './common/util/format_time'; window.hassUtil = window.hassUtil || {}; +const language = navigator.languages ? + navigator.languages[0] : navigator.language || navigator.userLanguage; + +window.fecha.masks.haDateTime = window.fecha.masks.shortTime + ' ' + window.fecha.masks.mediumDate; + window.hassUtil.attributeClassNames = attributeClassNames; +window.hassUtil.computeDomain = computeDomain; +window.hassUtil.computeStateDisplay = computeStateDisplay; +window.hassUtil.formatDate = dateObj => formatDate(dateObj, language); +window.hassUtil.formatDateTime = dateObj => formatDateTime(dateObj, language); +window.hassUtil.formatTime = dateObj => formatTime(dateObj, language); diff --git a/src/components/ha-cards.html b/src/components/ha-cards.html index e4d35670ea..f6e81a4ff5 100644 --- a/src/components/ha-cards.html +++ b/src/components/ha-cards.html @@ -7,6 +7,8 @@ + +