@homebridge-plugins/homebridge-sharkiq 1.6.1 → 1.6.2-beta.1
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/CHANGELOG.md +12 -0
- package/dist/login.d.ts +12 -0
- package/dist/login.d.ts.map +1 -1
- package/dist/login.js +20 -1
- package/dist/login.js.map +1 -1
- package/package.json +4 -3
- package/dist/sharkiq-js/ayla_api.test.d.ts +0 -2
- package/dist/sharkiq-js/ayla_api.test.d.ts.map +0 -1
- package/dist/sharkiq-js/ayla_api.test.js +0 -61
- package/dist/sharkiq-js/ayla_api.test.js.map +0 -1
- package/dist/sharkiq-js/skegox_api.test.d.ts +0 -2
- package/dist/sharkiq-js/skegox_api.test.d.ts.map +0 -1
- package/dist/sharkiq-js/skegox_api.test.js +0 -132
- package/dist/sharkiq-js/skegox_api.test.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file. This project uses [Semantic Versioning](https://semver.org/)
|
|
4
4
|
|
|
5
|
+
## v1.6.2 (Pending Release)
|
|
6
|
+
|
|
7
|
+
### Changed
|
|
8
|
+
|
|
9
|
+
- fix: explain that a failed code exchange usually means the login code was already used or has expired, instead of reporting a bare http error (#84)
|
|
10
|
+
- chore: keep test files out of the published package
|
|
11
|
+
- chore(github): run the build and tests in ci, on node 22, 24 and 26
|
|
12
|
+
- chore: use the same lint setup across every plugin
|
|
13
|
+
- chore: add a changelog:sync script to populate the pending section from the commits
|
|
14
|
+
- chore: count a repeated commit subject once when syncing the changelog
|
|
15
|
+
- chore(github): check the changelog against the commits in ci
|
|
16
|
+
|
|
5
17
|
## v1.6.1 (2026-07-28)
|
|
6
18
|
|
|
7
19
|
### Changed
|
package/dist/login.d.ts
CHANGED
|
@@ -2,6 +2,18 @@ import type { Logger } from 'homebridge';
|
|
|
2
2
|
interface LoginLogger {
|
|
3
3
|
debug: (message: string, ...parameters: any[]) => void;
|
|
4
4
|
}
|
|
5
|
+
/**
|
|
6
|
+
* Turn a failed token exchange into something a user can act on.
|
|
7
|
+
*
|
|
8
|
+
* A 403 here is by far the most common failure and it almost never means what
|
|
9
|
+
* the bare status suggests. The login code is single-use and short-lived, so
|
|
10
|
+
* it is already spent if the SharkClean app opened the callback (it treats it
|
|
11
|
+
* as an Alexa-style account link, consuming the code and showing a "Linking
|
|
12
|
+
* Error"), and it is stale if the sign-in happened a while ago or against an
|
|
13
|
+
* older login URL. Reported repeatedly in #84 and #85, where the bare
|
|
14
|
+
* `HTTP 403` sent people looking for a problem with their account.
|
|
15
|
+
*/
|
|
16
|
+
export declare function describeTokenExchangeFailure(status: number): string;
|
|
5
17
|
export declare function exchangeOAuthCodeForAuthTokens(auth_file: string, oauth_file: string, code: string, europe?: boolean, app_id?: string, app_secret?: string, log?: LoginLogger): Promise<void>;
|
|
6
18
|
export declare class Login {
|
|
7
19
|
log: Logger;
|
package/dist/login.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../src/login.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AASxC,UAAU,WAAW;IACnB,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,UAAU,EAAE,GAAG,EAAE,KAAK,IAAI,CAAA;CACvD;AAED,wBAAsB,8BAA8B,CAClD,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,MAAM,EACZ,MAAM,UAAQ,EACd,MAAM,CAAC,EAAE,MAAM,EACf,UAAU,CAAC,EAAE,MAAM,EACnB,GAAG,CAAC,EAAE,WAAW,GAChB,OAAO,CAAC,IAAI,CAAC,CAqEf;AAED,qBAAa,KAAK;IACT,GAAG,EAAE,MAAM,CAAA;IACX,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,EAAE,MAAM,CAAA;IAClB,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;IACd,UAAU,EAAE,MAAM,CAAA;IAClB,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,OAAO,CAAA;gBAEV,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,UAAQ,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM;IAY3J,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;YAoC1B,aAAa;CAW5B"}
|
|
1
|
+
{"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../src/login.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AASxC,UAAU,WAAW;IACnB,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,UAAU,EAAE,GAAG,EAAE,KAAK,IAAI,CAAA;CACvD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,4BAA4B,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAOnE;AAED,wBAAsB,8BAA8B,CAClD,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,MAAM,EACZ,MAAM,UAAQ,EACd,MAAM,CAAC,EAAE,MAAM,EACf,UAAU,CAAC,EAAE,MAAM,EACnB,GAAG,CAAC,EAAE,WAAW,GAChB,OAAO,CAAC,IAAI,CAAC,CAqEf;AAED,qBAAa,KAAK;IACT,GAAG,EAAE,MAAM,CAAA;IACX,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,EAAE,MAAM,CAAA;IAClB,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;IACd,UAAU,EAAE,MAAM,CAAA;IAClB,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,OAAO,CAAA;gBAEV,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,UAAQ,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM;IAY3J,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;YAoC1B,aAAa;CAW5B"}
|
package/dist/login.js
CHANGED
|
@@ -3,6 +3,25 @@ import process from 'node:process';
|
|
|
3
3
|
import { generateURL, getAuthData, getOAuthData, removeFile, setAuth0Data, setAuthData } from './config.js';
|
|
4
4
|
import { global_vars } from './sharkiq-js/const.js';
|
|
5
5
|
import { addSeconds } from './utils.js';
|
|
6
|
+
/**
|
|
7
|
+
* Turn a failed token exchange into something a user can act on.
|
|
8
|
+
*
|
|
9
|
+
* A 403 here is by far the most common failure and it almost never means what
|
|
10
|
+
* the bare status suggests. The login code is single-use and short-lived, so
|
|
11
|
+
* it is already spent if the SharkClean app opened the callback (it treats it
|
|
12
|
+
* as an Alexa-style account link, consuming the code and showing a "Linking
|
|
13
|
+
* Error"), and it is stale if the sign-in happened a while ago or against an
|
|
14
|
+
* older login URL. Reported repeatedly in #84 and #85, where the bare
|
|
15
|
+
* `HTTP 403` sent people looking for a problem with their account.
|
|
16
|
+
*/
|
|
17
|
+
export function describeTokenExchangeFailure(status) {
|
|
18
|
+
if (status === 403 || status === 401) {
|
|
19
|
+
return `Unable to get token data. HTTP ${status} - this usually means the login code has already been used or has expired, rather than a problem with your account. `
|
|
20
|
+
+ 'Generate a fresh login URL, sign in again, and exchange the new code straight away. '
|
|
21
|
+
+ 'If the SharkClean app opened when you accepted, it consumed the code - use a browser on a computer that does not have the app installed.';
|
|
22
|
+
}
|
|
23
|
+
return `Unable to get token data. HTTP ${status}`;
|
|
24
|
+
}
|
|
6
25
|
export async function exchangeOAuthCodeForAuthTokens(auth_file, oauth_file, code, europe = false, app_id, app_secret, log) {
|
|
7
26
|
const oauthConfig = europe ? global_vars.EU_OAUTH : global_vars.OAUTH;
|
|
8
27
|
const loginUrl = europe ? global_vars.EU_LOGIN_URL : global_vars.LOGIN_URL;
|
|
@@ -27,7 +46,7 @@ export async function exchangeOAuthCodeForAuthTokens(auth_file, oauth_file, code
|
|
|
27
46
|
log?.debug('Request Data', JSON.stringify(data));
|
|
28
47
|
const response = await fetch(oauthConfig.TOKEN_URL, reqData);
|
|
29
48
|
if (!response.ok) {
|
|
30
|
-
return Promise.reject(new Error(
|
|
49
|
+
return Promise.reject(new Error(describeTokenExchangeFailure(response.status)));
|
|
31
50
|
}
|
|
32
51
|
const tokenData = await response.json();
|
|
33
52
|
log?.debug('Token Data:', JSON.stringify(tokenData));
|
package/dist/login.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"login.js","sourceRoot":"","sources":["../src/login.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,OAAO,MAAM,cAAc,CAAA;AAElC,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAC3G,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AACnD,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAMvC,MAAM,CAAC,KAAK,UAAU,8BAA8B,CAClD,SAAiB,EACjB,UAAkB,EAClB,IAAY,EACZ,MAAM,GAAG,KAAK,EACd,MAAe,EACf,UAAmB,EACnB,GAAiB;IAEjB,MAAM,WAAW,GAAG,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,KAAK,CAAA;IACrE,MAAM,QAAQ,GAAG,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,YAAY,CAAC,CAAC,CAAC,WAAW,CAAC,SAAS,CAAA;IAC1E,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,eAAe,CAAC,CAAC,CAAC,WAAW,CAAC,YAAY,CAAC,CAAA;IACjG,MAAM,iBAAiB,GAAG,UAAU,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,mBAAmB,CAAC,CAAC,CAAC,WAAW,CAAC,gBAAgB,CAAC,CAAA;IACjH,MAAM,SAAS,GAAG,MAAM,YAAY,CAAC,UAAU,CAAC,CAAA;IAEhD,MAAM,IAAI,GAAG;QACX,UAAU,EAAE,oBAAoB;QAChC,SAAS,EAAE,WAAW,CAAC,SAAS;QAChC,IAAI;QACJ,aAAa,EAAE,SAAS,CAAC,WAAW;QACpC,YAAY,EAAE,WAAW,CAAC,YAAY;KACvC,CAAA;IAED,MAAM,OAAO,GAAG;QACd,MAAM,EAAE,MAAM;QACd,OAAO,EAAE;YACP,cAAc,EAAE,kBAAkB;YAClC,cAAc,EAAE,WAAW,CAAC,YAAY;SACzC;QACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;KAC3B,CAAA;IACD,GAAG,EAAE,KAAK,CAAC,cAAc,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAA;IAEhD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,WAAW,CAAC,SAAS,EAAE,OAAO,CAAC,CAAA;IAC5D,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,
|
|
1
|
+
{"version":3,"file":"login.js","sourceRoot":"","sources":["../src/login.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@homebridge-plugins/homebridge-sharkiq",
|
|
3
3
|
"displayName": "SharkIQ Plugin",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"version": "1.6.1",
|
|
5
|
+
"version": "1.6.2-beta.1",
|
|
6
6
|
"description": "A Homebridge plugin to connect your Shark Vacuum to homebridge.",
|
|
7
7
|
"author": {
|
|
8
8
|
"name": "Bubba8291",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"main": "dist/index.js",
|
|
33
33
|
"engines": {
|
|
34
34
|
"homebridge": "^1.11.4 || ^2.0.0",
|
|
35
|
-
"node": "^22.12.0 || ^24.0.0"
|
|
35
|
+
"node": "^22.12.0 || ^24.0.0 || ^26.0.0"
|
|
36
36
|
},
|
|
37
37
|
"scripts": {
|
|
38
38
|
"lint": "eslint . --max-warnings=0",
|
|
@@ -45,7 +45,8 @@
|
|
|
45
45
|
"test:watch": "vitest watch",
|
|
46
46
|
"test-coverage": "npm run test -- --coverage",
|
|
47
47
|
"docs": "typedoc",
|
|
48
|
-
"docs:lint": "typedoc --emit none --treatWarningsAsErrors"
|
|
48
|
+
"docs:lint": "typedoc --emit none --treatWarningsAsErrors",
|
|
49
|
+
"changelog:sync": "node .github/scripts/sync-changelog.mjs"
|
|
49
50
|
},
|
|
50
51
|
"publishConfig": {
|
|
51
52
|
"access": "public"
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ayla_api.test.d.ts","sourceRoot":"","sources":["../../src/sharkiq-js/ayla_api.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import { afterEach, describe, expect, it, vi } from 'vitest';
|
|
2
|
-
import { AylaApi } from './ayla_api.js';
|
|
3
|
-
const log = { debug: vi.fn(), info: vi.fn(), warn: vi.fn(), error: vi.fn(), success: vi.fn() };
|
|
4
|
-
// A SharkNinja account holds every appliance of the brand, so the device list
|
|
5
|
-
// can carry a Ninja grill next to a Shark vacuum (#85)
|
|
6
|
-
const WOODFIRE = { dsn: 'AC000W033162165', key: 1, oem_model: 'woodfire', product_name: 'Woodfire ' };
|
|
7
|
-
const VACUUM = { dsn: 'AC000W012345678', key: 2, oem_model: 'shark_iq', product_name: 'Shark IQ Robot' };
|
|
8
|
-
function apiWithDevices(devices, propertiesByDsn) {
|
|
9
|
-
const api = new AylaApi('/tmp/sharkiq-test-auth.json', 'app-id', 'app-secret', log, false);
|
|
10
|
-
vi.spyOn(api, 'list_devices').mockResolvedValue(devices);
|
|
11
|
-
// Stand in for the per-device property fetch each vacuum does on startup
|
|
12
|
-
vi.spyOn(api, 'makeRequest').mockImplementation((async (..._args) => {
|
|
13
|
-
const url = String(_args[1] ?? '');
|
|
14
|
-
return {
|
|
15
|
-
ok: true,
|
|
16
|
-
status: 200,
|
|
17
|
-
response: JSON.stringify(propertiesByDsn[Object.keys(propertiesByDsn).find(dsn => url.includes(dsn)) ?? ''] ?? []),
|
|
18
|
-
};
|
|
19
|
-
}));
|
|
20
|
-
vi.spyOn(api, 'auth_header').mockResolvedValue({ Authorization: 'auth' });
|
|
21
|
-
return api;
|
|
22
|
-
}
|
|
23
|
-
function props(names) {
|
|
24
|
-
return names.map(name => ({ property: { name, value: 1, key: 1, base_type: 'integer' } }));
|
|
25
|
-
}
|
|
26
|
-
describe('aylaApi.get_devices', () => {
|
|
27
|
-
afterEach(() => {
|
|
28
|
-
vi.restoreAllMocks();
|
|
29
|
-
vi.clearAllMocks();
|
|
30
|
-
});
|
|
31
|
-
it('keeps devices that report Operating_Mode', async () => {
|
|
32
|
-
const api = apiWithDevices([VACUUM], {
|
|
33
|
-
[VACUUM.dsn]: props(['Operating_Mode', 'Docked_Status', 'Battery_Capacity']),
|
|
34
|
-
});
|
|
35
|
-
const devices = await api.get_devices();
|
|
36
|
-
expect(devices).toHaveLength(1);
|
|
37
|
-
expect(devices[0].serial_number).toBe(VACUUM.dsn);
|
|
38
|
-
});
|
|
39
|
-
it('drops a non-vacuum appliance such as a Ninja Woodfire grill (#85)', async () => {
|
|
40
|
-
const api = apiWithDevices([WOODFIRE], {
|
|
41
|
-
[WOODFIRE.dsn]: props(['Cook_Mode', 'Probe_Temperature']),
|
|
42
|
-
});
|
|
43
|
-
const devices = await api.get_devices();
|
|
44
|
-
expect(devices).toHaveLength(0);
|
|
45
|
-
expect(log.info).toHaveBeenCalledWith(expect.stringContaining('is not a vacuum'));
|
|
46
|
-
});
|
|
47
|
-
it('keeps the vacuum and drops the grill when an account holds both', async () => {
|
|
48
|
-
const api = apiWithDevices([WOODFIRE, VACUUM], {
|
|
49
|
-
[WOODFIRE.dsn]: props(['Cook_Mode']),
|
|
50
|
-
[VACUUM.dsn]: props(['Operating_Mode']),
|
|
51
|
-
});
|
|
52
|
-
const devices = await api.get_devices();
|
|
53
|
-
expect(devices.map(device => device.serial_number)).toEqual([VACUUM.dsn]);
|
|
54
|
-
});
|
|
55
|
-
it('does not filter when the caller skips the property update', async () => {
|
|
56
|
-
const api = apiWithDevices([WOODFIRE, VACUUM], {});
|
|
57
|
-
const devices = await api.get_devices(false);
|
|
58
|
-
expect(devices).toHaveLength(2);
|
|
59
|
-
});
|
|
60
|
-
});
|
|
61
|
-
//# sourceMappingURL=ayla_api.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ayla_api.test.js","sourceRoot":"","sources":["../../src/sharkiq-js/ayla_api.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"skegox_api.test.d.ts","sourceRoot":"","sources":["../../src/sharkiq-js/skegox_api.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
import { Buffer } from 'node:buffer';
|
|
2
|
-
import { mkdtempSync, readFileSync, writeFileSync } from 'node:fs';
|
|
3
|
-
import { tmpdir } from 'node:os';
|
|
4
|
-
import { join } from 'node:path';
|
|
5
|
-
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
6
|
-
import { SkegoxApi } from './skegox_api.js';
|
|
7
|
-
const log = { debug: vi.fn(), info: vi.fn(), warn: vi.fn(), error: vi.fn() };
|
|
8
|
-
function fakeJwt(sub) {
|
|
9
|
-
const payload = Buffer.from(JSON.stringify({ sub })).toString('base64url');
|
|
10
|
-
return `header.${payload}.signature`;
|
|
11
|
-
}
|
|
12
|
-
function writeAuth0File(dir, msUntilExpiry = 3600 * 1000) {
|
|
13
|
-
const file = join(dir, '.sharkiq_auth0.json');
|
|
14
|
-
writeFileSync(file, JSON.stringify({
|
|
15
|
-
id_token: fakeJwt('auth0|user123'),
|
|
16
|
-
refresh_token: 'refresh-1',
|
|
17
|
-
expiration: new Date(Date.now() + msUntilExpiry),
|
|
18
|
-
}));
|
|
19
|
-
return file;
|
|
20
|
-
}
|
|
21
|
-
// A fetch stub that answers the discovery, command and token-refresh routes
|
|
22
|
-
function stubFetch(overrides = {}) {
|
|
23
|
-
let patchCount = 0;
|
|
24
|
-
const mock = vi.fn(async (url, options = {}) => {
|
|
25
|
-
const ok = (data) => ({ ok: true, status: 200, json: async () => data, text: async () => '' });
|
|
26
|
-
if (url.includes('/oauth/token')) {
|
|
27
|
-
return ok({ id_token: fakeJwt('auth0|user123'), refresh_token: 'refresh-2', expires_in: 3600 });
|
|
28
|
-
}
|
|
29
|
-
if (url.includes('/householdsEndUser')) {
|
|
30
|
-
return ok({ households: ['HH1'] });
|
|
31
|
-
}
|
|
32
|
-
if (url.includes('/users/user123')) {
|
|
33
|
-
return ok({ items: [{ deviceId: 'SND1' }] });
|
|
34
|
-
}
|
|
35
|
-
if (url.includes('/devices/SND1') && options.method === 'GET') {
|
|
36
|
-
return ok({
|
|
37
|
-
registry: { Battery_Serial_Num: 'DSN123-SND1' },
|
|
38
|
-
telemetry: { Battery_Capacity: 88 },
|
|
39
|
-
shadow: { properties: { reported: { Operating_Mode: { value: 2 }, DockedStatus: 0 } } },
|
|
40
|
-
connectivityStatus: { connected: true },
|
|
41
|
-
});
|
|
42
|
-
}
|
|
43
|
-
if (options.method === 'PATCH') {
|
|
44
|
-
patchCount += 1;
|
|
45
|
-
if (overrides.failFirstPatch && patchCount === 1) {
|
|
46
|
-
return { ok: false, status: 401, json: async () => ({}), text: async () => 'expired' };
|
|
47
|
-
}
|
|
48
|
-
return ok({});
|
|
49
|
-
}
|
|
50
|
-
return { ok: false, status: 404, json: async () => ({}), text: async () => 'not found' };
|
|
51
|
-
});
|
|
52
|
-
vi.stubGlobal('fetch', mock);
|
|
53
|
-
return mock;
|
|
54
|
-
}
|
|
55
|
-
describe('skegoxApi', () => {
|
|
56
|
-
let dir;
|
|
57
|
-
beforeEach(() => {
|
|
58
|
-
dir = mkdtempSync(join(tmpdir(), 'skegox-test-'));
|
|
59
|
-
});
|
|
60
|
-
afterEach(() => {
|
|
61
|
-
vi.unstubAllGlobals();
|
|
62
|
-
vi.clearAllMocks();
|
|
63
|
-
});
|
|
64
|
-
it('discovers the household and maps vacuums by their Ayla DSN', async () => {
|
|
65
|
-
stubFetch();
|
|
66
|
-
const api = new SkegoxApi(log, writeAuth0File(dir));
|
|
67
|
-
await expect(api.init()).resolves.toBe(1);
|
|
68
|
-
expect(api.available('DSN123')).toBe(true);
|
|
69
|
-
expect(api.available(' dsn123 ')).toBe(true);
|
|
70
|
-
expect(api.available('OTHER')).toBe(false);
|
|
71
|
-
});
|
|
72
|
-
it('sends commands as a desired-state shadow patch', async () => {
|
|
73
|
-
const fetchMock = stubFetch();
|
|
74
|
-
const api = new SkegoxApi(log, writeAuth0File(dir));
|
|
75
|
-
await api.init();
|
|
76
|
-
await api.setProperty('dsn123', 'Operating_Mode', 2);
|
|
77
|
-
const patch = fetchMock.mock.calls.find(([, options]) => options?.method === 'PATCH');
|
|
78
|
-
expect(patch).toBeDefined();
|
|
79
|
-
expect(patch[0]).toContain('/devicesEndUserController/HH1/devices/SND1');
|
|
80
|
-
expect(JSON.parse(patch[1].body)).toEqual({
|
|
81
|
-
shadow: { properties: { desired: { Operating_Mode: 2 } } },
|
|
82
|
-
});
|
|
83
|
-
});
|
|
84
|
-
it('refreshes an expired token first and stores the rotated refresh token', async () => {
|
|
85
|
-
const fetchMock = stubFetch();
|
|
86
|
-
const file = writeAuth0File(dir, -1000);
|
|
87
|
-
const api = new SkegoxApi(log, file);
|
|
88
|
-
await api.init();
|
|
89
|
-
expect(fetchMock.mock.calls[0][0]).toContain('/oauth/token');
|
|
90
|
-
const saved = JSON.parse(readFileSync(file, 'utf8'));
|
|
91
|
-
expect(saved.refresh_token).toBe('refresh-2');
|
|
92
|
-
});
|
|
93
|
-
it('retries a command once with a fresh token after a 401', async () => {
|
|
94
|
-
const fetchMock = stubFetch({ failFirstPatch: true });
|
|
95
|
-
const api = new SkegoxApi(log, writeAuth0File(dir));
|
|
96
|
-
await api.init();
|
|
97
|
-
await api.setProperty('DSN123', 'Operating_Mode', 2);
|
|
98
|
-
const patches = fetchMock.mock.calls.filter(([, options]) => options?.method === 'PATCH');
|
|
99
|
-
expect(patches).toHaveLength(2);
|
|
100
|
-
const refreshes = fetchMock.mock.calls.filter(([url]) => url.includes('/oauth/token'));
|
|
101
|
-
expect(refreshes).toHaveLength(1);
|
|
102
|
-
});
|
|
103
|
-
it('rejects init when no token set is stored', async () => {
|
|
104
|
-
stubFetch();
|
|
105
|
-
const api = new SkegoxApi(log, join(dir, 'missing.json'));
|
|
106
|
-
await expect(api.init()).rejects.toThrow();
|
|
107
|
-
});
|
|
108
|
-
it('rejects a command for an unmapped vacuum', async () => {
|
|
109
|
-
stubFetch();
|
|
110
|
-
const api = new SkegoxApi(log, writeAuth0File(dir));
|
|
111
|
-
await api.init();
|
|
112
|
-
await expect(api.setProperty('UNKNOWN', 'Operating_Mode', 2)).rejects.toThrow('not mapped');
|
|
113
|
-
});
|
|
114
|
-
it('reads live state keyed by clean property names', async () => {
|
|
115
|
-
stubFetch();
|
|
116
|
-
const api = new SkegoxApi(log, writeAuth0File(dir));
|
|
117
|
-
await api.init();
|
|
118
|
-
const values = await api.getPropertyValues('DSN123');
|
|
119
|
-
expect(values.Battery_Capacity).toBe(88);
|
|
120
|
-
expect(values.Operating_Mode).toBe(2);
|
|
121
|
-
expect(values.DockedStatus).toBe(0);
|
|
122
|
-
});
|
|
123
|
-
it('describes the shadow state for a mapped vacuum', async () => {
|
|
124
|
-
stubFetch();
|
|
125
|
-
const api = new SkegoxApi(log, writeAuth0File(dir));
|
|
126
|
-
await api.init();
|
|
127
|
-
const state = await api.describeState('DSN123');
|
|
128
|
-
expect(state).toContain('desired Operating_Mode=');
|
|
129
|
-
expect(state).toContain('connected=');
|
|
130
|
-
});
|
|
131
|
-
});
|
|
132
|
-
//# sourceMappingURL=skegox_api.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"skegox_api.test.js","sourceRoot":"","sources":["../../src/sharkiq-js/skegox_api.test.ts"],"names":[],"mappings":"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"}
|