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();