@roomi-fields/notebooklm-mcp 1.5.0 → 1.5.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.
Files changed (161) hide show
  1. package/LICENSE +22 -22
  2. package/README.md +2 -0
  3. package/deployment/INDEX.md +292 -0
  4. package/deployment/PACKAGE-FILES.txt +180 -0
  5. package/deployment/QUICK-START.md +100 -0
  6. package/deployment/docs/01-INSTALL.md +611 -0
  7. package/deployment/docs/02-CONFIGURATION.md +404 -0
  8. package/deployment/docs/03-API.md +1691 -0
  9. package/deployment/docs/04-N8N-INTEGRATION.md +373 -0
  10. package/deployment/docs/05-TROUBLESHOOTING.md +429 -0
  11. package/deployment/docs/06-NOTEBOOK-LIBRARY.md +692 -0
  12. package/deployment/docs/07-AUTO-DISCOVERY.md +236 -0
  13. package/deployment/docs/08-WSL-USAGE.md +363 -0
  14. package/deployment/docs/09-MULTI-INTERFACE.md +293 -0
  15. package/deployment/docs/10-CONTENT-MANAGEMENT.md +421 -0
  16. package/deployment/docs/11-MULTI-ACCOUNT.md +295 -0
  17. package/deployment/docs/README.md +207 -0
  18. package/deployment/scripts/README.md +564 -0
  19. package/deployment/scripts/install.ps1 +114 -0
  20. package/deployment/scripts/setup-auth.ps1 +217 -0
  21. package/deployment/scripts/start-server.ps1 +72 -0
  22. package/deployment/scripts/stop-server.ps1 +51 -0
  23. package/deployment/scripts/test-api.ps1 +651 -0
  24. package/deployment/scripts/test-auth.ps1 +323 -0
  25. package/deployment/scripts/test-auto-discovery.ps1 +295 -0
  26. package/deployment/scripts/test-cors.ps1 +398 -0
  27. package/deployment/scripts/test-errors.ps1 +581 -0
  28. package/deployment/scripts/test-server.ps1 +140 -0
  29. package/deployment/scripts/test-sessions.ps1 +426 -0
  30. package/deployment/scripts/test-validation.ps1 +299 -0
  31. package/dist/cli/accounts.js.map +1 -1
  32. package/dist/config.d.ts +1 -0
  33. package/dist/config.d.ts.map +1 -1
  34. package/dist/config.js +15 -0
  35. package/dist/config.js.map +1 -1
  36. package/dist/content/content-manager.d.ts.map +1 -1
  37. package/dist/content/content-manager.js +113 -118
  38. package/dist/content/content-manager.js.map +1 -1
  39. package/dist/i18n/en.json +120 -0
  40. package/dist/i18n/fr.json +120 -0
  41. package/dist/i18n/index.d.ts +168 -0
  42. package/dist/i18n/index.d.ts.map +1 -0
  43. package/dist/i18n/index.js +213 -0
  44. package/dist/i18n/index.js.map +1 -0
  45. package/dist/session/browser-session.d.ts.map +1 -1
  46. package/dist/session/browser-session.js +1 -0
  47. package/dist/session/browser-session.js.map +1 -1
  48. package/dist/session/shared-context-manager.d.ts.map +1 -1
  49. package/dist/session/shared-context-manager.js +2 -0
  50. package/dist/session/shared-context-manager.js.map +1 -1
  51. package/docs/ADDING_A_LANGUAGE.md +209 -0
  52. package/package.json +6 -3
  53. package/scripts/archive/add-and-activate-notebook.ps1 +31 -0
  54. package/scripts/archive/add-new-notebook.ps1 +25 -0
  55. package/scripts/archive/add-rom1pey.ps1 +2 -0
  56. package/scripts/archive/add-rpmonster.ps1 +2 -0
  57. package/scripts/archive/add-source-debug.ps1 +11 -0
  58. package/scripts/archive/add-source-e2e.ps1 +28 -0
  59. package/scripts/archive/add-source-visible.ps1 +11 -0
  60. package/scripts/archive/add-test-notebook.ps1 +13 -0
  61. package/scripts/archive/add-test-source.ps1 +50 -0
  62. package/scripts/archive/capture-screen.ps1 +11 -0
  63. package/scripts/archive/change-language.mjs +45 -0
  64. package/scripts/archive/change-language.ts +44 -0
  65. package/scripts/archive/check-account.ps1 +19 -0
  66. package/scripts/archive/check-notebook-2.ps1 +8 -0
  67. package/scripts/archive/check-test-notebook.ps1 +11 -0
  68. package/scripts/archive/create-notebook-auto.ps1 +31 -0
  69. package/scripts/archive/create-notebook.ps1 +8 -0
  70. package/scripts/archive/create-rom1pey-notebook.ps1 +19 -0
  71. package/scripts/archive/create-rom1pey.ps1 +8 -0
  72. package/scripts/archive/create-test-notebook-fresh.ps1 +21 -0
  73. package/scripts/archive/create-test-notebook.ps1 +16 -0
  74. package/scripts/archive/debug-add-source-auto.ps1 +29 -0
  75. package/scripts/archive/debug-add-source.ps1 +19 -0
  76. package/scripts/archive/debug-add-text-source.ps1 +47 -0
  77. package/scripts/archive/debug-home.ps1 +10 -0
  78. package/scripts/archive/debug-selectors.ps1 +55 -0
  79. package/scripts/archive/debug-sources-panel.ps1 +22 -0
  80. package/scripts/archive/debug-ui.ps1 +17 -0
  81. package/scripts/archive/discover-home.ps1 +26 -0
  82. package/scripts/archive/kill-automation-chrome.ps1 +37 -0
  83. package/scripts/archive/list-my-notebooks.ps1 +27 -0
  84. package/scripts/archive/navigate-home-visible.ps1 +23 -0
  85. package/scripts/archive/navigate-home.ps1 +15 -0
  86. package/scripts/archive/run-e2e-english.ps1 +111 -0
  87. package/scripts/archive/run-e2e-rom1pey-v2.ps1 +122 -0
  88. package/scripts/archive/run-e2e-rom1pey.ps1 +117 -0
  89. package/scripts/archive/setup-english-test.ps1 +36 -0
  90. package/scripts/archive/setup-test-notebook.ps1 +71 -0
  91. package/scripts/archive/simple-add-source.ps1 +14 -0
  92. package/scripts/archive/t10.ps1 +2 -0
  93. package/scripts/archive/t20.ps1 +4 -0
  94. package/scripts/archive/t30.ps1 +9 -0
  95. package/scripts/archive/t31.ps1 +11 -0
  96. package/scripts/archive/t32.ps1 +6 -0
  97. package/scripts/archive/t39.ps1 +5 -0
  98. package/scripts/archive/t40.ps1 +5 -0
  99. package/scripts/archive/t53.ps1 +12 -0
  100. package/scripts/archive/t54.ps1 +12 -0
  101. package/scripts/archive/t55.ps1 +11 -0
  102. package/scripts/archive/t9.ps1 +1 -0
  103. package/scripts/archive/test-access.ps1 +28 -0
  104. package/scripts/archive/test-add-delete-source.ps1 +64 -0
  105. package/scripts/archive/test-add-source-visible.ps1 +16 -0
  106. package/scripts/archive/test-add-source.ps1 +19 -0
  107. package/scripts/archive/test-add-text-debug.ps1 +28 -0
  108. package/scripts/archive/test-add-text-source.ps1 +8 -0
  109. package/scripts/archive/test-add-url-source.ps1 +7 -0
  110. package/scripts/archive/test-ask-ascii.ps1 +20 -0
  111. package/scripts/archive/test-ask-cnv.ps1 +20 -0
  112. package/scripts/archive/test-ask-headed.ps1 +51 -0
  113. package/scripts/archive/test-ask-ifs.ps1 +16 -0
  114. package/scripts/archive/test-ask-now.ps1 +24 -0
  115. package/scripts/archive/test-ask-real.ps1 +19 -0
  116. package/scripts/archive/test-ask-visible.ps1 +20 -0
  117. package/scripts/archive/test-create-notebook.ps1 +8 -0
  118. package/scripts/archive/test-create-then-add.ps1 +17 -0
  119. package/scripts/archive/test-delete-source.ps1 +41 -0
  120. package/scripts/archive/test-e2e-notebook.ps1 +21 -0
  121. package/scripts/archive/test-english-notebook.ps1 +20 -0
  122. package/scripts/archive/test-english.ps1 +7 -0
  123. package/scripts/archive/test-full-custom-instructions.ps1 +40 -0
  124. package/scripts/archive/test-full-infographic.ps1 +34 -0
  125. package/scripts/archive/test-full-language.ps1 +21 -0
  126. package/scripts/archive/test-full-presentation.ps1 +85 -0
  127. package/scripts/archive/test-full-report.ps1 +34 -0
  128. package/scripts/archive/test-full-source-selection.ps1 +35 -0
  129. package/scripts/archive/test-full-video-brief.ps1 +22 -0
  130. package/scripts/archive/test-full-video-explainer.ps1 +22 -0
  131. package/scripts/archive/test-full-video-styles.ps1 +37 -0
  132. package/scripts/archive/test-generate-report.ps1 +15 -0
  133. package/scripts/archive/test-generate-study-guide.ps1 +11 -0
  134. package/scripts/archive/test-headed-ask.ps1 +13 -0
  135. package/scripts/archive/test-headed-now.ps1 +9 -0
  136. package/scripts/archive/test-headed.ps1 +9 -0
  137. package/scripts/archive/test-hello.ps1 +7 -0
  138. package/scripts/archive/test-i18n-studio.ps1 +8 -0
  139. package/scripts/archive/test-i18n.ps1 +7 -0
  140. package/scripts/archive/test-manual-headed.ps1 +26 -0
  141. package/scripts/archive/test-mathieu-quota.ps1 +8 -0
  142. package/scripts/archive/test-notebook-1.ps1 +10 -0
  143. package/scripts/archive/test-notebook-2-sources.ps1 +12 -0
  144. package/scripts/archive/test-notebook1.ps1 +14 -0
  145. package/scripts/archive/test-personal-notebook.ps1 +14 -0
  146. package/scripts/archive/test-rate-limit.ps1 +19 -0
  147. package/scripts/archive/test-real-ask.ps1 +50 -0
  148. package/scripts/archive/test-real-ask2.ps1 +30 -0
  149. package/scripts/archive/test-rom1pey.ps1 +7 -0
  150. package/scripts/archive/test-rotation-complete.ps1 +14 -0
  151. package/scripts/archive/test-rotation.ps1 +8 -0
  152. package/scripts/archive/test-show-browser.ps1 +39 -0
  153. package/scripts/archive/test-update-notebook.ps1 +4 -0
  154. package/scripts/archive/verify-language-slow.ps1 +21 -0
  155. package/scripts/archive/verify-language.ps1 +15 -0
  156. package/scripts/check-server.ps1 +46 -0
  157. package/scripts/mcp-wsl-helper.sh +146 -0
  158. package/scripts/start-server.ps1 +94 -0
  159. package/scripts/stop-server.ps1 +30 -0
  160. package/scripts/switch-account-language.sh +191 -0
  161. package/scripts/test-account.ps1 +58 -0
@@ -0,0 +1,651 @@
1
+ #!/usr/bin/env pwsh
2
+ #Requires -Version 5.1
3
+
4
+ <#
5
+ .SYNOPSIS
6
+ Comprehensive test script for the NotebookLM MCP HTTP Server API
7
+
8
+ .DESCRIPTION
9
+ Tests all REST API endpoints with readable output
10
+
11
+ .PARAMETER BaseUrl
12
+ Base URL of the server (default: http://localhost:3000)
13
+
14
+ .EXAMPLE
15
+ .\test-api.ps1
16
+ Runs all tests on http://localhost:3000
17
+
18
+ .EXAMPLE
19
+ .\test-api.ps1 -BaseUrl "http://localhost:8080"
20
+ Runs all tests on a server with a different port
21
+
22
+ .EXAMPLE
23
+ .\test-api.ps1 -BaseUrl "http://192.168.1.100:3000"
24
+ Runs all tests on a remote server
25
+
26
+ .NOTES
27
+ Prerequisites:
28
+ - The server must be running
29
+ - At least one notebook must be configured for complete tests
30
+ #>
31
+
32
+ param(
33
+ [string]$BaseUrl = "http://localhost:3000"
34
+ )
35
+
36
+ # Colors for logs
37
+ function Write-TestHeader {
38
+ param([string]$Message, [int]$Number, [int]$Total)
39
+ Write-Host "`n" -NoNewline
40
+ Write-Host "═══════════════════════════════════════════════════════" -ForegroundColor Magenta
41
+ Write-Host " [$Number/$Total] $Message" -ForegroundColor Cyan
42
+ Write-Host "═══════════════════════════════════════════════════════" -ForegroundColor Magenta
43
+ }
44
+
45
+ function Write-Success {
46
+ param([string]$Message)
47
+ Write-Host "✓ $Message" -ForegroundColor Green
48
+ }
49
+
50
+ function Write-Info {
51
+ param([string]$Message)
52
+ Write-Host "ℹ $Message" -ForegroundColor Yellow
53
+ }
54
+
55
+ function Write-Error-Custom {
56
+ param([string]$Message)
57
+ Write-Host "✗ $Message" -ForegroundColor Red
58
+ }
59
+
60
+ # Banner
61
+ Clear-Host
62
+ Write-Host "`n" -NoNewline
63
+ Write-Host "╔════════════════════════════════════════════════════════╗" -ForegroundColor Magenta
64
+ Write-Host "║ ║" -ForegroundColor Magenta
65
+ Write-Host "║ NOTEBOOKLM MCP HTTP SERVER API TESTS ║" -ForegroundColor Cyan
66
+ Write-Host "║ ║" -ForegroundColor Magenta
67
+ Write-Host "╚════════════════════════════════════════════════════════╝" -ForegroundColor Magenta
68
+ Write-Host ""
69
+
70
+ # Check that the server is accessible
71
+ Write-Host "Checking server connection..." -ForegroundColor Yellow
72
+ try {
73
+ $null = Invoke-RestMethod -Uri "$BaseUrl/health" -TimeoutSec 5
74
+ Write-Success "Server accessible at $BaseUrl"
75
+ } catch {
76
+ Write-Error-Custom "Unable to connect to server at $BaseUrl"
77
+ Write-Host "Make sure the server is running with: npm run start:http" -ForegroundColor Yellow
78
+ exit 1
79
+ }
80
+
81
+ # Request a valid notebook URL for add tests
82
+ Write-Host "`n" -NoNewline
83
+ Write-Host "═══════════════════════════════════════════════════════" -ForegroundColor Yellow
84
+ Write-Host " Test Configuration (optional)" -ForegroundColor Yellow
85
+ Write-Host "═══════════════════════════════════════════════════════" -ForegroundColor Yellow
86
+ Write-Host ""
87
+ Write-Host "To test adding notebooks, provide a valid NotebookLM URL." -ForegroundColor White
88
+ Write-Host "Format: https://notebooklm.google.com/notebook/[id]" -ForegroundColor Gray
89
+ Write-Host ""
90
+ Write-Host "Press [Enter] to skip, or paste a URL:" -ForegroundColor Yellow
91
+ $testNotebookUrlForAdd = Read-Host "URL"
92
+
93
+ if ([string]::IsNullOrWhiteSpace($testNotebookUrlForAdd)) {
94
+ Write-Info "Notebook add tests will be skipped`n"
95
+ $script:testNotebookUrlForAdd = $null
96
+ } else {
97
+ Write-Success "URL provided for add tests: $testNotebookUrlForAdd`n"
98
+ $script:testNotebookUrlForAdd = $testNotebookUrlForAdd
99
+ }
100
+
101
+ $TotalTests = 11
102
+ $PassedTests = 0
103
+ $FailedTests = 0
104
+
105
+ # =============================================================================
106
+ # TEST 1: GET /health - Server health check
107
+ # =============================================================================
108
+ Write-TestHeader "GET /health - Server health check" 1 $TotalTests
109
+
110
+ try {
111
+ $health = Invoke-RestMethod -Uri "$BaseUrl/health"
112
+
113
+ if ($health.success) {
114
+ Write-Success "Server is healthy"
115
+ Write-Host "`nDetails:" -ForegroundColor White
116
+ $health.data | Format-List
117
+
118
+ if ($health.data.authenticated) {
119
+ Write-Success "Google Authentication: ACTIVE"
120
+ } else {
121
+ Write-Info "Google Authentication: INACTIVE (run: npm run setup-auth)"
122
+ }
123
+
124
+ Write-Success "Active sessions: $($health.data.sessions)"
125
+ Write-Success "Configured notebooks: $($health.data.library_notebooks)"
126
+
127
+ $PassedTests++
128
+ } else {
129
+ Write-Error-Custom "Server returned success: false"
130
+ $FailedTests++
131
+ }
132
+ } catch {
133
+ Write-Error-Custom "Error: $_"
134
+ $FailedTests++
135
+ }
136
+
137
+ # =============================================================================
138
+ # TEST 2: GET /notebooks - List all notebooks
139
+ # =============================================================================
140
+ Write-TestHeader "GET /notebooks - List all notebooks" 2 $TotalTests
141
+
142
+ try {
143
+ $notebooks = Invoke-RestMethod -Uri "$BaseUrl/notebooks"
144
+
145
+ if ($notebooks.success) {
146
+ $count = $notebooks.data.notebooks.Count
147
+ Write-Success "Retrieved $count notebook(s)"
148
+
149
+ if ($count -gt 0) {
150
+ Write-Host "`nNotebook list:" -ForegroundColor White
151
+ $notebooks.data.notebooks | Format-Table `
152
+ @{Label="ID"; Expression={$_.id}; Width=15}, `
153
+ @{Label="Name"; Expression={$_.name}; Width=20}, `
154
+ @{Label="Use Count"; Expression={$_.use_count}; Width=13}, `
155
+ @{Label="Active"; Expression={if($_.id -eq $notebooks.data.active_notebook_id){"✓"}else{""}}; Width=6}
156
+
157
+ Write-Info "Active notebook: $($notebooks.data.active_notebook_id)"
158
+ } else {
159
+ Write-Info "No configured notebooks. Add one with POST /notebooks"
160
+ }
161
+
162
+ $PassedTests++
163
+ } else {
164
+ Write-Error-Custom "Server returned success: false"
165
+ $FailedTests++
166
+ }
167
+ } catch {
168
+ Write-Error-Custom "Error: $_"
169
+ $FailedTests++
170
+ }
171
+
172
+ # Save a notebook for following tests
173
+ $testNotebook = $null
174
+ if ($notebooks.data.notebooks.Count -gt 0) {
175
+ $testNotebook = $notebooks.data.notebooks[0]
176
+ $testNotebookId = $testNotebook.id
177
+ $testNotebookUrl = $testNotebook.url
178
+ } else {
179
+ Write-Host "`n⚠️ WARNING: No configured notebooks" -ForegroundColor Yellow
180
+ Write-Host " Some tests will be skipped" -ForegroundColor Yellow
181
+ Write-Host " Add at least one notebook for complete tests" -ForegroundColor Yellow
182
+ }
183
+
184
+ # =============================================================================
185
+ # TEST 3: POST /notebooks - Add a notebook (with validation)
186
+ # =============================================================================
187
+ Write-TestHeader "POST /notebooks - Add a notebook (with validation)" 3 $TotalTests
188
+
189
+ if ($script:testNotebookUrlForAdd) {
190
+ Write-Info "This test may take 15-30 seconds (live validation)..."
191
+ Write-Info "URL to test: $($script:testNotebookUrlForAdd)"
192
+
193
+ # Sub-test 1: Add a valid notebook
194
+ Write-Host "`nSub-test 3.1: Add a valid notebook" -ForegroundColor Yellow
195
+
196
+ $testName = "Test-Notebook-Auto-$(Get-Date -Format 'HHmmss')"
197
+ $body = @{
198
+ url = $script:testNotebookUrlForAdd
199
+ name = $testName
200
+ description = "Automatic test notebook"
201
+ topics = @("test", "validation", "auto")
202
+ } | ConvertTo-Json
203
+
204
+ try {
205
+ $addResult = Invoke-RestMethod -Uri "$BaseUrl/notebooks" -Method Post -Body $body -ContentType "application/json"
206
+
207
+ if ($addResult.success) {
208
+ $addedNotebookId = $addResult.data.notebook.id
209
+ Write-Success "Notebook added successfully"
210
+ Write-Host " Generated ID: $addedNotebookId" -ForegroundColor Cyan
211
+ Write-Host " Name: $($addResult.data.notebook.name)" -ForegroundColor Cyan
212
+ Write-Host " URL: $($addResult.data.notebook.url)" -ForegroundColor Gray
213
+
214
+ # Save the ID for deletion test
215
+ $script:notebookToDelete = $addedNotebookId
216
+
217
+ $PassedTests++
218
+ } else {
219
+ Write-Error-Custom "Failed to add: $($addResult.error)"
220
+ $FailedTests++
221
+ }
222
+ } catch {
223
+ Write-Error-Custom "Error during add: $_"
224
+ if ($_.ErrorDetails) {
225
+ $errorDetail = $_.ErrorDetails.Message | ConvertFrom-Json
226
+ Write-Host " Detail: $($errorDetail.error)" -ForegroundColor Red
227
+ }
228
+ $FailedTests++
229
+ }
230
+
231
+ # Sub-test 2: Attempt to add a duplicate (same name)
232
+ Write-Host "`nSub-test 3.2: Block duplicate name" -ForegroundColor Yellow
233
+
234
+ $duplicateBody = @{
235
+ url = $script:testNotebookUrlForAdd
236
+ name = $testName # Same name!
237
+ description = "Duplicate attempt"
238
+ topics = @("test")
239
+ } | ConvertTo-Json
240
+
241
+ try {
242
+ $duplicateResult = Invoke-RestMethod -Uri "$BaseUrl/notebooks" -Method Post -Body $duplicateBody -ContentType "application/json"
243
+
244
+ if ($duplicateResult.success -eq $false -and $duplicateResult.error -like "*already exists*") {
245
+ Write-Success "Duplicate correctly blocked: $($duplicateResult.error.Substring(0, [Math]::Min(80, $duplicateResult.error.Length)))..."
246
+ } else {
247
+ Write-Error-Custom "Should block duplicate"
248
+ $FailedTests++
249
+ }
250
+ } catch {
251
+ # HTTP exception also OK
252
+ $errorResponse = $_.ErrorDetails.Message | ConvertFrom-Json
253
+ if ($errorResponse.error -like "*already exists*") {
254
+ Write-Success "Duplicate blocked (HTTP exception): $($errorResponse.error.Substring(0, [Math]::Min(80, $errorResponse.error.Length)))..."
255
+ } else {
256
+ Write-Error-Custom "Unexpected error: $($errorResponse.error)"
257
+ $FailedTests++
258
+ }
259
+ }
260
+
261
+ # Sub-test 3: Attempt to add with invalid URL
262
+ Write-Host "`nSub-test 3.3: Block invalid URL" -ForegroundColor Yellow
263
+
264
+ $invalidBody = @{
265
+ url = "https://invalid-url.com/not-a-notebook"
266
+ name = "Test-Invalid-URL"
267
+ description = "Test invalid URL"
268
+ topics = @("test")
269
+ } | ConvertTo-Json
270
+
271
+ try {
272
+ $invalidResult = Invoke-RestMethod -Uri "$BaseUrl/notebooks" -Method Post -Body $invalidBody -ContentType "application/json"
273
+
274
+ if ($invalidResult.success -eq $false -and $invalidResult.error -like "*Invalid*URL*") {
275
+ Write-Success "Invalid URL blocked: $($invalidResult.error.Substring(0, [Math]::Min(80, $invalidResult.error.Length)))..."
276
+ } else {
277
+ Write-Error-Custom "Should block invalid URL"
278
+ $FailedTests++
279
+ }
280
+ } catch {
281
+ # HTTP exception also OK
282
+ $errorResponse = $_.ErrorDetails.Message | ConvertFrom-Json
283
+ if ($errorResponse.error -like "*Invalid*URL*") {
284
+ Write-Success "Invalid URL blocked (HTTP exception): $($errorResponse.error.Substring(0, [Math]::Min(80, $errorResponse.error.Length)))..."
285
+ } else {
286
+ Write-Error-Custom "Unexpected error: $($errorResponse.error)"
287
+ $FailedTests++
288
+ }
289
+ }
290
+
291
+ } else {
292
+ Write-Info "Test skipped: No URL provided to test POST /notebooks"
293
+ Write-Info "Rerun with a valid NotebookLM URL to enable this test"
294
+ }
295
+
296
+ # =============================================================================
297
+ # TEST 4: GET /notebooks/:id - Notebook details
298
+ # =============================================================================
299
+ Write-TestHeader "GET /notebooks/:id - Notebook details" 4 $TotalTests
300
+
301
+ if ($testNotebookId) {
302
+ try {
303
+ $notebook = Invoke-RestMethod -Uri "$BaseUrl/notebooks/$testNotebookId"
304
+
305
+ if ($notebook.success) {
306
+ Write-Success "Retrieved notebook details: $testNotebookId"
307
+ Write-Host "`nDetails:" -ForegroundColor White
308
+ $notebook.data.notebook | Format-List id, name, description, url, topics, use_count, last_used
309
+ $PassedTests++
310
+ } else {
311
+ Write-Error-Custom "Server returned success: false"
312
+ $FailedTests++
313
+ }
314
+ } catch {
315
+ Write-Error-Custom "Error: $_"
316
+ $FailedTests++
317
+ }
318
+
319
+ # Error test: nonexistent notebook
320
+ Write-Host "`nError test: nonexistent notebook" -ForegroundColor Yellow
321
+ try {
322
+ $errorResult = Invoke-RestMethod -Uri "$BaseUrl/notebooks/nonexistent-notebook-xyz"
323
+ # If no HTTP exception, check success: false
324
+ if ($errorResult.success -eq $false) {
325
+ Write-Success "Expected error received: $($errorResult.error)"
326
+ } else {
327
+ Write-Error-Custom "Should return success: false"
328
+ $FailedTests++
329
+ }
330
+ } catch {
331
+ # HTTP exception (404, 500, etc.) - also OK
332
+ $errorResponse = $_.ErrorDetails.Message | ConvertFrom-Json
333
+ Write-Success "HTTP exception received: $($errorResponse.error)"
334
+ }
335
+ } else {
336
+ Write-Info "No notebook available to test GET /notebooks/:id"
337
+ Write-Info "Add a notebook with POST /notebooks to enable this test"
338
+ }
339
+
340
+ # =============================================================================
341
+ # TEST 5: PUT /notebooks/:id/activate - Activate a notebook
342
+ # =============================================================================
343
+ Write-TestHeader "PUT /notebooks/:id/activate - Activate a notebook" 5 $TotalTests
344
+
345
+ if ($testNotebookId) {
346
+ try {
347
+ $activate = Invoke-RestMethod -Uri "$BaseUrl/notebooks/$testNotebookId/activate" -Method Put
348
+
349
+ if ($activate.success) {
350
+ Write-Success "Notebook activated: $testNotebookId"
351
+ Write-Host "`nDetails:" -ForegroundColor White
352
+ $activate.data.notebook | Format-List id, name, last_used
353
+
354
+ # Verify it's actually active
355
+ $verify = Invoke-RestMethod -Uri "$BaseUrl/notebooks"
356
+ $actualActiveId = $verify.data.active_notebook_id
357
+ if ($actualActiveId -eq $testNotebookId) {
358
+ Write-Success "Verification: notebook is active (active_notebook_id = $actualActiveId)"
359
+ } else {
360
+ Write-Error-Custom "Verification failed:"
361
+ Write-Host " Expected: $testNotebookId" -ForegroundColor Red
362
+ Write-Host " Received: $actualActiveId" -ForegroundColor Red
363
+ $FailedTests++
364
+ }
365
+
366
+ $PassedTests++
367
+ } else {
368
+ Write-Error-Custom "Server returned success: false"
369
+ $FailedTests++
370
+ }
371
+ } catch {
372
+ Write-Error-Custom "Error: $_"
373
+ $FailedTests++
374
+ }
375
+ } else {
376
+ Write-Info "No notebook available to test PUT /notebooks/:id/activate"
377
+ }
378
+
379
+ # =============================================================================
380
+ # TEST 6: POST /ask - Question without notebook_id (uses active)
381
+ # =============================================================================
382
+ Write-TestHeader "POST /ask - Question without notebook_id (uses active)" 6 $TotalTests
383
+
384
+ if ($testNotebookId) {
385
+ Write-Info "This test may take 30-60 seconds (first question)..."
386
+ Write-Info "Notebook used: $testNotebookId"
387
+
388
+ try {
389
+ $body = @{
390
+ question = "Automatic test: just reply 'OK'"
391
+ } | ConvertTo-Json
392
+
393
+ $ask = Invoke-RestMethod -Uri "$BaseUrl/ask" -Method Post -Body $body -ContentType "application/json"
394
+
395
+ if ($ask.success) {
396
+ Write-Success "Question asked successfully"
397
+ Write-Host "`nDetails:" -ForegroundColor White
398
+ Write-Host " Question: $($ask.data.question)" -ForegroundColor Cyan
399
+ Write-Host " Notebook used: $($ask.data.notebook_url)" -ForegroundColor Yellow
400
+ Write-Host " Session ID: $($ask.data.session_id)" -ForegroundColor Magenta
401
+ Write-Host " Answer: $($ask.data.answer.Substring(0, [Math]::Min(100, $ask.data.answer.Length)))..." -ForegroundColor White
402
+
403
+ # Save session_id for test 7
404
+ $script:testSessionId = $ask.data.session_id
405
+
406
+ $PassedTests++
407
+ } else {
408
+ Write-Error-Custom "Server returned success: false"
409
+ $FailedTests++
410
+ }
411
+ } catch {
412
+ Write-Error-Custom "Error: $_"
413
+ if ($_.ErrorDetails) {
414
+ $errorDetail = $_.ErrorDetails.Message | ConvertFrom-Json
415
+ Write-Host "Detail: $($errorDetail.error)" -ForegroundColor Red
416
+ }
417
+ $FailedTests++
418
+ }
419
+ } else {
420
+ Write-Info "No notebook available to test POST /ask"
421
+ }
422
+
423
+ # =============================================================================
424
+ # TEST 7: GET /sessions - List active sessions
425
+ # =============================================================================
426
+ Write-TestHeader "GET /sessions - List active sessions" 7 $TotalTests
427
+
428
+ try {
429
+ $sessions = Invoke-RestMethod -Uri "$BaseUrl/sessions"
430
+
431
+ if ($sessions.success) {
432
+ $count = $sessions.data.count
433
+ Write-Success "Active sessions: $count / $($sessions.data.max_sessions)"
434
+
435
+ if ($count -gt 0) {
436
+ Write-Host "`nSession details:" -ForegroundColor White
437
+ $sessions.data.sessions | Format-Table `
438
+ @{Label="Session ID"; Expression={$_.id}; Width=12}, `
439
+ @{Label="Messages"; Expression={$_.message_count}; Width=9}, `
440
+ @{Label="Age (s)"; Expression={$_.age_seconds}; Width=9}, `
441
+ @{Label="Inactive (s)"; Expression={$_.inactive_seconds}; Width=12}, `
442
+ @{Label="Notebook"; Expression={$_.notebook_url.Substring(43, [Math]::Min(25, $_.notebook_url.Length - 43)) + "..."}; Width=30}
443
+
444
+ # Save a session for test 8
445
+ $script:testSessionIdForClose = $sessions.data.sessions[0].id
446
+ } else {
447
+ Write-Info "No active sessions"
448
+ }
449
+
450
+ $PassedTests++
451
+ } else {
452
+ Write-Error-Custom "Server returned success: false"
453
+ $FailedTests++
454
+ }
455
+ } catch {
456
+ Write-Error-Custom "Error: $_"
457
+ $FailedTests++
458
+ }
459
+
460
+ # =============================================================================
461
+ # TEST 8: POST /ask - Question with session_id (context)
462
+ # =============================================================================
463
+ Write-TestHeader "POST /ask - Question with session_id (continue conversation)" 8 $TotalTests
464
+
465
+ if ($script:testSessionId) {
466
+ Write-Info "This test may take 30-60 seconds (follow-up question)..."
467
+ Write-Info "Reusing session: $($script:testSessionId)"
468
+
469
+ try {
470
+ $body = @{
471
+ question = "Follow-up question: just reply 'FOLLOW-UP OK'"
472
+ session_id = $script:testSessionId
473
+ } | ConvertTo-Json
474
+
475
+ $ask = Invoke-RestMethod -Uri "$BaseUrl/ask" -Method Post -Body $body -ContentType "application/json"
476
+
477
+ if ($ask.success) {
478
+ Write-Success "Follow-up question asked successfully"
479
+ Write-Host "`nDetails:" -ForegroundColor White
480
+ Write-Host " Session reused: $($ask.data.session_id)" -ForegroundColor Magenta
481
+ Write-Host " Messages in session: $($ask.data.session_info.message_count)" -ForegroundColor Cyan
482
+ Write-Host " Session age (s): $($ask.data.session_info.age_seconds)" -ForegroundColor Yellow
483
+ Write-Host " Answer: $($ask.data.answer.Substring(0, [Math]::Min(100, $ask.data.answer.Length)))..." -ForegroundColor White
484
+
485
+ if ($ask.data.session_info.message_count -gt 1) {
486
+ Write-Success "Context preserved: $($ask.data.session_info.message_count) messages in session"
487
+ }
488
+
489
+ $PassedTests++
490
+ } else {
491
+ Write-Error-Custom "Server returned success: false"
492
+ $FailedTests++
493
+ }
494
+ } catch {
495
+ Write-Error-Custom "Error: $_"
496
+ $FailedTests++
497
+ }
498
+ } else {
499
+ Write-Info "No session available to test POST /ask with session_id"
500
+ }
501
+
502
+ # =============================================================================
503
+ # TEST 9: DELETE /sessions/:id - Close a session
504
+ # =============================================================================
505
+ Write-TestHeader "DELETE /sessions/:id - Close a session" 9 $TotalTests
506
+
507
+ if ($script:testSessionIdForClose) {
508
+ try {
509
+ Write-Info "Closing session: $($script:testSessionIdForClose)"
510
+
511
+ $close = Invoke-RestMethod -Uri "$BaseUrl/sessions/$($script:testSessionIdForClose)" -Method Delete
512
+
513
+ if ($close.success) {
514
+ Write-Success "Session closed successfully"
515
+ Write-Host "`nDetails:" -ForegroundColor White
516
+ $close.data | Format-List
517
+
518
+ # Verify it's gone
519
+ $sessionsAfter = Invoke-RestMethod -Uri "$BaseUrl/sessions"
520
+ Write-Success "Remaining sessions: $($sessionsAfter.data.count)"
521
+
522
+ $PassedTests++
523
+ } else {
524
+ Write-Error-Custom "Server returned success: false"
525
+ $FailedTests++
526
+ }
527
+ } catch {
528
+ Write-Error-Custom "Error: $_"
529
+ $FailedTests++
530
+ }
531
+ } else {
532
+ Write-Info "No session available to test DELETE /sessions/:id"
533
+ }
534
+
535
+ # =============================================================================
536
+ # TEST 10: POST /ask - Question with direct notebook_url
537
+ # =============================================================================
538
+ Write-TestHeader "POST /ask - Question with direct notebook_url (bypass library)" 10 $TotalTests
539
+
540
+ if ($testNotebookUrl) {
541
+ Write-Info "This test may take 30-60 seconds (direct URL)..."
542
+ Write-Info "URL used: $testNotebookUrl"
543
+
544
+ try {
545
+ $body = @{
546
+ question = "Test with direct URL: reply 'DIRECT OK'"
547
+ notebook_url = $testNotebookUrl
548
+ } | ConvertTo-Json
549
+
550
+ $ask = Invoke-RestMethod -Uri "$BaseUrl/ask" -Method Post -Body $body -ContentType "application/json"
551
+
552
+ if ($ask.success) {
553
+ Write-Success "Question with direct URL successful"
554
+ Write-Host "`nDetails:" -ForegroundColor White
555
+ Write-Host " Question: $($ask.data.question)" -ForegroundColor Cyan
556
+ Write-Host " URL used: $($ask.data.notebook_url)" -ForegroundColor Yellow
557
+ Write-Host " Session ID: $($ask.data.session_id)" -ForegroundColor Magenta
558
+ Write-Host " Answer: $($ask.data.answer.Substring(0, [Math]::Min(100, $ask.data.answer.Length)))..." -ForegroundColor White
559
+
560
+ $PassedTests++
561
+ } else {
562
+ Write-Error-Custom "Server returned success: false"
563
+ $FailedTests++
564
+ }
565
+ } catch {
566
+ Write-Error-Custom "Error: $_"
567
+ $FailedTests++
568
+ }
569
+ } else {
570
+ Write-Info "No notebook available to test POST /ask with notebook_url"
571
+ }
572
+
573
+ # =============================================================================
574
+ # TEST 11: DELETE /notebooks/:id - Delete a notebook
575
+ # =============================================================================
576
+ Write-TestHeader "DELETE /notebooks/:id - Delete a notebook" 11 $TotalTests
577
+
578
+ # ONLY delete the notebook created in test 3 (never delete existing notebooks)
579
+ if ($script:notebookToDelete) {
580
+ try {
581
+ Write-Info "Deleting notebook added in test 3: $($script:notebookToDelete)"
582
+
583
+ $delete = Invoke-RestMethod -Uri "$BaseUrl/notebooks/$($script:notebookToDelete)" -Method Delete
584
+
585
+ if ($delete.success) {
586
+ Write-Success "Notebook deleted successfully"
587
+ Write-Host "`nDetails:" -ForegroundColor White
588
+ $delete.data | Format-List
589
+
590
+ # Verify it's gone
591
+ $notebooksAfter = Invoke-RestMethod -Uri "$BaseUrl/notebooks"
592
+ $countAfter = $notebooksAfter.data.notebooks.Count
593
+ Write-Success "Remaining notebooks: $countAfter"
594
+
595
+ if ($notebooksAfter.data.notebooks.id -notcontains $script:notebookToDelete) {
596
+ Write-Success "Verification: notebook was successfully deleted"
597
+ } else {
598
+ Write-Error-Custom "Verification failed: notebook still exists"
599
+ }
600
+
601
+ $PassedTests++
602
+ } else {
603
+ Write-Error-Custom "Server returned success: false"
604
+ $FailedTests++
605
+ }
606
+ } catch {
607
+ Write-Error-Custom "Error: $_"
608
+ $FailedTests++
609
+ }
610
+ } else {
611
+ Write-Info "Test skipped: No notebook was added in test 3 (no URL provided)"
612
+ Write-Info "To test DELETE, provide a NotebookLM URL when prompted at the beginning"
613
+ }
614
+
615
+ # =============================================================================
616
+ # FINAL SUMMARY
617
+ # =============================================================================
618
+ Write-Host "`n" -NoNewline
619
+ Write-Host "╔════════════════════════════════════════════════════════╗" -ForegroundColor Magenta
620
+ Write-Host "║ ║" -ForegroundColor Magenta
621
+ Write-Host "║ TEST SUMMARY ║" -ForegroundColor Cyan
622
+ Write-Host "║ ║" -ForegroundColor Magenta
623
+ Write-Host "╚════════════════════════════════════════════════════════╝" -ForegroundColor Magenta
624
+ Write-Host ""
625
+
626
+ $TotalExecuted = $PassedTests + $FailedTests
627
+ $SuccessRate = if ($TotalExecuted -gt 0) { [math]::Round(($PassedTests / $TotalExecuted) * 100, 1) } else { 0 }
628
+
629
+ Write-Host "Total tests: $TotalTests" -ForegroundColor White
630
+ Write-Host "Tests passed: " -NoNewline -ForegroundColor White
631
+ Write-Host "$PassedTests" -ForegroundColor Green
632
+ Write-Host "Tests failed: " -NoNewline -ForegroundColor White
633
+ Write-Host "$FailedTests" -ForegroundColor $(if($FailedTests -gt 0){"Red"}else{"Green"})
634
+ Write-Host "Success rate: " -NoNewline -ForegroundColor White
635
+ Write-Host "$SuccessRate%" -ForegroundColor $(if($SuccessRate -eq 100){"Green"}elseif($SuccessRate -ge 80){"Yellow"}else{"Red"})
636
+
637
+ Write-Host ""
638
+
639
+ if ($FailedTests -eq 0) {
640
+ Write-Host "════════════════════════════════════════════════════════" -ForegroundColor Green
641
+ Write-Host " ✓ ALL TESTS PASSED SUCCESSFULLY!" -ForegroundColor Green
642
+ Write-Host "════════════════════════════════════════════════════════" -ForegroundColor Green
643
+ exit 0
644
+ } else {
645
+ Write-Host "════════════════════════════════════════════════════════" -ForegroundColor Yellow
646
+ Write-Host " ⚠ SOME TESTS FAILED" -ForegroundColor Yellow
647
+ Write-Host "════════════════════════════════════════════════════════" -ForegroundColor Yellow
648
+ Write-Host ""
649
+ Write-Host "Review the details above to identify issues." -ForegroundColor Yellow
650
+ exit 1
651
+ }