"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); });