een-api-toolkit 0.3.82 → 0.3.91

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.
Files changed (52) hide show
  1. package/.claude/agents/api-coverage-agent.md +264 -0
  2. package/.claude/agents/een-devices-agent.md +21 -0
  3. package/.claude/agents/een-ptz-agent.md +235 -0
  4. package/CHANGELOG.md +56 -60
  5. package/README.md +24 -1
  6. package/dist/index.cjs +3 -3
  7. package/dist/index.cjs.map +1 -1
  8. package/dist/index.d.ts +400 -0
  9. package/dist/index.js +1079 -951
  10. package/dist/index.js.map +1 -1
  11. package/docs/AI-CONTEXT.md +3 -1
  12. package/docs/ai-reference/AI-AUTH.md +1 -1
  13. package/docs/ai-reference/AI-AUTOMATIONS.md +1 -1
  14. package/docs/ai-reference/AI-DEVICES.md +1 -1
  15. package/docs/ai-reference/AI-EVENT-DATA-SCHEMAS.md +1 -1
  16. package/docs/ai-reference/AI-EVENTS.md +1 -1
  17. package/docs/ai-reference/AI-GROUPING.md +1 -1
  18. package/docs/ai-reference/AI-JOBS.md +1 -1
  19. package/docs/ai-reference/AI-MEDIA.md +1 -1
  20. package/docs/ai-reference/AI-PTZ.md +158 -0
  21. package/docs/ai-reference/AI-SETUP.md +1 -1
  22. package/docs/ai-reference/AI-USERS.md +1 -1
  23. package/examples/vue-ptz/.env.example +4 -0
  24. package/examples/vue-ptz/README.md +221 -0
  25. package/examples/vue-ptz/e2e/app.spec.ts +58 -0
  26. package/examples/vue-ptz/e2e/auth.spec.ts +296 -0
  27. package/examples/vue-ptz/index.html +13 -0
  28. package/examples/vue-ptz/package-lock.json +1729 -0
  29. package/examples/vue-ptz/package.json +29 -0
  30. package/examples/vue-ptz/playwright.config.ts +49 -0
  31. package/examples/vue-ptz/screenshot-ptz.png +0 -0
  32. package/examples/vue-ptz/src/App.vue +154 -0
  33. package/examples/vue-ptz/src/components/ApiLog.vue +387 -0
  34. package/examples/vue-ptz/src/components/CameraSelector.vue +155 -0
  35. package/examples/vue-ptz/src/components/DirectionPad.vue +350 -0
  36. package/examples/vue-ptz/src/components/LiveVideoPlayer.vue +248 -0
  37. package/examples/vue-ptz/src/components/PositionDisplay.vue +206 -0
  38. package/examples/vue-ptz/src/components/PositionInput.vue +190 -0
  39. package/examples/vue-ptz/src/components/PresetManager.vue +538 -0
  40. package/examples/vue-ptz/src/composables/useApiLog.ts +89 -0
  41. package/examples/vue-ptz/src/main.ts +22 -0
  42. package/examples/vue-ptz/src/router/index.ts +61 -0
  43. package/examples/vue-ptz/src/views/Callback.vue +76 -0
  44. package/examples/vue-ptz/src/views/Home.vue +199 -0
  45. package/examples/vue-ptz/src/views/Login.vue +32 -0
  46. package/examples/vue-ptz/src/views/Logout.vue +59 -0
  47. package/examples/vue-ptz/src/views/PtzControl.vue +173 -0
  48. package/examples/vue-ptz/src/vite-env.d.ts +12 -0
  49. package/examples/vue-ptz/tsconfig.json +21 -0
  50. package/examples/vue-ptz/tsconfig.node.json +11 -0
  51. package/examples/vue-ptz/vite.config.ts +12 -0
  52. package/package.json +1 -1
@@ -1,6 +1,6 @@
1
1
  # EEN API Toolkit - AI Reference
2
2
 
3
- > **Version:** 0.3.82
3
+ > **Version:** 0.3.91
4
4
  >
5
5
  > This documentation is optimized for AI assistants. It provides focused, domain-specific
6
6
  > references to help you understand and use the een-api-toolkit efficiently.
@@ -22,6 +22,7 @@
22
22
  | Events, alerts, metrics, SSE | [AI-EVENTS.md](./ai-reference/AI-EVENTS.md) | ~3.5K |
23
23
  | Automation rules, alert actions | [AI-AUTOMATIONS.md](./ai-reference/AI-AUTOMATIONS.md) | ~4K |
24
24
  | Jobs, exports, files, downloads | [AI-JOBS.md](./ai-reference/AI-JOBS.md) | ~3.5K |
25
+ | PTZ camera controls, presets | [AI-PTZ.md](./ai-reference/AI-PTZ.md) | ~2K |
25
26
 
26
27
  ## Specialized Agents
27
28
 
@@ -38,6 +39,7 @@ Specialized agents are available in `.claude/agents/` for domain-specific tasks:
38
39
  | `een-events-agent` | Events, alerts, metrics, real-time SSE subscriptions |
39
40
  | `een-automations-agent` | Automation rules, alert condition rules, alert actions |
40
41
  | `een-jobs-agent` | Jobs, exports, files, downloads, video export workflows |
42
+ | `een-ptz-agent` | PTZ camera controls, presets, click-to-center |
41
43
 
42
44
  **How to Use Agents:**
43
45
 
@@ -1,6 +1,6 @@
1
1
  # Authentication - EEN API Toolkit
2
2
 
3
- > **Version:** 0.3.82
3
+ > **Version:** 0.3.91
4
4
  >
5
5
  > OAuth flow implementation, token management, and session handling.
6
6
  > Load this document when implementing login, logout, or auth guards.
@@ -1,6 +1,6 @@
1
1
  # Automations API - EEN API Toolkit
2
2
 
3
- > **Version:** 0.3.82
3
+ > **Version:** 0.3.91
4
4
  >
5
5
  > Complete reference for automation rules and alert actions.
6
6
  > Load this document when working with automated alert workflows.
@@ -1,6 +1,6 @@
1
1
  # Cameras & Bridges API - EEN API Toolkit
2
2
 
3
- > **Version:** 0.3.82
3
+ > **Version:** 0.3.91
4
4
  >
5
5
  > Complete reference for camera and bridge management.
6
6
  > Load this document when working with devices.
@@ -1,6 +1,6 @@
1
1
  # Event Type to Data Schemas Mapping - EEN API Toolkit
2
2
 
3
- > **Version:** 0.3.82
3
+ > **Version:** 0.3.91
4
4
  >
5
5
  > Complete reference for event type to data schema mappings.
6
6
  > Load this document when building dynamic event queries with the `include` parameter.
@@ -1,6 +1,6 @@
1
1
  # Events, Alerts & Real-Time Streaming - EEN API Toolkit
2
2
 
3
- > **Version:** 0.3.82
3
+ > **Version:** 0.3.91
4
4
  >
5
5
  > Complete reference for events, alerts, metrics, and SSE subscriptions.
6
6
  > Load this document when implementing event-driven features.
@@ -1,6 +1,6 @@
1
1
  # Layouts API - EEN API Toolkit
2
2
 
3
- > **Version:** 0.3.82
3
+ > **Version:** 0.3.91
4
4
  >
5
5
  > Complete reference for layout management (camera grouping).
6
6
  > Load this document when working with layouts.
@@ -1,6 +1,6 @@
1
1
  # Jobs, Exports, Files & Downloads - EEN API Toolkit
2
2
 
3
- > **Version:** 0.3.82
3
+ > **Version:** 0.3.91
4
4
  >
5
5
  > Complete reference for async jobs, video exports, and file management.
6
6
  > Load this document when implementing export workflows or file downloads.
@@ -1,6 +1,6 @@
1
1
  # Media & Live Video - EEN API Toolkit
2
2
 
3
- > **Version:** 0.3.82
3
+ > **Version:** 0.3.91
4
4
  >
5
5
  > Complete reference for media retrieval, live streaming, and video playback.
6
6
  > Load this document when implementing video features.
@@ -0,0 +1,158 @@
1
+ # PTZ Camera Controls
2
+
3
+ > **Version:** 0.3.91
4
+ >
5
+ > Pan/Tilt/Zoom camera control: position, movement, presets, and automation.
6
+
7
+ ---
8
+
9
+ ## API Endpoints
10
+
11
+ | Function | Method | Endpoint | Returns |
12
+ |----------|--------|----------|---------|
13
+ | `getPtzPosition(cameraId)` | GET | `/cameras/{cameraId}/ptz/position` | `Result<PtzPosition>` |
14
+ | `movePtz(cameraId, move)` | PUT | `/cameras/{cameraId}/ptz/position` | `Result<void>` |
15
+ | `getPtzSettings(cameraId)` | GET | `/cameras/{cameraId}/ptz/settings` | `Result<PtzSettings>` |
16
+ | `updatePtzSettings(cameraId, settings)` | PATCH | `/cameras/{cameraId}/ptz/settings` | `Result<void>` |
17
+
18
+ ## Types
19
+
20
+ ### PtzPosition
21
+ ```typescript
22
+ interface PtzPosition {
23
+ x?: number // Pan (horizontal)
24
+ y?: number // Tilt (vertical)
25
+ z?: number // Zoom level
26
+ }
27
+ ```
28
+
29
+ ### PtzMove (discriminated union)
30
+ ```typescript
31
+ type PtzMove = PtzPositionMove | PtzDirectionMove | PtzCenterOnMove
32
+
33
+ // Absolute position
34
+ interface PtzPositionMove {
35
+ moveType: 'position'
36
+ x?: number; y?: number; z?: number
37
+ }
38
+
39
+ // Relative direction
40
+ interface PtzDirectionMove {
41
+ moveType: 'direction'
42
+ direction: PtzDirection[] // 'up' | 'down' | 'left' | 'right' | 'in' | 'out'
43
+ stepSize?: PtzStepSize // 'small' | 'medium' | 'large'
44
+ }
45
+
46
+ // Center on point in frame
47
+ interface PtzCenterOnMove {
48
+ moveType: 'centerOn'
49
+ relativeX: number // 0.0 (left) to 1.0 (right)
50
+ relativeY: number // 0.0 (top) to 1.0 (bottom)
51
+ }
52
+ ```
53
+
54
+ ### PtzSettings & PtzSettingsUpdate
55
+ ```typescript
56
+ interface PtzSettings {
57
+ presets: PtzPreset[]
58
+ homePreset: string | null
59
+ mode: PtzMode // 'homeReturn' | 'tour' | 'manualOnly'
60
+ autoStartDelay: number // seconds
61
+ }
62
+
63
+ interface PtzPreset {
64
+ name: string
65
+ position: PtzPosition
66
+ timeAtPreset: number // seconds at preset during tour
67
+ }
68
+
69
+ interface PtzSettingsUpdate {
70
+ presets?: PtzPreset[]
71
+ homePreset?: string | null
72
+ mode?: PtzMode
73
+ autoStartDelay?: number
74
+ }
75
+ ```
76
+
77
+ ## Usage Examples
78
+
79
+ ### Get Position
80
+ ```typescript
81
+ import { getPtzPosition } from 'een-api-toolkit'
82
+
83
+ const { data, error } = await getPtzPosition('camera-123')
84
+ if (data) {
85
+ console.log(`Pan: ${data.x}, Tilt: ${data.y}, Zoom: ${data.z}`)
86
+ }
87
+ ```
88
+
89
+ ### Move Camera
90
+ ```typescript
91
+ import { movePtz } from 'een-api-toolkit'
92
+
93
+ // Absolute position
94
+ await movePtz('camera-123', { moveType: 'position', x: 0.5, y: -0.3, z: 2.0 })
95
+
96
+ // Direction with step size
97
+ await movePtz('camera-123', {
98
+ moveType: 'direction', direction: ['up', 'left'], stepSize: 'medium'
99
+ })
100
+
101
+ // Click-to-center on video frame
102
+ await movePtz('camera-123', { moveType: 'centerOn', relativeX: 0.75, relativeY: 0.5 })
103
+ ```
104
+
105
+ ### Manage Presets
106
+ ```typescript
107
+ import { getPtzSettings, updatePtzSettings, getPtzPosition } from 'een-api-toolkit'
108
+
109
+ // Read presets
110
+ const { data: settings } = await getPtzSettings('camera-123')
111
+
112
+ // Save current position as preset
113
+ const { data: pos } = await getPtzPosition('camera-123')
114
+ if (pos && settings) {
115
+ await updatePtzSettings('camera-123', {
116
+ presets: [...settings.presets, { name: 'Gate', position: pos, timeAtPreset: 10 }],
117
+ homePreset: 'Gate'
118
+ })
119
+ }
120
+
121
+ // Change mode
122
+ await updatePtzSettings('camera-123', { mode: 'tour', autoStartDelay: 30 })
123
+ ```
124
+
125
+ ### Click-to-Center Pattern
126
+ ```typescript
127
+ function handleVideoClick(event: MouseEvent) {
128
+ const video = event.currentTarget as HTMLVideoElement
129
+ const rect = video.getBoundingClientRect()
130
+ const relativeX = (event.clientX - rect.left) / rect.width
131
+ const relativeY = (event.clientY - rect.top) / rect.height
132
+ movePtz(cameraId, { moveType: 'centerOn', relativeX, relativeY })
133
+ }
134
+ ```
135
+
136
+ ## Error Handling
137
+
138
+ | Error Code | Meaning | Action |
139
+ |------------|---------|--------|
140
+ | AUTH_REQUIRED | Not authenticated | Redirect to login |
141
+ | NOT_FOUND | Camera not found or no PTZ | Show message |
142
+ | FORBIDDEN | No permission | Show access denied |
143
+ | VALIDATION_ERROR | Empty camera ID | Fix input |
144
+
145
+ ---
146
+
147
+ ## Reference Examples
148
+
149
+ - `examples/vue-ptz/` - Complete PTZ control app with live video
150
+
151
+
152
+ ## See Also
153
+
154
+ - [AI-AUTH.md](./AI-AUTH.md)
155
+ - [AI-DEVICES.md](./AI-DEVICES.md)
156
+ - [AI-MEDIA.md](./AI-MEDIA.md)
157
+
158
+
@@ -1,6 +1,6 @@
1
1
  # Vue 3 Application Setup - EEN API Toolkit
2
2
 
3
- > **Version:** 0.3.82
3
+ > **Version:** 0.3.91
4
4
  >
5
5
  > Complete guide for setting up a Vue 3 application with the een-api-toolkit.
6
6
  > Load this document when creating a new project or troubleshooting setup issues.
@@ -1,6 +1,6 @@
1
1
  # Users API - EEN API Toolkit
2
2
 
3
- > **Version:** 0.3.82
3
+ > **Version:** 0.3.91
4
4
  >
5
5
  > Complete reference for user management.
6
6
  > Load this document when working with user data.
@@ -0,0 +1,4 @@
1
+ VITE_PROXY_URL=http://127.0.0.1:8787
2
+ VITE_EEN_CLIENT_ID=your-client-id
3
+ VITE_REDIRECT_URI=http://127.0.0.1:3333
4
+ VITE_DEBUG=true
@@ -0,0 +1,221 @@
1
+ # EEN API Toolkit - Vue PTZ Example
2
+
3
+ A Vue 3 example demonstrating PTZ (Pan/Tilt/Zoom) camera control using the een-api-toolkit, including live video streaming, directional movement, click-to-center, absolute positioning, and preset management.
4
+
5
+ ![PTZ Screenshot](screenshot-ptz.png)
6
+
7
+ ## Storage Strategy: sessionStorage
8
+
9
+ This example uses the `sessionStorage` storage strategy for balanced security. This means:
10
+
11
+ - **Per-tab isolation** - each browser tab has its own session
12
+ - **Page refresh preserves session** - tokens survive refresh within the same tab
13
+ - **Tab close clears session** - closing the tab removes tokens
14
+ - **New tabs require login** - opening a new tab requires separate authentication
15
+
16
+ This is a good balance between security (limiting XSS blast radius) and user experience (page refresh doesn't require re-login).
17
+
18
+ ## Features Demonstrated
19
+
20
+ - OAuth authentication flow (login, callback, logout)
21
+ - Protected routes with navigation guards
22
+ - PTZ camera discovery (filters cameras by PTZ capability)
23
+ - Live video streaming via `@een/live-video-web-sdk`
24
+ - Click-to-center on the live video feed
25
+ - Direction pad with pan/tilt/zoom controls
26
+ - Absolute position input (pan, tilt, zoom, field of view)
27
+ - Current position display with auto-refresh
28
+ - Preset management (list, recall, create, delete, set home)
29
+ - Real-time API call logging
30
+
31
+ ## Pages Overview
32
+
33
+ ### Home Page
34
+ The landing page that displays a welcome message and login prompt when not authenticated. Shows the available toolkit functions and their descriptions.
35
+
36
+ ### PTZ Control
37
+ The main control page with a two-column layout: live video on the left and PTZ controls on the right.
38
+
39
+ **Components:**
40
+
41
+ - **CameraSelector** - Discovers PTZ-capable cameras by checking each camera's capabilities and auto-selects the first one
42
+ - **LiveVideoPlayer** - Streams live video using the EEN Live Video Web SDK with click-to-center support
43
+ - **PositionDisplay** - Shows the current pan/tilt/zoom/field-of-view values with auto-refresh
44
+ - **DirectionPad** - Provides directional movement buttons (up/down/left/right, zoom in/out) and a home button
45
+ - **PositionInput** - Allows entering absolute pan/tilt/zoom/FOV values to move the camera
46
+ - **PresetManager** - Lists, recalls, creates, and deletes PTZ presets; designates a home preset
47
+ - **ApiLog** - Displays a real-time log of API calls made by the toolkit
48
+
49
+ ## APIs Used Summary
50
+
51
+ | API Function | Component | Purpose |
52
+ |--------------|-----------|---------|
53
+ | `getCameras()` | CameraSelector | List available cameras |
54
+ | `getCamera()` | CameraSelector | Check PTZ capability per camera |
55
+ | `getPtzPosition()` | PositionDisplay | Read current camera position |
56
+ | `movePtz()` | DirectionPad, PositionInput, LiveVideoPlayer, PresetManager | Move camera (direction, position, centerOn) |
57
+ | `getPtzSettings()` | PresetManager | Retrieve presets and automation settings |
58
+ | `updatePtzSettings()` | PresetManager | Create/delete presets, set home preset |
59
+ | `getCurrentUser()` | App.vue | Fetch logged-in user profile for header display |
60
+ | `useAuthStore()` | Multiple | Authentication state management |
61
+ | `getAuthUrl()` | Login | Generate OAuth login URL |
62
+ | `handleAuthCallback()` | Callback | Process OAuth callback |
63
+ | `revokeToken()` | Logout | Revoke authentication token on logout |
64
+ | `initEenToolkit()` | App initialization | Configure toolkit settings |
65
+ | `getStorageStrategy()` | Home | Get the current storage strategy |
66
+ | `STORAGE_STRATEGY_DESCRIPTIONS` | Home | Human-readable storage strategy descriptions |
67
+
68
+ ## Setup
69
+
70
+ ### Prerequisites
71
+
72
+ 1. **Start the OAuth proxy** (required for authentication):
73
+
74
+ The OAuth proxy is a separate project that handles token management securely.
75
+ Clone and run it from: https://github.com/klaushofrichter/een-oauth-proxy
76
+
77
+ ```bash
78
+ # In a separate terminal, from the een-oauth-proxy directory
79
+ npm install
80
+ npm run dev
81
+ ```
82
+
83
+ The proxy should be running at `http://localhost:8787`.
84
+
85
+ ### Example Setup
86
+
87
+ All commands below should be run from this example directory (`examples/vue-ptz/`):
88
+
89
+ 2. Copy the environment file:
90
+ ```bash
91
+ # From examples/vue-ptz/
92
+ cp .env.example .env
93
+ ```
94
+
95
+ 3. Edit `.env` with your EEN credentials:
96
+ ```env
97
+ VITE_EEN_CLIENT_ID=your-client-id
98
+ VITE_PROXY_URL=http://127.0.0.1:8787
99
+ # DO NOT change the redirect URI - EEN IDP only permits this URL
100
+ VITE_REDIRECT_URI=http://127.0.0.1:3333
101
+ ```
102
+
103
+ 4. Install dependencies and start:
104
+ ```bash
105
+ # From examples/vue-ptz/
106
+ npm install
107
+ npm run dev
108
+ ```
109
+
110
+ 5. Open http://127.0.0.1:3333 in your browser.
111
+
112
+ **Important:** The EEN Identity Provider only permits `http://127.0.0.1:3333` as the OAuth redirect URI. Do not use `localhost` or other ports.
113
+
114
+ **Note:** Development and testing was done on macOS. The `npm run stop` command uses `lsof`, which is not available on Windows. Windows users should manually stop any process on port 3333 or use `npx kill-port 3333` instead.
115
+
116
+ ## Project Structure
117
+
118
+ ```
119
+ src/
120
+ ├── main.ts # App entry, toolkit initialization
121
+ ├── App.vue # Root component with navigation and user info
122
+ ├── router/
123
+ │ └── index.ts # Vue Router with auth guards
124
+ ├── composables/
125
+ │ └── useApiLog.ts # Shared API call log state
126
+ ├── components/
127
+ │ ├── CameraSelector.vue # PTZ camera discovery and selection
128
+ │ ├── LiveVideoPlayer.vue # Live video stream with click-to-center
129
+ │ ├── DirectionPad.vue # Directional movement controls
130
+ │ ├── PositionDisplay.vue # Current position readout
131
+ │ ├── PositionInput.vue # Absolute position input form
132
+ │ ├── PresetManager.vue # Preset CRUD and home preset
133
+ │ └── ApiLog.vue # Real-time API call log
134
+ └── views/
135
+ ├── Home.vue # Home page with login prompt
136
+ ├── Login.vue # OAuth login redirect
137
+ ├── Callback.vue # OAuth callback handler
138
+ ├── PtzControl.vue # Main PTZ control page
139
+ └── Logout.vue # Logout handler
140
+ ```
141
+
142
+ ## Key Code Examples
143
+
144
+ ### Moving a PTZ Camera (DirectionPad.vue)
145
+
146
+ ```typescript
147
+ import { movePtz } from 'een-api-toolkit'
148
+
149
+ // Move camera using relative direction
150
+ await movePtz(cameraId, {
151
+ moveType: 'direction',
152
+ direction: ['right'],
153
+ stepSize: 'medium'
154
+ })
155
+
156
+ // Move camera to absolute position
157
+ await movePtz(cameraId, {
158
+ moveType: 'position',
159
+ x: 0.5, y: -0.3, z: 2.0
160
+ })
161
+ ```
162
+
163
+ ### Click-to-Center (LiveVideoPlayer.vue)
164
+
165
+ ```typescript
166
+ import { movePtz } from 'een-api-toolkit'
167
+
168
+ // Click coordinates on the video trigger centerOn move (0.0 to 1.0)
169
+ const relativeX = (event.clientX - rect.left) / rect.width
170
+ const relativeY = (event.clientY - rect.top) / rect.height
171
+ await movePtz(cameraId, { moveType: 'centerOn', relativeX, relativeY })
172
+ ```
173
+
174
+ ### Managing Presets (PresetManager.vue)
175
+
176
+ ```typescript
177
+ import { getPtzSettings, updatePtzSettings, getPtzPosition } from 'een-api-toolkit'
178
+
179
+ // List presets
180
+ const result = await getPtzSettings(cameraId)
181
+ const presets = result.data?.presets || []
182
+
183
+ // Recall a preset (move to its saved position)
184
+ await movePtz(cameraId, { moveType: 'position', x: preset.position.x, y: preset.position.y, z: preset.position.z })
185
+
186
+ // Save current position as a new preset (fetch existing presets first to avoid overwriting)
187
+ const { data: pos } = await getPtzPosition(cameraId)
188
+ if (pos && result.data) {
189
+ await updatePtzSettings(cameraId, {
190
+ presets: [...result.data.presets, { name: 'New Preset', position: pos, timeAtPreset: 10 }]
191
+ })
192
+ }
193
+ ```
194
+
195
+ ### Reading Camera Position (PositionDisplay.vue)
196
+
197
+ ```typescript
198
+ import { getPtzPosition } from 'een-api-toolkit'
199
+
200
+ const result = await getPtzPosition(cameraId)
201
+ if (result.data) {
202
+ const { x, y, z } = result.data // pan, tilt, zoom
203
+ }
204
+ ```
205
+
206
+ ### PTZ Camera Discovery (CameraSelector.vue)
207
+
208
+ ```typescript
209
+ import { getCameras } from 'een-api-toolkit'
210
+
211
+ // Fetch all cameras with capabilities in a single paginated request
212
+ const ptzCameras = []
213
+ let pageToken: string | undefined
214
+ do {
215
+ const result = await getCameras({ pageSize: 100, include: ['capabilities'], pageToken })
216
+ for (const cam of result.data?.results || []) {
217
+ if (cam.capabilities?.ptz?.capable) ptzCameras.push(cam)
218
+ }
219
+ pageToken = result.data?.nextPageToken ?? undefined
220
+ } while (pageToken)
221
+ ```
@@ -0,0 +1,58 @@
1
+ import { test, expect } from '@playwright/test'
2
+
3
+ test.describe('vue-ptz example app', () => {
4
+ test('home page shows login button when not authenticated', async ({ page }) => {
5
+ await page.goto('/')
6
+
7
+ // Should show the home page
8
+ await expect(page.getByRole('heading', { name: 'Welcome to the EEN PTZ Control Example' })).toBeVisible()
9
+
10
+ // Should show "not authenticated" state with login button
11
+ await expect(page.getByTestId('not-authenticated')).toBeVisible()
12
+ await expect(page.getByTestId('login-button')).toBeVisible()
13
+ await expect(page.getByText('Please log in to control PTZ cameras')).toBeVisible()
14
+ })
15
+
16
+ test('login button navigates to login page', async ({ page }) => {
17
+ await page.goto('/')
18
+
19
+ await page.getByTestId('login-button').click()
20
+
21
+ await expect(page).toHaveURL('/login')
22
+ await expect(page.getByRole('heading', { name: 'Login' })).toBeVisible()
23
+ await expect(page.getByText('Click the button below to authenticate with Eagle Eye Networks')).toBeVisible()
24
+ })
25
+
26
+ test('ptz route redirects to login when not authenticated', async ({ page }) => {
27
+ await page.goto('/ptz')
28
+
29
+ // Should redirect to login page (auth guard)
30
+ await expect(page).toHaveURL('/login')
31
+ })
32
+
33
+ test('navigation links work correctly', async ({ page }) => {
34
+ await page.goto('/')
35
+
36
+ // Check navigation is present
37
+ await expect(page.getByRole('navigation')).toBeVisible()
38
+
39
+ // Navigate to login via nav link (use testid to be specific)
40
+ await page.getByTestId('nav-login').click()
41
+ await expect(page).toHaveURL('/login')
42
+
43
+ // Navigate back home
44
+ await page.getByRole('link', { name: 'Home' }).click()
45
+ await expect(page).toHaveURL('/')
46
+ })
47
+
48
+ test('about section displays toolkit function list', async ({ page }) => {
49
+ await page.goto('/')
50
+
51
+ // Check for the function descriptions
52
+ await expect(page.getByText('getCameras()')).toBeVisible()
53
+ await expect(page.getByText('getPtzPosition()')).toBeVisible()
54
+ await expect(page.getByText('movePtz()')).toBeVisible()
55
+ await expect(page.getByText('getPtzSettings()')).toBeVisible()
56
+ await expect(page.getByText('updatePtzSettings()')).toBeVisible()
57
+ })
58
+ })