mirror of
https://github.com/Koenkk/zigbee2mqtt.git
synced 2024-11-15 01:48:32 -07:00
Enable TypeScript (#8074)
* Enable Typescript * Fix tests * Fix tests again * Automatically (re)build * Updates * Updates * Update shrinkwrap * Enable sourcemaps
This commit is contained in:
parent
321b34721f
commit
7b65dc631b
@ -1,5 +1,5 @@
|
||||
.eslintignore
|
||||
.eslintrc.json
|
||||
.eslintrc.js
|
||||
.git
|
||||
.github
|
||||
.gitignore
|
||||
@ -13,4 +13,5 @@ images
|
||||
node_modules
|
||||
scripts
|
||||
test
|
||||
coverage
|
||||
update.sh
|
||||
|
45
.eslintrc.js
Normal file
45
.eslintrc.js
Normal file
@ -0,0 +1,45 @@
|
||||
|
||||
module.exports = {
|
||||
'env': {
|
||||
'jest/globals': true,
|
||||
'es6': true,
|
||||
'node': true,
|
||||
},
|
||||
'extends': ['eslint:recommended', 'google', 'plugin:jest/recommended', 'plugin:jest/style'],
|
||||
'parserOptions': {
|
||||
'ecmaVersion': 2018,
|
||||
'sourceType': 'module',
|
||||
},
|
||||
'rules': {
|
||||
'require-jsdoc': 'off',
|
||||
'indent': ['error', 4],
|
||||
'max-len': ['error', {'code': 120}],
|
||||
'no-prototype-builtins': 'off',
|
||||
},
|
||||
'plugins': [
|
||||
'jest',
|
||||
],
|
||||
'overrides': [{
|
||||
files: ['*.ts'],
|
||||
parser: '@typescript-eslint/parser',
|
||||
plugins: ['@typescript-eslint'],
|
||||
extends: ['plugin:@typescript-eslint/recommended'],
|
||||
parserOptions: {
|
||||
project: './tsconfig.json',
|
||||
},
|
||||
rules: {
|
||||
'@typescript-eslint/await-thenable': 'error',
|
||||
'@typescript-eslint/ban-ts-ignore': 'off',
|
||||
'@typescript-eslint/explicit-function-return-type': 'error',
|
||||
'@typescript-eslint/no-empty-function': 'off',
|
||||
'@typescript-eslint/no-explicit-any': 'error',
|
||||
'@typescript-eslint/no-unused-vars': 'error',
|
||||
'@typescript-eslint/semi': ['error'],
|
||||
'array-bracket-spacing': ['error', 'never'],
|
||||
'indent': ['error', 4],
|
||||
'max-len': ['error', {'code': 120}],
|
||||
'no-return-await': 'error',
|
||||
'object-curly-spacing': ['error', 'never'],
|
||||
},
|
||||
}],
|
||||
};
|
@ -1,21 +0,0 @@
|
||||
{
|
||||
"env": {
|
||||
"jest/globals": true,
|
||||
"es6": true,
|
||||
"node": true
|
||||
},
|
||||
"extends": ["eslint:recommended", "google", "plugin:jest/recommended", "plugin:jest/style"],
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 2018,
|
||||
"sourceType": "module"
|
||||
},
|
||||
"rules": {
|
||||
"require-jsdoc": "off",
|
||||
"indent": ["error", 4],
|
||||
"max-len": ["error", { "code": 120 }],
|
||||
"no-prototype-builtins": "off"
|
||||
},
|
||||
"plugins": [
|
||||
"jest"
|
||||
]
|
||||
}
|
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
@ -24,6 +24,8 @@ jobs:
|
||||
- name: Install dependencies
|
||||
if: steps.cache-node-modules.outputs.cache-hit != 'true'
|
||||
run: npm ci
|
||||
- name: Build
|
||||
run: npm run build
|
||||
- name: Test
|
||||
run: npm run test-with-coverage
|
||||
- name: Lint
|
||||
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -11,6 +11,9 @@ pids
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Compiled source
|
||||
dist/*
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
|
@ -7,6 +7,7 @@ coverage
|
||||
.jenkins.yml
|
||||
.codeclimate.yml
|
||||
.github
|
||||
babel.config.js
|
||||
|
||||
#linters
|
||||
.jscsrc
|
||||
@ -14,11 +15,13 @@ coverage
|
||||
.eslintrc*
|
||||
.dockerignore
|
||||
.eslintignore
|
||||
.gitignore
|
||||
|
||||
#editor settings
|
||||
.vscode
|
||||
|
||||
#src
|
||||
lib
|
||||
docs
|
||||
docker
|
||||
images
|
||||
|
@ -69,6 +69,9 @@ Zigbee2MQTT integrates well with (almost) every home automation solution because
|
||||
### Internal Architecture
|
||||
Zigbee2MQTT is made up of three modules, each developed in its own Github project. Starting from the hardware (adapter) and moving up; [zigbee-herdsman](https://github.com/koenkk/zigbee-herdsman) connects to your Zigbee adapter an makes an API available to the higher levels of the stack. For e.g. Texas Instruments hardware, zigbee-herdsman uses the [TI zStack monitoring and test API](https://github.com/koenkk/zigbee-herdsman/raw/master/docs/Z-Stack%20Monitor%20and%20Test%20API.pdf) to communicate with the adapter. Zigbee-herdsman handles the core Zigbee communication. The module [zigbee-herdsman-converters](https://github.com/koenkk/zigbee-herdsman-converters) handles the mapping from individual device models to the Zigbee clusters they support. [Zigbee clusters](https://github.com/Koenkk/zigbee-herdsman/raw/master/docs/Zigbee%20Cluster%20Library%20Specification%20v7.pdf) are the layers of the Zigbee protocol on top of the base protocol that define things like how lights, sensors and switches talk to each other over the Zigbee network. Finally, the Zigbee2MQTT module drives zigbee-herdsman and maps the zigbee messages to MQTT messages. Zigbee2MQTT also keeps track of the state of the system. It uses a `database.db` file to store this state; a text file with a JSON database of connected devices and their capabilities.
|
||||
|
||||
### Developing
|
||||
Zigbee2MQTT uses TypeScript (partially for now). Therefore after making changes to files in the `lib/` directory you need to recompile Zigbee2MQTT. This can be done by executing `npm run build`. For faster development instead of running `npm run build` you can run `npm run build-watch` in another terminal session, this will recompile as you change files.
|
||||
|
||||
## Supported devices
|
||||
See [Supported devices](https://www.zigbee2mqtt.io/information/supported_devices.html) to check whether your device is supported. There is quite an extensive list, including devices from vendors like Xiaomi, Ikea, Philips, OSRAM and more.
|
||||
|
||||
|
6
babel.config.js
Normal file
6
babel.config.js
Normal file
@ -0,0 +1,6 @@
|
||||
module.exports = {
|
||||
presets: [
|
||||
['@babel/preset-env', {targets: {node: 'current'}}],
|
||||
'@babel/preset-typescript',
|
||||
],
|
||||
};
|
@ -5,20 +5,24 @@ RUN apk add --no-cache tzdata eudev tini
|
||||
|
||||
COPY package.json ./
|
||||
|
||||
# Dependencies
|
||||
FROM base as dependencies
|
||||
# Dependencies and build
|
||||
FROM base as dependencies_and_build
|
||||
|
||||
COPY npm-shrinkwrap.json ./
|
||||
COPY npm-shrinkwrap.json tsconfig.json index.js ./
|
||||
COPY lib ./lib
|
||||
|
||||
RUN apk add --no-cache --virtual .buildtools make gcc g++ python3 linux-headers git && \
|
||||
npm ci --production && \
|
||||
npm ci --no-audit --no-optional --no-update-notifier && \
|
||||
npm run build && \
|
||||
rm -rf node_modules && \
|
||||
npm ci --production --no-audit --no-optional --no-update-notifier && \
|
||||
apk del .buildtools
|
||||
|
||||
# Release
|
||||
FROM base as release
|
||||
|
||||
COPY --from=dependencies /app/node_modules ./node_modules
|
||||
COPY lib ./lib
|
||||
COPY --from=dependencies_and_build /app/node_modules ./node_modules
|
||||
COPY --from=dependencies_and_build /app/dist ./dist
|
||||
COPY LICENSE index.js data/configuration.yaml ./
|
||||
|
||||
COPY docker/docker-entrypoint.sh /usr/local/bin/
|
||||
@ -27,7 +31,7 @@ RUN chmod +x /usr/local/bin/docker-entrypoint.sh
|
||||
RUN mkdir /app/data
|
||||
|
||||
ARG COMMIT
|
||||
RUN echo "{\"hash\": \"$COMMIT\"}" > .hash.json
|
||||
RUN echo "$COMMIT" > dist/.hash
|
||||
|
||||
ENTRYPOINT ["docker-entrypoint.sh"]
|
||||
CMD [ "/sbin/tini", "--", "node", "index.js"]
|
||||
|
@ -1 +0,0 @@
|
||||
qemu-aarch64-static and qemu-arm-static are taken from https://github.com/resin-io/qemu/releases/tag/v2.9.0%2Bresin1
|
52
index.js
52
index.js
@ -1,10 +1,16 @@
|
||||
const semver = require('semver');
|
||||
const engines = require('./package.json').engines;
|
||||
const indexJsRestart = 'indexjs.restart';
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const {exec} = require('child_process');
|
||||
const rimraf = require('rimraf');
|
||||
|
||||
let controller;
|
||||
let stopping = false;
|
||||
|
||||
const hashFile = path.join('dist', '.hash');
|
||||
|
||||
async function restart() {
|
||||
await stop(indexJsRestart);
|
||||
await start();
|
||||
@ -16,14 +22,56 @@ async function exit(code, reason) {
|
||||
}
|
||||
}
|
||||
|
||||
async function currentHash() {
|
||||
const git = require('git-last-commit');
|
||||
return new Promise((resolve) => {
|
||||
git.getLastCommit((err, commit) => {
|
||||
if (err) resolve('unknown');
|
||||
else resolve(commit.shortHash);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async function build(reason) {
|
||||
return new Promise((resolve, reject) => {
|
||||
process.stdout.write(`Building Zigbee2MQTT... (${reason})`);
|
||||
rimraf.sync('dist');
|
||||
exec('npm run build', {cwd: __dirname}, async (err, stdout, stderr) => {
|
||||
if (err) {
|
||||
process.stdout.write(', failed\n');
|
||||
reject(err);
|
||||
} else {
|
||||
process.stdout.write(', finished\n');
|
||||
const hash = await currentHash();
|
||||
fs.writeFileSync(hashFile, hash);
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async function checkDist() {
|
||||
if (!fs.existsSync(hashFile)) {
|
||||
await build('initial build');
|
||||
}
|
||||
|
||||
const distHash = fs.readFileSync(hashFile, 'utf-8');
|
||||
const hash = await currentHash();
|
||||
if (hash !== 'unknown' && distHash !== hash) {
|
||||
await build('hash changed');
|
||||
}
|
||||
}
|
||||
|
||||
async function start() {
|
||||
await checkDist();
|
||||
|
||||
const version = engines.node;
|
||||
if (!semver.satisfies(process.version, version)) {
|
||||
console.log(`\t\tZigbee2MQTT requires node version ${version}, you are running ${process.version}!\n`); // eslint-disable-line
|
||||
}
|
||||
|
||||
// Validate settings
|
||||
const settings = require('./lib/util/settings');
|
||||
const settings = require('./dist/util/settings');
|
||||
settings.reRead();
|
||||
const errors = settings.validate();
|
||||
if (errors.length > 0) {
|
||||
@ -38,7 +86,7 @@ async function start() {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
const Controller = require('./lib/controller');
|
||||
const Controller = require('./dist/controller');
|
||||
controller = new Controller(restart, exit);
|
||||
await controller.start();
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
const settings = require('../util/settings');
|
||||
const logger = require('../util/logger');
|
||||
const utils = require('../util/utils');
|
||||
const zigbee2mqttVersion = require('../../package.json').version;
|
||||
const zigbee2mqttVersion = require('../..' + '/package.json').version;
|
||||
const Extension = require('./extension');
|
||||
const stringify = require('json-stable-stringify-without-jsonify');
|
||||
const zigbeeHerdsmanConverters = require('zigbee-herdsman-converters');
|
||||
|
@ -52,7 +52,7 @@ function capitalize(s) {
|
||||
async function getZigbee2mqttVersion() {
|
||||
return new Promise((resolve, reject) => {
|
||||
const git = require('git-last-commit');
|
||||
const packageJSON = require('../../package.json');
|
||||
const packageJSON = require('../..' + '/package.json');
|
||||
const version = packageJSON.version;
|
||||
|
||||
git.getLastCommit((err, commit) => {
|
||||
@ -60,8 +60,9 @@ async function getZigbee2mqttVersion() {
|
||||
|
||||
if (err) {
|
||||
try {
|
||||
commitHash = require('../../.hash.json').hash;
|
||||
commitHash = fs.readFileSync(path.join(__dirname, '..', '..', 'dist', '.hash'), 'utf-8');
|
||||
} catch (error) {
|
||||
/* istanbul ignore next */
|
||||
commitHash = 'unknown';
|
||||
}
|
||||
} else {
|
||||
@ -75,7 +76,7 @@ async function getZigbee2mqttVersion() {
|
||||
|
||||
async function getDependencyVersion(depend) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const packageJSON = require('../../node_modules/'+depend+'/package.json');
|
||||
const packageJSON = require(path.join(__dirname, '..', '..', 'node_modules', depend, 'package.json'));
|
||||
const version = packageJSON.version;
|
||||
resolve({version});
|
||||
});
|
||||
|
@ -1,9 +1,12 @@
|
||||
const yaml = require('js-yaml');
|
||||
const fs = require('fs');
|
||||
const equals = require('fast-deep-equal/es6');
|
||||
import yaml from 'js-yaml';
|
||||
import fs from 'fs';
|
||||
import equals from 'fast-deep-equal/es6';
|
||||
import 'source-map-support/register';
|
||||
|
||||
function read(file) {
|
||||
function read(file: string): Record<string, unknown> {
|
||||
try {
|
||||
// eslint-disable-next-line
|
||||
// @ts-ignore
|
||||
return yaml.load(fs.readFileSync(file, 'utf8'));
|
||||
} catch (error) {
|
||||
if (error.name === 'YAMLException') {
|
||||
@ -14,18 +17,18 @@ function read(file) {
|
||||
}
|
||||
}
|
||||
|
||||
function readIfExists(file, default_=null) {
|
||||
function readIfExists(file: string, default_?: Record<string, unknown>): Record<string, unknown> {
|
||||
return fs.existsSync(file) ? read(file) : default_;
|
||||
}
|
||||
|
||||
function writeIfChanged(file, content) {
|
||||
function writeIfChanged(file: string, content: Record<string, unknown>): void {
|
||||
const before = readIfExists(file);
|
||||
if (!equals(before, content)) {
|
||||
fs.writeFileSync(file, yaml.dump(content));
|
||||
}
|
||||
}
|
||||
|
||||
function updateIfChanged(file, key, value) {
|
||||
function updateIfChanged(file: string, key: string, value: unknown): void {
|
||||
const content = read(file);
|
||||
if (content[key] !== value) {
|
||||
content[key] = value;
|
4271
npm-shrinkwrap.json
generated
4271
npm-shrinkwrap.json
generated
File diff suppressed because it is too large
Load Diff
29
package.json
29
package.json
@ -20,9 +20,11 @@
|
||||
"cc2531"
|
||||
],
|
||||
"scripts": {
|
||||
"test-with-coverage": "jest test --coverage",
|
||||
"eslint": "node_modules/.bin/eslint lib/",
|
||||
"build": "node_modules/.bin/tsc",
|
||||
"build-watch": "node_modules/.bin/tsc --watch",
|
||||
"eslint": "node_modules/.bin/eslint lib/ --max-warnings=0",
|
||||
"start": "node index.js",
|
||||
"test-with-coverage": "jest test --coverage",
|
||||
"test": "jest test",
|
||||
"test-watch": "jest test --watch"
|
||||
},
|
||||
@ -41,7 +43,7 @@
|
||||
"git-last-commit": "^1.0.0",
|
||||
"humanize-duration": "^3.27.0",
|
||||
"js-yaml": "^4.1.0",
|
||||
"json-stable-stringify-without-jsonify": "=1.0.1",
|
||||
"json-stable-stringify-without-jsonify": "^1.0.1",
|
||||
"mkdir-recursive": "^0.4.0",
|
||||
"moment": "^2.29.1",
|
||||
"mqtt": "4.2.8",
|
||||
@ -57,11 +59,22 @@
|
||||
"zigbee2mqtt-frontend": "0.4.43"
|
||||
},
|
||||
"devDependencies": {
|
||||
"eslint": "*",
|
||||
"eslint-config-google": "*",
|
||||
"eslint-plugin-jest": "*",
|
||||
"jest": "*",
|
||||
"tmp": "*"
|
||||
"@babel/core": "^7.14.6",
|
||||
"@babel/preset-env": "^7.14.7",
|
||||
"@babel/preset-typescript": "^7.14.5",
|
||||
"@types/jest": "^26.0.24",
|
||||
"@types/js-yaml": "^4.0.2",
|
||||
"@types/ws": "^7.4.6",
|
||||
"@typescript-eslint/eslint-plugin": "^4.28.3",
|
||||
"@typescript-eslint/parser": "^4.28.3",
|
||||
"babel-jest": "^27.0.6",
|
||||
"eslint": "^7.30.0",
|
||||
"eslint-config-google": "^0.14.0",
|
||||
"eslint-plugin-jest": "^24.3.6",
|
||||
"jest": "^27.0.6",
|
||||
"source-map-support": "^0.5.19",
|
||||
"tmp": "^0.2.1",
|
||||
"typescript": "^4.3.5"
|
||||
},
|
||||
"jest": {
|
||||
"coverageThreshold": {
|
||||
|
@ -12,7 +12,7 @@ const debounce = require('debounce');
|
||||
describe('Bind', () => {
|
||||
let controller;
|
||||
|
||||
mockClear = (device) => {
|
||||
const mockClear = (device) => {
|
||||
for (const endpoint of device.endpoints) {
|
||||
endpoint.read.mockClear();
|
||||
endpoint.write.mockClear();
|
||||
@ -33,7 +33,6 @@ describe('Bind', () => {
|
||||
controller = new Controller(jest.fn(), jest.fn());
|
||||
await controller.start();
|
||||
await flushPromises();
|
||||
this.coordinatorEndoint = zigbeeHerdsman.devices.coordinator.getEndpoint(1);
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
@ -47,7 +46,7 @@ describe('Bind', () => {
|
||||
await resetExtension();
|
||||
MQTT.publish.mockClear();
|
||||
});
|
||||
|
||||
|
||||
afterAll(async () => {
|
||||
jest.useRealTimers();
|
||||
})
|
||||
|
@ -12,13 +12,14 @@ const mocksClear = [MQTT.publish, logger.warn, logger.debug];
|
||||
|
||||
describe('Configure', () => {
|
||||
let controller;
|
||||
let coordinatorEndpoint;
|
||||
|
||||
expectRemoteConfigured = () => {
|
||||
const expectRemoteConfigured = () => {
|
||||
const device = zigbeeHerdsman.devices.remote;
|
||||
const endpoint1 = device.getEndpoint(1);
|
||||
expect(endpoint1.bind).toHaveBeenCalledTimes(2);
|
||||
expect(endpoint1.bind).toHaveBeenCalledWith('genOnOff', this.coordinatorEndoint);
|
||||
expect(endpoint1.bind).toHaveBeenCalledWith('genLevelCtrl', this.coordinatorEndoint);
|
||||
expect(endpoint1.bind).toHaveBeenCalledWith('genOnOff', coordinatorEndpoint);
|
||||
expect(endpoint1.bind).toHaveBeenCalledWith('genLevelCtrl', coordinatorEndpoint);
|
||||
|
||||
const endpoint2 = device.getEndpoint(2);
|
||||
expect(endpoint2.write).toHaveBeenCalledTimes(1);
|
||||
@ -26,7 +27,7 @@ describe('Configure', () => {
|
||||
expect(device.meta.configured).toBe(1);
|
||||
}
|
||||
|
||||
expectBulbConfigured = () => {
|
||||
const expectBulbConfigured = () => {
|
||||
const device = zigbeeHerdsman.devices.bulb;
|
||||
const endpoint1 = device.getEndpoint(1);
|
||||
expect(endpoint1.read).toHaveBeenCalledTimes(2);
|
||||
@ -34,19 +35,19 @@ describe('Configure', () => {
|
||||
expect(endpoint1.read).toHaveBeenCalledWith('lightingColorCtrl', [ 'colorTempPhysicalMin', 'colorTempPhysicalMax' ]);
|
||||
}
|
||||
|
||||
expectBulbNotConfigured = () => {
|
||||
const expectBulbNotConfigured = () => {
|
||||
const device = zigbeeHerdsman.devices.bulb;
|
||||
const endpoint1 = device.getEndpoint(1);
|
||||
expect(endpoint1.read).toHaveBeenCalledTimes(0);
|
||||
}
|
||||
|
||||
expectRemoteNotConfigured = () => {
|
||||
const expectRemoteNotConfigured = () => {
|
||||
const device = zigbeeHerdsman.devices.remote;
|
||||
const endpoint1 = device.getEndpoint(1);
|
||||
expect(endpoint1.bind).toHaveBeenCalledTimes(0);
|
||||
}
|
||||
|
||||
mockClear = (device) => {
|
||||
const mockClear = (device) => {
|
||||
for (const endpoint of device.endpoints) {
|
||||
endpoint.read.mockClear();
|
||||
endpoint.write.mockClear();
|
||||
@ -71,10 +72,10 @@ describe('Configure', () => {
|
||||
data.writeDefaultConfiguration();
|
||||
settings.reRead();
|
||||
mocksClear.forEach((m) => m.mockClear());
|
||||
this.coordinatorEndoint = zigbeeHerdsman.devices.coordinator.getEndpoint(1);
|
||||
coordinatorEndpoint = zigbeeHerdsman.devices.coordinator.getEndpoint(1);
|
||||
await resetExtension();
|
||||
});
|
||||
|
||||
|
||||
afterAll(async () => {
|
||||
jest.useRealTimers();
|
||||
})
|
||||
|
@ -57,10 +57,9 @@ describe('Loads external converters', () => {
|
||||
data.writeDefaultConfiguration();
|
||||
settings.reRead();
|
||||
mocksClear.forEach((m) => m.mockClear());
|
||||
this.coordinatorEndoint = zigbeeHerdsman.devices.coordinator.getEndpoint(1);
|
||||
await resetExtension();
|
||||
});
|
||||
|
||||
|
||||
afterAll(async () => {
|
||||
jest.useRealTimers();
|
||||
});
|
||||
|
@ -13,9 +13,11 @@ const HomeAssistant = require('../lib/extension/homeassistant');
|
||||
const mockExit = jest.spyOn(process, 'exit').mockImplementation(() => {});
|
||||
|
||||
describe('HomeAssistant extension', () => {
|
||||
let version;
|
||||
|
||||
beforeEach(async () => {
|
||||
this.version = await require('../lib/util/utils').getZigbee2mqttVersion();
|
||||
this.version = `Zigbee2MQTT ${this.version.version}`;
|
||||
version = await require('../lib/util/utils').getZigbee2mqttVersion();
|
||||
version = `Zigbee2MQTT ${version.version}`;
|
||||
data.writeDefaultConfiguration();
|
||||
settings.reRead();
|
||||
data.writeEmptyState();
|
||||
@ -52,7 +54,7 @@ describe('HomeAssistant extension', () => {
|
||||
});
|
||||
|
||||
it('Should discover devices and groups', async () => {
|
||||
controller = new Controller(false);
|
||||
const controller = new Controller(false);
|
||||
await controller.start();
|
||||
|
||||
let payload;
|
||||
@ -67,7 +69,7 @@ describe('HomeAssistant extension', () => {
|
||||
"device":{
|
||||
"identifiers":["zigbee2mqtt_1221051039810110150109113116116_9"],
|
||||
"name":"ha_discovery_group",
|
||||
"sw_version":this.version,
|
||||
"sw_version":version,
|
||||
},
|
||||
"max_mireds": 454,
|
||||
"min_mireds": 250,
|
||||
@ -95,7 +97,7 @@ describe('HomeAssistant extension', () => {
|
||||
"device":{
|
||||
"identifiers":["zigbee2mqtt_1221051039810110150109113116116_9"],
|
||||
"name":"ha_discovery_group",
|
||||
"sw_version":this.version,
|
||||
"sw_version":version,
|
||||
},
|
||||
"json_attributes_topic":"zigbee2mqtt/ha_discovery_group",
|
||||
"name":"ha_discovery_group",
|
||||
@ -125,7 +127,7 @@ describe('HomeAssistant extension', () => {
|
||||
'device': {
|
||||
'identifiers': ['zigbee2mqtt_0x0017880104e45522'],
|
||||
'name': 'weather_sensor',
|
||||
'sw_version': this.version,
|
||||
'sw_version': version,
|
||||
'model': 'Aqara temperature, humidity and pressure sensor (WSDCGQ11LM)',
|
||||
'manufacturer': 'Xiaomi',
|
||||
},
|
||||
@ -151,7 +153,7 @@ describe('HomeAssistant extension', () => {
|
||||
'device': {
|
||||
'identifiers': ['zigbee2mqtt_0x0017880104e45522'],
|
||||
'name': 'weather_sensor',
|
||||
'sw_version': this.version,
|
||||
'sw_version': version,
|
||||
'model': 'Aqara temperature, humidity and pressure sensor (WSDCGQ11LM)',
|
||||
'manufacturer': 'Xiaomi',
|
||||
},
|
||||
@ -177,7 +179,7 @@ describe('HomeAssistant extension', () => {
|
||||
'device': {
|
||||
'identifiers': ['zigbee2mqtt_0x0017880104e45522'],
|
||||
'name': 'weather_sensor',
|
||||
'sw_version': this.version,
|
||||
'sw_version': version,
|
||||
'model': 'Aqara temperature, humidity and pressure sensor (WSDCGQ11LM)',
|
||||
'manufacturer': 'Xiaomi',
|
||||
},
|
||||
@ -203,7 +205,7 @@ describe('HomeAssistant extension', () => {
|
||||
'device': {
|
||||
'identifiers': ['zigbee2mqtt_0x0017880104e45522'],
|
||||
'name': 'weather_sensor',
|
||||
'sw_version': this.version,
|
||||
'sw_version': version,
|
||||
'model': 'Aqara temperature, humidity and pressure sensor (WSDCGQ11LM)',
|
||||
'manufacturer': 'Xiaomi',
|
||||
},
|
||||
@ -230,7 +232,7 @@ describe('HomeAssistant extension', () => {
|
||||
'device': {
|
||||
'identifiers': ['zigbee2mqtt_0x0017880104e45522'],
|
||||
'name': 'weather_sensor',
|
||||
'sw_version': this.version,
|
||||
'sw_version': version,
|
||||
'model': 'Aqara temperature, humidity and pressure sensor (WSDCGQ11LM)',
|
||||
'manufacturer': 'Xiaomi',
|
||||
},
|
||||
@ -258,7 +260,7 @@ describe('HomeAssistant extension', () => {
|
||||
"manufacturer":"Xiaomi",
|
||||
"model":"Aqara double key wired wall switch without neutral wire. Doesn't work as a router and doesn't support power meter (QBKG03LM)",
|
||||
"name":"wall_switch_double",
|
||||
"sw_version":this.version
|
||||
"sw_version":version
|
||||
},
|
||||
"json_attributes_topic":"zigbee2mqtt/wall_switch_double",
|
||||
"name":"wall_switch_double_left",
|
||||
@ -290,7 +292,7 @@ describe('HomeAssistant extension', () => {
|
||||
"manufacturer":"Xiaomi",
|
||||
"model":"Aqara double key wired wall switch without neutral wire. Doesn't work as a router and doesn't support power meter (QBKG03LM)",
|
||||
"name":"wall_switch_double",
|
||||
"sw_version":this.version
|
||||
"sw_version":version
|
||||
},
|
||||
"json_attributes_topic":"zigbee2mqtt/wall_switch_double",
|
||||
"name":"wall_switch_double_right",
|
||||
@ -328,7 +330,7 @@ describe('HomeAssistant extension', () => {
|
||||
"manufacturer":"IKEA",
|
||||
"model":"TRADFRI LED bulb E26/E27 980 lumen, dimmable, white spectrum, opal white (LED1545G12)",
|
||||
"name":"bulb",
|
||||
"sw_version":this.version,
|
||||
"sw_version":version,
|
||||
},
|
||||
"effect":true,
|
||||
"effect_list":[
|
||||
@ -363,7 +365,7 @@ describe('HomeAssistant extension', () => {
|
||||
retain: false,
|
||||
})
|
||||
|
||||
controller = new Controller(false);
|
||||
const controller = new Controller(false);
|
||||
await controller.start();
|
||||
|
||||
let payload;
|
||||
@ -381,7 +383,7 @@ describe('HomeAssistant extension', () => {
|
||||
'device': {
|
||||
'identifiers': ['zigbee2mqtt_0x0017880104e45522'],
|
||||
'name': 'weather_sensor',
|
||||
'sw_version': this.version,
|
||||
'sw_version': version,
|
||||
'model': 'Aqara temperature, humidity and pressure sensor (WSDCGQ11LM)',
|
||||
'manufacturer': 'Xiaomi',
|
||||
},
|
||||
@ -407,7 +409,7 @@ describe('HomeAssistant extension', () => {
|
||||
'device': {
|
||||
'identifiers': ['zigbee2mqtt_0x0017880104e45522'],
|
||||
'name': 'weather_sensor',
|
||||
'sw_version': this.version,
|
||||
'sw_version': version,
|
||||
'model': 'Aqara temperature, humidity and pressure sensor (WSDCGQ11LM)',
|
||||
'manufacturer': 'Xiaomi',
|
||||
},
|
||||
@ -433,7 +435,7 @@ describe('HomeAssistant extension', () => {
|
||||
'device': {
|
||||
'identifiers': ['zigbee2mqtt_0x0017880104e45522'],
|
||||
'name': 'weather_sensor',
|
||||
'sw_version': this.version,
|
||||
'sw_version': version,
|
||||
'model': 'Aqara temperature, humidity and pressure sensor (WSDCGQ11LM)',
|
||||
'manufacturer': 'Xiaomi',
|
||||
},
|
||||
@ -472,7 +474,7 @@ describe('HomeAssistant extension', () => {
|
||||
retain: false,
|
||||
})
|
||||
|
||||
controller = new Controller(false);
|
||||
const controller = new Controller(false);
|
||||
await controller.start();
|
||||
|
||||
let payload;
|
||||
@ -517,7 +519,7 @@ describe('HomeAssistant extension', () => {
|
||||
'device': {
|
||||
'identifiers': ['zigbee2mqtt_0x0017880104e45522'],
|
||||
'name': 'weather_sensor',
|
||||
'sw_version': this.version,
|
||||
'sw_version': version,
|
||||
'model': 'custom model',
|
||||
'manufacturer': 'Not from Xiaomi',
|
||||
},
|
||||
@ -550,7 +552,7 @@ describe('HomeAssistant extension', () => {
|
||||
},
|
||||
})
|
||||
|
||||
controller = new Controller(false);
|
||||
const controller = new Controller(false);
|
||||
await controller.start();
|
||||
|
||||
let payload;
|
||||
@ -566,7 +568,7 @@ describe('HomeAssistant extension', () => {
|
||||
"manufacturer": "Xiaomi",
|
||||
"model": "Aqara single key wired wall switch without neutral wire. Doesn't work as a router and doesn't support power meter (QBKG04LM)",
|
||||
"name": "my_switch",
|
||||
"sw_version": this.version
|
||||
"sw_version": version
|
||||
},
|
||||
"json_attributes_topic": "zigbee2mqtt/my_switch",
|
||||
"name": "my_light_name_override",
|
||||
@ -593,7 +595,7 @@ describe('HomeAssistant extension', () => {
|
||||
retain: false,
|
||||
})
|
||||
|
||||
controller = new Controller(false);
|
||||
const controller = new Controller(false);
|
||||
await controller.start();
|
||||
|
||||
await flushPromises();
|
||||
@ -611,7 +613,7 @@ describe('HomeAssistant extension', () => {
|
||||
retain: false,
|
||||
})
|
||||
|
||||
controller = new Controller(false);
|
||||
const controller = new Controller(false);
|
||||
await controller.start();
|
||||
|
||||
await flushPromises();
|
||||
@ -622,7 +624,7 @@ describe('HomeAssistant extension', () => {
|
||||
});
|
||||
|
||||
it('Should discover devices with fan', async () => {
|
||||
controller = new Controller(false);
|
||||
const controller = new Controller(false);
|
||||
await controller.start();
|
||||
|
||||
let payload;
|
||||
@ -652,7 +654,7 @@ describe('HomeAssistant extension', () => {
|
||||
"zigbee2mqtt_0x0017880104e45548"
|
||||
],
|
||||
"name":"fan",
|
||||
"sw_version":this.version,
|
||||
"sw_version":version,
|
||||
"model":"Universal wink enabled white ceiling fan premier remote control (99432)",
|
||||
"manufacturer":"Hampton Bay"
|
||||
},
|
||||
@ -668,7 +670,7 @@ describe('HomeAssistant extension', () => {
|
||||
});
|
||||
|
||||
it('Should discover thermostat devices', async () => {
|
||||
controller = new Controller(false);
|
||||
const controller = new Controller(false);
|
||||
await controller.start();
|
||||
|
||||
let payload;
|
||||
@ -688,7 +690,7 @@ describe('HomeAssistant extension', () => {
|
||||
"manufacturer":"TuYa",
|
||||
"model":"Radiator valve with thermostat (TS0601_thermostat)",
|
||||
"name":"TS0601_thermostat",
|
||||
"sw_version": this.version,
|
||||
"sw_version": version,
|
||||
},
|
||||
"hold_command_topic":"zigbee2mqtt/TS0601_thermostat/set/preset",
|
||||
"hold_modes":[
|
||||
@ -728,7 +730,7 @@ describe('HomeAssistant extension', () => {
|
||||
});
|
||||
|
||||
it('Should discover devices with cover_position', async () => {
|
||||
controller = new Controller(false);
|
||||
const controller = new Controller(false);
|
||||
await controller.start();
|
||||
|
||||
let payload;
|
||||
@ -747,7 +749,7 @@ describe('HomeAssistant extension', () => {
|
||||
{
|
||||
identifiers: [ 'zigbee2mqtt_0x0017880104e45551' ],
|
||||
name: 'smart vent',
|
||||
sw_version: this.version,
|
||||
sw_version: version,
|
||||
model: 'Smart vent (SV01)',
|
||||
manufacturer: 'Keen Home'
|
||||
},
|
||||
@ -764,7 +766,7 @@ describe('HomeAssistant extension', () => {
|
||||
|
||||
it('Should discover devices with custom homeassistant_discovery_topic', async () => {
|
||||
settings.set(['advanced', 'homeassistant_discovery_topic'], 'my_custom_discovery_topic')
|
||||
controller = new Controller(false);
|
||||
const controller = new Controller(false);
|
||||
await controller.start();
|
||||
|
||||
let payload;
|
||||
@ -782,7 +784,7 @@ describe('HomeAssistant extension', () => {
|
||||
'device': {
|
||||
'identifiers': ['zigbee2mqtt_0x0017880104e45522'],
|
||||
'name': 'weather_sensor',
|
||||
'sw_version': this.version,
|
||||
'sw_version': version,
|
||||
'model': 'Aqara temperature, humidity and pressure sensor (WSDCGQ11LM)',
|
||||
'manufacturer': 'Xiaomi',
|
||||
},
|
||||
@ -800,20 +802,20 @@ describe('HomeAssistant extension', () => {
|
||||
it('Should throw error when starting with attributes output', async () => {
|
||||
settings.set(['experimental', 'output'], 'attribute')
|
||||
expect(() => {
|
||||
controller = new Controller(false);
|
||||
const controller = new Controller(false);
|
||||
}).toThrowError('Home Assitant integration is not possible with attribute output!');
|
||||
});
|
||||
|
||||
it('Should warn when starting with cache_state false', async () => {
|
||||
settings.set(['advanced', 'cache_state'], false);
|
||||
logger.warn.mockClear();
|
||||
controller = new Controller(false);
|
||||
const controller = new Controller(false);
|
||||
expect(logger.warn).toHaveBeenCalledWith("In order for HomeAssistant integration to work properly set `cache_state: true");
|
||||
});
|
||||
|
||||
it('Should set missing values to null', async () => {
|
||||
// https://github.com/Koenkk/zigbee2mqtt/issues/6987
|
||||
controller = new Controller(false);
|
||||
const controller = new Controller(false);
|
||||
await controller.start();
|
||||
await flushPromises();
|
||||
const device = zigbeeHerdsman.devices.WSDCGQ11LM;
|
||||
@ -832,7 +834,7 @@ describe('HomeAssistant extension', () => {
|
||||
});
|
||||
|
||||
it('Should copy hue/saturtion to h/s if present', async () => {
|
||||
controller = new Controller(false);
|
||||
const controller = new Controller(false);
|
||||
await controller.start();
|
||||
await flushPromises();
|
||||
const device = zigbeeHerdsman.devices.bulb_color;
|
||||
@ -851,7 +853,7 @@ describe('HomeAssistant extension', () => {
|
||||
});
|
||||
|
||||
it('Should not copy hue/saturtion if properties are missing', async () => {
|
||||
controller = new Controller(false);
|
||||
const controller = new Controller(false);
|
||||
await controller.start();
|
||||
await flushPromises();
|
||||
const device = zigbeeHerdsman.devices.bulb_color;
|
||||
@ -870,7 +872,7 @@ describe('HomeAssistant extension', () => {
|
||||
});
|
||||
|
||||
it('Should not copy hue/saturtion if color is missing', async () => {
|
||||
controller = new Controller(false);
|
||||
const controller = new Controller(false);
|
||||
await controller.start();
|
||||
await flushPromises();
|
||||
const device = zigbeeHerdsman.devices.bulb_color;
|
||||
@ -889,7 +891,7 @@ describe('HomeAssistant extension', () => {
|
||||
});
|
||||
|
||||
it('Shouldt discover when already discovered', async () => {
|
||||
controller = new Controller(false);
|
||||
const controller = new Controller(false);
|
||||
await controller.start();
|
||||
await flushPromises();
|
||||
const device = zigbeeHerdsman.devices.WSDCGQ11LM;
|
||||
@ -903,7 +905,7 @@ describe('HomeAssistant extension', () => {
|
||||
});
|
||||
|
||||
it('Should discover when not discovered yet', async () => {
|
||||
controller = new Controller(false);
|
||||
const controller = new Controller(false);
|
||||
await controller.start();
|
||||
await flushPromises();
|
||||
controller.extensions.find((e) => e.constructor.name === 'HomeAssistant').discovered = {};
|
||||
@ -925,7 +927,7 @@ describe('HomeAssistant extension', () => {
|
||||
'device': {
|
||||
'identifiers': ['zigbee2mqtt_0x0017880104e45522'],
|
||||
'name': 'weather_sensor',
|
||||
'sw_version': this.version,
|
||||
'sw_version': version,
|
||||
'model': 'Aqara temperature, humidity and pressure sensor (WSDCGQ11LM)',
|
||||
'manufacturer': 'Xiaomi',
|
||||
},
|
||||
@ -941,7 +943,7 @@ describe('HomeAssistant extension', () => {
|
||||
});
|
||||
|
||||
it('Shouldnt discover when device leaves', async () => {
|
||||
controller = new Controller(jest.fn(), jest.fn());
|
||||
const controller = new Controller(jest.fn(), jest.fn());
|
||||
await controller.start();
|
||||
await flushPromises();
|
||||
controller.extensions.find((e) => e.constructor.name === 'HomeAssistant').discovered = {};
|
||||
@ -954,7 +956,7 @@ describe('HomeAssistant extension', () => {
|
||||
|
||||
it('Should send all status when home assistant comes online (default topic)', async () => {
|
||||
data.writeDefaultState();
|
||||
controller = new Controller(jest.fn(), jest.fn());
|
||||
const controller = new Controller(jest.fn(), jest.fn());
|
||||
await controller.start();
|
||||
expect(MQTT.subscribe).toHaveBeenCalledWith('homeassistant/status');
|
||||
await flushPromises();
|
||||
@ -979,7 +981,7 @@ describe('HomeAssistant extension', () => {
|
||||
|
||||
it('Should send all status when home assistant comes online', async () => {
|
||||
data.writeDefaultState();
|
||||
controller = new Controller(jest.fn(), jest.fn());
|
||||
const controller = new Controller(jest.fn(), jest.fn());
|
||||
await controller.start();
|
||||
await flushPromises();
|
||||
expect(MQTT.subscribe).toHaveBeenCalledWith('hass/status');
|
||||
@ -1004,7 +1006,7 @@ describe('HomeAssistant extension', () => {
|
||||
|
||||
it('Shouldnt send all status when home assistant comes offline', async () => {
|
||||
data.writeDefaultState();
|
||||
controller = new Controller(jest.fn(), jest.fn());
|
||||
const controller = new Controller(jest.fn(), jest.fn());
|
||||
await controller.start();
|
||||
await flushPromises();
|
||||
MQTT.publish.mockClear();
|
||||
@ -1017,7 +1019,7 @@ describe('HomeAssistant extension', () => {
|
||||
|
||||
it('Shouldnt send all status when home assistant comes online with different topic', async () => {
|
||||
data.writeDefaultState();
|
||||
controller = new Controller(jest.fn(), jest.fn());
|
||||
const controller = new Controller(jest.fn(), jest.fn());
|
||||
await controller.start();
|
||||
await flushPromises();
|
||||
MQTT.publish.mockClear();
|
||||
@ -1030,7 +1032,7 @@ describe('HomeAssistant extension', () => {
|
||||
|
||||
it('Should discover devices with availability', async () => {
|
||||
settings.set(['advanced', 'availability_timeout'], 1)
|
||||
controller = new Controller(false);
|
||||
const controller = new Controller(false);
|
||||
await controller.start();
|
||||
|
||||
let payload;
|
||||
@ -1048,7 +1050,7 @@ describe('HomeAssistant extension', () => {
|
||||
'device': {
|
||||
'identifiers': ['zigbee2mqtt_0x0017880104e45522'],
|
||||
'name': 'weather_sensor',
|
||||
'sw_version': this.version,
|
||||
'sw_version': version,
|
||||
'model': 'Aqara temperature, humidity and pressure sensor (WSDCGQ11LM)',
|
||||
'manufacturer': 'Xiaomi',
|
||||
},
|
||||
@ -1064,7 +1066,7 @@ describe('HomeAssistant extension', () => {
|
||||
});
|
||||
|
||||
it('Should clear discovery when device is removed', async () => {
|
||||
controller = new Controller(false);
|
||||
const controller = new Controller(false);
|
||||
await controller.start();
|
||||
await flushPromises();
|
||||
MQTT.publish.mockClear();
|
||||
@ -1104,7 +1106,7 @@ describe('HomeAssistant extension', () => {
|
||||
});
|
||||
|
||||
it('Should not clear discovery when unsupported device is removed', async () => {
|
||||
controller = new Controller(false);
|
||||
const controller = new Controller(false);
|
||||
await controller.start();
|
||||
await flushPromises();
|
||||
MQTT.publish.mockClear();
|
||||
@ -1114,7 +1116,7 @@ describe('HomeAssistant extension', () => {
|
||||
});
|
||||
|
||||
it('Should refresh discovery when device is renamed', async () => {
|
||||
controller = new Controller(false);
|
||||
const controller = new Controller(false);
|
||||
await controller.start();
|
||||
await flushPromises();
|
||||
await MQTT.events.message('homeassistant/device_automation/0x0017880104e45522/action_double/config', stringify({topic: 'zigbee2mqtt/weather_sensor/action'}));
|
||||
@ -1135,7 +1137,7 @@ describe('HomeAssistant extension', () => {
|
||||
'device': {
|
||||
'identifiers': ['zigbee2mqtt_0x0017880104e45522'],
|
||||
'name': 'weather_sensor_renamed',
|
||||
'sw_version': this.version,
|
||||
'sw_version': version,
|
||||
'model': 'Aqara temperature, humidity and pressure sensor (WSDCGQ11LM)',
|
||||
'manufacturer': 'Xiaomi',
|
||||
},
|
||||
@ -1169,7 +1171,7 @@ describe('HomeAssistant extension', () => {
|
||||
"zigbee2mqtt_0x0017880104e45522"
|
||||
],
|
||||
"name":"weather_sensor_renamed",
|
||||
"sw_version": this.version,
|
||||
"sw_version": version,
|
||||
"model":"Aqara temperature, humidity and pressure sensor (WSDCGQ11LM)",
|
||||
"manufacturer":"Xiaomi"
|
||||
}
|
||||
@ -1180,7 +1182,7 @@ describe('HomeAssistant extension', () => {
|
||||
});
|
||||
|
||||
it('Shouldnt refresh discovery when device is renamed and homeassistant_rename is false', async () => {
|
||||
controller = new Controller(false);
|
||||
const controller = new Controller(false);
|
||||
await controller.start();
|
||||
await flushPromises();
|
||||
MQTT.publish.mockClear();
|
||||
@ -1206,7 +1208,7 @@ describe('HomeAssistant extension', () => {
|
||||
'device': {
|
||||
'identifiers': ['zigbee2mqtt_0x0017880104e45522'],
|
||||
'name': 'weather_sensor_renamed',
|
||||
'sw_version': this.version,
|
||||
'sw_version': version,
|
||||
'model': 'Aqara temperature, humidity and pressure sensor (WSDCGQ11LM)',
|
||||
'manufacturer': 'Xiaomi',
|
||||
},
|
||||
@ -1222,7 +1224,7 @@ describe('HomeAssistant extension', () => {
|
||||
});
|
||||
|
||||
it('Should discover update_available sensor when device supports it', async () => {
|
||||
controller = new Controller(false);
|
||||
const controller = new Controller(false);
|
||||
await controller.start();
|
||||
await flushPromises();
|
||||
const payload = {
|
||||
@ -1239,7 +1241,7 @@ describe('HomeAssistant extension', () => {
|
||||
"zigbee2mqtt_0x000b57fffec6a5b2"
|
||||
],
|
||||
"name":"bulb",
|
||||
'sw_version': this.version,
|
||||
'sw_version': version,
|
||||
"model":"TRADFRI LED bulb E26/E27 980 lumen, dimmable, white spectrum, opal white (LED1545G12)",
|
||||
"manufacturer":"IKEA"
|
||||
},
|
||||
@ -1255,7 +1257,7 @@ describe('HomeAssistant extension', () => {
|
||||
});
|
||||
|
||||
it('Should discover trigger when click is published', async () => {
|
||||
controller = new Controller(false);
|
||||
const controller = new Controller(false);
|
||||
await controller.start();
|
||||
await flushPromises();
|
||||
|
||||
@ -1282,7 +1284,7 @@ describe('HomeAssistant extension', () => {
|
||||
"zigbee2mqtt_0x0017880104e45520"
|
||||
],
|
||||
"name":"button",
|
||||
"sw_version": this.version,
|
||||
"sw_version": version,
|
||||
"model":"Aqara wireless switch (WXKG11LM)",
|
||||
"manufacturer":"Xiaomi"
|
||||
}
|
||||
@ -1306,7 +1308,7 @@ describe('HomeAssistant extension', () => {
|
||||
"zigbee2mqtt_0x0017880104e45520"
|
||||
],
|
||||
"name":"button",
|
||||
"sw_version": this.version,
|
||||
"sw_version": version,
|
||||
"model":"Aqara wireless switch (WXKG11LM)",
|
||||
"manufacturer":"Xiaomi"
|
||||
}
|
||||
@ -1411,7 +1413,7 @@ describe('HomeAssistant extension', () => {
|
||||
settings.set(['device_options'], {
|
||||
homeassistant: {device_automation: null},
|
||||
})
|
||||
controller = new Controller(false);
|
||||
const controller = new Controller(false);
|
||||
await controller.start();
|
||||
await flushPromises();
|
||||
MQTT.publish.mockClear();
|
||||
@ -1435,7 +1437,7 @@ describe('HomeAssistant extension', () => {
|
||||
friendly_name: 'weather_sensor',
|
||||
retain: false,
|
||||
})
|
||||
controller = new Controller(false);
|
||||
const controller = new Controller(false);
|
||||
await controller.start();
|
||||
await flushPromises();
|
||||
|
||||
@ -1448,7 +1450,7 @@ describe('HomeAssistant extension', () => {
|
||||
|
||||
it('Should disable Home Assistant legacy triggers', async () => {
|
||||
settings.set(['advanced', 'homeassistant_legacy_triggers'], false);
|
||||
controller = new Controller(false);
|
||||
const controller = new Controller(false);
|
||||
await controller.start();
|
||||
await flushPromises();
|
||||
|
||||
@ -1476,7 +1478,7 @@ describe('HomeAssistant extension', () => {
|
||||
"zigbee2mqtt_0x0017880104e45520"
|
||||
],
|
||||
"name":"button",
|
||||
"sw_version": this.version,
|
||||
"sw_version": version,
|
||||
"model":"Aqara wireless switch (WXKG11LM)",
|
||||
"manufacturer":"Xiaomi"
|
||||
}
|
||||
@ -1507,7 +1509,7 @@ describe('HomeAssistant extension', () => {
|
||||
});
|
||||
|
||||
it('Should republish payload to postfix topic with lightWithPostfix config', async () => {
|
||||
controller = new Controller(false);
|
||||
const controller = new Controller(false);
|
||||
await controller.start();
|
||||
await flushPromises();
|
||||
MQTT.publish.mockClear();
|
||||
@ -1520,7 +1522,7 @@ describe('HomeAssistant extension', () => {
|
||||
});
|
||||
|
||||
it('Shouldnt crash in onPublishEntityState on group publish', async () => {
|
||||
controller = new Controller(false);
|
||||
const controller = new Controller(false);
|
||||
await controller.start();
|
||||
await flushPromises();
|
||||
logger.error.mockClear();
|
||||
@ -1532,7 +1534,7 @@ describe('HomeAssistant extension', () => {
|
||||
});
|
||||
|
||||
it('Should counter an action payload with an empty payload', async () => {
|
||||
controller = new Controller(false);
|
||||
const controller = new Controller(false);
|
||||
await controller.start();
|
||||
await flushPromises();
|
||||
MQTT.publish.mockClear();
|
||||
@ -1556,7 +1558,7 @@ describe('HomeAssistant extension', () => {
|
||||
it('Load Home Assistant mapping from external converters', async () => {
|
||||
fs.copyFileSync(path.join(__dirname, 'assets', 'mock-external-converter-multiple.js'), path.join(data.mockDir, 'mock-external-converter-multiple.js'));
|
||||
settings.set(['external_converters'], ['mock-external-converter-multiple.js']);
|
||||
controller = new Controller(jest.fn(), jest.fn());
|
||||
const controller = new Controller(jest.fn(), jest.fn());
|
||||
const ha = controller.extensions.find((e) => e.constructor.name === 'HomeAssistant');
|
||||
await controller.start();
|
||||
await flushPromises();
|
||||
@ -1575,7 +1577,7 @@ describe('HomeAssistant extension', () => {
|
||||
});
|
||||
|
||||
it('Should clear outdated configs', async () => {
|
||||
controller = new Controller(jest.fn(), jest.fn());
|
||||
let controller = new Controller(jest.fn(), jest.fn());
|
||||
await controller.start();
|
||||
await flushPromises();
|
||||
|
||||
@ -1670,7 +1672,7 @@ describe('HomeAssistant extension', () => {
|
||||
|
||||
it('Should not have Home Assistant legacy entity attributes when disabled', async () => {
|
||||
settings.set(['advanced', 'homeassistant_legacy_entity_attributes'], false);
|
||||
controller = new Controller(false);
|
||||
const controller = new Controller(false);
|
||||
await controller.start();
|
||||
|
||||
let payload;
|
||||
@ -1687,7 +1689,7 @@ describe('HomeAssistant extension', () => {
|
||||
'device': {
|
||||
'identifiers': ['zigbee2mqtt_0x0017880104e45522'],
|
||||
'name': 'weather_sensor',
|
||||
'sw_version': this.version,
|
||||
'sw_version': version,
|
||||
'model': 'Aqara temperature, humidity and pressure sensor (WSDCGQ11LM)',
|
||||
'manufacturer': 'Xiaomi',
|
||||
},
|
||||
@ -1703,7 +1705,7 @@ describe('HomeAssistant extension', () => {
|
||||
});
|
||||
|
||||
it('Should rediscover group when device is added to it', async () => {
|
||||
controller = new Controller(false);
|
||||
const controller = new Controller(false);
|
||||
await controller.start();
|
||||
await flushPromises();
|
||||
MQTT.publish.mockClear();
|
||||
@ -1719,7 +1721,7 @@ describe('HomeAssistant extension', () => {
|
||||
"device":{
|
||||
"identifiers":["zigbee2mqtt_1221051039810110150109113116116_9"],
|
||||
"name":"ha_discovery_group",
|
||||
"sw_version":this.version,
|
||||
"sw_version":version,
|
||||
},
|
||||
"json_attributes_topic":"zigbee2mqtt/ha_discovery_group",
|
||||
"max_mireds": 454,
|
||||
|
@ -12,10 +12,11 @@ const flushPromises = require('../lib/flushPromises');
|
||||
|
||||
describe('Bridge legacy', () => {
|
||||
let controller;
|
||||
let version;
|
||||
|
||||
beforeAll(async () => {
|
||||
jest.useFakeTimers();
|
||||
this.version = await require('../../lib/util/utils').getZigbee2mqttVersion();
|
||||
version = await require('../../lib/util/utils').getZigbee2mqttVersion();
|
||||
controller = new Controller(jest.fn(), jest.fn());
|
||||
await controller.start();
|
||||
})
|
||||
@ -34,7 +35,7 @@ describe('Bridge legacy', () => {
|
||||
it('Should publish bridge configuration on startup', async () => {
|
||||
expect(MQTT.publish).toHaveBeenCalledWith(
|
||||
'zigbee2mqtt/bridge/config',
|
||||
stringify({"version":this.version.version,"commit":this.version.commitHash,"coordinator":{"type":"z-Stack","meta":{"version":1, "revision": 20190425}},"network":{"panID":5674,"extendedPanID":[0,11,22],"channel":15},"log_level":'info',"permit_join":false}),
|
||||
stringify({"version":version.version,"commit":version.commitHash,"coordinator":{"type":"z-Stack","meta":{"version":1, "revision": 20190425}},"network":{"panID":5674,"extendedPanID":[0,11,22],"channel":15},"log_level":'info',"permit_join":false}),
|
||||
{ retain: true, qos: 0 },
|
||||
expect.any(Function)
|
||||
);
|
||||
|
@ -60,7 +60,7 @@ describe('Report', () => {
|
||||
}
|
||||
}
|
||||
|
||||
mockClear = (device) => {
|
||||
const mockClear = (device) => {
|
||||
for (const endpoint of device.endpoints) {
|
||||
endpoint.read.mockClear();
|
||||
endpoint.write.mockClear();
|
||||
|
@ -11,11 +11,11 @@ const stringify = require('json-stable-stringify-without-jsonify');
|
||||
describe('OTA update', () => {
|
||||
let controller;
|
||||
|
||||
mockClear = (mapped) => {
|
||||
const mockClear = (mapped) => {
|
||||
mapped.ota.updateToLatest = jest.fn();
|
||||
mapped.ota.isUpdateAvailable = jest.fn();
|
||||
}
|
||||
|
||||
|
||||
beforeAll(async () => {
|
||||
data.writeDefaultConfiguration();
|
||||
settings.reRead();
|
||||
|
@ -39,7 +39,7 @@ describe('Utils', () => {
|
||||
expect(await utils.getZigbee2mqttVersion()).toStrictEqual({"commitHash": "123", "version": version});
|
||||
|
||||
mockReturnValue = [true, null]
|
||||
expect(await utils.getZigbee2mqttVersion()).toStrictEqual({"commitHash": "unknown", "version": version});
|
||||
expect(await utils.getZigbee2mqttVersion()).toStrictEqual({"commitHash": expect.any(String), "version": version});
|
||||
})
|
||||
|
||||
it('Check dependency version', async () => {
|
||||
|
28
tsconfig.json
Normal file
28
tsconfig.json
Normal file
@ -0,0 +1,28 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"esModuleInterop": true,
|
||||
"target": "es2018",
|
||||
"lib": ["es2018"],
|
||||
"noImplicitAny": true,
|
||||
"noImplicitThis": true,
|
||||
"moduleResolution": "node",
|
||||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
"outDir": "dist",
|
||||
"baseUrl": ".",
|
||||
"allowJs": true,
|
||||
"rootDir": "lib",
|
||||
"inlineSourceMap": true,
|
||||
"resolveJsonModule": true,
|
||||
"paths": {
|
||||
"*": [
|
||||
"node_modules/*",
|
||||
"lib/types/*"
|
||||
]
|
||||
},
|
||||
},
|
||||
"include": [
|
||||
"lib/**/*"
|
||||
],
|
||||
}
|
Loading…
Reference in New Issue
Block a user