Alexa.SecurityPanelController is described from its page: version 3 (the stub of 1.5.2 said 1), armState and the four alarms, Arm and Disarm. ctx.respond() answers Arm with Arm.Response under the namespace of the interface, its payload checked (exitDelayInSeconds 0 to 255, bypassedEndpoints), and Disarm with a Response. A Disarm carries the PIN the user said when the panel is declared with supportedAuthorizationTypes; the handler checks it and answers UNAUTHORIZED, which goes under Alexa.SecurityPanelController like the five other error types. A panel declared without options lists armState, where 1.5.2 listed no property; alarms are declared. 17 examples of the two pages are saved as fixtures. 215 tests pass, 207 before. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
51 lines
3.2 KiB
JavaScript
51 lines
3.2 KiB
JavaScript
"use strict";
|
|
// Alexa.SecurityPanelController: what the examples of its page do not show. The examples themselves are run by
|
|
// descriptors.test.js, device/discovery.test.js and dispatch/interfaces.test.js.
|
|
const { test } = require("node:test");
|
|
const assert = require("node:assert/strict");
|
|
const { AlexaInterfaceType, DeclarationError, SecurityPanelController } = require("alex2node");
|
|
const { endpoint } = require("../helpers/endpoint.js");
|
|
|
|
const panel = () => endpoint("panel-1", "Panel", ["SECURITY_PANEL"]);
|
|
|
|
test("a panel declared without options lists the arm state and no configuration, the 1.x way or with add()", () => {
|
|
const announced = {
|
|
type: "AlexaInterface",
|
|
interface: "Alexa.SecurityPanelController",
|
|
version: "3",
|
|
properties: { supported: [{ name: "armState" }], proactivelyReported: false, retrievable: true },
|
|
};
|
|
assert.deepEqual(panel().addCapability(AlexaInterfaceType.SECURITY_PANEL_CONTROLLER).getJSON(), announced);
|
|
const device = panel();
|
|
assert.deepEqual(device.add(SecurityPanelController).toJSON(), announced);
|
|
assert.deepEqual(device.check(), []);
|
|
});
|
|
|
|
test("the alarms and the arm states of a declaration are the ones of the page, each listed once", () => {
|
|
const { properties, configuration } = panel().add(SecurityPanelController, {
|
|
supportedArmStates: ["ARMED_NIGHT", "DISARMED"],
|
|
alarms: ["waterAlarm", "carbonMonoxideAlarm"],
|
|
}).toJSON();
|
|
assert.deepEqual(properties.supported, [{ name: "armState" }, { name: "waterAlarm" }, { name: "carbonMonoxideAlarm" }]);
|
|
assert.deepEqual(configuration, { supportedArmStates: [{ value: "ARMED_NIGHT" }, { value: "DISARMED" }] });
|
|
|
|
const refused = (options, message) => assert.throws(
|
|
() => panel().add(SecurityPanelController, options),
|
|
(err) => err instanceof DeclarationError && err.message === `panel-1: Alexa.SecurityPanelController: ${message}`
|
|
);
|
|
refused({ alarms: ["smokeAlarm"] }, 'alarms[0]: expected burglaryAlarm | fireAlarm | carbonMonoxideAlarm | waterAlarm, got "smokeAlarm"');
|
|
refused({ alarms: ["fireAlarm", "fireAlarm"] }, "fireAlarm is listed twice");
|
|
refused({ supportedArmStates: [] }, "supportedArmStates: expected a list with 1 or more entries, got []");
|
|
refused({ supportedAuthorizationTypes: ["SIX_DIGIT_PIN"] }, 'supportedAuthorizationTypes[0]: expected FOUR_DIGIT_PIN, got "SIX_DIGIT_PIN"');
|
|
});
|
|
|
|
test("Arm.Response: an exit delay of 0 to 255 seconds, and the sensors that were bypassed", () => {
|
|
const { namespace, name, payload } = SecurityPanelController.responseFor("Arm");
|
|
assert.deepEqual([namespace, name], ["Alexa.SecurityPanelController", "Arm.Response"]);
|
|
for (const fields of [{}, { exitDelayInSeconds: 0 }, { exitDelayInSeconds: 255, bypassedEndpoints: [{ friendlyName: "water sensor" }] }]) {
|
|
assert.deepEqual(payload.parse(fields, "payload"), fields);
|
|
}
|
|
assert.throws(() => payload.parse({ exitDelayInSeconds: 1.5 }, "payload"), /^SchemaError: payload\.exitDelayInSeconds: expected an integer from 0 to 255, got 1\.5$/);
|
|
assert.throws(() => payload.parse({ bypassedEndpoints: ["side window"] }, "payload"), /^SchemaError: payload\.bypassedEndpoints\[0\]: expected an object/);
|
|
assert.equal(SecurityPanelController.responseFor("Disarm"), undefined);
|
|
});
|