mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-18 23:06:40 +00:00
Separate more JS util logic to be unit tested (#705)
* Move featureClassNames to js util * Add tests for featureClassNames * Strip empty feature class names * Move canToggleDomain to js util * Add tests for canToggleDomain * Refactor canToggleDomain to ensure boolean return * Switch to chai assert for richer syntax options * Move canToggleState to js util * Tests for canToggleState * Enable linting for mocha tests * Move stateCardType to js util * Add tests for stateCardType * Move stateMoreInfoType to js util * Tests for stateMoreInfoType * Include mdn Array includes polyfill
This commit is contained in:
parent
c1e7f4cc77
commit
a723c62f4f
11
js/common/util/can_toggle_domain.js
Normal file
11
js/common/util/can_toggle_domain.js
Normal file
@ -0,0 +1,11 @@
|
||||
export default function canToggleDomain(hass, domain) {
|
||||
const services = hass.config.services[domain];
|
||||
if (!services) { return false; }
|
||||
|
||||
if (domain === 'lock') {
|
||||
return 'lock' in services;
|
||||
} else if (domain === 'cover') {
|
||||
return 'open_cover' in services;
|
||||
}
|
||||
return 'turn_on' in services;
|
||||
}
|
11
js/common/util/can_toggle_state.js
Normal file
11
js/common/util/can_toggle_state.js
Normal file
@ -0,0 +1,11 @@
|
||||
import canToggleDomain from './can_toggle_domain.js';
|
||||
import computeStateDomain from './compute_state_domain.js';
|
||||
|
||||
export default function canToggleState(hass, stateObj) {
|
||||
const domain = computeStateDomain(stateObj);
|
||||
if (domain === 'group') {
|
||||
return stateObj.state === 'on' || stateObj.state === 'off';
|
||||
}
|
||||
|
||||
return canToggleDomain(hass, domain);
|
||||
}
|
10
js/common/util/feature_class_names.js
Normal file
10
js/common/util/feature_class_names.js
Normal file
@ -0,0 +1,10 @@
|
||||
// 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(' ');
|
||||
}
|
31
js/common/util/state_card_type.js
Normal file
31
js/common/util/state_card_type.js
Normal file
@ -0,0 +1,31 @@
|
||||
import canToggleState from './can_toggle_state.js';
|
||||
import computeStateDomain from './compute_state_domain.js';
|
||||
|
||||
const DOMAINS_WITH_CARD = [
|
||||
'climate',
|
||||
'cover',
|
||||
'configurator',
|
||||
'input_select',
|
||||
'input_number',
|
||||
'input_text',
|
||||
'media_player',
|
||||
'scene',
|
||||
'script',
|
||||
'weblink',
|
||||
];
|
||||
|
||||
export default function stateCardType(hass, stateObj) {
|
||||
if (stateObj.state === 'unavailable') {
|
||||
return 'display';
|
||||
}
|
||||
|
||||
const domain = computeStateDomain(stateObj);
|
||||
|
||||
if (DOMAINS_WITH_CARD.includes(domain)) {
|
||||
return domain;
|
||||
} else if (canToggleState(hass, stateObj) &&
|
||||
stateObj.attributes.control !== 'hidden') {
|
||||
return 'toggle';
|
||||
}
|
||||
return 'display';
|
||||
}
|
23
js/common/util/state_more_info_type.js
Normal file
23
js/common/util/state_more_info_type.js
Normal file
@ -0,0 +1,23 @@
|
||||
import computeStateDomain from './compute_state_domain.js';
|
||||
|
||||
const DOMAINS_WITH_MORE_INFO = [
|
||||
'alarm_control_panel', 'automation', 'camera', 'climate', 'configurator',
|
||||
'cover', 'fan', 'group', 'history_graph', 'light', 'lock', 'media_player', 'script',
|
||||
'sun', 'updater', 'vacuum', 'input_datetime',
|
||||
];
|
||||
|
||||
const HIDE_MORE_INFO = [
|
||||
'input_select', 'scene', 'input_number', 'input_text'
|
||||
];
|
||||
|
||||
export default function stateMoreInfoType(stateObj) {
|
||||
const domain = computeStateDomain(stateObj);
|
||||
|
||||
if (DOMAINS_WITH_MORE_INFO.includes(domain)) {
|
||||
return domain;
|
||||
}
|
||||
if (HIDE_MORE_INFO.includes(domain)) {
|
||||
return 'hidden';
|
||||
}
|
||||
return 'default';
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
import 'mdn-polyfills/Array.prototype.includes';
|
||||
import 'unfetch/polyfill';
|
||||
import objAssign from 'es6-object-assign';
|
||||
|
||||
|
10
js/util.js
10
js/util.js
@ -7,11 +7,16 @@
|
||||
*/
|
||||
|
||||
import attributeClassNames from './common/util/attribute_class_names.js';
|
||||
import canToggleDomain from './common/util/can_toggle_domain.js';
|
||||
import canToggleState from './common/util/can_toggle_state.js';
|
||||
import computeStateDomain from './common/util/compute_state_domain.js';
|
||||
import computeStateDisplay from './common/util/compute_state_display.js';
|
||||
import featureClassNames from './common/util/feature_class_names.js';
|
||||
import formatDate from './common/util/format_date.js';
|
||||
import formatDateTime from './common/util/format_date_time.js';
|
||||
import formatTime from './common/util/format_time.js';
|
||||
import stateCardType from './common/util/state_card_type.js';
|
||||
import stateMoreInfoType from './common/util/state_more_info_type.js';
|
||||
|
||||
window.hassUtil = window.hassUtil || {};
|
||||
|
||||
@ -21,8 +26,13 @@ const language = navigator.languages ?
|
||||
window.fecha.masks.haDateTime = window.fecha.masks.shortTime + ' ' + window.fecha.masks.mediumDate;
|
||||
|
||||
window.hassUtil.attributeClassNames = attributeClassNames;
|
||||
window.hassUtil.canToggleDomain = canToggleDomain;
|
||||
window.hassUtil.canToggleState = canToggleState;
|
||||
window.hassUtil.computeDomain = computeStateDomain;
|
||||
window.hassUtil.computeStateDisplay = computeStateDisplay;
|
||||
window.hassUtil.featureClassNames = featureClassNames;
|
||||
window.hassUtil.formatDate = dateObj => formatDate(dateObj, language);
|
||||
window.hassUtil.formatDateTime = dateObj => formatDateTime(dateObj, language);
|
||||
window.hassUtil.formatTime = dateObj => formatTime(dateObj, language);
|
||||
window.hassUtil.stateCardType = stateCardType;
|
||||
window.hassUtil.stateMoreInfoType = stateMoreInfoType;
|
||||
|
@ -15,7 +15,7 @@
|
||||
"dev-watch": "npm run gulp watch_ru_all gen-service-worker",
|
||||
"dev-es5": "npm run gulp ru_all_es5 gen-service-worker-es5",
|
||||
"dev-watch-es5": "npm run gulp watch_ru_all_es5 gen-service-worker-es5",
|
||||
"lint_js": "eslint src panels js --ext js,html",
|
||||
"lint_js": "eslint src panels js test-mocha --ext js,html",
|
||||
"lint_html": "ls -1 src/home-assistant.html panels/**/ha-panel-*.html | xargs polymer lint --input",
|
||||
"mocha": "node_modules/.bin/mocha --opts test-mocha/mocha.opts",
|
||||
"test": "npm run lint_js && npm run lint_html && npm run mocha"
|
||||
@ -29,6 +29,7 @@
|
||||
"babel-plugin-transform-react-jsx": "^6.24.1",
|
||||
"babel-preset-es2015": "^6.24.1",
|
||||
"bower": "^1.8.2",
|
||||
"chai": "^4.1.2",
|
||||
"css-slam": "^2.0.2",
|
||||
"del": "^3.0.0",
|
||||
"es6-object-assign": "^1.1.0",
|
||||
@ -58,6 +59,7 @@
|
||||
"gulp-vinyl-zip": "^2.1.0",
|
||||
"home-assistant-js-websocket": "^1.1.2",
|
||||
"html-minifier": "^3.5.6",
|
||||
"mdn-polyfills": "^5.5.0",
|
||||
"merge-stream": "^1.0.1",
|
||||
"mocha": "^4.0.1",
|
||||
"parse5": "^3.0.3",
|
||||
|
@ -11,67 +11,8 @@ window.hassUtil.DEFAULT_ICON = 'mdi:bookmark';
|
||||
|
||||
window.hassUtil.OFF_STATES = ['off', 'closed', 'unlocked'];
|
||||
|
||||
window.hassUtil.DOMAINS_WITH_CARD = [
|
||||
'climate',
|
||||
'cover',
|
||||
'configurator',
|
||||
'input_select',
|
||||
'input_number',
|
||||
'input_text',
|
||||
'media_player',
|
||||
'scene',
|
||||
'script',
|
||||
'weblink',
|
||||
];
|
||||
|
||||
window.hassUtil.DOMAINS_WITH_MORE_INFO = [
|
||||
'alarm_control_panel', 'automation', 'camera', 'climate', 'configurator',
|
||||
'cover', 'fan', 'group', 'history_graph', 'light', 'lock', 'media_player', 'script',
|
||||
'sun', 'updater', 'vacuum', 'input_datetime',
|
||||
];
|
||||
|
||||
window.hassUtil.DOMAINS_WITH_NO_HISTORY = ['camera', 'configurator', 'history_graph', 'scene'];
|
||||
|
||||
window.hassUtil.HIDE_MORE_INFO = [
|
||||
'input_select', 'scene', 'input_number', 'input_text'
|
||||
];
|
||||
|
||||
// Expects featureClassNames to be an object mapping feature-bit -> className
|
||||
window.hassUtil.featureClassNames = function (stateObj, featureClassNames) {
|
||||
if (!stateObj || !stateObj.attributes.supported_features) return '';
|
||||
|
||||
var features = stateObj.attributes.supported_features;
|
||||
|
||||
return Object.keys(featureClassNames).map(function (feature) {
|
||||
return (features & feature) !== 0 ? featureClassNames[feature] : '';
|
||||
}).join(' ');
|
||||
};
|
||||
|
||||
|
||||
window.hassUtil.canToggleState = function (hass, stateObj) {
|
||||
var domain = window.hassUtil.computeDomain(stateObj);
|
||||
if (domain === 'group') {
|
||||
return stateObj.state === 'on' || stateObj.state === 'off';
|
||||
}
|
||||
|
||||
return window.hassUtil.canToggleDomain(hass, domain);
|
||||
};
|
||||
|
||||
window.hassUtil.canToggleDomain = function (hass, domain) {
|
||||
var turnOnService;
|
||||
var services = hass.config.services[domain];
|
||||
|
||||
if (domain === 'lock') {
|
||||
turnOnService = 'lock';
|
||||
} else if (domain === 'cover') {
|
||||
turnOnService = 'open_cover';
|
||||
} else {
|
||||
turnOnService = 'turn_on';
|
||||
}
|
||||
|
||||
return services && turnOnService in services;
|
||||
};
|
||||
|
||||
// Update root's child element to be newElementTag replacing another existing child if any.
|
||||
// Copy attributes into the child element.
|
||||
window.hassUtil.dynamicContentUpdater = function (root, newElementTag, attributes) {
|
||||
@ -133,34 +74,6 @@ window.hassUtil.relativeTime.tests = [
|
||||
7, 'day',
|
||||
];
|
||||
|
||||
window.hassUtil.stateCardType = function (hass, stateObj) {
|
||||
if (stateObj.state === 'unavailable') {
|
||||
return 'display';
|
||||
}
|
||||
|
||||
var domain = window.hassUtil.computeDomain(stateObj);
|
||||
|
||||
if (window.hassUtil.DOMAINS_WITH_CARD.indexOf(domain) !== -1) {
|
||||
return domain;
|
||||
} else if (window.hassUtil.canToggleState(hass, stateObj) &&
|
||||
stateObj.attributes.control !== 'hidden') {
|
||||
return 'toggle';
|
||||
}
|
||||
return 'display';
|
||||
};
|
||||
|
||||
window.hassUtil.stateMoreInfoType = function (stateObj) {
|
||||
var domain = window.hassUtil.computeDomain(stateObj);
|
||||
|
||||
if (window.hassUtil.DOMAINS_WITH_MORE_INFO.indexOf(domain) !== -1) {
|
||||
return domain;
|
||||
}
|
||||
if (window.hassUtil.HIDE_MORE_INFO.indexOf(domain) !== -1) {
|
||||
return 'hidden';
|
||||
}
|
||||
return 'default';
|
||||
};
|
||||
|
||||
window.hassUtil.domainIcon = function (domain, state) {
|
||||
switch (domain) {
|
||||
case 'alarm_control_panel':
|
||||
|
@ -1,6 +1,6 @@
|
||||
import attributeClassNames from '../../../js/common/util/attribute_class_names';
|
||||
import { assert } from 'chai';
|
||||
|
||||
const assert = require('assert');
|
||||
import attributeClassNames from '../../../js/common/util/attribute_class_names';
|
||||
|
||||
describe('attributeClassNames', () => {
|
||||
const attrs = ['mock_attr1', 'mock_attr2'];
|
||||
|
39
test-mocha/common/util/can_toggle_domain_test.js
Normal file
39
test-mocha/common/util/can_toggle_domain_test.js
Normal file
@ -0,0 +1,39 @@
|
||||
import { assert } from 'chai';
|
||||
|
||||
import canToggleDomain from '../../../js/common/util/can_toggle_domain';
|
||||
|
||||
describe('canToggleDomain', () => {
|
||||
const hass = {
|
||||
config: {
|
||||
services: {
|
||||
light: {
|
||||
turn_on: null, // Service keys only need to be present for test
|
||||
turn_off: null,
|
||||
},
|
||||
lock: {
|
||||
lock: null,
|
||||
unlock: null,
|
||||
},
|
||||
sensor: {
|
||||
custom_service: null,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
it('Detects lights toggle', () => {
|
||||
assert.isTrue(canToggleDomain(hass, 'light'));
|
||||
});
|
||||
|
||||
it('Detects locks toggle', () => {
|
||||
assert.isTrue(canToggleDomain(hass, 'lock'));
|
||||
});
|
||||
|
||||
it('Detects sensors do not toggle', () => {
|
||||
assert.isFalse(canToggleDomain(hass, 'sensor'));
|
||||
});
|
||||
|
||||
it('Detects binary sensors do not toggle', () => {
|
||||
assert.isFalse(canToggleDomain(hass, 'binary_sensor'));
|
||||
});
|
||||
});
|
40
test-mocha/common/util/can_toggle_state_test.js
Normal file
40
test-mocha/common/util/can_toggle_state_test.js
Normal file
@ -0,0 +1,40 @@
|
||||
import { assert } from 'chai';
|
||||
|
||||
import canToggleState from '../../../js/common/util/can_toggle_state';
|
||||
|
||||
describe('canToggleState', () => {
|
||||
const hass = {
|
||||
config: {
|
||||
services: {
|
||||
light: {
|
||||
turn_on: null, // Service keys only need to be present for test
|
||||
turn_off: null,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
it('Detects lights toggle', () => {
|
||||
const stateObj = {
|
||||
entity_id: 'light.bla',
|
||||
state: 'on',
|
||||
};
|
||||
assert.isTrue(canToggleState(hass, stateObj));
|
||||
});
|
||||
|
||||
it('Detects group with toggle', () => {
|
||||
const stateObj = {
|
||||
entity_id: 'group.bla',
|
||||
state: 'on',
|
||||
};
|
||||
assert.isTrue(canToggleState(hass, stateObj));
|
||||
});
|
||||
|
||||
it('Detects group without toggle', () => {
|
||||
const stateObj = {
|
||||
entity_id: 'group.devices',
|
||||
state: 'home',
|
||||
};
|
||||
assert.isFalse(canToggleState(hass, stateObj));
|
||||
});
|
||||
});
|
@ -1,6 +1,6 @@
|
||||
import computeDomain from '../../../js/common/util/compute_domain';
|
||||
import { assert } from 'chai';
|
||||
|
||||
const assert = require('assert');
|
||||
import computeDomain from '../../../js/common/util/compute_domain';
|
||||
|
||||
describe('computeDomain', () => {
|
||||
it('Returns domains', () => {
|
||||
|
@ -1,6 +1,6 @@
|
||||
import computeStateDisplay from '../../../js/common/util/compute_state_display';
|
||||
import { assert } from 'chai';
|
||||
|
||||
const assert = require('assert');
|
||||
import computeStateDisplay from '../../../js/common/util/compute_state_display';
|
||||
|
||||
describe('computeStateDisplay', () => {
|
||||
const haLocalize = function (namespace, message, ...args) {
|
||||
@ -156,7 +156,7 @@ describe('computeStateDisplay', () => {
|
||||
});
|
||||
|
||||
it('Localizes custom state', () => {
|
||||
const altHaLocalize = function (namespace, message, ...args) {
|
||||
const altHaLocalize = function () {
|
||||
// No matches can be found
|
||||
return null;
|
||||
};
|
||||
|
@ -1,6 +1,6 @@
|
||||
import computeStateDomain from '../../../js/common/util/compute_state_domain.js';
|
||||
import { assert } from 'chai';
|
||||
|
||||
const assert = require('assert');
|
||||
import computeStateDomain from '../../../js/common/util/compute_state_domain.js';
|
||||
|
||||
describe('computeStateDomain', () => {
|
||||
it('Detects sensor domain', () => {
|
||||
|
56
test-mocha/common/util/feature_class_names_test.js
Normal file
56
test-mocha/common/util/feature_class_names_test.js
Normal file
@ -0,0 +1,56 @@
|
||||
import { assert } from 'chai';
|
||||
|
||||
import featureClassNames from '../../../js/common/util/feature_class_names';
|
||||
|
||||
describe('featureClassNames', () => {
|
||||
const classNames = {
|
||||
1: 'has-feature_a',
|
||||
2: 'has-feature_b',
|
||||
4: 'has-feature_c',
|
||||
8: 'has-feature_d',
|
||||
};
|
||||
|
||||
it('Skips null states', () => {
|
||||
const stateObj = null;
|
||||
assert.strictEqual(
|
||||
featureClassNames(stateObj, classNames),
|
||||
''
|
||||
);
|
||||
});
|
||||
|
||||
it('Matches no features', () => {
|
||||
const stateObj = {
|
||||
attributes: {
|
||||
supported_features: 64,
|
||||
},
|
||||
};
|
||||
assert.strictEqual(
|
||||
featureClassNames(stateObj, classNames),
|
||||
''
|
||||
);
|
||||
});
|
||||
|
||||
it('Matches one feature', () => {
|
||||
const stateObj = {
|
||||
attributes: {
|
||||
supported_features: 72,
|
||||
},
|
||||
};
|
||||
assert.strictEqual(
|
||||
featureClassNames(stateObj, classNames),
|
||||
'has-feature_d'
|
||||
);
|
||||
});
|
||||
|
||||
it('Matches two features', () => {
|
||||
const stateObj = {
|
||||
attributes: {
|
||||
supported_features: 73,
|
||||
},
|
||||
};
|
||||
assert.strictEqual(
|
||||
featureClassNames(stateObj, classNames),
|
||||
'has-feature_a has-feature_d'
|
||||
);
|
||||
});
|
||||
});
|
@ -1,6 +1,6 @@
|
||||
import formatDate from '../../../js/common/util/format_date';
|
||||
import { assert } from 'chai';
|
||||
|
||||
const assert = require('assert');
|
||||
import formatDate from '../../../js/common/util/format_date';
|
||||
|
||||
describe('formatDate', () => {
|
||||
const dateObj = new Date(
|
||||
|
@ -1,6 +1,6 @@
|
||||
import formatDateTime from '../../../js/common/util/format_date_time';
|
||||
import { assert } from 'chai';
|
||||
|
||||
const assert = require('assert');
|
||||
import formatDateTime from '../../../js/common/util/format_date_time';
|
||||
|
||||
describe('formatDateTime', () => {
|
||||
const dateObj = new Date(
|
||||
|
@ -1,6 +1,6 @@
|
||||
import formatTime from '../../../js/common/util/format_time';
|
||||
import { assert } from 'chai';
|
||||
|
||||
const assert = require('assert');
|
||||
import formatTime from '../../../js/common/util/format_time';
|
||||
|
||||
describe('formatTime', () => {
|
||||
const dateObj = new Date(
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { hasLocation } from '../../../js/common/util/location';
|
||||
import { assert } from 'chai';
|
||||
|
||||
const assert = require('assert');
|
||||
import { hasLocation } from '../../../js/common/util/location';
|
||||
|
||||
describe('hasLocation', () => {
|
||||
it('flags states with location', () => {
|
||||
|
55
test-mocha/common/util/state_card_type_test.js
Normal file
55
test-mocha/common/util/state_card_type_test.js
Normal file
@ -0,0 +1,55 @@
|
||||
import { assert } from 'chai';
|
||||
|
||||
import stateCardType from '../../../js/common/util/state_card_type';
|
||||
|
||||
describe('stateCardType', () => {
|
||||
const hass = {
|
||||
config: {
|
||||
services: {
|
||||
light: {
|
||||
turn_on: null, // Service keys only need to be present for test
|
||||
turn_off: null,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
it('Returns display for unavailable states', () => {
|
||||
const stateObj = {
|
||||
state: 'unavailable',
|
||||
};
|
||||
assert.strictEqual(stateCardType(hass, stateObj), 'display');
|
||||
});
|
||||
|
||||
it('Returns media_player for media_player states', () => {
|
||||
const stateObj = {
|
||||
entity_id: 'media_player.bla',
|
||||
};
|
||||
assert.strictEqual(stateCardType(hass, stateObj), 'media_player');
|
||||
});
|
||||
|
||||
it('Returns toggle for states that can toggle', () => {
|
||||
const stateObj = {
|
||||
entity_id: 'light.bla',
|
||||
attributes: {},
|
||||
};
|
||||
assert.strictEqual(stateCardType(hass, stateObj), 'toggle');
|
||||
});
|
||||
|
||||
it('Returns display for states with hidden control', () => {
|
||||
const stateObj = {
|
||||
entity_id: 'light.bla',
|
||||
attributes: {
|
||||
control: 'hidden',
|
||||
},
|
||||
};
|
||||
assert.strictEqual(stateCardType(hass, stateObj), 'display');
|
||||
});
|
||||
|
||||
it('Returns display for entities that cannot toggle', () => {
|
||||
const stateObj = {
|
||||
entity_id: 'sensor.bla',
|
||||
};
|
||||
assert.strictEqual(stateCardType(hass, stateObj), 'display');
|
||||
});
|
||||
});
|
28
test-mocha/common/util/state_more_info_type_test.js
Normal file
28
test-mocha/common/util/state_more_info_type_test.js
Normal file
@ -0,0 +1,28 @@
|
||||
import { assert } from 'chai';
|
||||
|
||||
import stateMoreInfoType from '../../../js/common/util/state_more_info_type';
|
||||
|
||||
describe('stateMoreInfoType', () => {
|
||||
it('Returns media_player for media_player states', () => {
|
||||
const stateObj = {
|
||||
entity_id: 'media_player.bla',
|
||||
};
|
||||
assert.strictEqual(stateMoreInfoType(stateObj), 'media_player');
|
||||
});
|
||||
|
||||
it('Returns hidden for input_select states', () => {
|
||||
const stateObj = {
|
||||
entity_id: 'input_select.bla',
|
||||
attributes: {},
|
||||
};
|
||||
assert.strictEqual(stateMoreInfoType(stateObj), 'hidden');
|
||||
});
|
||||
|
||||
it('Returns default for switch states', () => {
|
||||
const stateObj = {
|
||||
entity_id: 'switch.bla',
|
||||
attributes: {},
|
||||
};
|
||||
assert.strictEqual(stateMoreInfoType(stateObj), 'default');
|
||||
});
|
||||
});
|
@ -1707,7 +1707,7 @@ chai@^3.5.0:
|
||||
deep-eql "^0.1.3"
|
||||
type-detect "^1.0.0"
|
||||
|
||||
chai@^4.0.2:
|
||||
chai@^4.0.2, chai@^4.1.2:
|
||||
version "4.1.2"
|
||||
resolved "https://registry.yarnpkg.com/chai/-/chai-4.1.2.tgz#0f64584ba642f0f2ace2806279f4f06ca23ad73c"
|
||||
dependencies:
|
||||
@ -5194,6 +5194,10 @@ md5@^2.2.1:
|
||||
crypt "~0.0.1"
|
||||
is-buffer "~1.1.1"
|
||||
|
||||
mdn-polyfills@^5.5.0:
|
||||
version "5.5.0"
|
||||
resolved "https://registry.yarnpkg.com/mdn-polyfills/-/mdn-polyfills-5.5.0.tgz#b8ce237a0a7cbae66c56a6fdd0334b659360d364"
|
||||
|
||||
media-typer@0.3.0:
|
||||
version "0.3.0"
|
||||
resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
|
||||
|
Loading…
x
Reference in New Issue
Block a user