$ProgressPreference = "SilentlyContinue" $ErrorActionPreference = "Continue" Write-Host "=== 1. Get captcha and login ===" -ForegroundColor Cyan $captchaResp = Invoke-RestMethod -Uri "http://localhost:5000/api/auth/captcha" -Method Get $captchaId = $captchaResp.data.captchaId $svg = $captchaResp.data.svg $matches = [regex]::Matches($svg, ']*>([^<])') $code = -join ($matches | ForEach-Object { $_.Groups[1].Value }) $loginBody = @{ username = "admin"; password = "admin123"; captchaId = $captchaId; captchaCode = $code } | ConvertTo-Json $loginResp = Invoke-RestMethod -Uri "http://localhost:5000/api/auth/login" -Method Post -ContentType "application/json" -Body $loginBody $token = $loginResp.data.token $headers = @{ Authorization = "Bearer $token" } Write-Host "Login OK" Write-Host "" Write-Host "=== 2. Get all projects detail ===" -ForegroundColor Cyan $projResp = Invoke-RestMethod -Uri "http://localhost:5000/api/projects?pageIndex=1&pageSize=10" -Headers $headers -Method Get $projects = $projResp.data.items foreach ($p in $projects) { $d = (Invoke-RestMethod -Uri "http://localhost:5000/api/projects/$($p.id)" -Headers $headers -Method Get).data Write-Host "Project $($p.id): name=$($d.name), coverImage='$($d.coverImage)', videoUrl='$($d.videoUrl)', tags=[$($d.tags -join ',')]" } Write-Host "" Write-Host "=== 3. Get tags list ===" -ForegroundColor Cyan $tagResp = Invoke-RestMethod -Uri "http://localhost:5000/api/tags" -Headers $headers -Method Get $tags = $tagResp.data Write-Host "Tags count: $($tags.Count)" $tags | Select-Object id, name | Format-Table -AutoSize Write-Host "" Write-Host "=== 4. Test scenarios on project 5 ===" -ForegroundColor Cyan $projId = 5 $detail = (Invoke-RestMethod -Uri "http://localhost:5000/api/projects/$projId" -Headers $headers -Method Get).data Write-Host "--- Scenario A: with tagIds ---" -ForegroundColor Yellow $tagIds = @($tags[0].id) if ($tags.Count -gt 1) { $tagIds += $tags[1].id } $payloadA = @{ name = $detail.name categoryId = $detail.categoryId coverImage = $detail.coverImage videoUrl = $detail.videoUrl description = $detail.description content = $detail.content platforms = $detail.platforms status = $detail.status tagIds = $tagIds packages = @() } | ConvertTo-Json -Depth 5 try { $r = Invoke-RestMethod -Uri "http://localhost:5000/api/projects/$projId" -Headers $headers -Method Put -ContentType "application/json" -Body $payloadA Write-Host "[OK] Scenario A succeeded, tags=[$($r.data.tags -join ',')]" } catch { Write-Host "[FAIL] Scenario A failed: $($_.Exception.Response.StatusCode.value__) $($_.Exception.Response.StatusDescription)" try { $reader = New-Object System.IO.StreamReader($_.Exception.Response.GetResponseStream()); Write-Host "Body: $($reader.ReadToEnd())" } catch {} } Write-Host "" Write-Host "--- Scenario B: with signed coverImage URL ---" -ForegroundColor Yellow # Simulate a signed local URL (as IconUpload would return) $fakeCoverUrl = "/uploads/projects/cover/test_signature_url.png" $payloadB = @{ name = $detail.name categoryId = $detail.categoryId coverImage = $fakeCoverUrl videoUrl = $detail.videoUrl description = $detail.description content = $detail.content platforms = $detail.platforms status = $detail.status tagIds = @() packages = @() } | ConvertTo-Json -Depth 5 try { $r = Invoke-RestMethod -Uri "http://localhost:5000/api/projects/$projId" -Headers $headers -Method Put -ContentType "application/json" -Body $payloadB Write-Host "[OK] Scenario B succeeded, coverImage='$($r.data.coverImage)'" } catch { Write-Host "[FAIL] Scenario B failed: $($_.Exception.Response.StatusCode.value__) $($_.Exception.Response.StatusDescription)" try { $reader = New-Object System.IO.StreamReader($_.Exception.Response.GetResponseStream()); Write-Host "Body: $($reader.ReadToEnd())" } catch {} } Write-Host "" Write-Host "--- Scenario C: with packages array (simulating wake protocol) ---" -ForegroundColor Yellow $payloadC = @{ name = $detail.name categoryId = $detail.categoryId coverImage = $detail.coverImage videoUrl = $detail.videoUrl description = $detail.description content = $detail.content platforms = $detail.platforms status = $detail.status tagIds = @() packages = @( @{ id = 0; type = 1; wakeProtocolPrefix = "millisim"; wakeProtocolParam = "action=wake&projectId=$projId" } ) } | ConvertTo-Json -Depth 5 try { $r = Invoke-RestMethod -Uri "http://localhost:5000/api/projects/$projId" -Headers $headers -Method Put -ContentType "application/json" -Body $payloadC Write-Host "[OK] Scenario C succeeded" } catch { Write-Host "[FAIL] Scenario C failed: $($_.Exception.Response.StatusCode.value__) $($_.Exception.Response.StatusDescription)" try { $reader = New-Object System.IO.StreamReader($_.Exception.Response.GetResponseStream()); Write-Host "Body: $($reader.ReadToEnd())" } catch {} } Write-Host "" Write-Host "--- Scenario D: with full payload (tags + cover + packages + video proxy url) ---" -ForegroundColor Yellow $payloadD = @{ name = $detail.name + " (edit test)" categoryId = $detail.categoryId coverImage = $detail.coverImage videoUrl = "/api/projects/$projId/video" description = $detail.description content = $detail.content platforms = $detail.platforms status = $detail.status tagIds = $tagIds packages = @( @{ id = 0; type = 2; wakeProtocolPrefix = "millisim"; wakeProtocolParam = "test" } ) } | ConvertTo-Json -Depth 5 try { $r = Invoke-RestMethod -Uri "http://localhost:5000/api/projects/$projId" -Headers $headers -Method Put -ContentType "application/json" -Body $payloadD Write-Host "[OK] Scenario D succeeded" } catch { Write-Host "[FAIL] Scenario D failed: $($_.Exception.Response.StatusCode.value__) $($_.Exception.Response.StatusDescription)" try { $reader = New-Object System.IO.StreamReader($_.Exception.Response.GetResponseStream()); Write-Host "Body: $($reader.ReadToEnd())" } catch {} }