148 lines
5.0 KiB
TypeScript
148 lines
5.0 KiB
TypeScript
|
|
import { expect, tap } from '@git.zone/tstest/tapbundle';
|
||
|
|
import { Qenv } from '@push.rocks/qenv';
|
||
|
|
import * as unifi from '../ts/index.js';
|
||
|
|
|
||
|
|
// =============================================================================
|
||
|
|
// PROTECT API INTEGRATION TESTS (Local NVR API)
|
||
|
|
// Tests may use live production keys to test specific features at scale.
|
||
|
|
// Make sure to avoid dangerous, destructive or security relevant operations.
|
||
|
|
// =============================================================================
|
||
|
|
|
||
|
|
const testQenv = new Qenv('./', './.nogit/');
|
||
|
|
|
||
|
|
let testProtect: unifi.UnifiProtect;
|
||
|
|
|
||
|
|
tap.test('setup - create UnifiProtect with API key', async () => {
|
||
|
|
const host = await testQenv.getEnvVarOnDemand('UNIFI_CONSOLE_IP');
|
||
|
|
const apiKey = await testQenv.getEnvVarOnDemand('UNIFI_PROTECT_DEV_KEY');
|
||
|
|
|
||
|
|
testProtect = new unifi.UnifiProtect({
|
||
|
|
host,
|
||
|
|
apiKey,
|
||
|
|
verifySsl: false,
|
||
|
|
});
|
||
|
|
|
||
|
|
expect(testProtect.isAuthenticated()).toBeTrue();
|
||
|
|
console.log('UnifiProtect created with API key authentication');
|
||
|
|
|
||
|
|
// Load bootstrap data
|
||
|
|
await testProtect.refreshBootstrap();
|
||
|
|
});
|
||
|
|
|
||
|
|
// READ-ONLY: Get NVR info
|
||
|
|
tap.test('READ-ONLY - should get NVR info', async () => {
|
||
|
|
const nvrInfo = testProtect.getNvrInfo();
|
||
|
|
|
||
|
|
if (nvrInfo) {
|
||
|
|
console.log(`NVR: ${nvrInfo.name} (${nvrInfo.type})`);
|
||
|
|
console.log(` Firmware: ${nvrInfo.firmwareVersion}`);
|
||
|
|
console.log(` Cloud connected: ${testProtect.isCloudConnected()}`);
|
||
|
|
} else {
|
||
|
|
console.log('NVR info not available in bootstrap (may be different API version)');
|
||
|
|
}
|
||
|
|
// Don't fail - NVR info may not be present in all API versions
|
||
|
|
});
|
||
|
|
|
||
|
|
// READ-ONLY: Get storage info
|
||
|
|
tap.test('READ-ONLY - should get storage info', async () => {
|
||
|
|
const storageInfo = testProtect.getStorageInfo();
|
||
|
|
|
||
|
|
if (storageInfo && storageInfo.totalSize) {
|
||
|
|
const totalGB = (storageInfo.totalSize / 1024 / 1024 / 1024).toFixed(2);
|
||
|
|
const usedGB = storageInfo.usedSpace ? (storageInfo.usedSpace / 1024 / 1024 / 1024).toFixed(2) : 'unknown';
|
||
|
|
console.log(`Storage: ${usedGB} GB used of ${totalGB} GB`);
|
||
|
|
} else {
|
||
|
|
console.log('Storage info not available');
|
||
|
|
}
|
||
|
|
// Don't fail - storage info may not be present
|
||
|
|
});
|
||
|
|
|
||
|
|
// READ-ONLY: List cameras
|
||
|
|
tap.test('READ-ONLY - should list cameras', async () => {
|
||
|
|
const cameras = await testProtect.cameraManager.listCameras();
|
||
|
|
|
||
|
|
console.log(`Found ${cameras.length} cameras`);
|
||
|
|
expect(cameras).toBeArray();
|
||
|
|
|
||
|
|
for (const camera of cameras) {
|
||
|
|
expect(camera).toBeInstanceOf(unifi.UnifiCamera);
|
||
|
|
console.log(` - ${camera.name} (${camera.type}) - ${camera.isOnline() ? 'online' : 'offline'}`);
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
// READ-ONLY: List online cameras
|
||
|
|
tap.test('READ-ONLY - should list online cameras', async () => {
|
||
|
|
const onlineCameras = await testProtect.cameraManager.getOnlineCameras();
|
||
|
|
|
||
|
|
console.log(`Found ${onlineCameras.length} online cameras`);
|
||
|
|
expect(onlineCameras).toBeArray();
|
||
|
|
});
|
||
|
|
|
||
|
|
// READ-ONLY: List offline cameras
|
||
|
|
tap.test('READ-ONLY - should list offline cameras', async () => {
|
||
|
|
const offlineCameras = await testProtect.cameraManager.getOfflineCameras();
|
||
|
|
|
||
|
|
console.log(`Found ${offlineCameras.length} offline cameras`);
|
||
|
|
expect(offlineCameras).toBeArray();
|
||
|
|
});
|
||
|
|
|
||
|
|
// READ-ONLY: List doorbells
|
||
|
|
tap.test('READ-ONLY - should list doorbells', async () => {
|
||
|
|
const doorbells = await testProtect.cameraManager.getDoorbells();
|
||
|
|
|
||
|
|
console.log(`Found ${doorbells.length} doorbells`);
|
||
|
|
expect(doorbells).toBeArray();
|
||
|
|
});
|
||
|
|
|
||
|
|
// READ-ONLY: List smart detect cameras
|
||
|
|
tap.test('READ-ONLY - should list smart detect cameras', async () => {
|
||
|
|
const smartCameras = await testProtect.cameraManager.getSmartDetectCameras();
|
||
|
|
|
||
|
|
console.log(`Found ${smartCameras.length} cameras with smart detect`);
|
||
|
|
expect(smartCameras).toBeArray();
|
||
|
|
});
|
||
|
|
|
||
|
|
// READ-ONLY: List cameras with recent motion
|
||
|
|
tap.test('READ-ONLY - should list cameras with recent motion', async () => {
|
||
|
|
const recentMotion = await testProtect.cameraManager.getCamerasWithRecentMotion(300);
|
||
|
|
|
||
|
|
console.log(`Found ${recentMotion.length} cameras with motion in last 5 minutes`);
|
||
|
|
expect(recentMotion).toBeArray();
|
||
|
|
});
|
||
|
|
|
||
|
|
// READ-ONLY: Get motion events
|
||
|
|
tap.test('READ-ONLY - should get recent motion events', async () => {
|
||
|
|
const events = await testProtect.cameraManager.getAllMotionEvents({ limit: 10 });
|
||
|
|
|
||
|
|
// API might return object or array, handle both
|
||
|
|
const eventsArray = Array.isArray(events) ? events : [];
|
||
|
|
console.log(`Retrieved ${eventsArray.length} recent motion events`);
|
||
|
|
expect(eventsArray).toBeArray();
|
||
|
|
});
|
||
|
|
|
||
|
|
// READ-ONLY: Get lights
|
||
|
|
tap.test('READ-ONLY - should get lights', async () => {
|
||
|
|
const lights = testProtect.getLights();
|
||
|
|
|
||
|
|
console.log(`Found ${lights.length} lights`);
|
||
|
|
expect(lights).toBeArray();
|
||
|
|
});
|
||
|
|
|
||
|
|
// READ-ONLY: Get sensors
|
||
|
|
tap.test('READ-ONLY - should get sensors', async () => {
|
||
|
|
const sensors = testProtect.getSensors();
|
||
|
|
|
||
|
|
console.log(`Found ${sensors.length} sensors`);
|
||
|
|
expect(sensors).toBeArray();
|
||
|
|
});
|
||
|
|
|
||
|
|
// READ-ONLY: Get liveviews
|
||
|
|
tap.test('READ-ONLY - should get liveviews', async () => {
|
||
|
|
const liveviews = await testProtect.getLiveviews();
|
||
|
|
|
||
|
|
console.log('Liveviews retrieved');
|
||
|
|
expect(liveviews).toBeDefined();
|
||
|
|
});
|
||
|
|
|
||
|
|
export default tap.start();
|