homebridge-virtual-accessories 3.16.4 → 3.16.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/accessories/updatableChargingState.d.ts +1 -1
- package/dist/accessories/virtualAccessoryBattery.d.ts +1 -1
- package/dist/accessories/virtualAccessoryBattery.js.map +1 -1
- package/dist/webhookServer.d.ts +1 -0
- package/dist/webhookServer.js +90 -47
- package/dist/webhookServer.js.map +1 -1
- package/package.json +4 -3
- package/test/webhookServer.test.js +450 -0
|
@@ -15,7 +15,7 @@ export declare class Battery extends Accessory implements UpdatableChargingStatu
|
|
|
15
15
|
getBatteryLevelHandler(): Promise<CharacteristicValue>;
|
|
16
16
|
getChargingStateHandler(): Promise<CharacteristicValue>;
|
|
17
17
|
protected getJsonState(): string;
|
|
18
|
-
updateChargingStatus(charging: boolean, charge: number, accessoryId: string): void;
|
|
18
|
+
updateChargingStatus(charging: boolean | undefined, charge: number | undefined, accessoryId: string): void;
|
|
19
19
|
static get BATTERY_LEVEL_NORMAL(): number;
|
|
20
20
|
static get BATTERY_LEVEL_LOW(): number;
|
|
21
21
|
static get NOT_CHARGING(): number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"virtualAccessoryBattery.js","sourceRoot":"","sources":["../../src/accessories/virtualAccessoryBattery.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"virtualAccessoryBattery.js","sourceRoot":"","sources":["../../src/accessories/virtualAccessoryBattery.ts"],"names":[],"mappings":"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"}
|
package/dist/webhookServer.d.ts
CHANGED
package/dist/webhookServer.js
CHANGED
|
@@ -4,7 +4,7 @@ import { BinarySensor } from './sensors/binarySensor.js';
|
|
|
4
4
|
import { SensorValueUpdateNotAllowed } from './errors.js';
|
|
5
5
|
import express from 'express';
|
|
6
6
|
function ToBoolean(value) {
|
|
7
|
-
switch (value) {
|
|
7
|
+
switch (value.toLowerCase()) {
|
|
8
8
|
case 'true':
|
|
9
9
|
return true;
|
|
10
10
|
case 'false':
|
|
@@ -41,12 +41,14 @@ export class WebhookServer {
|
|
|
41
41
|
const routeHumidity = '/humidity';
|
|
42
42
|
this.log.info(`[${this.serverName}] Setting up route: ${routeHumidity}`);
|
|
43
43
|
this.server.post(routeHumidity, (request, response) => {
|
|
44
|
+
if (!this.parametersArePresent(request, response)) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
44
47
|
const useQueryParams = this.usingQueryParams(request);
|
|
45
48
|
const accessoryId = (useQueryParams) ? request.query.id : request.body.id;
|
|
46
49
|
const humidity = (useQueryParams) ? request.query.value : request.body.value;
|
|
47
|
-
if (this.
|
|
48
|
-
this.
|
|
49
|
-
this.percentageIsValid(humidity, response)) {
|
|
50
|
+
if (this.accessoryIdIsValid(accessoryId, response) &&
|
|
51
|
+
this.percentageIsValid(humidity, response, request)) {
|
|
50
52
|
this.processRequest(routeHumidity, accessoryId, ['humidifierdehumidifier', 'measurement'], Number(humidity), response);
|
|
51
53
|
}
|
|
52
54
|
});
|
|
@@ -55,12 +57,14 @@ export class WebhookServer {
|
|
|
55
57
|
const routeTemperature = '/temperature';
|
|
56
58
|
this.log.info(`[${this.serverName}] Setting up route: ${routeTemperature}`);
|
|
57
59
|
this.server.post(routeTemperature, (request, response) => {
|
|
60
|
+
if (!this.parametersArePresent(request, response)) {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
58
63
|
const useQueryParams = this.usingQueryParams(request);
|
|
59
64
|
const accessoryId = (useQueryParams) ? request.query.id : request.body.id;
|
|
60
65
|
const temperature = (useQueryParams) ? request.query.value : request.body.value;
|
|
61
|
-
if (this.
|
|
62
|
-
this.
|
|
63
|
-
this.numberIsValid(temperature, response)) {
|
|
66
|
+
if (this.accessoryIdIsValid(accessoryId, response) &&
|
|
67
|
+
this.numberIsValid(temperature, response, request)) {
|
|
64
68
|
this.processRequest(routeTemperature, accessoryId, ['heatercooler', 'measurement'], Number(temperature), response);
|
|
65
69
|
}
|
|
66
70
|
});
|
|
@@ -69,13 +73,15 @@ export class WebhookServer {
|
|
|
69
73
|
const routeObstruction = '/obstruction';
|
|
70
74
|
this.log.info(`[${this.serverName}] Setting up route: ${routeObstruction}`);
|
|
71
75
|
this.server.post(routeObstruction, (request, response) => {
|
|
76
|
+
if (!this.parametersArePresent(request, response)) {
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
72
79
|
const useQueryParams = this.usingQueryParams(request);
|
|
73
80
|
const accessoryId = (useQueryParams) ? request.query.id : request.body.id;
|
|
74
|
-
const obstruction = (
|
|
75
|
-
if (this.
|
|
76
|
-
this.
|
|
77
|
-
this.
|
|
78
|
-
this.processRequest(routeObstruction, accessoryId, ['garagedoor'], ToBoolean(obstruction), response);
|
|
81
|
+
const obstruction = (useQueryParams) ? request.query.value : request.body.value;
|
|
82
|
+
if (this.accessoryIdIsValid(accessoryId, response) &&
|
|
83
|
+
this.booleanIsValid(obstruction, response, request)) {
|
|
84
|
+
this.processRequest(routeObstruction, accessoryId, ['garagedoor'], ToBoolean(obstruction.toString()), response);
|
|
79
85
|
}
|
|
80
86
|
});
|
|
81
87
|
// id
|
|
@@ -83,14 +89,16 @@ export class WebhookServer {
|
|
|
83
89
|
const routeTriggerAlarm = '/triggeralarm';
|
|
84
90
|
this.log.info(`[${this.serverName}] Setting up route: ${routeTriggerAlarm}`);
|
|
85
91
|
this.server.post(routeTriggerAlarm, (request, response) => {
|
|
92
|
+
if (!this.parametersArePresent(request, response)) {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
86
95
|
const useQueryParams = this.usingQueryParams(request);
|
|
87
96
|
const accessoryId = (useQueryParams) ? request.query.id : request.body.id;
|
|
88
|
-
const trigger = (
|
|
89
|
-
if (this.
|
|
90
|
-
this.
|
|
91
|
-
this.booleanIsValid(trigger, response)) {
|
|
97
|
+
const trigger = (useQueryParams) ? request.query.value : request.body.value;
|
|
98
|
+
if (this.accessoryIdIsValid(accessoryId, response) &&
|
|
99
|
+
this.booleanIsValid(trigger, response, request)) {
|
|
92
100
|
// eslint-disable-next-line max-len
|
|
93
|
-
this.processRequest(routeTriggerAlarm, accessoryId, ['securitysystem'], (ToBoolean(trigger) ? SecurityServiceTriggerType.TriggerAlarm : SecurityServiceTriggerType.None), response);
|
|
101
|
+
this.processRequest(routeTriggerAlarm, accessoryId, ['securitysystem'], (ToBoolean(trigger.toString()) ? SecurityServiceTriggerType.TriggerAlarm : SecurityServiceTriggerType.None), response);
|
|
94
102
|
}
|
|
95
103
|
});
|
|
96
104
|
// id
|
|
@@ -98,14 +106,16 @@ export class WebhookServer {
|
|
|
98
106
|
const routeTriggerPanic = '/triggerpanic';
|
|
99
107
|
this.log.info(`[${this.serverName}] Setting up route: ${routeTriggerPanic}`);
|
|
100
108
|
this.server.post(routeTriggerPanic, (request, response) => {
|
|
109
|
+
if (!this.parametersArePresent(request, response)) {
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
101
112
|
const useQueryParams = this.usingQueryParams(request);
|
|
102
113
|
const accessoryId = (useQueryParams) ? request.query.id : request.body.id;
|
|
103
|
-
const trigger = (
|
|
104
|
-
if (this.
|
|
105
|
-
this.
|
|
106
|
-
this.booleanIsValid(trigger, response)) {
|
|
114
|
+
const trigger = (useQueryParams) ? request.query.value : request.body.value;
|
|
115
|
+
if (this.accessoryIdIsValid(accessoryId, response) &&
|
|
116
|
+
this.booleanIsValid(trigger, response, request)) {
|
|
107
117
|
// eslint-disable-next-line max-len
|
|
108
|
-
this.processRequest(routeTriggerPanic, accessoryId, ['securitysystem'], (ToBoolean(trigger) ? SecurityServiceTriggerType.TriggerPanic : SecurityServiceTriggerType.None), response);
|
|
118
|
+
this.processRequest(routeTriggerPanic, accessoryId, ['securitysystem'], (ToBoolean(trigger.toString()) ? SecurityServiceTriggerType.TriggerPanic : SecurityServiceTriggerType.None), response);
|
|
109
119
|
}
|
|
110
120
|
});
|
|
111
121
|
// id
|
|
@@ -113,13 +123,15 @@ export class WebhookServer {
|
|
|
113
123
|
const routeTriggerSensor = '/triggersensor';
|
|
114
124
|
this.log.info(`[${this.serverName}] Setting up route: ${routeTriggerSensor}`);
|
|
115
125
|
this.server.post(routeTriggerSensor, (request, response) => {
|
|
126
|
+
if (!this.parametersArePresent(request, response)) {
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
116
129
|
const useQueryParams = this.usingQueryParams(request);
|
|
117
130
|
const accessoryId = (useQueryParams) ? request.query.id : request.body.id;
|
|
118
|
-
const trigger = (
|
|
119
|
-
if (this.
|
|
120
|
-
this.
|
|
121
|
-
this.
|
|
122
|
-
this.processRequest(routeTriggerSensor, accessoryId, ['sensor'], ToBoolean(trigger), response);
|
|
131
|
+
const trigger = (useQueryParams) ? request.query.value : request.body.value;
|
|
132
|
+
if (this.accessoryIdIsValid(accessoryId, response) &&
|
|
133
|
+
this.booleanIsValid(trigger, response, request)) {
|
|
134
|
+
this.processRequest(routeTriggerSensor, accessoryId, ['sensor'], ToBoolean(trigger.toString()), response);
|
|
123
135
|
}
|
|
124
136
|
});
|
|
125
137
|
// id
|
|
@@ -128,15 +140,21 @@ export class WebhookServer {
|
|
|
128
140
|
const routeChargingState = '/chargingstate';
|
|
129
141
|
this.log.info(`[${this.serverName}] Setting up route: ${routeChargingState}`);
|
|
130
142
|
this.server.post(routeChargingState, (request, response) => {
|
|
143
|
+
if (!this.parametersArePresent(request, response)) {
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
131
146
|
const useQueryParams = this.usingQueryParams(request);
|
|
132
147
|
const accessoryId = (useQueryParams) ? request.query.id : request.body.id;
|
|
133
|
-
const charging = (
|
|
134
|
-
const charge = (useQueryParams) ?
|
|
135
|
-
if (
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
148
|
+
const charging = (useQueryParams) ? request.query.charging : request.body.charging;
|
|
149
|
+
const charge = (useQueryParams) ? request.query.charge : request.body.charge;
|
|
150
|
+
if (charging === undefined && charge === undefined) {
|
|
151
|
+
response.status(HttpResponse.BadRequest).send('At least one of charging or charge must be supplied');
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
if (this.accessoryIdIsValid(accessoryId, response) &&
|
|
155
|
+
(charging === undefined || this.booleanIsValid(charging, response, request)) &&
|
|
156
|
+
(charge === undefined || this.percentageIsValid(charge, response, request))) {
|
|
157
|
+
const chargingState = new ChargingState(charging === undefined ? undefined : ToBoolean(charging.toString()), charge === undefined ? undefined : Number(charge));
|
|
140
158
|
this.processRequest(routeChargingState, accessoryId, ['battery'], chargingState, response);
|
|
141
159
|
}
|
|
142
160
|
});
|
|
@@ -194,19 +212,25 @@ export class WebhookServer {
|
|
|
194
212
|
}
|
|
195
213
|
accessoryIdIsValid(accessoryId, response) {
|
|
196
214
|
const patternRegex = new RegExp(WebhookServer.accessoryIdPattern);
|
|
197
|
-
const isValidAccessoryId = (
|
|
215
|
+
const isValidAccessoryId = (typeof accessoryId === 'string' &&
|
|
198
216
|
patternRegex.test(accessoryId));
|
|
199
217
|
if (!isValidAccessoryId) {
|
|
200
|
-
|
|
218
|
+
// Do not invoke conversion methods on malformed objects or arrays.
|
|
219
|
+
const invalidId = accessoryId !== null && typeof accessoryId === 'object' ? typeof accessoryId : String(accessoryId);
|
|
220
|
+
const errorMsg = `Invalid accessory id: ${invalidId}`;
|
|
201
221
|
this.log.error(`[${this.serverName}] ${errorMsg}`);
|
|
202
222
|
response.status(HttpResponse.BadRequest).send(`${errorMsg}`);
|
|
203
223
|
return false;
|
|
204
224
|
}
|
|
205
225
|
return true;
|
|
206
226
|
}
|
|
207
|
-
percentageIsValid(value, response) {
|
|
227
|
+
percentageIsValid(value, response, request) {
|
|
228
|
+
if (!this.numberIsValid(value, response, request)) {
|
|
229
|
+
return false;
|
|
230
|
+
}
|
|
208
231
|
const valuePercent = Number(value);
|
|
209
|
-
if (
|
|
232
|
+
if (!Number.isInteger(valuePercent) || valuePercent < 0 || valuePercent > 100 ||
|
|
233
|
+
(typeof value === 'string' && !/^[+-]?\d+$/.test(value))) {
|
|
210
234
|
const errorMsg = `Invalid value: ${value}. Value must be a percentage`;
|
|
211
235
|
this.log.error(`[${this.serverName}] ${errorMsg}`);
|
|
212
236
|
response.status(HttpResponse.BadRequest).send(`${errorMsg}`);
|
|
@@ -214,20 +238,29 @@ export class WebhookServer {
|
|
|
214
238
|
}
|
|
215
239
|
return true;
|
|
216
240
|
}
|
|
217
|
-
numberIsValid(value, response) {
|
|
218
|
-
const
|
|
219
|
-
|
|
220
|
-
|
|
241
|
+
numberIsValid(value, response, request) {
|
|
242
|
+
const isScalar = this.usingStringValues(request)
|
|
243
|
+
? typeof value === 'string' && value === value.trim() && /^[+-]?(?:\d+(?:\.\d*)?|\.\d+)$/.test(value)
|
|
244
|
+
: typeof value === 'number';
|
|
245
|
+
if (!isScalar || !Number.isFinite(Number(value))) {
|
|
246
|
+
// Do not invoke conversion methods on malformed objects or arrays.
|
|
247
|
+
const invalidValue = value !== null && typeof value === 'object' ? typeof value : String(value);
|
|
248
|
+
const errorMsg = `Invalid value: ${invalidValue}. Value must be a finite number`;
|
|
221
249
|
this.log.error(`[${this.serverName}] ${errorMsg}`);
|
|
222
250
|
response.status(HttpResponse.BadRequest).send(`${errorMsg}`);
|
|
223
251
|
return false;
|
|
224
252
|
}
|
|
225
253
|
return true;
|
|
226
254
|
}
|
|
227
|
-
booleanIsValid(value, response) {
|
|
228
|
-
const valueBoolean =
|
|
255
|
+
booleanIsValid(value, response, request) {
|
|
256
|
+
const valueBoolean = (this.usingStringValues(request)
|
|
257
|
+
? typeof value === 'string' && ['true', 'false'].includes(value.toLowerCase())
|
|
258
|
+
: typeof value === 'boolean');
|
|
229
259
|
if (!valueBoolean) {
|
|
230
|
-
|
|
260
|
+
// Avoid invoking user-supplied conversion methods when reporting malformed values.
|
|
261
|
+
const invalidValue = value !== null && (typeof value === 'object' || typeof value === 'function')
|
|
262
|
+
? typeof value : String(value);
|
|
263
|
+
const errorMsg = `Invalid value: ${invalidValue}. Value must be a boolean`;
|
|
231
264
|
this.log.error(`[${this.serverName}] ${errorMsg}`);
|
|
232
265
|
response.status(HttpResponse.BadRequest).send(`${errorMsg}`);
|
|
233
266
|
return false;
|
|
@@ -284,13 +317,20 @@ export class WebhookServer {
|
|
|
284
317
|
}
|
|
285
318
|
}
|
|
286
319
|
parametersArePresent(request, response) {
|
|
320
|
+
const header = request.header(this.UseQueryParamsHeader)?.trim().toLowerCase();
|
|
321
|
+
if (header !== undefined && header !== 'true' && header !== 'false') {
|
|
322
|
+
const errorMsg = `Invalid ${this.UseQueryParamsHeader} header. Value must be true or false`;
|
|
323
|
+
this.log.error(`[${this.serverName}] ${errorMsg}`);
|
|
324
|
+
response.status(HttpResponse.BadRequest).send(errorMsg);
|
|
325
|
+
return false;
|
|
326
|
+
}
|
|
287
327
|
const useQueryParams = this.usingQueryParams(request);
|
|
288
328
|
this.log.debug(`[${this.serverName}] ${this.UseQueryParamsHeader}: ${useQueryParams}`);
|
|
289
329
|
this.log.debug(`[${this.serverName}] Request: ${request.method} ${request.path}`);
|
|
290
330
|
this.log.debug(`[${this.serverName}] POST body: ${JSON.stringify(request.body)}`);
|
|
291
331
|
this.log.debug(`[${this.serverName}] POST query: ${JSON.stringify(request.query)}`);
|
|
292
332
|
// POST body
|
|
293
|
-
if (!useQueryParams && JSON.stringify(request.body) === '{}') {
|
|
333
|
+
if (!useQueryParams && (request.body == null || JSON.stringify(request.body) === '{}')) {
|
|
294
334
|
const errorMsg = 'No parameters found in POST body';
|
|
295
335
|
this.log.error(`[${this.serverName}] ${errorMsg}`);
|
|
296
336
|
response.status(HttpResponse.BadRequest).send(`${errorMsg}`);
|
|
@@ -305,9 +345,12 @@ export class WebhookServer {
|
|
|
305
345
|
}
|
|
306
346
|
return true;
|
|
307
347
|
}
|
|
348
|
+
usingStringValues(request) {
|
|
349
|
+
return this.usingQueryParams(request) || request.is('application/x-www-form-urlencoded') === 'application/x-www-form-urlencoded';
|
|
350
|
+
}
|
|
308
351
|
usingQueryParams(request) {
|
|
309
352
|
const useQueryParamsHeader = request.header(this.UseQueryParamsHeader);
|
|
310
|
-
return (useQueryParamsHeader === undefined) ? false : ToBoolean(useQueryParamsHeader);
|
|
353
|
+
return (useQueryParamsHeader === undefined) ? false : ToBoolean(useQueryParamsHeader.trim());
|
|
311
354
|
}
|
|
312
355
|
}
|
|
313
356
|
class HttpResponse {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webhookServer.js","sourceRoot":"","sources":["../src/webhookServer.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"webhookServer.js","sourceRoot":"","sources":["../src/webhookServer.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "homebridge-virtual-accessories",
|
|
3
3
|
"displayName": "Virtual Accessories for Homebridge",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"version": "3.16.
|
|
5
|
+
"version": "3.16.5",
|
|
6
6
|
"description": "Virtual HomeKit accessories for Homebridge.",
|
|
7
7
|
"author": "justjam2023 (Renzo Zanelli - renzo.zanelli6@gmail.com)",
|
|
8
8
|
"license": "MIT",
|
|
@@ -102,7 +102,8 @@
|
|
|
102
102
|
"homebridge": "^1.8.0 || ^2.0.0-beta.0"
|
|
103
103
|
},
|
|
104
104
|
"scripts": {
|
|
105
|
-
"build": "rimraf ./dist && tsc",
|
|
105
|
+
"build": "rimraf ./dist && tsc && npm test",
|
|
106
|
+
"test": "node --test test/*.test.js",
|
|
106
107
|
"generate-schemas": "node scripts/generate-schemas.js",
|
|
107
108
|
"generate-template": "node scripts/generate-template.js",
|
|
108
109
|
"lint": "eslint . --max-warnings=0",
|
|
@@ -111,7 +112,7 @@
|
|
|
111
112
|
},
|
|
112
113
|
"dependencies": {
|
|
113
114
|
"@js-joda/core": "^6.0.0",
|
|
114
|
-
"@js-joda/timezone": "^
|
|
115
|
+
"@js-joda/timezone": "^3.0.0",
|
|
115
116
|
"@justjam2013/net-ping": "^2.0.0",
|
|
116
117
|
"@types/express": "^5.0.3",
|
|
117
118
|
"cheerio": "^1.2.0",
|
|
@@ -0,0 +1,450 @@
|
|
|
1
|
+
/* global fetch */
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import { once } from 'node:events';
|
|
4
|
+
import { URLSearchParams } from 'node:url';
|
|
5
|
+
import { test } from 'node:test';
|
|
6
|
+
import { Battery } from '../dist/accessories/virtualAccessoryBattery.js';
|
|
7
|
+
import { WebhookServer } from '../dist/webhookServer.js';
|
|
8
|
+
import { SecurityServiceTriggerType } from '../dist/accessories/virtualAccessorySecuritySystem.js';
|
|
9
|
+
|
|
10
|
+
// Run with npm test (builds the source before testing).
|
|
11
|
+
test('accessory IDs reject malformed HTTP input without dispatching updates', async (t) => {
|
|
12
|
+
const webhook = new WebhookServer({ info() {}, error() {}, debug() {} }, 0);
|
|
13
|
+
const updates = [];
|
|
14
|
+
webhook.processRequest = (route, id, types, value, response) => {
|
|
15
|
+
updates.push({ route, id });
|
|
16
|
+
response.sendStatus(200);
|
|
17
|
+
};
|
|
18
|
+
const server = webhook.server.listen(0, '127.0.0.1');
|
|
19
|
+
t.after(() => new Promise((resolve, reject) => server.close(error => error ? reject(error) : resolve())));
|
|
20
|
+
await once(server, 'listening');
|
|
21
|
+
const base = `http://127.0.0.1:${server.address().port}`;
|
|
22
|
+
const routes = ['/humidity', '/temperature', '/obstruction', '/triggeralarm', '/triggerpanic', '/triggersensor', '/chargingstate'];
|
|
23
|
+
|
|
24
|
+
for (const route of routes) {
|
|
25
|
+
const fields = route === '/chargingstate' ? { charging: false, charge: 0 }
|
|
26
|
+
: { value: route === '/humidity' || route === '/temperature' ? 0 : false };
|
|
27
|
+
const invalidIds = [
|
|
28
|
+
[{ toString: 1 }, 'object'], [{}, 'object'], [[], 'object'], [['a00005'], 'object'],
|
|
29
|
+
[[{ toString: 1 }], 'object'], [null, 'null'], [12345, '12345'], [false, 'false'],
|
|
30
|
+
[undefined, 'undefined'], ['', ''], ['abcd', 'abcd'], ['invalid id', 'invalid id'],
|
|
31
|
+
];
|
|
32
|
+
for (const [id, description] of invalidIds) {
|
|
33
|
+
await t.test(`${route} rejects JSON id ${JSON.stringify(id)}`, async () => {
|
|
34
|
+
const before = updates.length;
|
|
35
|
+
const response = await fetch(`${base}${route}`, {
|
|
36
|
+
method: 'POST', headers: { 'Content-Type': 'application/json' },
|
|
37
|
+
body: JSON.stringify({ id, ...fields }),
|
|
38
|
+
});
|
|
39
|
+
assert.equal(response.status, 400);
|
|
40
|
+
assert.equal(await response.text(), `Invalid accessory id: ${description}`);
|
|
41
|
+
assert.equal(updates.length, before);
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
for (const mode of ['query', 'form']) {
|
|
45
|
+
for (const id of ['id[toString]=1', 'id[]=a00005', 'id[0][toString]=1', 'id=a00005&id=b00006']) {
|
|
46
|
+
await t.test(`${route} rejects ${mode} ${id}`, async () => {
|
|
47
|
+
const before = updates.length;
|
|
48
|
+
const encoded = `${id}&${new URLSearchParams(fields)}`;
|
|
49
|
+
const options = mode === 'query' ? { headers: { 'Use-Query-Params': 'true' } }
|
|
50
|
+
: { headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: encoded };
|
|
51
|
+
const response = await fetch(`${base}${route}${mode === 'query' ? `?${encoded}` : ''}`, { method: 'POST', ...options });
|
|
52
|
+
assert.equal(response.status, 400);
|
|
53
|
+
assert.match(await response.text(), /^Invalid accessory id: (object|undefined)$/);
|
|
54
|
+
assert.equal(updates.length, before);
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
for (const mode of ['JSON', 'query', 'form']) {
|
|
59
|
+
for (const id of ['a00005', '12345', 'AbC-09']) {
|
|
60
|
+
await t.test(`${route} accepts ${mode} string id ${id}`, async () => {
|
|
61
|
+
const before = updates.length;
|
|
62
|
+
const payload = { id, ...fields };
|
|
63
|
+
const encoded = new URLSearchParams(payload).toString();
|
|
64
|
+
const options = mode === 'query' ? { headers: { 'Use-Query-Params': 'true' } }
|
|
65
|
+
: mode === 'JSON' ? { headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) }
|
|
66
|
+
: { headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: encoded };
|
|
67
|
+
const response = await fetch(`${base}${route}${mode === 'query' ? `?${encoded}` : ''}`, { method: 'POST', ...options });
|
|
68
|
+
assert.equal(response.status, 200, await response.text());
|
|
69
|
+
assert.equal(updates.length, before + 1);
|
|
70
|
+
assert.deepEqual(updates.at(-1), { route, id });
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
test('boolean webhook validation rejects malformed values and preserves valid booleans', async (t) => {
|
|
78
|
+
const webhook = new WebhookServer({ info() {}, error() {}, debug() {} }, 0);
|
|
79
|
+
const updates = [];
|
|
80
|
+
webhook.processRequest = (route, id, types, value, response) => {
|
|
81
|
+
updates.push(value);
|
|
82
|
+
response.sendStatus(200);
|
|
83
|
+
};
|
|
84
|
+
const server = webhook.server.listen(0, '127.0.0.1');
|
|
85
|
+
t.after(() => new Promise((resolve, reject) => server.close(error => error ? reject(error) : resolve())));
|
|
86
|
+
await once(server, 'listening');
|
|
87
|
+
const base = `http://127.0.0.1:${server.address().port}`;
|
|
88
|
+
|
|
89
|
+
for (const route of ['/obstruction', '/triggeralarm', '/triggerpanic', '/triggersensor', '/chargingstate']) {
|
|
90
|
+
const field = route === '/chargingstate' ? 'charging' : 'value';
|
|
91
|
+
const invalid = [null, { toString: 1 }, {}, [], [true], [false], ['true'], [{ toString: 1 }],
|
|
92
|
+
0, 1, '', 'invalid', 'true', 'false', 'TRUE', 'False', undefined];
|
|
93
|
+
for (const value of invalid) {
|
|
94
|
+
// An omitted charging field is valid when charge is supplied.
|
|
95
|
+
if (route === '/chargingstate' && value === undefined) {
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
await t.test(`${route} rejects ${JSON.stringify(value)}`, async () => {
|
|
99
|
+
const before = updates.length;
|
|
100
|
+
const response = await fetch(`${base}${route}`, {
|
|
101
|
+
method: 'POST',
|
|
102
|
+
headers: { 'Content-Type': 'application/json' },
|
|
103
|
+
body: JSON.stringify({ id: 'a00005', [field]: value, charge: 50 }),
|
|
104
|
+
});
|
|
105
|
+
assert.equal(response.status, 400);
|
|
106
|
+
assert.match(await response.text(), /^Invalid value: .*\. Value must be a boolean$/);
|
|
107
|
+
assert.equal(updates.length, before);
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
for (const mode of ['query', 'form']) {
|
|
111
|
+
for (const value of ['', ' ', ' true', 'false ', 'true\n', '1', '0', 'yes', 'null', 'undefined']) {
|
|
112
|
+
await t.test(`${route} rejects ${mode} boolean ${JSON.stringify(value)}`, async () => {
|
|
113
|
+
const before = updates.length;
|
|
114
|
+
const encoded = new URLSearchParams({ id: 'a00005', [field]: value, charge: 50 }).toString();
|
|
115
|
+
const options = mode === 'query' ? { headers: { 'Use-Query-Params': 'true' } }
|
|
116
|
+
: { headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: encoded };
|
|
117
|
+
const response = await fetch(`${base}${route}${mode === 'query' ? `?${encoded}` : ''}`, { method: 'POST', ...options });
|
|
118
|
+
assert.equal(response.status, 400, await response.text());
|
|
119
|
+
assert.equal(updates.length, before);
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
for (const value of [true, false, 'true', 'false', 'TRUE', 'FALSE', 'True', 'False']) {
|
|
124
|
+
const expected = String(value).toLowerCase() === 'true';
|
|
125
|
+
for (const mode of ['JSON', 'query', 'form']) {
|
|
126
|
+
if (mode === 'JSON' && typeof value !== 'boolean') {
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
const query = mode === 'query';
|
|
130
|
+
await t.test(`${route} accepts ${mode} ${value}`, async () => {
|
|
131
|
+
const before = updates.length;
|
|
132
|
+
const response = await fetch(`${base}${route}${query ? `?id=a00005&${field}=${value}&charge=50` : ''}`, {
|
|
133
|
+
method: 'POST',
|
|
134
|
+
headers: { 'Content-Type': mode === 'form' ? 'application/x-www-form-urlencoded' : 'application/json', 'Use-Query-Params': String(query) },
|
|
135
|
+
body: mode === 'form' ? new URLSearchParams({ id: 'a00005', [field]: value, charge: 50 }).toString()
|
|
136
|
+
: JSON.stringify({ id: 'a00005', [field]: value, charge: 50 }),
|
|
137
|
+
});
|
|
138
|
+
assert.equal(response.status, 200);
|
|
139
|
+
assert.equal(updates.length, before + 1);
|
|
140
|
+
if (route === '/chargingstate') {
|
|
141
|
+
assert.equal(updates.at(-1).charging, expected);
|
|
142
|
+
}
|
|
143
|
+
else if (route === '/obstruction' || route === '/triggersensor') {
|
|
144
|
+
assert.equal(updates.at(-1), expected);
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
const trigger = route === '/triggeralarm' ? SecurityServiceTriggerType.TriggerAlarm : SecurityServiceTriggerType.TriggerPanic;
|
|
148
|
+
assert.equal(updates.at(-1), expected ? trigger : SecurityServiceTriggerType.None);
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
test('webhook routes handle missing bodies before reading fields', async (t) => {
|
|
157
|
+
const webhook = new WebhookServer({ info() {}, error() {}, debug() {} }, 0);
|
|
158
|
+
const updates = [];
|
|
159
|
+
webhook.processRequest = (route, id, types, value, response) => {
|
|
160
|
+
updates.push({ route, id, value });
|
|
161
|
+
response.sendStatus(200);
|
|
162
|
+
};
|
|
163
|
+
const server = webhook.server.listen(0, '127.0.0.1');
|
|
164
|
+
t.after(() => new Promise((resolve, reject) => server.close(error => error ? reject(error) : resolve())));
|
|
165
|
+
await once(server, 'listening');
|
|
166
|
+
const base = `http://127.0.0.1:${server.address().port}`;
|
|
167
|
+
const routes = ['/humidity', '/temperature', '/obstruction', '/triggeralarm', '/triggerpanic', '/triggersensor', '/chargingstate'];
|
|
168
|
+
const missingBodies = [
|
|
169
|
+
['no body or content type', {}],
|
|
170
|
+
['empty JSON body', { headers: { 'Content-Type': 'application/json' } }],
|
|
171
|
+
['unparsed text body', { headers: { 'Content-Type': 'text/plain' }, body: 'id=a00005&value=true' }],
|
|
172
|
+
['empty JSON object', { headers: { 'Content-Type': 'application/json' }, body: '{}' }],
|
|
173
|
+
];
|
|
174
|
+
for (const route of routes) {
|
|
175
|
+
for (const [label, options] of missingBodies) {
|
|
176
|
+
await t.test(`${route} rejects ${label}`, async () => {
|
|
177
|
+
const before = updates.length;
|
|
178
|
+
const response = await fetch(`${base}${route}?id=a00005&value=true&charging=true&charge=50`, {
|
|
179
|
+
method: 'POST', ...options,
|
|
180
|
+
});
|
|
181
|
+
assert.equal(response.status, 400);
|
|
182
|
+
assert.equal(await response.text(), 'No parameters found in POST body');
|
|
183
|
+
assert.equal(updates.length, before);
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
await t.test(`${route} rejects empty query mode without a body`, async () => {
|
|
187
|
+
const before = updates.length;
|
|
188
|
+
const response = await fetch(`${base}${route}`, {
|
|
189
|
+
method: 'POST', headers: { 'Use-Query-Params': 'true' },
|
|
190
|
+
});
|
|
191
|
+
assert.equal(response.status, 400);
|
|
192
|
+
assert.equal(await response.text(), 'No parameters found in POST query. The webhook server is using query parameters');
|
|
193
|
+
assert.equal(updates.length, before);
|
|
194
|
+
});
|
|
195
|
+
const numeric = route === '/humidity' || route === '/temperature';
|
|
196
|
+
const payload = route === '/chargingstate'
|
|
197
|
+
? { id: 'a00005', charging: false, charge: 0 }
|
|
198
|
+
: { id: 'a00005', value: numeric ? 0 : false };
|
|
199
|
+
for (const mode of ['JSON', 'query', 'form']) {
|
|
200
|
+
await t.test(`${route} preserves ${mode} updates`, async () => {
|
|
201
|
+
const before = updates.length;
|
|
202
|
+
const query = new URLSearchParams(payload).toString();
|
|
203
|
+
const options = mode === 'query'
|
|
204
|
+
? { headers: { 'Use-Query-Params': 'true' } }
|
|
205
|
+
: mode === 'JSON'
|
|
206
|
+
? { headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) }
|
|
207
|
+
: { headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: query };
|
|
208
|
+
const response = await fetch(`${base}${route}${mode === 'query' ? `?${query}` : ''}`, {
|
|
209
|
+
method: 'POST', ...options,
|
|
210
|
+
});
|
|
211
|
+
assert.equal(response.status, 200);
|
|
212
|
+
assert.equal(updates.length, before + 1);
|
|
213
|
+
assert.equal(updates.at(-1).id, payload.id);
|
|
214
|
+
assert.equal(updates.at(-1).route, route);
|
|
215
|
+
const actual = updates.at(-1).value;
|
|
216
|
+
if (route === '/chargingstate') {
|
|
217
|
+
assert.equal(actual.charging, false);
|
|
218
|
+
assert.equal(actual.charge, 0);
|
|
219
|
+
}
|
|
220
|
+
else {
|
|
221
|
+
const alarm = route === '/triggeralarm' || route === '/triggerpanic';
|
|
222
|
+
assert.equal(actual, numeric ? 0 : alarm ? SecurityServiceTriggerType.None : false);
|
|
223
|
+
}
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
test('charging updates preserve omitted battery properties', async (t) => {
|
|
231
|
+
// Homebridge normally initializes these characteristic constants at startup.
|
|
232
|
+
t.mock.getter(Battery, 'NOT_CHARGING', () => 0);
|
|
233
|
+
t.mock.getter(Battery, 'CHARGING', () => 1);
|
|
234
|
+
t.mock.getter(Battery, 'NOT_CHARGEABLE', () => 2);
|
|
235
|
+
const log = { info() {}, error() {}, debug() {} };
|
|
236
|
+
const webhook = new WebhookServer(log, 0);
|
|
237
|
+
const updates = [];
|
|
238
|
+
const state = { charging: true, charge: 42 };
|
|
239
|
+
// Exercise real route dispatch and Battery.updateChargingStatus without HomeKit setup.
|
|
240
|
+
const battery = {
|
|
241
|
+
log,
|
|
242
|
+
accessoryConfiguration: { accessoryID: 'a00005', accessoryType: 'battery' },
|
|
243
|
+
getChargingState: () => state.charging ? Battery.CHARGING : Battery.NOT_CHARGING,
|
|
244
|
+
updateChargingState(value) {
|
|
245
|
+
state.charging = value === Battery.CHARGING;
|
|
246
|
+
return value;
|
|
247
|
+
},
|
|
248
|
+
updateBatteryLevel(value) {
|
|
249
|
+
state.charge = value;
|
|
250
|
+
return value;
|
|
251
|
+
},
|
|
252
|
+
saveState() {},
|
|
253
|
+
updateChargingStatus(charging, charge, id) {
|
|
254
|
+
updates.push({ charging, charge, id });
|
|
255
|
+
Battery.prototype.updateChargingStatus.call(this, charging, charge, id);
|
|
256
|
+
},
|
|
257
|
+
};
|
|
258
|
+
webhook.addAccessory(battery);
|
|
259
|
+
const server = webhook.server.listen(0, '127.0.0.1');
|
|
260
|
+
t.after(() => new Promise((resolve, reject) => server.close(error => error ? reject(error) : resolve())));
|
|
261
|
+
await once(server, 'listening');
|
|
262
|
+
const base = `http://127.0.0.1:${server.address().port}/chargingstate`;
|
|
263
|
+
const cases = [
|
|
264
|
+
['charge only', { charge: 75 }, 200],
|
|
265
|
+
['zero charge', { charge: 0 }, 200],
|
|
266
|
+
['full charge', { charge: 100 }, 200],
|
|
267
|
+
['charging only', { charging: true }, 200],
|
|
268
|
+
['not charging', { charging: false }, 200],
|
|
269
|
+
['both properties', { charge: 75, charging: false }, 200],
|
|
270
|
+
['both falsy values', { charge: 0, charging: false }, 200],
|
|
271
|
+
['neither property', {}, 400],
|
|
272
|
+
['invalid charging alone', { charging: 'invalid' }, 400],
|
|
273
|
+
['invalid charging with charge', { charging: 'invalid', charge: 75 }, 400],
|
|
274
|
+
['null charge alone', { charge: null }, 400],
|
|
275
|
+
['null charge with charging', { charge: null, charging: false }, 400],
|
|
276
|
+
['array charging with charge', { charging: [true], charge: 0 }, 400],
|
|
277
|
+
['fractional charge', { charge: 75.5 }, 400],
|
|
278
|
+
['negative charge', { charge: -1, charging: false }, 400],
|
|
279
|
+
['excess charge', { charge: 101, charging: false }, 400],
|
|
280
|
+
['invalid charge alone', { charge: 'invalid' }, 400],
|
|
281
|
+
['invalid charge with charging', { charge: 'invalid', charging: false }, 400],
|
|
282
|
+
];
|
|
283
|
+
for (const mode of ['JSON', 'query', 'form']) {
|
|
284
|
+
for (const [label, fields, status] of cases) {
|
|
285
|
+
if (mode !== 'JSON' && Array.isArray(fields.charging)) {
|
|
286
|
+
continue;
|
|
287
|
+
}
|
|
288
|
+
await t.test(`${mode}: ${label}`, async () => {
|
|
289
|
+
Object.assign(state, { charging: true, charge: 42 });
|
|
290
|
+
const before = updates.length;
|
|
291
|
+
const payload = { id: 'a00005', ...fields };
|
|
292
|
+
const query = new URLSearchParams(payload).toString();
|
|
293
|
+
const options = mode === 'query'
|
|
294
|
+
? { headers: { 'Use-Query-Params': 'true' } }
|
|
295
|
+
: mode === 'JSON'
|
|
296
|
+
? { headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) }
|
|
297
|
+
: { headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: query };
|
|
298
|
+
const response = await fetch(`${base}${mode === 'query' ? `?${query}` : ''}`, { method: 'POST', ...options });
|
|
299
|
+
assert.equal(response.status, status, await response.text());
|
|
300
|
+
assert.equal(updates.length, before + (status === 200 ? 1 : 0));
|
|
301
|
+
if (status === 200) {
|
|
302
|
+
assert.deepEqual(updates.at(-1), { id: payload.id, charging: fields.charging, charge: fields.charge });
|
|
303
|
+
assert.deepEqual(state, { charging: true, charge: 42, ...fields });
|
|
304
|
+
}
|
|
305
|
+
else {
|
|
306
|
+
assert.deepEqual(state, { charging: true, charge: 42 });
|
|
307
|
+
}
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
test('Use-Query-Params headers reject invalid values and select the requested parameter source', async (t) => {
|
|
315
|
+
const webhook = new WebhookServer({ info() {}, error() {}, debug() {} }, 0);
|
|
316
|
+
const updates = [];
|
|
317
|
+
webhook.processRequest = (route, id, types, value, response) => {
|
|
318
|
+
updates.push({ route, id });
|
|
319
|
+
response.sendStatus(200);
|
|
320
|
+
};
|
|
321
|
+
const server = webhook.server.listen(0, '127.0.0.1');
|
|
322
|
+
t.after(() => new Promise((resolve, reject) => server.close(error => error ? reject(error) : resolve())));
|
|
323
|
+
await once(server, 'listening');
|
|
324
|
+
const base = `http://127.0.0.1:${server.address().port}`;
|
|
325
|
+
const routes = ['/humidity', '/temperature', '/obstruction', '/triggeralarm', '/triggerpanic', '/triggersensor', '/chargingstate'];
|
|
326
|
+
for (const route of routes) {
|
|
327
|
+
const payload = { id: 'body-id', value: route === '/humidity' || route === '/temperature' ? 50 : true, charge: 50, charging: true };
|
|
328
|
+
const query = new URLSearchParams({ ...payload, id: 'query-id' });
|
|
329
|
+
for (const header of ['yes', '1', '', ' ', 'true,false', 'tru e']) {
|
|
330
|
+
for (const withBody of [true, false]) {
|
|
331
|
+
await t.test(`${route} rejects header ${JSON.stringify(header)} ${withBody ? 'with' : 'without'} body`, async () => {
|
|
332
|
+
const before = updates.length;
|
|
333
|
+
const response = await fetch(`${base}${route}?${query}`, {
|
|
334
|
+
method: 'POST',
|
|
335
|
+
headers: { 'Content-Type': 'application/json', 'Use-Query-Params': header },
|
|
336
|
+
...(withBody ? { body: JSON.stringify(payload) } : {}),
|
|
337
|
+
});
|
|
338
|
+
assert.equal(response.status, 400);
|
|
339
|
+
assert.equal(await response.text(), 'Invalid Use-Query-Params header. Value must be true or false');
|
|
340
|
+
assert.equal(updates.length, before);
|
|
341
|
+
});
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
for (const header of [undefined, 'true', 'TRUE', 'True', 'false', 'FALSE', 'False', ' \tTrUe\t ', ' \tFaLsE\t ']) {
|
|
345
|
+
for (const name of ['Use-Query-Params', 'use-query-params', 'UsE-QuErY-PaRaMs']) {
|
|
346
|
+
await t.test(`${route} accepts ${name}: ${JSON.stringify(header)}`, async () => {
|
|
347
|
+
const before = updates.length;
|
|
348
|
+
const response = await fetch(`${base}${route}?${query}`, {
|
|
349
|
+
method: 'POST',
|
|
350
|
+
headers: { 'Content-Type': 'application/json', ...(header === undefined ? {} : { [name]: header }) },
|
|
351
|
+
body: JSON.stringify(payload),
|
|
352
|
+
});
|
|
353
|
+
assert.equal(response.status, 200, await response.text());
|
|
354
|
+
assert.equal(updates.length, before + 1);
|
|
355
|
+
assert.deepEqual(updates.at(-1), { route, id: header?.trim().toLowerCase() === 'true' ? 'query-id' : 'body-id' });
|
|
356
|
+
});
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
});
|
|
361
|
+
|
|
362
|
+
test('numeric webhook inputs require finite scalar numbers', async (t) => {
|
|
363
|
+
const webhook = new WebhookServer({ info() {}, error() {}, debug() {} }, 0);
|
|
364
|
+
const updates = [];
|
|
365
|
+
webhook.processRequest = (route, id, types, value, response) => {
|
|
366
|
+
updates.push(value);
|
|
367
|
+
response.sendStatus(200);
|
|
368
|
+
};
|
|
369
|
+
const server = webhook.server.listen(0, '127.0.0.1');
|
|
370
|
+
t.after(() => new Promise((resolve, reject) => server.close(error => error ? reject(error) : resolve())));
|
|
371
|
+
await once(server, 'listening');
|
|
372
|
+
const base = `http://127.0.0.1:${server.address().port}`;
|
|
373
|
+
for (const route of ['/humidity', '/temperature', '/chargingstate']) {
|
|
374
|
+
const field = route === '/chargingstate' ? 'charge' : 'value';
|
|
375
|
+
const invalid = [
|
|
376
|
+
null, true, false, [], [0], [50], ['50'], {}, { toString: 1 }, { valueOf: 0 },
|
|
377
|
+
'50', '50.5', '', ' \t ', 'NaN', 'Infinity', '-Infinity', '1e309', '12oops',
|
|
378
|
+
];
|
|
379
|
+
for (const value of invalid) {
|
|
380
|
+
await t.test(`${route} rejects JSON ${JSON.stringify(value)}`, async () => {
|
|
381
|
+
const before = updates.length;
|
|
382
|
+
const response = await fetch(`${base}${route}`, {
|
|
383
|
+
method: 'POST', headers: { 'Content-Type': 'application/json' },
|
|
384
|
+
body: JSON.stringify({ id: 'a00005', [field]: value, charging: false }),
|
|
385
|
+
});
|
|
386
|
+
assert.equal(response.status, 400);
|
|
387
|
+
assert.match(await response.text(), /Value must be a finite number/);
|
|
388
|
+
assert.equal(updates.length, before);
|
|
389
|
+
});
|
|
390
|
+
}
|
|
391
|
+
for (const mode of ['JSON', 'query', 'form']) {
|
|
392
|
+
// Expected validity is explicit, independent of the implementation's parsing rules.
|
|
393
|
+
const cases = [
|
|
394
|
+
[0, true, true], [75, true, true], [100, true, true],
|
|
395
|
+
[72.5, false, true], [-5.5, false, true], [-1, false, true], [101, false, true],
|
|
396
|
+
['0', true, true], ['75', true, true], ['100', true, true], ['+75', true, true], ['075', true, true],
|
|
397
|
+
['-0', true, true], ['75.0', false, true], ['72.5', false, true], ['-5.5', false, true],
|
|
398
|
+
['.5', false, true], ['5.', false, true], ['+72.5', false, true],
|
|
399
|
+
['-1', false, true], ['101', false, true],
|
|
400
|
+
...[' 25 ', '', ' ', 'NaN', 'Infinity', '-Infinity', '1e309', '1e1', '0x10', '0b10', '12oops', 'true', '75\n', '75\r', '75\t', '9'.repeat(400)]
|
|
401
|
+
.map(value => [value, false, false]),
|
|
402
|
+
];
|
|
403
|
+
for (const [value, percentageValid, numberValid] of cases) {
|
|
404
|
+
await t.test(`${route} ${mode} scalar ${JSON.stringify(value)}`, async () => {
|
|
405
|
+
const before = updates.length;
|
|
406
|
+
const payload = { id: 'a00005', [field]: value };
|
|
407
|
+
const encoded = new URLSearchParams(payload).toString();
|
|
408
|
+
const options = mode === 'query' ? { headers: { 'Use-Query-Params': 'true' } }
|
|
409
|
+
: mode === 'JSON' ? { headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) }
|
|
410
|
+
: { headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: encoded };
|
|
411
|
+
const response = await fetch(`${base}${route}${mode === 'query' ? `?${encoded}` : ''}`, { method: 'POST', ...options });
|
|
412
|
+
const valid = (mode !== 'JSON' || typeof value === 'number') &&
|
|
413
|
+
(route === '/temperature' ? numberValid : percentageValid);
|
|
414
|
+
assert.equal(response.status, valid ? 200 : 400, await response.text());
|
|
415
|
+
assert.equal(updates.length, before + (valid ? 1 : 0));
|
|
416
|
+
if (valid) {
|
|
417
|
+
if (route === '/chargingstate') {
|
|
418
|
+
assert.equal(updates.at(-1).charge, Number(value));
|
|
419
|
+
assert.equal(updates.at(-1).charging, undefined);
|
|
420
|
+
}
|
|
421
|
+
else {
|
|
422
|
+
assert.equal(updates.at(-1), Number(value));
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
});
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
for (const route of ['/humidity', '/temperature', '/obstruction', '/triggeralarm', '/triggerpanic', '/triggersensor', '/chargingstate']) {
|
|
430
|
+
const fields = route === '/chargingstate' ? ['charge', 'charging'] : ['value'];
|
|
431
|
+
for (const field of fields) {
|
|
432
|
+
const scalar = field === 'charge' || route === '/humidity' || route === '/temperature' ? '50' : 'true';
|
|
433
|
+
for (const mode of ['query', 'form']) {
|
|
434
|
+
const shapes = mode === 'query' ? [`${field}=${scalar}&${field}=${scalar}`]
|
|
435
|
+
: [`${field}=${scalar}&${field}=${scalar}`, `${field}[]=${scalar}`, `${field}[toString]=1`];
|
|
436
|
+
for (const shape of shapes) {
|
|
437
|
+
await t.test(`${route} rejects ${mode} structured ${shape}`, async () => {
|
|
438
|
+
const before = updates.length;
|
|
439
|
+
const encoded = `id=a00005&${shape}`;
|
|
440
|
+
const options = mode === 'query' ? { headers: { 'Use-Query-Params': 'true' } }
|
|
441
|
+
: { headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: encoded };
|
|
442
|
+
const response = await fetch(`${base}${route}${mode === 'query' ? `?${encoded}` : ''}`, { method: 'POST', ...options });
|
|
443
|
+
assert.equal(response.status, 400, await response.text());
|
|
444
|
+
assert.equal(updates.length, before);
|
|
445
|
+
});
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
});
|