camstreamerlib 4.0.17-dev-milestone.0 → 4.0.17-dev-milestone.2
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/cjs/PlaneTrackerAPI.d.ts +3 -1
- package/cjs/PlaneTrackerAPI.js +13 -0
- package/cjs/node/events/MilestoneAgent.js +4 -4
- package/cjs/types/PlaneTrackerAPI.d.ts +15 -0
- package/cjs/types/PlaneTrackerAPI.js +8 -1
- package/esm/PlaneTrackerAPI.js +14 -1
- package/esm/node/events/MilestoneAgent.js +4 -4
- package/esm/types/PlaneTrackerAPI.js +7 -0
- package/package.json +1 -1
- package/types/PlaneTrackerAPI.d.ts +3 -1
- package/types/types/PlaneTrackerAPI.d.ts +15 -0
- package/cjs/node/events/MilestoneAgent.test.d.ts +0 -1
- package/cjs/node/events/MilestoneAgent.test.js +0 -102
- package/esm/node/events/MilestoneAgent.test.js +0 -100
- package/types/node/events/MilestoneAgent.test.d.ts +0 -1
package/cjs/PlaneTrackerAPI.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { IClient, TResponse } from './internal/types';
|
|
2
|
-
import { ICAO, TBlackList, TCameraSettings, TExportDataType, TGetIcaoByOption, TImportDataType, TPriorityList, TTrackingMode, TWhiteList, TZones } from './types/PlaneTrackerAPI';
|
|
2
|
+
import { ICAO, TBlackList, TCameraSettings, TConnection, TExportDataType, TGetIcaoByOption, TImportDataType, TMilestoneCameraOption, TPriorityList, TTrackingMode, TWhiteList, TZones } from './types/PlaneTrackerAPI';
|
|
3
3
|
import { THttpRequestOptions } from './types/common';
|
|
4
4
|
import { BasicAPI } from './internal/BasicAPI';
|
|
5
5
|
import { TApiUser } from './types/ws/PlaneTrackerEvents';
|
|
@@ -259,5 +259,7 @@ export declare class PlaneTrackerAPI<Client extends IClient<TResponse, any>> ext
|
|
|
259
259
|
}>;
|
|
260
260
|
setZones(zones: TZones, options?: THttpRequestOptions): Promise<void>;
|
|
261
261
|
goToCoordinates(lat: number, lon: number, alt?: number, options?: THttpRequestOptions): Promise<void>;
|
|
262
|
+
checkMilestoneConnection(params: TConnection, options?: THttpRequestOptions): Promise<boolean>;
|
|
263
|
+
getMilestoneCameraList(params: TConnection, options?: THttpRequestOptions): Promise<TMilestoneCameraOption[]>;
|
|
262
264
|
downloadReport(options?: THttpRequestOptions): Promise<string>;
|
|
263
265
|
}
|
package/cjs/PlaneTrackerAPI.js
CHANGED
|
@@ -196,6 +196,19 @@ class PlaneTrackerAPI extends BasicAPI_1.BasicAPI {
|
|
|
196
196
|
}
|
|
197
197
|
}
|
|
198
198
|
}
|
|
199
|
+
async checkMilestoneConnection(params, options) {
|
|
200
|
+
try {
|
|
201
|
+
await this._postUrlEncoded(`${BASE_PATH}/package/checkMilestoneConnection.cgi`, { ...params }, options);
|
|
202
|
+
return true;
|
|
203
|
+
}
|
|
204
|
+
catch {
|
|
205
|
+
return false;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
async getMilestoneCameraList(params, options) {
|
|
209
|
+
const res = await this._postUrlEncoded(`${BASE_PATH}/package/getMilestoneCameraList.cgi`, { ...params }, options);
|
|
210
|
+
return PlaneTrackerAPI_1.milestoneCameraListSchema.parse(await res.json());
|
|
211
|
+
}
|
|
199
212
|
downloadReport(options) {
|
|
200
213
|
return this._getText(`${BASE_PATH}/report.cgi`, undefined, options);
|
|
201
214
|
}
|
|
@@ -27,11 +27,11 @@ class MilestoneAgent {
|
|
|
27
27
|
}
|
|
28
28
|
async checkConnection() {
|
|
29
29
|
await this.getToken(true);
|
|
30
|
-
await this.getCamerasPage(
|
|
30
|
+
await this.getCamerasPage(0, 1);
|
|
31
31
|
}
|
|
32
32
|
async getAllCameras() {
|
|
33
33
|
const cameras = [];
|
|
34
|
-
let page =
|
|
34
|
+
let page = 0;
|
|
35
35
|
for (;;) {
|
|
36
36
|
const pageCameras = await this.getCamerasPage(page, PAGE_SIZE);
|
|
37
37
|
cameras.push(...pageCameras);
|
|
@@ -55,9 +55,9 @@ class MilestoneAgent {
|
|
|
55
55
|
throw new errors_1.ErrorWithResponse(res);
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
|
-
async getCamerasPage(page,
|
|
58
|
+
async getCamerasPage(page, size) {
|
|
59
59
|
const token = await this.getToken();
|
|
60
|
-
const res = await this.sender.sendRequest(this.getRequestOptions('GET', `/api/rest/v1/cameras?page=${page}&
|
|
60
|
+
const res = await this.sender.sendRequest(this.getRequestOptions('GET', `/api/rest/v1/cameras?page=${page}&size=${size}`, token));
|
|
61
61
|
if (!res.ok) {
|
|
62
62
|
throw new errors_1.ErrorWithResponse(res);
|
|
63
63
|
}
|
|
@@ -33,6 +33,21 @@ export declare const connectionSchema: z.ZodObject<{
|
|
|
33
33
|
user: string;
|
|
34
34
|
protocol: "https" | "http" | "https_insecure";
|
|
35
35
|
}>;
|
|
36
|
+
export type TConnection = z.infer<typeof connectionSchema>;
|
|
37
|
+
export declare const milestoneCameraListSchema: z.ZodArray<z.ZodObject<{
|
|
38
|
+
index: z.ZodNumber;
|
|
39
|
+
value: z.ZodString;
|
|
40
|
+
label: z.ZodString;
|
|
41
|
+
}, "strip", z.ZodTypeAny, {
|
|
42
|
+
value: string;
|
|
43
|
+
label: string;
|
|
44
|
+
index: number;
|
|
45
|
+
}, {
|
|
46
|
+
value: string;
|
|
47
|
+
label: string;
|
|
48
|
+
index: number;
|
|
49
|
+
}>, "many">;
|
|
50
|
+
export type TMilestoneCameraOption = z.infer<typeof milestoneCameraListSchema>[number];
|
|
36
51
|
export declare const widgetSchema: z.ZodObject<{
|
|
37
52
|
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
38
53
|
coord: z.ZodUnion<[z.ZodLiteral<"top_left">, z.ZodLiteral<"top_right">, z.ZodLiteral<"bottom_left">, z.ZodLiteral<"bottom_right">]>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.REMOTE_ID_CATEGORY_IDS = exports.ADSB_CATEGORY_IDS = exports.domainListSchema = exports.domainIdSchema = exports.zonesSchema = exports.mapInfoSchema = exports.mapTypeSchema = exports.priorityListSchema = exports.blackListSchema = exports.whiteListSchema = exports.priorityListEntrySchema = exports.listEntrySchema = exports.listEntryIdTypeSchema = exports.listEntryDomainSchema = exports.flightInfoSchema = exports.trackingModeSchema = exports.getIcaoSchema = exports.serverSettingsSchema = exports.cameraSettingsSchema = exports.widgetSchema = exports.connectionSchema = exports.wsAliasResponseSchema = void 0;
|
|
3
|
+
exports.REMOTE_ID_CATEGORY_IDS = exports.ADSB_CATEGORY_IDS = exports.domainListSchema = exports.domainIdSchema = exports.zonesSchema = exports.mapInfoSchema = exports.mapTypeSchema = exports.priorityListSchema = exports.blackListSchema = exports.whiteListSchema = exports.priorityListEntrySchema = exports.listEntrySchema = exports.listEntryIdTypeSchema = exports.listEntryDomainSchema = exports.flightInfoSchema = exports.trackingModeSchema = exports.getIcaoSchema = exports.serverSettingsSchema = exports.cameraSettingsSchema = exports.widgetSchema = exports.milestoneCameraListSchema = exports.connectionSchema = exports.wsAliasResponseSchema = void 0;
|
|
4
4
|
const zod_1 = require("zod");
|
|
5
5
|
exports.wsAliasResponseSchema = zod_1.z.object({
|
|
6
6
|
alias: zod_1.z.string(),
|
|
@@ -14,6 +14,13 @@ exports.connectionSchema = zod_1.z.object({
|
|
|
14
14
|
user: zod_1.z.string(),
|
|
15
15
|
pass: zod_1.z.string(),
|
|
16
16
|
});
|
|
17
|
+
exports.milestoneCameraListSchema = zod_1.z
|
|
18
|
+
.object({
|
|
19
|
+
index: zod_1.z.number(),
|
|
20
|
+
value: zod_1.z.string(),
|
|
21
|
+
label: zod_1.z.string(),
|
|
22
|
+
})
|
|
23
|
+
.array();
|
|
17
24
|
exports.widgetSchema = zod_1.z.object({
|
|
18
25
|
enabled: zod_1.z.boolean().default(true),
|
|
19
26
|
coord: zod_1.z.union([
|
package/esm/PlaneTrackerAPI.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import { blackListSchema, cameraSettingsSchema, domainListSchema, flightInfoSchema, getIcaoSchema, mapInfoSchema, priorityListSchema, serverSettingsSchema, trackingModeSchema, whiteListSchema, wsAliasResponseSchema, zonesSchema, } from './types/PlaneTrackerAPI';
|
|
2
|
+
import { blackListSchema, cameraSettingsSchema, domainListSchema, flightInfoSchema, getIcaoSchema, mapInfoSchema, milestoneCameraListSchema, priorityListSchema, serverSettingsSchema, trackingModeSchema, whiteListSchema, wsAliasResponseSchema, zonesSchema, } from './types/PlaneTrackerAPI';
|
|
3
3
|
import { CannotSetCoordsInAutoModeError, ImportSettingsError, InvalidAltitudeError, InvalidLatLngError, ResetCalibrationError, ServerError, BadRequestError, } from './errors/errors';
|
|
4
4
|
import { BasicAPI } from './internal/BasicAPI';
|
|
5
5
|
const BASE_PATH = '/local/planetracker';
|
|
@@ -193,6 +193,19 @@ export class PlaneTrackerAPI extends BasicAPI {
|
|
|
193
193
|
}
|
|
194
194
|
}
|
|
195
195
|
}
|
|
196
|
+
async checkMilestoneConnection(params, options) {
|
|
197
|
+
try {
|
|
198
|
+
await this._postUrlEncoded(`${BASE_PATH}/package/checkMilestoneConnection.cgi`, { ...params }, options);
|
|
199
|
+
return true;
|
|
200
|
+
}
|
|
201
|
+
catch {
|
|
202
|
+
return false;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
async getMilestoneCameraList(params, options) {
|
|
206
|
+
const res = await this._postUrlEncoded(`${BASE_PATH}/package/getMilestoneCameraList.cgi`, { ...params }, options);
|
|
207
|
+
return milestoneCameraListSchema.parse(await res.json());
|
|
208
|
+
}
|
|
196
209
|
downloadReport(options) {
|
|
197
210
|
return this._getText(`${BASE_PATH}/report.cgi`, undefined, options);
|
|
198
211
|
}
|
|
@@ -24,11 +24,11 @@ export class MilestoneAgent {
|
|
|
24
24
|
}
|
|
25
25
|
async checkConnection() {
|
|
26
26
|
await this.getToken(true);
|
|
27
|
-
await this.getCamerasPage(
|
|
27
|
+
await this.getCamerasPage(0, 1);
|
|
28
28
|
}
|
|
29
29
|
async getAllCameras() {
|
|
30
30
|
const cameras = [];
|
|
31
|
-
let page =
|
|
31
|
+
let page = 0;
|
|
32
32
|
for (;;) {
|
|
33
33
|
const pageCameras = await this.getCamerasPage(page, PAGE_SIZE);
|
|
34
34
|
cameras.push(...pageCameras);
|
|
@@ -52,9 +52,9 @@ export class MilestoneAgent {
|
|
|
52
52
|
throw new ErrorWithResponse(res);
|
|
53
53
|
}
|
|
54
54
|
}
|
|
55
|
-
async getCamerasPage(page,
|
|
55
|
+
async getCamerasPage(page, size) {
|
|
56
56
|
const token = await this.getToken();
|
|
57
|
-
const res = await this.sender.sendRequest(this.getRequestOptions('GET', `/api/rest/v1/cameras?page=${page}&
|
|
57
|
+
const res = await this.sender.sendRequest(this.getRequestOptions('GET', `/api/rest/v1/cameras?page=${page}&size=${size}`, token));
|
|
58
58
|
if (!res.ok) {
|
|
59
59
|
throw new ErrorWithResponse(res);
|
|
60
60
|
}
|
|
@@ -11,6 +11,13 @@ export const connectionSchema = z.object({
|
|
|
11
11
|
user: z.string(),
|
|
12
12
|
pass: z.string(),
|
|
13
13
|
});
|
|
14
|
+
export const milestoneCameraListSchema = z
|
|
15
|
+
.object({
|
|
16
|
+
index: z.number(),
|
|
17
|
+
value: z.string(),
|
|
18
|
+
label: z.string(),
|
|
19
|
+
})
|
|
20
|
+
.array();
|
|
14
21
|
export const widgetSchema = z.object({
|
|
15
22
|
enabled: z.boolean().default(true),
|
|
16
23
|
coord: z.union([
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { IClient, TResponse } from './internal/types';
|
|
2
|
-
import { ICAO, TBlackList, TCameraSettings, TExportDataType, TGetIcaoByOption, TImportDataType, TPriorityList, TTrackingMode, TWhiteList, TZones } from './types/PlaneTrackerAPI';
|
|
2
|
+
import { ICAO, TBlackList, TCameraSettings, TConnection, TExportDataType, TGetIcaoByOption, TImportDataType, TMilestoneCameraOption, TPriorityList, TTrackingMode, TWhiteList, TZones } from './types/PlaneTrackerAPI';
|
|
3
3
|
import { THttpRequestOptions } from './types/common';
|
|
4
4
|
import { BasicAPI } from './internal/BasicAPI';
|
|
5
5
|
import { TApiUser } from './types/ws/PlaneTrackerEvents';
|
|
@@ -259,5 +259,7 @@ export declare class PlaneTrackerAPI<Client extends IClient<TResponse, any>> ext
|
|
|
259
259
|
}>;
|
|
260
260
|
setZones(zones: TZones, options?: THttpRequestOptions): Promise<void>;
|
|
261
261
|
goToCoordinates(lat: number, lon: number, alt?: number, options?: THttpRequestOptions): Promise<void>;
|
|
262
|
+
checkMilestoneConnection(params: TConnection, options?: THttpRequestOptions): Promise<boolean>;
|
|
263
|
+
getMilestoneCameraList(params: TConnection, options?: THttpRequestOptions): Promise<TMilestoneCameraOption[]>;
|
|
262
264
|
downloadReport(options?: THttpRequestOptions): Promise<string>;
|
|
263
265
|
}
|
|
@@ -33,6 +33,21 @@ export declare const connectionSchema: z.ZodObject<{
|
|
|
33
33
|
user: string;
|
|
34
34
|
protocol: "https" | "http" | "https_insecure";
|
|
35
35
|
}>;
|
|
36
|
+
export type TConnection = z.infer<typeof connectionSchema>;
|
|
37
|
+
export declare const milestoneCameraListSchema: z.ZodArray<z.ZodObject<{
|
|
38
|
+
index: z.ZodNumber;
|
|
39
|
+
value: z.ZodString;
|
|
40
|
+
label: z.ZodString;
|
|
41
|
+
}, "strip", z.ZodTypeAny, {
|
|
42
|
+
value: string;
|
|
43
|
+
label: string;
|
|
44
|
+
index: number;
|
|
45
|
+
}, {
|
|
46
|
+
value: string;
|
|
47
|
+
label: string;
|
|
48
|
+
index: number;
|
|
49
|
+
}>, "many">;
|
|
50
|
+
export type TMilestoneCameraOption = z.infer<typeof milestoneCameraListSchema>[number];
|
|
36
51
|
export declare const widgetSchema: z.ZodObject<{
|
|
37
52
|
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
38
53
|
coord: z.ZodUnion<[z.ZodLiteral<"top_left">, z.ZodLiteral<"top_right">, z.ZodLiteral<"bottom_left">, z.ZodLiteral<"bottom_right">]>;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const globals_1 = require("@jest/globals");
|
|
4
|
-
const HttpRequestSender_1 = require("../HttpRequestSender");
|
|
5
|
-
const MilestoneAgent_1 = require("./MilestoneAgent");
|
|
6
|
-
globals_1.jest.mock('../HttpRequestSender');
|
|
7
|
-
function jsonResponse(body, status = 200) {
|
|
8
|
-
return {
|
|
9
|
-
ok: status >= 200 && status < 300,
|
|
10
|
-
status,
|
|
11
|
-
statusText: 'OK',
|
|
12
|
-
text: () => Promise.resolve(JSON.stringify(body)),
|
|
13
|
-
};
|
|
14
|
-
}
|
|
15
|
-
const TOKEN_BODY = { access_token: 'abc123', expires_in: 3600, token_type: 'Bearer', scope: 'managementserver' };
|
|
16
|
-
(0, globals_1.describe)('MilestoneAgent', () => {
|
|
17
|
-
const MockedSender = globals_1.jest.mocked(HttpRequestSender_1.HttpRequestSender);
|
|
18
|
-
let sendRequest;
|
|
19
|
-
(0, globals_1.beforeEach)(() => {
|
|
20
|
-
sendRequest = globals_1.jest.fn();
|
|
21
|
-
MockedSender.mockImplementation(() => ({ sendRequest }));
|
|
22
|
-
});
|
|
23
|
-
function callsTo(prefix) {
|
|
24
|
-
return sendRequest.mock.calls.filter((c) => c[0].path.startsWith(prefix));
|
|
25
|
-
}
|
|
26
|
-
function routeByPath(handlers) {
|
|
27
|
-
sendRequest.mockImplementation((...args) => {
|
|
28
|
-
const options = args[0];
|
|
29
|
-
if (options.path === '/idp/connect/token') {
|
|
30
|
-
return Promise.resolve(jsonResponse(TOKEN_BODY));
|
|
31
|
-
}
|
|
32
|
-
for (const [prefix, handler] of Object.entries(handlers)) {
|
|
33
|
-
if (options.path.startsWith(prefix)) {
|
|
34
|
-
if (typeof handler === 'function') {
|
|
35
|
-
const page = Number(new URLSearchParams(options.path.split('?')[1]).get('page'));
|
|
36
|
-
return Promise.resolve(handler(page));
|
|
37
|
-
}
|
|
38
|
-
return Promise.resolve(handler);
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
throw new Error(`Unexpected path ${options.path}`);
|
|
42
|
-
});
|
|
43
|
-
}
|
|
44
|
-
(0, globals_1.test)('fetches a bearer token before listing cameras and sends it in the header', async () => {
|
|
45
|
-
routeByPath({ '/api/rest/v1/cameras': jsonResponse({ array: [{ id: 'cam-1', displayName: 'Cam 1' }] }) });
|
|
46
|
-
const agent = new MilestoneAgent_1.MilestoneAgent({ ip: '1.2.3.4' });
|
|
47
|
-
const cameras = await agent.getAllCameras();
|
|
48
|
-
(0, globals_1.expect)(cameras).toEqual([{ id: 'cam-1', displayName: 'Cam 1' }]);
|
|
49
|
-
const tokenCalls = callsTo('/idp/connect/token');
|
|
50
|
-
(0, globals_1.expect)(tokenCalls.length).toBe(1);
|
|
51
|
-
(0, globals_1.expect)(tokenCalls[0][0].method).toBe('POST');
|
|
52
|
-
const camerasCall = callsTo('/api/rest/v1/cameras')[0];
|
|
53
|
-
(0, globals_1.expect)(camerasCall[0].headers.Authorization).toBe('Bearer abc123');
|
|
54
|
-
});
|
|
55
|
-
(0, globals_1.test)('reuses the cached token across calls', async () => {
|
|
56
|
-
routeByPath({ '/api/rest/v1/cameras': jsonResponse({ array: [] }) });
|
|
57
|
-
const agent = new MilestoneAgent_1.MilestoneAgent({ ip: '1.2.3.4' });
|
|
58
|
-
await agent.getAllCameras();
|
|
59
|
-
await agent.getAllCameras();
|
|
60
|
-
(0, globals_1.expect)(callsTo('/idp/connect/token').length).toBe(1);
|
|
61
|
-
});
|
|
62
|
-
(0, globals_1.test)('pages through cameras until a non-full page is returned', async () => {
|
|
63
|
-
const fullPage = (page) => jsonResponse({ array: Array.from({ length: 100 }, (_, i) => ({ id: `p${page}-${i}` })) });
|
|
64
|
-
routeByPath({
|
|
65
|
-
'/api/rest/v1/cameras': (page) => page < 3 ? fullPage(page) : jsonResponse({ array: [{ id: 'last' }] }),
|
|
66
|
-
});
|
|
67
|
-
const agent = new MilestoneAgent_1.MilestoneAgent({ ip: '1.2.3.4' });
|
|
68
|
-
const cameras = await agent.getAllCameras();
|
|
69
|
-
(0, globals_1.expect)(cameras.length).toBe(201);
|
|
70
|
-
(0, globals_1.expect)(cameras[cameras.length - 1]).toEqual({ id: 'last' });
|
|
71
|
-
});
|
|
72
|
-
(0, globals_1.test)('sends a bookmark with the camera devicePath', async () => {
|
|
73
|
-
routeByPath({ '/api/rest/v1/bookmarks': jsonResponse({ result: {} }, 201) });
|
|
74
|
-
const agent = new MilestoneAgent_1.MilestoneAgent({ ip: '1.2.3.4' });
|
|
75
|
-
await agent.sendBookmark('cam-guid', {
|
|
76
|
-
header: 'Airbus A320',
|
|
77
|
-
description: 'ICAO BC4AA',
|
|
78
|
-
timeBegin: '2026-04-16T10:25:00.000Z',
|
|
79
|
-
timeEnd: '2026-04-16T10:25:00.000Z',
|
|
80
|
-
timeTriggered: '2026-04-16T10:25:00.000Z',
|
|
81
|
-
reference: 'BC4AA',
|
|
82
|
-
});
|
|
83
|
-
const call = callsTo('/api/rest/v1/bookmarks')[0];
|
|
84
|
-
(0, globals_1.expect)(call).toBeDefined();
|
|
85
|
-
const body = JSON.parse(call[1]);
|
|
86
|
-
(0, globals_1.expect)(body.devicePath).toEqual({ type: 'cameras', id: 'cam-guid' });
|
|
87
|
-
(0, globals_1.expect)(body.header).toBe('Airbus A320');
|
|
88
|
-
(0, globals_1.expect)(body.description).toBe('ICAO BC4AA');
|
|
89
|
-
});
|
|
90
|
-
(0, globals_1.test)('throws on a non-ok bookmark response', async () => {
|
|
91
|
-
routeByPath({ '/api/rest/v1/bookmarks': jsonResponse({ error: 'nope' }, 500) });
|
|
92
|
-
const agent = new MilestoneAgent_1.MilestoneAgent({ ip: '1.2.3.4' });
|
|
93
|
-
await (0, globals_1.expect)(agent.sendBookmark('cam-guid', {
|
|
94
|
-
header: 'h',
|
|
95
|
-
description: 'd',
|
|
96
|
-
timeBegin: 't',
|
|
97
|
-
timeEnd: 't',
|
|
98
|
-
timeTriggered: 't',
|
|
99
|
-
reference: 'r',
|
|
100
|
-
})).rejects.toThrow();
|
|
101
|
-
});
|
|
102
|
-
});
|
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
import { describe, test, expect, beforeEach, jest } from '@jest/globals';
|
|
2
|
-
import { HttpRequestSender } from '../HttpRequestSender';
|
|
3
|
-
import { MilestoneAgent } from './MilestoneAgent';
|
|
4
|
-
jest.mock('../HttpRequestSender');
|
|
5
|
-
function jsonResponse(body, status = 200) {
|
|
6
|
-
return {
|
|
7
|
-
ok: status >= 200 && status < 300,
|
|
8
|
-
status,
|
|
9
|
-
statusText: 'OK',
|
|
10
|
-
text: () => Promise.resolve(JSON.stringify(body)),
|
|
11
|
-
};
|
|
12
|
-
}
|
|
13
|
-
const TOKEN_BODY = { access_token: 'abc123', expires_in: 3600, token_type: 'Bearer', scope: 'managementserver' };
|
|
14
|
-
describe('MilestoneAgent', () => {
|
|
15
|
-
const MockedSender = jest.mocked(HttpRequestSender);
|
|
16
|
-
let sendRequest;
|
|
17
|
-
beforeEach(() => {
|
|
18
|
-
sendRequest = jest.fn();
|
|
19
|
-
MockedSender.mockImplementation(() => ({ sendRequest }));
|
|
20
|
-
});
|
|
21
|
-
function callsTo(prefix) {
|
|
22
|
-
return sendRequest.mock.calls.filter((c) => c[0].path.startsWith(prefix));
|
|
23
|
-
}
|
|
24
|
-
function routeByPath(handlers) {
|
|
25
|
-
sendRequest.mockImplementation((...args) => {
|
|
26
|
-
const options = args[0];
|
|
27
|
-
if (options.path === '/idp/connect/token') {
|
|
28
|
-
return Promise.resolve(jsonResponse(TOKEN_BODY));
|
|
29
|
-
}
|
|
30
|
-
for (const [prefix, handler] of Object.entries(handlers)) {
|
|
31
|
-
if (options.path.startsWith(prefix)) {
|
|
32
|
-
if (typeof handler === 'function') {
|
|
33
|
-
const page = Number(new URLSearchParams(options.path.split('?')[1]).get('page'));
|
|
34
|
-
return Promise.resolve(handler(page));
|
|
35
|
-
}
|
|
36
|
-
return Promise.resolve(handler);
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
throw new Error(`Unexpected path ${options.path}`);
|
|
40
|
-
});
|
|
41
|
-
}
|
|
42
|
-
test('fetches a bearer token before listing cameras and sends it in the header', async () => {
|
|
43
|
-
routeByPath({ '/api/rest/v1/cameras': jsonResponse({ array: [{ id: 'cam-1', displayName: 'Cam 1' }] }) });
|
|
44
|
-
const agent = new MilestoneAgent({ ip: '1.2.3.4' });
|
|
45
|
-
const cameras = await agent.getAllCameras();
|
|
46
|
-
expect(cameras).toEqual([{ id: 'cam-1', displayName: 'Cam 1' }]);
|
|
47
|
-
const tokenCalls = callsTo('/idp/connect/token');
|
|
48
|
-
expect(tokenCalls.length).toBe(1);
|
|
49
|
-
expect(tokenCalls[0][0].method).toBe('POST');
|
|
50
|
-
const camerasCall = callsTo('/api/rest/v1/cameras')[0];
|
|
51
|
-
expect(camerasCall[0].headers.Authorization).toBe('Bearer abc123');
|
|
52
|
-
});
|
|
53
|
-
test('reuses the cached token across calls', async () => {
|
|
54
|
-
routeByPath({ '/api/rest/v1/cameras': jsonResponse({ array: [] }) });
|
|
55
|
-
const agent = new MilestoneAgent({ ip: '1.2.3.4' });
|
|
56
|
-
await agent.getAllCameras();
|
|
57
|
-
await agent.getAllCameras();
|
|
58
|
-
expect(callsTo('/idp/connect/token').length).toBe(1);
|
|
59
|
-
});
|
|
60
|
-
test('pages through cameras until a non-full page is returned', async () => {
|
|
61
|
-
const fullPage = (page) => jsonResponse({ array: Array.from({ length: 100 }, (_, i) => ({ id: `p${page}-${i}` })) });
|
|
62
|
-
routeByPath({
|
|
63
|
-
'/api/rest/v1/cameras': (page) => page < 3 ? fullPage(page) : jsonResponse({ array: [{ id: 'last' }] }),
|
|
64
|
-
});
|
|
65
|
-
const agent = new MilestoneAgent({ ip: '1.2.3.4' });
|
|
66
|
-
const cameras = await agent.getAllCameras();
|
|
67
|
-
expect(cameras.length).toBe(201);
|
|
68
|
-
expect(cameras[cameras.length - 1]).toEqual({ id: 'last' });
|
|
69
|
-
});
|
|
70
|
-
test('sends a bookmark with the camera devicePath', async () => {
|
|
71
|
-
routeByPath({ '/api/rest/v1/bookmarks': jsonResponse({ result: {} }, 201) });
|
|
72
|
-
const agent = new MilestoneAgent({ ip: '1.2.3.4' });
|
|
73
|
-
await agent.sendBookmark('cam-guid', {
|
|
74
|
-
header: 'Airbus A320',
|
|
75
|
-
description: 'ICAO BC4AA',
|
|
76
|
-
timeBegin: '2026-04-16T10:25:00.000Z',
|
|
77
|
-
timeEnd: '2026-04-16T10:25:00.000Z',
|
|
78
|
-
timeTriggered: '2026-04-16T10:25:00.000Z',
|
|
79
|
-
reference: 'BC4AA',
|
|
80
|
-
});
|
|
81
|
-
const call = callsTo('/api/rest/v1/bookmarks')[0];
|
|
82
|
-
expect(call).toBeDefined();
|
|
83
|
-
const body = JSON.parse(call[1]);
|
|
84
|
-
expect(body.devicePath).toEqual({ type: 'cameras', id: 'cam-guid' });
|
|
85
|
-
expect(body.header).toBe('Airbus A320');
|
|
86
|
-
expect(body.description).toBe('ICAO BC4AA');
|
|
87
|
-
});
|
|
88
|
-
test('throws on a non-ok bookmark response', async () => {
|
|
89
|
-
routeByPath({ '/api/rest/v1/bookmarks': jsonResponse({ error: 'nope' }, 500) });
|
|
90
|
-
const agent = new MilestoneAgent({ ip: '1.2.3.4' });
|
|
91
|
-
await expect(agent.sendBookmark('cam-guid', {
|
|
92
|
-
header: 'h',
|
|
93
|
-
description: 'd',
|
|
94
|
-
timeBegin: 't',
|
|
95
|
-
timeEnd: 't',
|
|
96
|
-
timeTriggered: 't',
|
|
97
|
-
reference: 'r',
|
|
98
|
-
})).rejects.toThrow();
|
|
99
|
-
});
|
|
100
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|