Skip to content

Commit

Permalink
Merge pull request #375 from athombv/feat/zigbee-validation
Browse files Browse the repository at this point in the history
feat(zigbee): add validation
  • Loading branch information
RobinBol authored Nov 7, 2023
2 parents fda8bef + 51065b2 commit c6fa24a
Show file tree
Hide file tree
Showing 2 changed files with 350 additions and 1 deletion.
74 changes: 73 additions & 1 deletion assets/app/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -747,6 +747,78 @@
]
}
},
"zigbeeDevice": {
"type": "object",
"required": [
"manufacturerName", "productId", "endpoints"
],
"properties": {
"manufacturerName": {
"oneOf": [
{
"type": "string"
},
{
"type": "array",
"items": {
"type": "string"
}
}
]
},
"productId": {
"oneOf": [
{
"type": "string"
},
{
"type": "array",
"items": {
"type": "string"
}
}
]
},
"endpoints": {
"type": "object",
"additionalProperties": false,
"patternProperties": {
"[0-255]": {
"type": "object",
"additionalProperties": false,
"properties": {
"clusters": {
"type": "array",
"items": {
"type": "number"
}
},
"bindings": {
"type": "array",
"items": {
"type": "number"
}
}
}
}
}
},
"learnmode": {
"type": "object",
"required": [
"instruction"
],
"properties": {
"image": {
"type": "string"
},
"instruction": {
"$ref": "#/definitions/i18nObject"
}
}
}
}
},
"zwaveDevice": {
"type": "object",
"required": [
Expand Down Expand Up @@ -1242,7 +1314,7 @@
"$ref": "#/definitions/zwaveDevice"
},
"zigbee": {
"type": "object"
"$ref": "#/definitions/zigbeeDevice"
},
"rf433": {
"type": "object",
Expand Down
277 changes: 277 additions & 0 deletions test/validate-driver-manifest.js
Original file line number Diff line number Diff line change
Expand Up @@ -248,4 +248,281 @@ describe('HomeyLib.App#validate() driver manifest', function() {
verified: /connectivity\[0\] should be equal to one of the allowed values/i,
});
});

/*
* Zigbee Driver
*/

it('`zigbee.productId` needs to be defined', async function() {
const app = mockApp({
...baseAppManifest,
drivers: [{
...baseDriverManifest,
zigbee: {
manufacturerName: ['dummyManufacturer'],
endpoints: {},
},
}],
});

await assertValidates(app, {
debug: /zigbee should have required property 'productId'/i,
publish: /zigbee should have required property 'productId'/i,
verified: /zigbee should have required property 'productId'/i,
});
});

it('`zigbee.productId` needs to be valid', async function() {
const app = mockApp({
...baseAppManifest,
drivers: [{
...baseDriverManifest,
zigbee: {
productId: true,
manufacturerName: ['dummyManufacturer'],
endpoints: {},
},
}],
});

// Product ID can be a string
await assertValidates(app, {
debug: /zigbee\.productId should be string/i,
publish: /zigbee\.productId should be string/i,
verified: /zigbee\.productId should be string/i,
});

// or an array of strings
await assertValidates(app, {
debug: /zigbee\.productId should be array/i,
publish: /zigbee\.productId should be array/i,
verified: /zigbee\.productId should be array/i,
});
});

it('`zigbee.manufacturerName` needs to be defined', async function() {
const app = mockApp({
...baseAppManifest,
drivers: [{
...baseDriverManifest,
zigbee: {
productId: ['dummyProduct'],
endpoints: {},
},
}],
});

await assertValidates(app, {
debug: /zigbee should have required property 'manufacturerName'/i,
publish: /zigbee should have required property 'manufacturerName'/i,
verified: /zigbee should have required property 'manufacturerName'/i,
});
});

it('`zigbee.manufacturerName` needs to be valid', async function() {
const app = mockApp({
...baseAppManifest,
drivers: [{
...baseDriverManifest,
zigbee: {
productId: 'dummyProduct',
manufacturerName: true,
endpoints: {},
},
}],
});

// manufacturerName can be a string
await assertValidates(app, {
debug: /zigbee\.manufacturerName should be string/i,
publish: /zigbee\.manufacturerName should be string/i,
verified: /zigbee\.manufacturerName should be string/i,
});

// or an array of strings
await assertValidates(app, {
debug: /zigbee\.manufacturerName should be array/i,
publish: /zigbee\.manufacturerName should be array/i,
verified: /zigbee\.manufacturerName should be array/i,
});
});

it('`zigbee.endpoints` needs to be defined', async function() {
const app = mockApp({
...baseAppManifest,
drivers: [{
...baseDriverManifest,
zigbee: {
productId: ['dummyProduct'],
manufacturerName: 'dummyManufacturer',
},
}],
});

await assertValidates(app, {
debug: /zigbee should have required property 'endpoints'/i,
publish: /zigbee should have required property 'endpoints'/i,
verified: /zigbee should have required property 'endpoints'/i,
});
});

it('`zigbee.endpoints` needs to be valid', async function() {
const app = mockApp({
...baseAppManifest,
drivers: [{
...baseDriverManifest,
zigbee: {
productId: ['dummyProduct'],
manufacturerName: ['dummyManufacturer'],
endpoints: true,
},
}],
});

await assertValidates(app, {
debug: /zigbee\.endpoints should be object/i,
publish: /zigbee\.endpoints should be object/i,
verified: /zigbee\.endpoints should be object/i,
});
});

it('`zigbee.endpoints` key needs to be valid', async function() {
const app = mockApp({
...baseAppManifest,
drivers: [{
...baseDriverManifest,
zigbee: {
productId: ['dummyProduct'],
manufacturerName: ['dummyManufacturer'],
endpoints: {
bla: [],
},
},
}],
});

await assertValidates(app, {
debug: /zigbee\.endpoints should NOT have additional properties/i,
publish: /zigbee\.endpoints should NOT have additional properties/i,
verified: /zigbee\.endpoints should NOT have additional properties/i,
});
});

it('`zigbee.endpoints.x` needs to be an object', async function() {
const app = mockApp({
...baseAppManifest,
drivers: [{
...baseDriverManifest,
zigbee: {
productId: ['dummyProduct'],
manufacturerName: ['dummyManufacturer'],
endpoints: {
1: [],
},
},
}],
});

await assertValidates(app, {
debug: /zigbee\.endpoints\['1'] should be object/i,
publish: /zigbee\.endpoints\['1'] should be object/i,
verified: /zigbee\.endpoints\['1'] should be object/i,
});
});

it('`zigbee.endpoints.x.clusters` needs to be an array', async function() {
const app = mockApp({
...baseAppManifest,
drivers: [{
...baseDriverManifest,
zigbee: {
productId: ['dummyProduct'],
manufacturerName: ['dummyManufacturer'],
endpoints: {
1: {
clusters: {},
},
},
},
}],
});

await assertValidates(app, {
debug: /zigbee\.endpoints\['1'].clusters should be array/i,
publish: /zigbee\.endpoints\['1'].clusters should be array/i,
verified: /zigbee\.endpoints\['1'].clusters should be array/i,
});
});

it('`zigbee.endpoints.x.clusters` needs to be an array of only numbers', async function() {
const app = mockApp({
...baseAppManifest,
drivers: [{
...baseDriverManifest,
zigbee: {
productId: ['dummyProduct'],
manufacturerName: ['dummyManufacturer'],
endpoints: {
1: {
clusters: [true],
},
},
},
}],
});

await assertValidates(app, {
debug: /zigbee\.endpoints\['1'].clusters\[0] should be number/i,
publish: /zigbee\.endpoints\['1'].clusters\[0] should be number/i,
verified: /zigbee\.endpoints\['1'].clusters\[0] should be number/i,
});
});

it('`zigbee.endpoints.x.bindings` needs to be an array', async function() {
const app = mockApp({
...baseAppManifest,
drivers: [{
...baseDriverManifest,
zigbee: {
productId: ['dummyProduct'],
manufacturerName: ['dummyManufacturer'],
endpoints: {
1: {
bindings: {},
},
},
},
}],
});

await assertValidates(app, {
debug: /zigbee\.endpoints\['1'].bindings should be array/i,
publish: /zigbee\.endpoints\['1'].bindings should be array/i,
verified: /zigbee\.endpoints\['1'].bindings should be array/i,
});
});

it('`zigbee.endpoints.x.bindings` needs to be an array of only numbers', async function() {
const app = mockApp({
...baseAppManifest,
drivers: [{
...baseDriverManifest,
zigbee: {
productId: ['dummyProduct'],
manufacturerName: ['dummyManufacturer'],
endpoints: {
1: {
bindings: [true],
},
},
},
}],
});

await assertValidates(app, {
debug: /zigbee\.endpoints\['1'].bindings\[0] should be number/i,
publish: /zigbee\.endpoints\['1'].bindings\[0] should be number/i,
verified: /zigbee\.endpoints\['1'].bindings\[0] should be number/i,
});
});
});

0 comments on commit c6fa24a

Please sign in to comment.