mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-08 01:46:35 +00:00
Ts all the tests (#1998)
* Convert tests to TypeScript * Add types for tests * Rename files to TS * Fix up test imports * Fix TSC errors * Liiiint * Add types to util method signatures * Some more types
This commit is contained in:
parent
856ef34964
commit
cdb2093ea6
12
package.json
12
package.json
@ -8,8 +8,8 @@
|
||||
"version": "1.0.0",
|
||||
"scripts": {
|
||||
"build": "script/build_frontend",
|
||||
"lint": "eslint src hassio/src gallery/src test-mocha && tslint -c tslint.json 'src/**/*.ts' 'hassio/src/**/*.ts' 'gallery/src/**/*.ts' 'test-mocha/**/*.ts' && polymer lint && tsc",
|
||||
"mocha": "node_modules/.bin/mocha --opts test-mocha/mocha.opts",
|
||||
"lint": "eslint src hassio/src gallery/src && tslint 'src/**/*.ts' 'hassio/src/**/*.ts' 'gallery/src/**/*.ts' 'test-mocha/**/*.ts' && polymer lint && tsc",
|
||||
"mocha": "node_modules/.bin/ts-mocha -p test-mocha/tsconfig.test.json --opts test-mocha/mocha.opts",
|
||||
"test": "npm run lint && npm run mocha",
|
||||
"docker_build": "sh ./script/docker_run.sh build $npm_package_version",
|
||||
"bash": "sh ./script/docker_run.sh bash $npm_package_version"
|
||||
@ -100,10 +100,12 @@
|
||||
"@babel/preset-env": "^7.1.0",
|
||||
"@babel/preset-typescript": "^7.1.0",
|
||||
"@gfx/zopfli": "^1.0.9",
|
||||
"@types/chai": "^4.1.7",
|
||||
"@types/mocha": "^5.2.5",
|
||||
"babel-eslint": "^10",
|
||||
"babel-loader": "^8.0.4",
|
||||
"babel-minify-webpack-plugin": "^0.3.1",
|
||||
"chai": "^4.1.2",
|
||||
"chai": "^4.2.0",
|
||||
"compression-webpack-plugin": "^2.0.0",
|
||||
"copy-webpack-plugin": "^4.5.2",
|
||||
"del": "^3.0.0",
|
||||
@ -126,7 +128,6 @@
|
||||
"husky": "^1.1.0",
|
||||
"lint-staged": "^8.0.2",
|
||||
"merge-stream": "^1.0.1",
|
||||
"mocha": "^5.2.0",
|
||||
"parse5": "^5.1.0",
|
||||
"polymer-analyzer": "^3.1.2",
|
||||
"polymer-bundler": "^4.0.2",
|
||||
@ -135,7 +136,8 @@
|
||||
"raw-loader": "^0.5.1",
|
||||
"reify": "^0.18.1",
|
||||
"require-dir": "^1.0.0",
|
||||
"sinon": "^7.1.0",
|
||||
"sinon": "^7.1.1",
|
||||
"ts-mocha": "^2.0.0",
|
||||
"tslint": "^5.11.0",
|
||||
"tslint-config-prettier": "^1.15.0",
|
||||
"tslint-eslint-rules": "^5.4.0",
|
||||
|
@ -1,4 +0,0 @@
|
||||
/** Return if a component is loaded. */
|
||||
export default function isComponentLoaded(hass, component) {
|
||||
return hass && hass.config.components.indexOf(component) !== -1;
|
||||
}
|
9
src/common/config/is_component_loaded.ts
Normal file
9
src/common/config/is_component_loaded.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import { HomeAssistant } from "../../types";
|
||||
|
||||
/** Return if a component is loaded. */
|
||||
export default function isComponentLoaded(
|
||||
hass: HomeAssistant,
|
||||
component: string
|
||||
): boolean {
|
||||
return hass && hass.config.components.indexOf(component) !== -1;
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
/** Return if the displaymode is in standalone mode (PWA). */
|
||||
export default function isPwa() {
|
||||
export default function isPwa(): boolean {
|
||||
return window.matchMedia("(display-mode: standalone)").matches;
|
||||
}
|
@ -1,4 +0,0 @@
|
||||
/** Get the location name from a hass object. */
|
||||
export default function computeLocationName(hass) {
|
||||
return hass && hass.config.location_name;
|
||||
}
|
6
src/common/config/location_name.ts
Normal file
6
src/common/config/location_name.ts
Normal file
@ -0,0 +1,6 @@
|
||||
import { HomeAssistant } from "../../types";
|
||||
|
||||
/** Get the location name from a hass object. */
|
||||
export default function computeLocationName(hass: HomeAssistant): string {
|
||||
return hass && hass.config.location_name;
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
export default function durationToSeconds(duration) {
|
||||
export default function durationToSeconds(duration: string): number {
|
||||
const parts = duration.split(":").map(Number);
|
||||
return parts[0] * 3600 + parts[1] * 60 + parts[2];
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
import fecha from "fecha";
|
||||
import * as fecha from "fecha";
|
||||
|
||||
// Check for support of native locale string options
|
||||
function toLocaleDateStringSupportsOptions() {
|
||||
@ -11,11 +11,10 @@ function toLocaleDateStringSupportsOptions() {
|
||||
}
|
||||
|
||||
export default (toLocaleDateStringSupportsOptions()
|
||||
? (dateObj, locales) =>
|
||||
? (dateObj: Date, locales: string) =>
|
||||
dateObj.toLocaleDateString(locales, {
|
||||
year: "numeric",
|
||||
month: "long",
|
||||
day: "numeric",
|
||||
})
|
||||
: // eslint-disable-next-line no-unused-vars
|
||||
(dateObj, locales) => fecha.format(dateObj, "mediumDate"));
|
||||
: (dateObj: Date) => fecha.format(dateObj, "mediumDate"));
|
@ -1,4 +1,4 @@
|
||||
import fecha from "fecha";
|
||||
import * as fecha from "fecha";
|
||||
|
||||
// Check for support of native locale string options
|
||||
function toLocaleStringSupportsOptions() {
|
||||
@ -11,7 +11,7 @@ function toLocaleStringSupportsOptions() {
|
||||
}
|
||||
|
||||
export default (toLocaleStringSupportsOptions()
|
||||
? (dateObj, locales) =>
|
||||
? (dateObj: Date, locales: string) =>
|
||||
dateObj.toLocaleString(locales, {
|
||||
year: "numeric",
|
||||
month: "long",
|
||||
@ -19,5 +19,4 @@ export default (toLocaleStringSupportsOptions()
|
||||
hour: "numeric",
|
||||
minute: "2-digit",
|
||||
})
|
||||
: // eslint-disable-next-line no-unused-vars
|
||||
(dateObj, locales) => fecha.format(dateObj, "haDateTime"));
|
||||
: (dateObj: Date) => fecha.format(dateObj, "haDateTime"));
|
@ -1,4 +1,4 @@
|
||||
import fecha from "fecha";
|
||||
import * as fecha from "fecha";
|
||||
|
||||
// Check for support of native locale string options
|
||||
function toLocaleTimeStringSupportsOptions() {
|
||||
@ -11,10 +11,9 @@ function toLocaleTimeStringSupportsOptions() {
|
||||
}
|
||||
|
||||
export default (toLocaleTimeStringSupportsOptions()
|
||||
? (dateObj, locales) =>
|
||||
? (dateObj: Date, locales: string) =>
|
||||
dateObj.toLocaleTimeString(locales, {
|
||||
hour: "numeric",
|
||||
minute: "2-digit",
|
||||
})
|
||||
: // eslint-disable-next-line no-unused-vars
|
||||
(dateObj, locales) => fecha.format(dateObj, "shortTime"));
|
||||
: (dateObj: Date) => fecha.format(dateObj, "shortTime"));
|
@ -1,33 +0,0 @@
|
||||
/** Calculate a string representing a date object as relative time from now.
|
||||
*
|
||||
* Example output: 5 minutes ago, in 3 days.
|
||||
*/
|
||||
const tests = [60, "second", 60, "minute", 24, "hour", 7, "day"];
|
||||
|
||||
export default function relativeTime(dateObj, localize) {
|
||||
let delta = (new Date() - dateObj) / 1000;
|
||||
const tense = delta >= 0 ? "past" : "future";
|
||||
delta = Math.abs(delta);
|
||||
|
||||
for (let i = 0; i < tests.length; i += 2) {
|
||||
if (delta < tests[i]) {
|
||||
delta = Math.floor(delta);
|
||||
const time = localize(
|
||||
`ui.components.relative_time.duration.${tests[i + 1]}`,
|
||||
"count",
|
||||
delta
|
||||
);
|
||||
return localize(`ui.components.relative_time.${tense}`, "time", time);
|
||||
}
|
||||
|
||||
delta /= tests[i];
|
||||
}
|
||||
|
||||
delta = Math.floor(delta);
|
||||
const time = localize(
|
||||
"ui.components.relative_time.duration.week",
|
||||
"count",
|
||||
delta
|
||||
);
|
||||
return localize(`ui.components.relative_time.${tense}`, "time", time);
|
||||
}
|
40
src/common/datetime/relative_time.ts
Normal file
40
src/common/datetime/relative_time.ts
Normal file
@ -0,0 +1,40 @@
|
||||
import { LocalizeFunc } from "../../mixins/localize-base-mixin";
|
||||
|
||||
/**
|
||||
* Calculate a string representing a date object as relative time from now.
|
||||
*
|
||||
* Example output: 5 minutes ago, in 3 days.
|
||||
*/
|
||||
const tests = [60, 60, 24, 7];
|
||||
const langKey = ["second", "minute", "hour", "day"];
|
||||
|
||||
export default function relativeTime(
|
||||
dateObj: Date,
|
||||
localize: LocalizeFunc
|
||||
): string {
|
||||
let delta = (new Date().getTime() - dateObj.getTime()) / 1000;
|
||||
const tense = delta >= 0 ? "past" : "future";
|
||||
delta = Math.abs(delta);
|
||||
|
||||
for (let i = 0; i < tests.length; i++) {
|
||||
if (delta < tests[i]) {
|
||||
delta = Math.floor(delta);
|
||||
const timeDesc = localize(
|
||||
`ui.components.relative_time.duration.${langKey[i]}`,
|
||||
"count",
|
||||
delta
|
||||
);
|
||||
return localize(`ui.components.relative_time.${tense}`, "time", timeDesc);
|
||||
}
|
||||
|
||||
delta /= tests[i];
|
||||
}
|
||||
|
||||
delta = Math.floor(delta);
|
||||
const time = localize(
|
||||
"ui.components.relative_time.duration.week",
|
||||
"count",
|
||||
delta
|
||||
);
|
||||
return localize(`ui.components.relative_time.${tense}`, "time", time);
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
const leftPad = (number) => (number < 10 ? `0${number}` : number);
|
||||
const leftPad = (num: number) => (num < 10 ? `0${num}` : num);
|
||||
|
||||
export default function secondsToDuration(d) {
|
||||
export default function secondsToDuration(d: number) {
|
||||
const h = Math.floor(d / 3600);
|
||||
const m = Math.floor((d % 3600) / 60);
|
||||
const s = Math.floor((d % 3600) % 60);
|
@ -1,9 +0,0 @@
|
||||
export default function attributeClassNames(stateObj, attributes) {
|
||||
if (!stateObj) return "";
|
||||
return attributes
|
||||
.map(function(attribute) {
|
||||
return attribute in stateObj.attributes ? "has-" + attribute : "";
|
||||
})
|
||||
.filter((attr) => attr !== "")
|
||||
.join(" ");
|
||||
}
|
17
src/common/entity/attribute_class_names.ts
Normal file
17
src/common/entity/attribute_class_names.ts
Normal file
@ -0,0 +1,17 @@
|
||||
import { HassEntity } from "home-assistant-js-websocket";
|
||||
|
||||
export default function attributeClassNames(
|
||||
stateObj: HassEntity,
|
||||
attributes: string[]
|
||||
): string {
|
||||
if (!stateObj) {
|
||||
return "";
|
||||
}
|
||||
return attributes
|
||||
.map(
|
||||
(attribute) =>
|
||||
attribute in stateObj.attributes ? "has-" + attribute : ""
|
||||
)
|
||||
.filter((attr) => attr !== "")
|
||||
.join(" ");
|
||||
}
|
@ -1,7 +1,9 @@
|
||||
import { HassEntity } from "home-assistant-js-websocket";
|
||||
|
||||
/** Return an icon representing a binary sensor state. */
|
||||
|
||||
export default function binarySensorIcon(state) {
|
||||
var activated = state.state && state.state === "off";
|
||||
export default function binarySensorIcon(state: HassEntity) {
|
||||
const activated = state.state && state.state === "off";
|
||||
switch (state.attributes.device_class) {
|
||||
case "battery":
|
||||
return activated ? "hass:battery" : "hass:battery-outline";
|
@ -1,4 +1,6 @@
|
||||
export default function canToggleDomain(hass, domain) {
|
||||
import { HomeAssistant } from "../../types";
|
||||
|
||||
export default function canToggleDomain(hass: HomeAssistant, domain: string) {
|
||||
const services = hass.services[domain];
|
||||
if (!services) {
|
||||
return false;
|
@ -1,13 +1,19 @@
|
||||
import { HassEntity } from "home-assistant-js-websocket";
|
||||
import canToggleDomain from "./can_toggle_domain";
|
||||
import computeStateDomain from "./compute_state_domain";
|
||||
import { HomeAssistant } from "../../types";
|
||||
|
||||
export default function canToggleState(hass, stateObj) {
|
||||
export default function canToggleState(
|
||||
hass: HomeAssistant,
|
||||
stateObj: HassEntity
|
||||
) {
|
||||
const domain = computeStateDomain(stateObj);
|
||||
if (domain === "group") {
|
||||
return stateObj.state === "on" || stateObj.state === "off";
|
||||
}
|
||||
if (domain === "climate") {
|
||||
return !!((stateObj.attributes || {}).supported_features & 4096);
|
||||
// tslint:disable-next-line
|
||||
return (stateObj.attributes.supported_features! & 4096) !== 0;
|
||||
}
|
||||
|
||||
return canToggleDomain(hass, domain);
|
@ -1,3 +0,0 @@
|
||||
export default function computeDomain(entityId) {
|
||||
return entityId.substr(0, entityId.indexOf("."));
|
||||
}
|
3
src/common/entity/compute_domain.ts
Normal file
3
src/common/entity/compute_domain.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export default function computeDomain(entityId: string): string {
|
||||
return entityId.substr(0, entityId.indexOf("."));
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
/** Compute the object ID of a state. */
|
||||
export default function computeObjectId(entityId) {
|
||||
export default function computeObjectId(entityId: string): string {
|
||||
return entityId.substr(entityId.indexOf(".") + 1);
|
||||
}
|
@ -1,84 +0,0 @@
|
||||
import computeStateDomain from "./compute_state_domain";
|
||||
import formatDateTime from "../datetime/format_date_time";
|
||||
import formatDate from "../datetime/format_date";
|
||||
import formatTime from "../datetime/format_time";
|
||||
|
||||
export default function computeStateDisplay(localize, stateObj, language) {
|
||||
if (!stateObj._stateDisplay) {
|
||||
const domain = computeStateDomain(stateObj);
|
||||
if (domain === "binary_sensor") {
|
||||
// Try device class translation, then default binary sensor translation
|
||||
if (stateObj.attributes.device_class) {
|
||||
stateObj._stateDisplay = localize(
|
||||
`state.${domain}.${stateObj.attributes.device_class}.${
|
||||
stateObj.state
|
||||
}`
|
||||
);
|
||||
}
|
||||
if (!stateObj._stateDisplay) {
|
||||
stateObj._stateDisplay = localize(
|
||||
`state.${domain}.default.${stateObj.state}`
|
||||
);
|
||||
}
|
||||
} else if (
|
||||
stateObj.attributes.unit_of_measurement &&
|
||||
!["unknown", "unavailable"].includes(stateObj.state)
|
||||
) {
|
||||
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) {
|
||||
const now = new Date();
|
||||
date = new Date(
|
||||
// Due to bugs.chromium.org/p/chromium/issues/detail?id=797548
|
||||
// don't use artificial 1970 year.
|
||||
now.getFullYear(),
|
||||
now.getMonth(),
|
||||
now.getDay(),
|
||||
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 = localize(
|
||||
`state.zwave.query_stage.${stateObj.state}`,
|
||||
"query_stage",
|
||||
stateObj.attributes.query_stage
|
||||
);
|
||||
} else {
|
||||
stateObj._stateDisplay = localize(
|
||||
`state.zwave.default.${stateObj.state}`
|
||||
);
|
||||
}
|
||||
} else {
|
||||
stateObj._stateDisplay = localize(`state.${domain}.${stateObj.state}`);
|
||||
}
|
||||
// Fall back to default, component backend translation, or raw state if nothing else matches.
|
||||
stateObj._stateDisplay =
|
||||
stateObj._stateDisplay ||
|
||||
localize(`state.default.${stateObj.state}`) ||
|
||||
localize(`component.${domain}.state.${stateObj.state}`) ||
|
||||
stateObj.state;
|
||||
}
|
||||
|
||||
return stateObj._stateDisplay;
|
||||
}
|
91
src/common/entity/compute_state_display.ts
Normal file
91
src/common/entity/compute_state_display.ts
Normal file
@ -0,0 +1,91 @@
|
||||
import { HassEntity } from "home-assistant-js-websocket";
|
||||
import computeStateDomain from "./compute_state_domain";
|
||||
import formatDateTime from "../datetime/format_date_time";
|
||||
import formatDate from "../datetime/format_date";
|
||||
import formatTime from "../datetime/format_time";
|
||||
import { LocalizeFunc } from "../../mixins/localize-base-mixin";
|
||||
|
||||
type CachedDisplayEntity = HassEntity & {
|
||||
_stateDisplay?: string;
|
||||
};
|
||||
|
||||
export default function computeStateDisplay(
|
||||
localize: LocalizeFunc,
|
||||
stateObj: HassEntity,
|
||||
language: string
|
||||
) {
|
||||
const state = stateObj as CachedDisplayEntity;
|
||||
if (!state._stateDisplay) {
|
||||
const domain = computeStateDomain(state);
|
||||
if (domain === "binary_sensor") {
|
||||
// Try device class translation, then default binary sensor translation
|
||||
if (state.attributes.device_class) {
|
||||
state._stateDisplay = localize(
|
||||
`state.${domain}.${state.attributes.device_class}.${state.state}`
|
||||
);
|
||||
}
|
||||
if (!state._stateDisplay) {
|
||||
state._stateDisplay = localize(
|
||||
`state.${domain}.default.${state.state}`
|
||||
);
|
||||
}
|
||||
} else if (
|
||||
state.attributes.unit_of_measurement &&
|
||||
!["unknown", "unavailable"].includes(state.state)
|
||||
) {
|
||||
state._stateDisplay =
|
||||
state.state + " " + state.attributes.unit_of_measurement;
|
||||
} else if (domain === "input_datetime") {
|
||||
let date;
|
||||
if (!state.attributes.has_time) {
|
||||
date = new Date(
|
||||
state.attributes.year,
|
||||
state.attributes.month - 1,
|
||||
state.attributes.day
|
||||
);
|
||||
state._stateDisplay = formatDate(date, language);
|
||||
} else if (!state.attributes.has_date) {
|
||||
const now = new Date();
|
||||
date = new Date(
|
||||
// Due to bugs.chromium.org/p/chromium/issues/detail?id=797548
|
||||
// don't use artificial 1970 year.
|
||||
now.getFullYear(),
|
||||
now.getMonth(),
|
||||
now.getDay(),
|
||||
state.attributes.hour,
|
||||
state.attributes.minute
|
||||
);
|
||||
state._stateDisplay = formatTime(date, language);
|
||||
} else {
|
||||
date = new Date(
|
||||
state.attributes.year,
|
||||
state.attributes.month - 1,
|
||||
state.attributes.day,
|
||||
state.attributes.hour,
|
||||
state.attributes.minute
|
||||
);
|
||||
state._stateDisplay = formatDateTime(date, language);
|
||||
}
|
||||
} else if (domain === "zwave") {
|
||||
if (["initializing", "dead"].includes(state.state)) {
|
||||
state._stateDisplay = localize(
|
||||
`state.zwave.query_stage.${state.state}`,
|
||||
"query_stage",
|
||||
state.attributes.query_stage
|
||||
);
|
||||
} else {
|
||||
state._stateDisplay = localize(`state.zwave.default.${state.state}`);
|
||||
}
|
||||
} else {
|
||||
state._stateDisplay = localize(`state.${domain}.${state.state}`);
|
||||
}
|
||||
// Fall back to default, component backend translation, or raw state if nothing else matches.
|
||||
state._stateDisplay =
|
||||
state._stateDisplay ||
|
||||
localize(`state.default.${state.state}`) ||
|
||||
localize(`component.${domain}.state.${state.state}`) ||
|
||||
state.state;
|
||||
}
|
||||
|
||||
return state._stateDisplay;
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
import computeDomain from "./compute_domain";
|
||||
|
||||
export default function computeStateDomain(stateObj) {
|
||||
return computeDomain(stateObj.entity_id);
|
||||
}
|
6
src/common/entity/compute_state_domain.ts
Normal file
6
src/common/entity/compute_state_domain.ts
Normal file
@ -0,0 +1,6 @@
|
||||
import { HassEntity } from "home-assistant-js-websocket";
|
||||
import computeDomain from "./compute_domain";
|
||||
|
||||
export default function computeStateDomain(stateObj: HassEntity) {
|
||||
return computeDomain(stateObj.entity_id);
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
import computeObjectId from "./compute_object_id";
|
||||
|
||||
export default function computeStateName(stateObj) {
|
||||
if (stateObj._entityDisplay === undefined) {
|
||||
stateObj._entityDisplay =
|
||||
stateObj.attributes.friendly_name ||
|
||||
computeObjectId(stateObj.entity_id).replace(/_/g, " ");
|
||||
}
|
||||
|
||||
return stateObj._entityDisplay;
|
||||
}
|
18
src/common/entity/compute_state_name.ts
Normal file
18
src/common/entity/compute_state_name.ts
Normal file
@ -0,0 +1,18 @@
|
||||
import { HassEntity } from "home-assistant-js-websocket";
|
||||
import computeObjectId from "./compute_object_id";
|
||||
|
||||
type CachedDisplayEntity = HassEntity & {
|
||||
_entityDisplay?: string;
|
||||
};
|
||||
|
||||
export default function computeStateName(stateObj: HassEntity) {
|
||||
const state = stateObj as CachedDisplayEntity;
|
||||
|
||||
if (state._entityDisplay === undefined) {
|
||||
state._entityDisplay =
|
||||
state.attributes.friendly_name ||
|
||||
computeObjectId(state.entity_id).replace(/_/g, " ");
|
||||
}
|
||||
|
||||
return state._entityDisplay;
|
||||
}
|
@ -1,8 +1,9 @@
|
||||
/** Return an icon representing a cover state. */
|
||||
import { HassEntity } from "home-assistant-js-websocket";
|
||||
import domainIcon from "./domain_icon";
|
||||
|
||||
export default function coverIcon(state) {
|
||||
var open = state.state && state.state !== "closed";
|
||||
export default function coverIcon(state: HassEntity): string {
|
||||
const open = state.state !== "closed";
|
||||
switch (state.attributes.device_class) {
|
||||
case "garage":
|
||||
return open ? "hass:garage-open" : "hass:garage";
|
@ -44,7 +44,7 @@ const fixedIcons = {
|
||||
weblink: "hass:open-in-new",
|
||||
};
|
||||
|
||||
export default function domainIcon(domain, state) {
|
||||
export default function domainIcon(domain: string, state?: string): string {
|
||||
if (domain in fixedIcons) {
|
||||
return fixedIcons[domain];
|
||||
}
|
||||
@ -93,11 +93,10 @@ export default function domainIcon(domain, state) {
|
||||
}
|
||||
|
||||
default:
|
||||
/* eslint-disable no-console */
|
||||
// tslint:disable-next-line
|
||||
console.warn(
|
||||
"Unable to find icon for domain " + domain + " (" + state + ")"
|
||||
);
|
||||
/* eslint-enable no-console */
|
||||
return DEFAULT_DOMAIN_ICON;
|
||||
}
|
||||
}
|
@ -1,8 +1,9 @@
|
||||
import { HassEntities, HassEntity } from "home-assistant-js-websocket";
|
||||
import { DEFAULT_VIEW_ENTITY_ID } from "../const";
|
||||
|
||||
// Return an ordered array of available views
|
||||
export default function extractViews(entities) {
|
||||
const views = [];
|
||||
export default function extractViews(entities: HassEntities): HassEntity[] {
|
||||
const views: HassEntity[] = [];
|
||||
|
||||
Object.keys(entities).forEach((entityId) => {
|
||||
const entity = entities[entityId];
|
@ -1,11 +0,0 @@
|
||||
// Expects classNames to be an object mapping feature-bit -> className
|
||||
export default function featureClassNames(stateObj, classNames) {
|
||||
if (!stateObj || !stateObj.attributes.supported_features) return "";
|
||||
|
||||
const features = stateObj.attributes.supported_features;
|
||||
|
||||
return Object.keys(classNames)
|
||||
.map((feature) => ((features & feature) !== 0 ? classNames[feature] : ""))
|
||||
.filter((attr) => attr !== "")
|
||||
.join(" ");
|
||||
}
|
22
src/common/entity/feature_class_names.ts
Normal file
22
src/common/entity/feature_class_names.ts
Normal file
@ -0,0 +1,22 @@
|
||||
import { HassEntity } from "home-assistant-js-websocket";
|
||||
|
||||
// Expects classNames to be an object mapping feature-bit -> className
|
||||
export default function featureClassNames(
|
||||
stateObj: HassEntity,
|
||||
classNames: { [feature: number]: string }
|
||||
) {
|
||||
if (!stateObj || !stateObj.attributes.supported_features) {
|
||||
return "";
|
||||
}
|
||||
|
||||
const features = stateObj.attributes.supported_features;
|
||||
|
||||
return Object.keys(classNames)
|
||||
.map(
|
||||
(feature) =>
|
||||
// tslint:disable-next-line
|
||||
(features & Number(feature)) !== 0 ? classNames[feature] : ""
|
||||
)
|
||||
.filter((attr) => attr !== "")
|
||||
.join(" ");
|
||||
}
|
@ -1,4 +1,10 @@
|
||||
export default function getGroupEntities(entities, group) {
|
||||
import { HassEntities } from "home-assistant-js-websocket";
|
||||
import { GroupEntity } from "../../types";
|
||||
|
||||
export default function getGroupEntities(
|
||||
entities: HassEntities,
|
||||
group: GroupEntity
|
||||
) {
|
||||
const result = {};
|
||||
|
||||
group.attributes.entity_id.forEach((entityId) => {
|
@ -1,9 +1,14 @@
|
||||
import { HassEntities } from "home-assistant-js-websocket";
|
||||
import computeDomain from "./compute_domain";
|
||||
import getGroupEntities from "./get_group_entities";
|
||||
import { GroupEntity } from "../../types";
|
||||
|
||||
// Return an object containing all entities that the view will show
|
||||
// including embedded groups.
|
||||
export default function getViewEntities(entities, view) {
|
||||
export default function getViewEntities(
|
||||
entities: HassEntities,
|
||||
view: GroupEntity
|
||||
) {
|
||||
const viewEntities = {};
|
||||
|
||||
view.attributes.entity_id.forEach((entityId) => {
|
||||
@ -13,7 +18,7 @@ export default function getViewEntities(entities, view) {
|
||||
viewEntities[entity.entity_id] = entity;
|
||||
|
||||
if (computeDomain(entity.entity_id) === "group") {
|
||||
const groupEntities = getGroupEntities(entities, entity);
|
||||
const groupEntities = getGroupEntities(entities, entity as GroupEntity);
|
||||
|
||||
Object.keys(groupEntities).forEach((grEntityId) => {
|
||||
const grEntity = groupEntities[grEntityId];
|
@ -1,5 +0,0 @@
|
||||
export default function hasLocation(stateObj) {
|
||||
return (
|
||||
"latitude" in stateObj.attributes && "longitude" in stateObj.attributes
|
||||
);
|
||||
}
|
7
src/common/entity/has_location.ts
Normal file
7
src/common/entity/has_location.ts
Normal file
@ -0,0 +1,7 @@
|
||||
import { HassEntity } from "home-assistant-js-websocket";
|
||||
|
||||
export default function hasLocation(stateObj: HassEntity) {
|
||||
return (
|
||||
"latitude" in stateObj.attributes && "longitude" in stateObj.attributes
|
||||
);
|
||||
}
|
@ -1,7 +1,8 @@
|
||||
/** Return an icon representing an input datetime state. */
|
||||
import domainIcon from "./domain_icon";
|
||||
import { HassEntity } from "home-assistant-js-websocket";
|
||||
|
||||
export default function inputDateTimeIcon(state) {
|
||||
export default function inputDateTimeIcon(state: HassEntity): string {
|
||||
if (!state.attributes.has_date) {
|
||||
return "hass:clock";
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
/** Return an icon representing a sensor state. */
|
||||
import { HassEntity } from "home-assistant-js-websocket";
|
||||
import { UNIT_C, UNIT_F } from "../const";
|
||||
import domainIcon from "./domain_icon";
|
||||
|
||||
@ -9,17 +10,18 @@ const fixedDeviceClassIcons = {
|
||||
pressure: "hass:gauge",
|
||||
};
|
||||
|
||||
export default function sensorIcon(state) {
|
||||
export default function sensorIcon(state: HassEntity) {
|
||||
const dclass = state.attributes.device_class;
|
||||
|
||||
if (dclass in fixedDeviceClassIcons) {
|
||||
if (dclass && dclass in fixedDeviceClassIcons) {
|
||||
return fixedDeviceClassIcons[dclass];
|
||||
}
|
||||
if (dclass === "battery") {
|
||||
if (isNaN(state.state)) {
|
||||
const battery = Number(state.state);
|
||||
if (isNaN(battery)) {
|
||||
return "hass:battery-unknown";
|
||||
}
|
||||
const batteryRound = Math.round(state.state / 10) * 10;
|
||||
const batteryRound = Math.round(battery / 10) * 10;
|
||||
if (batteryRound >= 100) {
|
||||
return "hass:battery";
|
||||
}
|
@ -1,11 +1,12 @@
|
||||
import computeDomain from "./compute_domain";
|
||||
import { HassEntity, HassEntities } from "home-assistant-js-websocket";
|
||||
|
||||
// Split a collection into a list of groups and a 'rest' list of ungrouped
|
||||
// entities.
|
||||
// Returns { groups: [], ungrouped: {} }
|
||||
export default function splitByGroups(entities) {
|
||||
const groups = [];
|
||||
const ungrouped = {};
|
||||
export default function splitByGroups(entities: HassEntities) {
|
||||
const groups: HassEntity[] = [];
|
||||
const ungrouped: HassEntities = {};
|
||||
|
||||
Object.keys(entities).forEach((entityId) => {
|
||||
const entity = entities[entityId];
|
@ -1,8 +1,13 @@
|
||||
import { HassEntity } from "home-assistant-js-websocket";
|
||||
import canToggleState from "./can_toggle_state";
|
||||
import computeStateDomain from "./compute_state_domain";
|
||||
import { DOMAINS_WITH_CARD } from "../const";
|
||||
import { HomeAssistant } from "../../types";
|
||||
|
||||
export default function stateCardType(hass, stateObj) {
|
||||
export default function stateCardType(
|
||||
hass: HomeAssistant,
|
||||
stateObj: HassEntity
|
||||
) {
|
||||
if (stateObj.state === "unavailable") {
|
||||
return "display";
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
/** Return an icon representing a state. */
|
||||
import { HassEntity } from "home-assistant-js-websocket";
|
||||
import { DEFAULT_DOMAIN_ICON } from "../const";
|
||||
|
||||
import computeDomain from "./compute_domain";
|
||||
@ -16,7 +17,7 @@ const domainIcons = {
|
||||
input_datetime: inputDateTimeIcon,
|
||||
};
|
||||
|
||||
export default function stateIcon(state) {
|
||||
export default function stateIcon(state: HassEntity) {
|
||||
if (!state) {
|
||||
return DEFAULT_DOMAIN_ICON;
|
||||
}
|
@ -1,7 +1,8 @@
|
||||
import { HassEntity } from "home-assistant-js-websocket";
|
||||
import computeStateDomain from "./compute_state_domain";
|
||||
import { DOMAINS_HIDE_MORE_INFO, DOMAINS_WITH_MORE_INFO } from "../const";
|
||||
|
||||
export default function stateMoreInfoType(stateObj) {
|
||||
export default function stateMoreInfoType(stateObj: HassEntity) {
|
||||
const domain = computeStateDomain(stateObj);
|
||||
|
||||
if (DOMAINS_WITH_MORE_INFO.includes(domain)) {
|
@ -5,9 +5,13 @@
|
||||
* const states = [state1, state2]
|
||||
* states.sort(statesSortByName);
|
||||
*/
|
||||
import { HassEntity } from "home-assistant-js-websocket";
|
||||
import computeStateName from "./compute_state_name";
|
||||
|
||||
export default function sortStatesByName(entityA, entityB) {
|
||||
export default function sortStatesByName(
|
||||
entityA: HassEntity,
|
||||
entityB: HassEntity
|
||||
) {
|
||||
const nameA = computeStateName(entityA);
|
||||
const nameB = computeStateName(entityB);
|
||||
if (nameA < nameB) {
|
@ -1,11 +1,12 @@
|
||||
import { HassEntity } from "home-assistant-js-websocket";
|
||||
import durationToSeconds from "../datetime/duration_to_seconds";
|
||||
|
||||
export default function timerTimeRemaining(stateObj) {
|
||||
export default function timerTimeRemaining(stateObj: HassEntity) {
|
||||
let timeRemaining = durationToSeconds(stateObj.attributes.remaining);
|
||||
|
||||
if (stateObj.state === "active") {
|
||||
const now = new Date();
|
||||
const madeActive = new Date(stateObj.last_changed);
|
||||
const now = new Date().getTime();
|
||||
const madeActive = new Date(stateObj.last_changed).getTime();
|
||||
timeRemaining = Math.max(timeRemaining - (now - madeActive) / 1000, 0);
|
||||
}
|
||||
|
@ -1,3 +0,0 @@
|
||||
export default function validEntityId(entityId) {
|
||||
return /^(\w+)\.(\w+)$/.test(entityId);
|
||||
}
|
2
src/common/entity/valid_entity_id.ts
Normal file
2
src/common/entity/valid_entity_id.ts
Normal file
@ -0,0 +1,2 @@
|
||||
const validEntityId = /^(\w+)\.(\w+)$/;
|
||||
export default validEntityId.test;
|
@ -1,9 +1,11 @@
|
||||
export default function parseAspectRatio(input) {
|
||||
// Handle 16x9, 16:9, 1.78x1, 1.78:1, 1.78
|
||||
// Ignore everything else
|
||||
function parseOrThrow(number) {
|
||||
const parsed = parseFloat(number);
|
||||
if (isNaN(parsed)) throw new Error(`${number} is not a number`);
|
||||
function parseOrThrow(num) {
|
||||
const parsed = parseFloat(num);
|
||||
if (isNaN(parsed)) {
|
||||
throw new Error(`${num} is not a number`);
|
||||
}
|
||||
return parsed;
|
||||
}
|
||||
try {
|
@ -211,7 +211,11 @@ export class HuiGlanceCard extends hassLocalizeLitMixin(LitElement)
|
||||
></state-badge>
|
||||
${
|
||||
this._config!.show_state !== false
|
||||
? html`<div>${computeStateDisplay(this.localize, stateObj)}</div>`
|
||||
? html`<div>${computeStateDisplay(
|
||||
this.localize,
|
||||
stateObj,
|
||||
this.hass!.language
|
||||
)}</div>`
|
||||
: ""
|
||||
}
|
||||
</div>
|
||||
|
@ -48,7 +48,9 @@ class HuiStateLabelElement extends hassLocalizeLitMixin(LitElement)
|
||||
.longPress="${longPress()}"
|
||||
>
|
||||
${this._config.prefix}${
|
||||
state ? computeStateDisplay(this.localize, state) : "-"
|
||||
state
|
||||
? computeStateDisplay(this.localize, state, this.hass!.language)
|
||||
: "-"
|
||||
}${this._config.suffix}
|
||||
</div>
|
||||
`;
|
||||
|
12
src/types.ts
12
src/types.ts
@ -6,6 +6,7 @@ import {
|
||||
MessageBase,
|
||||
HassEntityBase,
|
||||
HassEntityAttributeBase,
|
||||
HassServices,
|
||||
} from "home-assistant-js-websocket";
|
||||
|
||||
declare global {
|
||||
@ -75,6 +76,7 @@ export interface HomeAssistant {
|
||||
connection: Connection;
|
||||
connected: boolean;
|
||||
states: HassEntities;
|
||||
services: HassServices;
|
||||
config: HassConfig;
|
||||
themes: Themes;
|
||||
panels: Panels;
|
||||
@ -141,3 +143,13 @@ export type LightEntity = HassEntityBase & {
|
||||
hs_color: number[];
|
||||
};
|
||||
};
|
||||
|
||||
export type GroupEntity = HassEntityBase & {
|
||||
attributes: HassEntityAttributeBase & {
|
||||
entity_id: string[];
|
||||
order: number;
|
||||
auto?: boolean;
|
||||
view?: boolean;
|
||||
control?: "hidden";
|
||||
};
|
||||
};
|
||||
|
@ -6,12 +6,12 @@ describe("attributeClassNames", () => {
|
||||
const attrs = ["mock_attr1", "mock_attr2"];
|
||||
|
||||
it("Skips null states", () => {
|
||||
const stateObj = null;
|
||||
const stateObj: any = null;
|
||||
assert.strictEqual(attributeClassNames(stateObj, attrs), "");
|
||||
});
|
||||
|
||||
it("Matches no attrbutes", () => {
|
||||
const stateObj = {
|
||||
const stateObj: any = {
|
||||
attributes: {
|
||||
other_attr_1: 1,
|
||||
other_attr_2: 2,
|
||||
@ -21,7 +21,7 @@ describe("attributeClassNames", () => {
|
||||
});
|
||||
|
||||
it("Matches one attrbute", () => {
|
||||
const stateObj = {
|
||||
const stateObj: any = {
|
||||
attributes: {
|
||||
other_attr_1: 1,
|
||||
other_attr_2: 2,
|
||||
@ -32,7 +32,7 @@ describe("attributeClassNames", () => {
|
||||
});
|
||||
|
||||
it("Matches two attrbutes", () => {
|
||||
const stateObj = {
|
||||
const stateObj: any = {
|
||||
attributes: {
|
||||
other_attr_1: 1,
|
||||
other_attr_2: 2,
|
@ -3,7 +3,7 @@ import { assert } from "chai";
|
||||
import canToggleDomain from "../../../src/common/entity/can_toggle_domain";
|
||||
|
||||
describe("canToggleDomain", () => {
|
||||
const hass = {
|
||||
const hass: any = {
|
||||
services: {
|
||||
light: {
|
||||
turn_on: null, // Service keys only need to be present for test
|
@ -3,7 +3,7 @@ import { assert } from "chai";
|
||||
import canToggleState from "../../../src/common/entity/can_toggle_state";
|
||||
|
||||
describe("canToggleState", () => {
|
||||
const hass = {
|
||||
const hass: any = {
|
||||
services: {
|
||||
light: {
|
||||
turn_on: null, // Service keys only need to be present for test
|
||||
@ -13,7 +13,7 @@ describe("canToggleState", () => {
|
||||
};
|
||||
|
||||
it("Detects lights toggle", () => {
|
||||
const stateObj = {
|
||||
const stateObj: any = {
|
||||
entity_id: "light.bla",
|
||||
state: "on",
|
||||
};
|
||||
@ -21,7 +21,7 @@ describe("canToggleState", () => {
|
||||
});
|
||||
|
||||
it("Detects group with toggle", () => {
|
||||
const stateObj = {
|
||||
const stateObj: any = {
|
||||
entity_id: "group.bla",
|
||||
state: "on",
|
||||
};
|
||||
@ -29,7 +29,7 @@ describe("canToggleState", () => {
|
||||
});
|
||||
|
||||
it("Detects group without toggle", () => {
|
||||
const stateObj = {
|
||||
const stateObj: any = {
|
||||
entity_id: "group.devices",
|
||||
state: "home",
|
||||
};
|
||||
@ -37,7 +37,7 @@ describe("canToggleState", () => {
|
||||
});
|
||||
|
||||
it("Detects climate with toggle", () => {
|
||||
const stateObj = {
|
||||
const stateObj: any = {
|
||||
entity_id: "climate.bla",
|
||||
attributes: {
|
||||
supported_features: 4096,
|
||||
@ -47,8 +47,11 @@ describe("canToggleState", () => {
|
||||
});
|
||||
|
||||
it("Detects climate without toggle", () => {
|
||||
const stateObj = {
|
||||
const stateObj: any = {
|
||||
entity_id: "climate.bla",
|
||||
attributes: {
|
||||
supported_features: 0,
|
||||
},
|
||||
};
|
||||
assert.isFalse(canToggleState(hass, stateObj));
|
||||
});
|
@ -3,13 +3,12 @@ import { assert } from "chai";
|
||||
import computeStateDisplay from "../../../src/common/entity/compute_state_display";
|
||||
|
||||
describe("computeStateDisplay", () => {
|
||||
const localize = function(message, ...args) {
|
||||
// Mock Localize function for testing
|
||||
return message + (args.length ? ": " + args.join(",") : "");
|
||||
};
|
||||
// Mock Localize function for testing
|
||||
const localize = (message, ...args) =>
|
||||
message + (args.length ? ": " + args.join(",") : "");
|
||||
|
||||
it("Localizes binary sensor defaults", () => {
|
||||
const stateObj = {
|
||||
const stateObj: any = {
|
||||
entity_id: "binary_sensor.test",
|
||||
state: "off",
|
||||
attributes: {},
|
||||
@ -21,7 +20,7 @@ describe("computeStateDisplay", () => {
|
||||
});
|
||||
|
||||
it("Localizes binary sensor device class", () => {
|
||||
const stateObj = {
|
||||
const stateObj: any = {
|
||||
entity_id: "binary_sensor.test",
|
||||
state: "off",
|
||||
attributes: {
|
||||
@ -35,12 +34,13 @@ describe("computeStateDisplay", () => {
|
||||
});
|
||||
|
||||
it("Localizes binary sensor invalid device class", () => {
|
||||
const altLocalize = function(message, ...args) {
|
||||
if (message === "state.binary_sensor.invalid_device_class.off")
|
||||
return null;
|
||||
const altLocalize = (message, ...args) => {
|
||||
if (message === "state.binary_sensor.invalid_device_class.off") {
|
||||
return "";
|
||||
}
|
||||
return localize(message, ...args);
|
||||
};
|
||||
const stateObj = {
|
||||
const stateObj: any = {
|
||||
entity_id: "binary_sensor.test",
|
||||
state: "off",
|
||||
attributes: {
|
||||
@ -54,7 +54,7 @@ describe("computeStateDisplay", () => {
|
||||
});
|
||||
|
||||
it("Localizes sensor value with units", () => {
|
||||
const stateObj = {
|
||||
const stateObj: any = {
|
||||
entity_id: "sensor.test",
|
||||
state: "123",
|
||||
attributes: {
|
||||
@ -65,11 +65,13 @@ describe("computeStateDisplay", () => {
|
||||
});
|
||||
|
||||
it("Localizes unknown sensor value with units", () => {
|
||||
const altLocalize = function(message, ...args) {
|
||||
if (message === "state.sensor.unknown") return null;
|
||||
const altLocalize = (message, ...args) => {
|
||||
if (message === "state.sensor.unknown") {
|
||||
return "";
|
||||
}
|
||||
return localize(message, ...args);
|
||||
};
|
||||
const stateObj = {
|
||||
const stateObj: any = {
|
||||
entity_id: "sensor.test",
|
||||
state: "unknown",
|
||||
attributes: {
|
||||
@ -83,11 +85,13 @@ describe("computeStateDisplay", () => {
|
||||
});
|
||||
|
||||
it("Localizes unavailable sensor value with units", () => {
|
||||
const altLocalize = function(message, ...args) {
|
||||
if (message === "state.sensor.unavailable") return null;
|
||||
const altLocalize = (message, ...args) => {
|
||||
if (message === "state.sensor.unavailable") {
|
||||
return "";
|
||||
}
|
||||
return localize(message, ...args);
|
||||
};
|
||||
const stateObj = {
|
||||
const stateObj: any = {
|
||||
entity_id: "sensor.test",
|
||||
state: "unavailable",
|
||||
attributes: {
|
||||
@ -101,11 +105,13 @@ describe("computeStateDisplay", () => {
|
||||
});
|
||||
|
||||
it("Localizes sensor value with component translation", () => {
|
||||
const altLocalize = function(message, ...args) {
|
||||
if (message !== "component.sensor.state.custom_state") return null;
|
||||
const altLocalize = (message, ...args) => {
|
||||
if (message !== "component.sensor.state.custom_state") {
|
||||
return "";
|
||||
}
|
||||
return localize(message, ...args);
|
||||
};
|
||||
const stateObj = {
|
||||
const stateObj: any = {
|
||||
entity_id: "sensor.test",
|
||||
state: "custom_state",
|
||||
attributes: {},
|
||||
@ -117,7 +123,7 @@ describe("computeStateDisplay", () => {
|
||||
});
|
||||
|
||||
it("Localizes input_datetime with full date time", () => {
|
||||
const stateObj = {
|
||||
const stateObj: any = {
|
||||
entity_id: "input_datetime.test",
|
||||
state: "123",
|
||||
attributes: {
|
||||
@ -138,7 +144,7 @@ describe("computeStateDisplay", () => {
|
||||
});
|
||||
|
||||
it("Localizes input_datetime with date", () => {
|
||||
const stateObj = {
|
||||
const stateObj: any = {
|
||||
entity_id: "input_datetime.test",
|
||||
state: "123",
|
||||
attributes: {
|
||||
@ -159,7 +165,7 @@ describe("computeStateDisplay", () => {
|
||||
});
|
||||
|
||||
it("Localizes input_datetime with time", () => {
|
||||
const stateObj = {
|
||||
const stateObj: any = {
|
||||
entity_id: "input_datetime.test",
|
||||
state: "123",
|
||||
attributes: {
|
||||
@ -180,7 +186,7 @@ describe("computeStateDisplay", () => {
|
||||
});
|
||||
|
||||
it("Localizes zwave ready", () => {
|
||||
const stateObj = {
|
||||
const stateObj: any = {
|
||||
entity_id: "zwave.test",
|
||||
state: "ready",
|
||||
attributes: {
|
||||
@ -194,7 +200,7 @@ describe("computeStateDisplay", () => {
|
||||
});
|
||||
|
||||
it("Localizes zwave initializing", () => {
|
||||
const stateObj = {
|
||||
const stateObj: any = {
|
||||
entity_id: "zwave.test",
|
||||
state: "initializing",
|
||||
attributes: {
|
||||
@ -208,7 +214,7 @@ describe("computeStateDisplay", () => {
|
||||
});
|
||||
|
||||
it("Localizes cover open", () => {
|
||||
const stateObj = {
|
||||
const stateObj: any = {
|
||||
entity_id: "cover.test",
|
||||
state: "open",
|
||||
attributes: {},
|
||||
@ -220,11 +226,13 @@ describe("computeStateDisplay", () => {
|
||||
});
|
||||
|
||||
it("Localizes unavailable", () => {
|
||||
const altLocalize = function(message, ...args) {
|
||||
if (message === "state.sensor.unavailable") return null;
|
||||
const altLocalize = (message, ...args) => {
|
||||
if (message === "state.sensor.unavailable") {
|
||||
return "";
|
||||
}
|
||||
return localize(message, ...args);
|
||||
};
|
||||
const stateObj = {
|
||||
const stateObj: any = {
|
||||
entity_id: "sensor.test",
|
||||
state: "unavailable",
|
||||
attributes: {},
|
||||
@ -236,11 +244,11 @@ describe("computeStateDisplay", () => {
|
||||
});
|
||||
|
||||
it("Localizes custom state", () => {
|
||||
const altLocalize = function() {
|
||||
const altLocalize = () => {
|
||||
// No matches can be found
|
||||
return null;
|
||||
return "";
|
||||
};
|
||||
const stateObj = {
|
||||
const stateObj: any = {
|
||||
entity_id: "sensor.test",
|
||||
state: "My Custom State",
|
||||
attributes: {},
|
||||
@ -252,7 +260,7 @@ describe("computeStateDisplay", () => {
|
||||
});
|
||||
|
||||
it("Only calculates state display once per immutable state object", () => {
|
||||
const stateObj = {
|
||||
const stateObj: any = {
|
||||
entity_id: "cover.test",
|
||||
state: "open",
|
||||
attributes: {},
|
@ -4,7 +4,7 @@ import computeStateDomain from "../../../src/common/entity/compute_state_domain"
|
||||
|
||||
describe("computeStateDomain", () => {
|
||||
it("Detects sensor domain", () => {
|
||||
const stateObj = {
|
||||
const stateObj: any = {
|
||||
entity_id: "sensor.test",
|
||||
};
|
||||
assert.strictEqual(computeStateDomain(stateObj), "sensor");
|
@ -1,4 +1,4 @@
|
||||
import assert from "assert";
|
||||
import * as assert from "assert";
|
||||
|
||||
import extractViews from "../../../src/common/entity/extract_views";
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { assert } from "chai";
|
||||
|
||||
import featureClassNames from "../../../src/common/entity/feature_class_names";
|
||||
import { HassEntity } from "home-assistant-js-websocket";
|
||||
|
||||
describe("featureClassNames", () => {
|
||||
const classNames = {
|
||||
@ -12,11 +13,12 @@ describe("featureClassNames", () => {
|
||||
|
||||
it("Skips null states", () => {
|
||||
const stateObj = null;
|
||||
assert.strictEqual(featureClassNames(stateObj, classNames), "");
|
||||
assert.strictEqual(featureClassNames(stateObj!, classNames), "");
|
||||
});
|
||||
|
||||
it("Matches no features", () => {
|
||||
const stateObj = {
|
||||
// tslint:disable-next-line
|
||||
const stateObj = <HassEntity>{
|
||||
attributes: {
|
||||
supported_features: 64,
|
||||
},
|
||||
@ -25,7 +27,8 @@ describe("featureClassNames", () => {
|
||||
});
|
||||
|
||||
it("Matches one feature", () => {
|
||||
const stateObj = {
|
||||
// tslint:disable-next-line
|
||||
const stateObj = <HassEntity>{
|
||||
attributes: {
|
||||
supported_features: 72,
|
||||
},
|
||||
@ -37,7 +40,8 @@ describe("featureClassNames", () => {
|
||||
});
|
||||
|
||||
it("Matches two features", () => {
|
||||
const stateObj = {
|
||||
// tslint:disable-next-line
|
||||
const stateObj = <HassEntity>{
|
||||
attributes: {
|
||||
supported_features: 73,
|
||||
},
|
@ -1,4 +1,4 @@
|
||||
import assert from "assert";
|
||||
import * as assert from "assert";
|
||||
|
||||
import getGroupEntities from "../../../src/common/entity/get_group_entities";
|
||||
|
@ -1,4 +1,4 @@
|
||||
import assert from "assert";
|
||||
import * as assert from "assert";
|
||||
|
||||
import getViewEntities from "../../../src/common/entity/get_view_entities";
|
||||
|
@ -4,7 +4,7 @@ import hasLocation from "../../../src/common/entity/has_location";
|
||||
|
||||
describe("hasLocation", () => {
|
||||
it("flags states with location", () => {
|
||||
const stateObj = {
|
||||
const stateObj: any = {
|
||||
attributes: {
|
||||
latitude: 12.34,
|
||||
longitude: 12.34,
|
||||
@ -13,7 +13,7 @@ describe("hasLocation", () => {
|
||||
assert(hasLocation(stateObj));
|
||||
});
|
||||
it("does not flag states with only latitude", () => {
|
||||
const stateObj = {
|
||||
const stateObj: any = {
|
||||
attributes: {
|
||||
latitude: 12.34,
|
||||
},
|
||||
@ -21,7 +21,7 @@ describe("hasLocation", () => {
|
||||
assert(!hasLocation(stateObj));
|
||||
});
|
||||
it("does not flag states with only longitude", () => {
|
||||
const stateObj = {
|
||||
const stateObj: any = {
|
||||
attributes: {
|
||||
longitude: 12.34,
|
||||
},
|
||||
@ -29,7 +29,7 @@ describe("hasLocation", () => {
|
||||
assert(!hasLocation(stateObj));
|
||||
});
|
||||
it("does not flag states with no location", () => {
|
||||
const stateObj = {
|
||||
const stateObj: any = {
|
||||
attributes: {},
|
||||
};
|
||||
assert(!hasLocation(stateObj));
|
@ -1,4 +1,4 @@
|
||||
import assert from "assert";
|
||||
import * as assert from "assert";
|
||||
|
||||
import splitByGroups from "../../../src/common/entity/split_by_groups";
|
||||
|
@ -3,7 +3,7 @@ import { assert } from "chai";
|
||||
import stateCardType from "../../../src/common/entity/state_card_type";
|
||||
|
||||
describe("stateCardType", () => {
|
||||
const hass = {
|
||||
const hass: any = {
|
||||
services: {
|
||||
light: {
|
||||
turn_on: null, // Service keys only need to be present for test
|
||||
@ -13,21 +13,21 @@ describe("stateCardType", () => {
|
||||
};
|
||||
|
||||
it("Returns display for unavailable states", () => {
|
||||
const stateObj = {
|
||||
const stateObj: any = {
|
||||
state: "unavailable",
|
||||
};
|
||||
assert.strictEqual(stateCardType(hass, stateObj), "display");
|
||||
});
|
||||
|
||||
it("Returns media_player for media_player states", () => {
|
||||
const stateObj = {
|
||||
const stateObj: any = {
|
||||
entity_id: "media_player.bla",
|
||||
};
|
||||
assert.strictEqual(stateCardType(hass, stateObj), "media_player");
|
||||
});
|
||||
|
||||
it("Returns toggle for states that can toggle", () => {
|
||||
const stateObj = {
|
||||
const stateObj: any = {
|
||||
entity_id: "light.bla",
|
||||
attributes: {},
|
||||
};
|
||||
@ -35,7 +35,7 @@ describe("stateCardType", () => {
|
||||
});
|
||||
|
||||
it("Returns display for states with hidden control", () => {
|
||||
const stateObj = {
|
||||
const stateObj: any = {
|
||||
entity_id: "light.bla",
|
||||
attributes: {
|
||||
control: "hidden",
|
||||
@ -45,7 +45,7 @@ describe("stateCardType", () => {
|
||||
});
|
||||
|
||||
it("Returns display for entities that cannot toggle", () => {
|
||||
const stateObj = {
|
||||
const stateObj: any = {
|
||||
entity_id: "sensor.bla",
|
||||
};
|
||||
assert.strictEqual(stateCardType(hass, stateObj), "display");
|
@ -4,14 +4,14 @@ import stateMoreInfoType from "../../../src/common/entity/state_more_info_type";
|
||||
|
||||
describe("stateMoreInfoType", () => {
|
||||
it("Returns media_player for media_player states", () => {
|
||||
const stateObj = {
|
||||
const stateObj: any = {
|
||||
entity_id: "media_player.bla",
|
||||
};
|
||||
assert.strictEqual(stateMoreInfoType(stateObj), "media_player");
|
||||
});
|
||||
|
||||
it("Returns hidden for input_select states", () => {
|
||||
const stateObj = {
|
||||
const stateObj: any = {
|
||||
entity_id: "input_select.bla",
|
||||
attributes: {},
|
||||
};
|
||||
@ -19,7 +19,7 @@ describe("stateMoreInfoType", () => {
|
||||
});
|
||||
|
||||
it("Returns default for switch states", () => {
|
||||
const stateObj = {
|
||||
const stateObj: any = {
|
||||
entity_id: "switch.bla",
|
||||
attributes: {},
|
||||
};
|
@ -27,7 +27,7 @@ export function createView(entity) {
|
||||
return createGroup(entity);
|
||||
}
|
||||
|
||||
export function createLightEntity(isOn) {
|
||||
export function createLightEntity(isOn?) {
|
||||
mockState++;
|
||||
if (isOn === undefined) {
|
||||
isOn = Math.random() > 0.5;
|
@ -1,5 +1,5 @@
|
||||
import { assert } from "chai";
|
||||
import sinon from "sinon";
|
||||
import * as sinon from "sinon";
|
||||
|
||||
import timerTimeRemaining from "../../../src/common/entity/timer_time_remaining";
|
||||
|
||||
@ -11,7 +11,7 @@ describe("timerTimeRemaining", () => {
|
||||
attributes: {
|
||||
remaining: "0:01:05",
|
||||
},
|
||||
}),
|
||||
} as any),
|
||||
65
|
||||
);
|
||||
});
|
||||
@ -23,7 +23,7 @@ describe("timerTimeRemaining", () => {
|
||||
attributes: {
|
||||
remaining: "0:01:05",
|
||||
},
|
||||
}),
|
||||
} as any),
|
||||
65
|
||||
);
|
||||
});
|
||||
@ -44,7 +44,7 @@ describe("timerTimeRemaining", () => {
|
||||
remaining: "0:01:05",
|
||||
},
|
||||
last_changed: "2018-01-17T16:15:12Z",
|
||||
}),
|
||||
} as any),
|
||||
47
|
||||
);
|
||||
});
|
@ -1,4 +1,4 @@
|
||||
import assert from "assert";
|
||||
import * as assert from "assert";
|
||||
|
||||
import parseAspectRatio from "../../../src/common/util/parse-aspect-ratio";
|
||||
|
@ -1,4 +1,3 @@
|
||||
--recursive
|
||||
--require reify
|
||||
--timeout 10000
|
||||
test-mocha
|
||||
test-mocha/**/*.ts
|
||||
|
6
test-mocha/tsconfig.test.json
Normal file
6
test-mocha/tsconfig.test.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"extends": "../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"module": "commonjs"
|
||||
}
|
||||
}
|
6
test-mocha/tslint.json
Normal file
6
test-mocha/tslint.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"extends": ["../tslint.json"],
|
||||
"rules": {
|
||||
"no-implicit-dependencies": [true, "dev"]
|
||||
}
|
||||
}
|
150
yarn.lock
150
yarn.lock
@ -1372,10 +1372,10 @@
|
||||
dependencies:
|
||||
any-observable "^0.3.0"
|
||||
|
||||
"@sinonjs/commons@^1.0.2":
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.0.2.tgz#3e0ac737781627b8844257fadc3d803997d0526e"
|
||||
integrity sha512-WR3dlgqJP4QNrLC4iXN/5/2WaLQQ0VijOOkmflqFGVJ6wLEpbSjo7c0ZeGIdtY8Crk7xBBp87sM6+Mkerz7alw==
|
||||
"@sinonjs/commons@^1.2.0":
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.3.0.tgz#50a2754016b6f30a994ceda6d9a0a8c36adda849"
|
||||
integrity sha512-j4ZwhaHmwsCb4DlDOIWnI5YyKDNMoNThsmwEpfHx6a1EpsGZ9qYLxP++LMlmBRjtGptGHFsGItJ768snllFWpA==
|
||||
dependencies:
|
||||
type-detect "4.0.8"
|
||||
|
||||
@ -1449,7 +1449,7 @@
|
||||
dependencies:
|
||||
"@types/chai" "*"
|
||||
|
||||
"@types/chai@*":
|
||||
"@types/chai@*", "@types/chai@^4.1.7":
|
||||
version "4.1.7"
|
||||
resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.1.7.tgz#1b8e33b61a8c09cbe1f85133071baa0dbf9fa71a"
|
||||
integrity sha512-2Y8uPt0/jwjhQ6EiluT0XCri1Dbplr0ZxfFXUz+ye13gaqE8u5gL5ppao1JrUYr9cIip5S6MvQzBS7Kke7U9VA==
|
||||
@ -1624,6 +1624,11 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/is-windows/-/is-windows-0.2.0.tgz#6f24ee48731d31168ea510610d6dd15e5fc9c6ff"
|
||||
integrity sha1-byTuSHMdMRaOpRBhDW3RXl/Jxv8=
|
||||
|
||||
"@types/json5@^0.0.29":
|
||||
version "0.0.29"
|
||||
resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee"
|
||||
integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4=
|
||||
|
||||
"@types/launchpad@^0.6.0":
|
||||
version "0.6.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/launchpad/-/launchpad-0.6.0.tgz#37296109b7f277f6e6c5fd7e0c0706bc918fbb51"
|
||||
@ -1646,6 +1651,11 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d"
|
||||
integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==
|
||||
|
||||
"@types/mocha@^5.2.5":
|
||||
version "5.2.5"
|
||||
resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-5.2.5.tgz#8a4accfc403c124a0bafe8a9fc61a05ec1032073"
|
||||
integrity sha512-lAVp+Kj54ui/vLUFxsJTMtWvZraZxum3w3Nwkble2dNuV5VnPA+Mi2oGX9XYJAaIvZi3tn3cbjS/qcJXRb6Bww==
|
||||
|
||||
"@types/mz@0.0.29":
|
||||
version "0.0.29"
|
||||
resolved "https://registry.yarnpkg.com/@types/mz/-/mz-0.0.29.tgz#bc24728c649973f1c7851e9033f9ce525668c27b"
|
||||
@ -3667,11 +3677,6 @@ browser-stdout@1.3.0:
|
||||
resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.0.tgz#f351d32969d32fa5d7a5567154263d928ae3bd1f"
|
||||
integrity sha1-81HTKWnTL6XXpVZxVCY9korjvR8=
|
||||
|
||||
browser-stdout@1.3.1:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60"
|
||||
integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==
|
||||
|
||||
browserify-aes@^1.0.0, browserify-aes@^1.0.4:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48"
|
||||
@ -3777,7 +3782,7 @@ buffer-fill@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c"
|
||||
integrity sha1-+PeLdniYiO858gXNY39o5wISKyw=
|
||||
|
||||
buffer-from@^1.0.0:
|
||||
buffer-from@^1.0.0, buffer-from@^1.1.0:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef"
|
||||
integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==
|
||||
@ -3965,7 +3970,7 @@ chai@^3.5.0:
|
||||
deep-eql "^0.1.3"
|
||||
type-detect "^1.0.0"
|
||||
|
||||
chai@^4.1.2:
|
||||
chai@^4.2.0:
|
||||
version "4.2.0"
|
||||
resolved "https://registry.yarnpkg.com/chai/-/chai-4.2.0.tgz#760aa72cf20e3795e84b12877ce0e83737aa29e5"
|
||||
integrity sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==
|
||||
@ -4369,7 +4374,7 @@ command-line-usage@^5.0.5:
|
||||
table-layout "^0.4.3"
|
||||
typical "^2.6.1"
|
||||
|
||||
commander@2.15.1, commander@2.15.x, commander@~2.15.0:
|
||||
commander@2.15.x, commander@~2.15.0:
|
||||
version "2.15.1"
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f"
|
||||
integrity sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==
|
||||
@ -4848,7 +4853,7 @@ debug@2.6.8:
|
||||
dependencies:
|
||||
ms "2.0.0"
|
||||
|
||||
debug@3.1.0, debug@=3.1.0, debug@~3.1.0:
|
||||
debug@=3.1.0, debug@~3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
|
||||
integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==
|
||||
@ -4939,6 +4944,11 @@ deep-is@~0.1.3:
|
||||
resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34"
|
||||
integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=
|
||||
|
||||
deepmerge@^2.0.1:
|
||||
version "2.2.1"
|
||||
resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-2.2.1.tgz#5d3ff22a01c00f645405a2fbc17d0778a1801170"
|
||||
integrity sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==
|
||||
|
||||
default-gateway@^2.6.0:
|
||||
version "2.7.2"
|
||||
resolved "https://registry.yarnpkg.com/default-gateway/-/default-gateway-2.7.2.tgz#b7ef339e5e024b045467af403d50348db4642d0f"
|
||||
@ -5118,16 +5128,16 @@ diff@3.2.0:
|
||||
resolved "https://registry.yarnpkg.com/diff/-/diff-3.2.0.tgz#c9ce393a4b7cbd0b058a725c93df299027868ff9"
|
||||
integrity sha1-yc45Okt8vQsFinJck98pkCeGj/k=
|
||||
|
||||
diff@3.5.0, diff@^3.1.0, diff@^3.2.0, diff@^3.5.0:
|
||||
version "3.5.0"
|
||||
resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12"
|
||||
integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==
|
||||
|
||||
diff@^2.1.2:
|
||||
version "2.2.3"
|
||||
resolved "https://registry.yarnpkg.com/diff/-/diff-2.2.3.tgz#60eafd0d28ee906e4e8ff0a52c1229521033bf99"
|
||||
integrity sha1-YOr9DSjukG5Oj/ClLBIpUhAzv5k=
|
||||
|
||||
diff@^3.1.0, diff@^3.2.0, diff@^3.5.0:
|
||||
version "3.5.0"
|
||||
resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12"
|
||||
integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==
|
||||
|
||||
diffie-hellman@^5.0.0:
|
||||
version "5.0.3"
|
||||
resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875"
|
||||
@ -6772,18 +6782,6 @@ glob@7.1.1:
|
||||
once "^1.3.0"
|
||||
path-is-absolute "^1.0.0"
|
||||
|
||||
glob@7.1.2:
|
||||
version "7.1.2"
|
||||
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15"
|
||||
integrity sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==
|
||||
dependencies:
|
||||
fs.realpath "^1.0.0"
|
||||
inflight "^1.0.4"
|
||||
inherits "2"
|
||||
minimatch "^3.0.4"
|
||||
once "^1.3.0"
|
||||
path-is-absolute "^1.0.0"
|
||||
|
||||
glob@^4.3.1:
|
||||
version "4.5.3"
|
||||
resolved "https://registry.yarnpkg.com/glob/-/glob-4.5.3.tgz#c6cb73d3226c1efef04de3c56d012f03377ee15f"
|
||||
@ -7065,11 +7063,6 @@ grouped-queue@^0.3.0, grouped-queue@^0.3.3:
|
||||
dependencies:
|
||||
lodash "^4.17.2"
|
||||
|
||||
growl@1.10.5:
|
||||
version "1.10.5"
|
||||
resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e"
|
||||
integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==
|
||||
|
||||
growl@1.9.2:
|
||||
version "1.9.2"
|
||||
resolved "https://registry.yarnpkg.com/growl/-/growl-1.9.2.tgz#0ea7743715db8d8de2c5ede1775e1b45ac85c02f"
|
||||
@ -9334,6 +9327,11 @@ make-dir@^1.0.0, make-dir@^1.1.0:
|
||||
dependencies:
|
||||
pify "^3.0.0"
|
||||
|
||||
make-error@^1.1.1:
|
||||
version "1.3.5"
|
||||
resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.5.tgz#efe4e81f6db28cadd605c70f29c831b58ef776c8"
|
||||
integrity sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g==
|
||||
|
||||
map-age-cleaner@^0.1.1:
|
||||
version "0.1.2"
|
||||
resolved "https://registry.yarnpkg.com/map-age-cleaner/-/map-age-cleaner-0.1.2.tgz#098fb15538fd3dbe461f12745b0ca8568d4e3f74"
|
||||
@ -9599,7 +9597,7 @@ minimatch-all@^1.1.0:
|
||||
dependencies:
|
||||
minimatch "^3.0.2"
|
||||
|
||||
"minimatch@2 || 3", minimatch@3.0.4, minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4:
|
||||
"minimatch@2 || 3", minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4:
|
||||
version "3.0.4"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
|
||||
integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
|
||||
@ -9721,23 +9719,6 @@ mocha@^3.4.2:
|
||||
mkdirp "0.5.1"
|
||||
supports-color "3.1.2"
|
||||
|
||||
mocha@^5.2.0:
|
||||
version "5.2.0"
|
||||
resolved "https://registry.yarnpkg.com/mocha/-/mocha-5.2.0.tgz#6d8ae508f59167f940f2b5b3c4a612ae50c90ae6"
|
||||
integrity sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==
|
||||
dependencies:
|
||||
browser-stdout "1.3.1"
|
||||
commander "2.15.1"
|
||||
debug "3.1.0"
|
||||
diff "3.5.0"
|
||||
escape-string-regexp "1.0.5"
|
||||
glob "7.1.2"
|
||||
growl "1.10.5"
|
||||
he "1.1.1"
|
||||
minimatch "3.0.4"
|
||||
mkdirp "0.5.1"
|
||||
supports-color "5.4.0"
|
||||
|
||||
moment@^2.10.2, moment@^2.22.0:
|
||||
version "2.22.1"
|
||||
resolved "https://registry.yarnpkg.com/moment/-/moment-2.22.1.tgz#529a2e9bf973f259c9643d237fda84de3a26e8ad"
|
||||
@ -12321,12 +12302,12 @@ sinon@^2.3.5:
|
||||
text-encoding "0.6.4"
|
||||
type-detect "^4.0.0"
|
||||
|
||||
sinon@^7.1.0:
|
||||
version "7.1.0"
|
||||
resolved "https://registry.yarnpkg.com/sinon/-/sinon-7.1.0.tgz#819b63002ee09a90a3b50a0da4e0bdecb2e3f345"
|
||||
integrity sha512-ffASxced8xr8eU0EGyfj9K++bRCtv/NyOFOxl7UBD86YH97oZjVxvecMhObwRlXe27GRUa6rVFEn67khPZ29rQ==
|
||||
sinon@^7.1.1:
|
||||
version "7.1.1"
|
||||
resolved "https://registry.yarnpkg.com/sinon/-/sinon-7.1.1.tgz#1202f317aa14d93cb9b69ff50b6bd49c0e05ffc9"
|
||||
integrity sha512-iYagtjLVt1vN3zZY7D8oH7dkjNJEjLjyuzy8daX5+3bbQl8gaohrheB9VfH1O3L6LKuue5WTJvFluHiuZ9y3nQ==
|
||||
dependencies:
|
||||
"@sinonjs/commons" "^1.0.2"
|
||||
"@sinonjs/commons" "^1.2.0"
|
||||
"@sinonjs/formatio" "^3.0.0"
|
||||
"@sinonjs/samsam" "^2.1.2"
|
||||
diff "^3.5.0"
|
||||
@ -12503,6 +12484,14 @@ source-map-support@^0.4.15:
|
||||
dependencies:
|
||||
source-map "^0.5.6"
|
||||
|
||||
source-map-support@^0.5.6:
|
||||
version "0.5.9"
|
||||
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.9.tgz#41bc953b2534267ea2d605bccfa7bfa3111ced5f"
|
||||
integrity sha512-gR6Rw4MvUlYy83vP0vxoVNzM6t8MUXqNuRsuBmBHQDu1Fh6X015FrLdgoDKcNdkwGubozq0P4N0Q37UyFVr1EA==
|
||||
dependencies:
|
||||
buffer-from "^1.0.0"
|
||||
source-map "^0.6.0"
|
||||
|
||||
source-map-url@^0.4.0:
|
||||
version "0.4.0"
|
||||
resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3"
|
||||
@ -12513,7 +12502,7 @@ source-map@0.5.x, source-map@^0.5.0, source-map@^0.5.6, source-map@^0.5.7, sourc
|
||||
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
|
||||
integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=
|
||||
|
||||
source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1:
|
||||
source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1:
|
||||
version "0.6.1"
|
||||
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
|
||||
integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
|
||||
@ -12875,7 +12864,7 @@ strip-json-comments@^2.0.1, strip-json-comments@~2.0.1:
|
||||
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
|
||||
integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo=
|
||||
|
||||
supports-color@3.1.2, supports-color@5.4.0, supports-color@^0.2.0, supports-color@^2.0.0, supports-color@^5.1.0, supports-color@^5.3.0, supports-color@^5.4.0, supports-color@^5.5.0:
|
||||
supports-color@3.1.2, supports-color@^0.2.0, supports-color@^2.0.0, supports-color@^5.1.0, supports-color@^5.3.0, supports-color@^5.4.0, supports-color@^5.5.0:
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.1.2.tgz#72a262894d9d408b956ca05ff37b2ed8a6e2a2d5"
|
||||
integrity sha1-cqJiiU2dQIuVbKBf83su2KbiotU=
|
||||
@ -13251,6 +13240,40 @@ triple-beam@^1.2.0, triple-beam@^1.3.0:
|
||||
resolved "https://registry.yarnpkg.com/triple-beam/-/triple-beam-1.3.0.tgz#a595214c7298db8339eeeee083e4d10bd8cb8dd9"
|
||||
integrity sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw==
|
||||
|
||||
ts-mocha@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/ts-mocha/-/ts-mocha-2.0.0.tgz#0dbd3cd04671df9933b9303b4aa46347573c5635"
|
||||
integrity sha512-Rj6+vvwKtOTs5GsNO1jLl4DIXUGnyAg5HFt2Yb4SHIRN45clTJkHWpNdTxCSL0u+1oeavSYJah6d1PZ++Ju5pw==
|
||||
dependencies:
|
||||
ts-node "7.0.0"
|
||||
optionalDependencies:
|
||||
tsconfig-paths "^3.5.0"
|
||||
|
||||
ts-node@7.0.0:
|
||||
version "7.0.0"
|
||||
resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-7.0.0.tgz#a94a13c75e5e1aa6b82814b84c68deb339ba7bff"
|
||||
integrity sha512-klJsfswHP0FuOLsvBZ/zzCfUvakOSSxds78mVeK7I+qP76YWtxf16hEZsp3U+b0kIo82R5UatGFeblYMqabb2Q==
|
||||
dependencies:
|
||||
arrify "^1.0.0"
|
||||
buffer-from "^1.1.0"
|
||||
diff "^3.1.0"
|
||||
make-error "^1.1.1"
|
||||
minimist "^1.2.0"
|
||||
mkdirp "^0.5.1"
|
||||
source-map-support "^0.5.6"
|
||||
yn "^2.0.0"
|
||||
|
||||
tsconfig-paths@^3.5.0:
|
||||
version "3.6.0"
|
||||
resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.6.0.tgz#f14078630d9d6e8b1dc690c1fc0cfb9cd0663891"
|
||||
integrity sha512-mrqQIP2F4e03aMTCiPdedCIT300//+q0ET53o5WqqtQjmEICxP9yfz/sHTpPqXpssuJEzODsEzJaLRaf5J2X1g==
|
||||
dependencies:
|
||||
"@types/json5" "^0.0.29"
|
||||
deepmerge "^2.0.1"
|
||||
json5 "^1.0.1"
|
||||
minimist "^1.2.0"
|
||||
strip-bom "^3.0.0"
|
||||
|
||||
tslib@1.9.0:
|
||||
version "1.9.0"
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.0.tgz#e37a86fda8cbbaf23a057f473c9f4dc64e5fc2e8"
|
||||
@ -14645,6 +14668,11 @@ yeoman-generator@^3.1.1:
|
||||
through2 "^2.0.0"
|
||||
yeoman-environment "^2.0.5"
|
||||
|
||||
yn@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/yn/-/yn-2.0.0.tgz#e5adabc8acf408f6385fc76495684c88e6af689a"
|
||||
integrity sha1-5a2ryKz0CPY4X8dklWhMiOavaJo=
|
||||
|
||||
zip-stream@^1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/zip-stream/-/zip-stream-1.2.0.tgz#a8bc45f4c1b49699c6b90198baacaacdbcd4ba04"
|
||||
|
Loading…
x
Reference in New Issue
Block a user