commit e1b9d48b3d53b919d6734de891531c44b375fccd Author: NurAlan Date: Mon Jan 19 08:54:54 2026 +0700 chore: first commit diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..fc5e62c Binary files /dev/null and b/.DS_Store differ diff --git a/.github/workflows/monocart.yml b/.github/workflows/monocart.yml new file mode 100644 index 0000000..e510785 --- /dev/null +++ b/.github/workflows/monocart.yml @@ -0,0 +1,41 @@ +name: Monocart Report + +on: + push: + branches: + - main + workflow_dispatch: + +permissions: + contents: write + pages: write + id-token: write + +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-node@v4 + with: + node-version: 18 + cache: 'npm' + + - name: Install dependencies + run: npm ci + + - name: Install Playwright Browsers + run: npx playwright install --with-deps firefox + + - name: Run tests + run: npx playwright test tests/api-command.spec.ts --project=firefox + continue-on-error: true + + - name: Deploy report to GitHub Pages + if: always() + uses: peaceiris/actions-gh-pages@v3 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_branch: gh-pages + publish_dir: monocart-report diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..335bd46 --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ + +# Playwright +node_modules/ +/test-results/ +/playwright-report/ +/blob-report/ +/playwright/.cache/ +/playwright/.auth/ diff --git a/data.json b/data.json new file mode 100644 index 0000000..50060e3 --- /dev/null +++ b/data.json @@ -0,0 +1,277 @@ +[ + { + "commandType": "C", + "deviceName": "L", + "deviceType": "S", + "floorName": "L3", + "merchantName": "SAVY", + "payload": { "action": "On" }, + "roomName": "LV", + "towerNumber": "T2", + "unitNumber": "01" + }, + { + "commandType": "C", + "deviceName": "L", + "deviceType": "S", + "floorName": "L3", + "merchantName": "SAVY", + "payload": { "action": "On" }, + "roomName": "MS", + "towerNumber": "T2", + "unitNumber": "01" + }, + { + "commandType": "C", + "deviceName": "L", + "deviceType": "S", + "floorName": "L3", + "merchantName": "SAVY", + "payload": { "action": "On" }, + "roomName": "BT", + "towerNumber": "T2", + "unitNumber": "01" + }, + { + "commandType": "C", + "deviceName": "L", + "deviceType": "S", + "floorName": "L3", + "merchantName": "SAVY", + "payload": { "action": "On" }, + "roomName": "WIC", + "towerNumber": "T2", + "unitNumber": "01" + }, + { + "commandType": "C", + "deviceName": "BL", + "deviceType": "S", + "floorName": "L3", + "merchantName": "SAVY", + "payload": { "action": "Open" }, + "roomName": "LV", + "towerNumber": "T2", + "unitNumber": "01" + }, + { + "commandType": "C", + "deviceName": "BL", + "deviceType": "S", + "floorName": "L3", + "merchantName": "SAVY", + "payload": { "action": "Open" }, + "roomName": "MS", + "towerNumber": "T2", + "unitNumber": "01" + }, + { + "commandType": "C", + "deviceName": "BL", + "deviceType": "S", + "floorName": "L3", + "merchantName": "SAVY", + "payload": { "action": "Open" }, + "roomName": "JB", + "towerNumber": "T2", + "unitNumber": "01" + }, + { + "commandType": "C", + "deviceName": "AC", + "deviceType": "S", + "floorName": "L3", + "merchantName": "SAVY", + "payload": { "action": "On" }, + "roomName": "KN", + "towerNumber": "T2", + "unitNumber": "01" + }, + { + "commandType": "C", + "deviceName": "AC", + "deviceType": "A", + "floorName": "L3", + "merchantName": "SAVY", + "payload": { "action": "On" }, + "roomName": "KN", + "towerNumber": "T2", + "unitNumber": "01" + }, + { + "commandType": "C", + "deviceName": "AC", + "deviceType": "S", + "floorName": "L3", + "merchantName": "SAVY", + "payload": { "action": "On" }, + "roomName": "LV", + "towerNumber": "T2", + "unitNumber": "01" + }, + { + "commandType": "C", + "deviceName": "AC", + "deviceType": "A", + "floorName": "L3", + "merchantName": "SAVY", + "payload": { "action": "On" }, + "roomName": "LV", + "towerNumber": "T2", + "unitNumber": "01" + }, + { + "commandType": "C", + "deviceName": "AC", + "deviceType": "S", + "floorName": "L3", + "merchantName": "SAVY", + "payload": { "action": "On" }, + "roomName": "BR1", + "towerNumber": "T2", + "unitNumber": "01" + }, + { + "commandType": "C", + "deviceName": "AC", + "deviceType": "A", + "floorName": "L3", + "merchantName": "SAVY", + "payload": { "action": "On" }, + "roomName": "BR1", + "towerNumber": "T2", + "unitNumber": "01" + }, + { + "commandType": "C", + "deviceName": "AC", + "deviceType": "S", + "floorName": "L3", + "merchantName": "SAVY", + "payload": { "action": "On" }, + "roomName": "BR2", + "towerNumber": "T2", + "unitNumber": "01" + }, + { + "commandType": "C", + "deviceName": "AC", + "deviceType": "A", + "floorName": "L3", + "merchantName": "SAVY", + "payload": { "action": "On" }, + "roomName": "BR2", + "towerNumber": "T2", + "unitNumber": "01" + }, + { + "commandType": "C", + "deviceName": "AC", + "deviceType": "S", + "floorName": "L3", + "merchantName": "SAVY", + "payload": { "action": "On" }, + "roomName": "MS", + "towerNumber": "T2", + "unitNumber": "01" + }, + { + "commandType": "C", + "deviceName": "AC", + "deviceType": "A", + "floorName": "L3", + "merchantName": "SAVY", + "payload": { "action": "On" }, + "roomName": "MS", + "towerNumber": "T2", + "unitNumber": "01" + }, + { + "commandType": "C", + "deviceName": "AC", + "deviceType": "S", + "floorName": "L3", + "merchantName": "SAVY", + "payload": { "action": "On" }, + "roomName": "MR", + "towerNumber": "T2", + "unitNumber": "01" + }, + { + "commandType": "C", + "deviceName": "AC", + "deviceType": "A", + "floorName": "L3", + "merchantName": "SAVY", + "payload": { "action": "On" }, + "roomName": "MR", + "towerNumber": "T2", + "unitNumber": "01" + }, + { + "commandType": "C", + "deviceName": "FT1", + "deviceType": "A", + "floorName": "L3", + "merchantName": "SAVY", + "payload": { "action": "On" }, + "roomName": "LV", + "towerNumber": "T2", + "unitNumber": "01" + }, + { + "commandType": "C", + "deviceName": "FT2", + "deviceType": "S", + "floorName": "L3", + "merchantName": "SAVY", + "payload": { "action": "On" }, + "roomName": "LV", + "towerNumber": "T2", + "unitNumber": "01" + }, + { + "commandType": "C", + "deviceName": "PM25", + "deviceType": "S", + "floorName": "L3", + "merchantName": "SAVY", + "payload": { "action": "On" }, + "roomName": "LV", + "towerNumber": "T2", + "unitNumber": "01" + }, + { + "commandType": "C", + "deviceName": "DL", + "deviceType": "S", + "floorName": "L3", + "merchantName": "SAVY", + "payload": { "action": "On" }, + "roomName": "KN", + "towerNumber": "T2", + "unitNumber": "01" + }, + { + "commandType": "C", + "deviceName": "KC", + "deviceType": "S", + "floorName": "L3", + "merchantName": "SAVY", + "payload": { "action": "On" }, + "roomName": "KN", + "towerNumber": "T2", + "unitNumber": "01" + }, + { + "commandType": "C", + "deviceName": "ERV", + "deviceType": "S", + "floorName": "L3", + "merchantName": "SAVY", + "payload": { "action": "On" }, + "roomName": "LV", + "towerNumber": "T2", + "unitNumber": "01" + } +] \ No newline at end of file diff --git a/monocart-report.zip b/monocart-report.zip new file mode 100644 index 0000000..0e5ad19 Binary files /dev/null and b/monocart-report.zip differ diff --git a/monocart-report/index.html b/monocart-report/index.html new file mode 100644 index 0000000..c0b80bd --- /dev/null +++ b/monocart-report/index.html @@ -0,0 +1,52 @@ + + + + + + + + + + +
+ + + +
+ + + diff --git a/monocart-report/index.json b/monocart-report/index.json new file mode 100644 index 0000000..c00552e --- /dev/null +++ b/monocart-report/index.json @@ -0,0 +1 @@ +{"name":"Savy API Test Report","logo":null,"date":1768299461607,"dateH":"1/13/2026, 5:17:41 PM","duration":4227,"durationH":"4.2s","timezone":-7,"timezoneOffset":0,"locale":null,"cwd":"/Users/nuralan/skyrain/savy/playwright","outputFile":"/Users/nuralan/skyrain/savy/playwright/monocart-report/index.html","outputDir":"/Users/nuralan/skyrain/savy/playwright/monocart-report","metadata":{"actualWorkers":1},"system":{"cpu":{"color":"#117DBB","count":8,"model":"Apple M1","speed":2400},"mem":{"color":"#8B12AE","total":8589934592},"arch":"arm64","platform":"darwin","release":"25.1.0","type":"Darwin","version":"Darwin Kernel Version 25.1.0: Mon Oct 20 19:32:47 PDT 2025; root:xnu-12377.41.6~2/RELEASE_ARM64_T8103","uptime":2918085,"hostname":"192.168.99.105","pid":76784,"node":"22.18.0","v8":"12.4.254.21-node.27","timestampStart":1768299461607,"ticks":[{"cpu":{"percent":16.58},"mem":{"free":170377216},"timestamp":1768299462608},{"cpu":{"percent":19.8},"mem":{"free":124157952},"timestamp":1768299464610},{"cpu":{"percent":17.09},"mem":{"free":75808768},"timestamp":1768299465834}],"workers":1,"jobs":[{"caseId":"382fde42d0bb50d3ed52","parallelIndex":0,"workerIndex":0,"timestamp":1768299461974,"duration":258},{"caseId":"d6efc586d91d1299405d","parallelIndex":0,"workerIndex":0,"timestamp":1768299462235,"duration":62},{"caseId":"f82a46626b4babb900fe","parallelIndex":0,"workerIndex":0,"timestamp":1768299462298,"duration":72},{"caseId":"66d985cfdeadefb7ddc4","parallelIndex":0,"workerIndex":0,"timestamp":1768299462371,"duration":91},{"caseId":"e1495246d4d6dff02047","parallelIndex":0,"workerIndex":0,"timestamp":1768299462469,"duration":103},{"caseId":"684e826b3fe90595fac6","parallelIndex":0,"workerIndex":0,"timestamp":1768299462573,"duration":78},{"caseId":"8a17c0e22a9dee41c290","parallelIndex":0,"workerIndex":0,"timestamp":1768299462652,"duration":64},{"caseId":"d12f70250e85942d044a","parallelIndex":0,"workerIndex":0,"timestamp":1768299462717,"duration":87},{"caseId":"eaa3e641a5c80939475f","parallelIndex":0,"workerIndex":0,"timestamp":1768299462806,"duration":63},{"caseId":"b91cd39fa7982ed85bca","parallelIndex":0,"workerIndex":0,"timestamp":1768299462870,"duration":71},{"caseId":"f94beee4da9a3f4e28ab","parallelIndex":0,"workerIndex":0,"timestamp":1768299462941,"duration":65},{"caseId":"da911117638a18b78656","parallelIndex":0,"workerIndex":0,"timestamp":1768299463007,"duration":60},{"caseId":"cd91623c43621ada4ad3","parallelIndex":0,"workerIndex":0,"timestamp":1768299463068,"duration":59},{"caseId":"d721efdde91cf0029d36","parallelIndex":0,"workerIndex":0,"timestamp":1768299463128,"duration":54},{"caseId":"337b01fb6409677a6077","parallelIndex":0,"workerIndex":0,"timestamp":1768299463183,"duration":116},{"caseId":"46f31440ee5942e8295d","parallelIndex":0,"workerIndex":1,"timestamp":1768299463657,"duration":173},{"caseId":"19eb170dd569cd788304","parallelIndex":0,"workerIndex":1,"timestamp":1768299463833,"duration":90},{"caseId":"de038ae7a3e9522a5666","parallelIndex":0,"workerIndex":2,"timestamp":1768299464291,"duration":179},{"caseId":"50659f71d91abeb8af18","parallelIndex":0,"workerIndex":2,"timestamp":1768299464470,"duration":98},{"caseId":"c147dab815a14eb8d5d8","parallelIndex":0,"workerIndex":3,"timestamp":1768299464923,"duration":223},{"caseId":"4eef833e4bdce4410e38","parallelIndex":0,"workerIndex":3,"timestamp":1768299465150,"duration":96},{"caseId":"76215751f0f3967e7490","parallelIndex":0,"workerIndex":4,"timestamp":1768299465596,"duration":188}],"cwd":"/Users/nuralan/skyrain/savy/playwright","configFile":"playwright.config.ts","playwright":"1.57.0","monocart":"2.9.23","testDir":"tests","outputFile":"monocart-report/index.html","outputDir":"monocart-report","timestampEnd":1768299465834},"artifacts":[],"trends":[],"columns":[{"id":"caseType","name":"","width":36,"sortable":false,"align":"center","formatter":"iconCaseType","detailed":false},{"id":"title","name":"Title","searchable":true,"width":350,"maxWidth":1230,"detailed":false},{"id":"type","name":"Type","width":50,"sortable":false,"align":"center","formatter":"iconType","detailed":false},{"id":"duration","name":"Duration","align":"right","sortAsc":false,"formatter":"duration","detailed":false},{"id":"errors","name":"Errors","width":60,"align":"center","comparer":"errors","formatter":"errors","detailed":false},{"id":"logs","name":"Logs","width":60,"align":"center","comparer":"logs","formatter":"logs","detailed":false},{"id":"annotations","name":"Annotations","width":100,"markdown":true,"searchable":true,"comparer":"annotations","formatter":"annotations","detailed":false},{"id":"attachments","name":"Attachments","width":100,"align":"center","formatter":"attachments","detailed":false},{"id":"status","name":"Status","align":"center","detailed":false},{"id":"expectedStatus","name":"Expected","align":"center","detailed":false},{"id":"outcome","name":"Outcome","align":"center","width":85,"detailed":false},{"id":"retry","name":"Retry","align":"center","width":50,"detailed":false},{"id":"location","name":"Location","classMap":"mcr-location","width":200,"maxWidth":1981,"detailed":false}],"rows":[{"id":"acb943ac7d07d80a71fa","title":"firefox","type":"suite","suiteType":"project","caseNum":22,"subs":[{"id":"c949ea0e13cbd87ad9ad","title":"api-command.spec.ts","type":"suite","suiteType":"file","caseNum":22,"subs":[{"id":"dcba24ef684ee99bd49e","title":"Device Command & Status Tests","type":"suite","suiteType":"describe","caseNum":22,"subs":[{"id":"c53b5233ff376be0d746","title":"1. Command API Tests","type":"suite","suiteType":"describe","caseNum":11,"subs":[{"id":"382fde42d0bb50d3ed52","title":"POST Command: BL (S) - L29_E - LV","type":"case","caseType":"passed","ok":true,"outcome":"expected","expectedStatus":"passed","location":"tests/api-command.spec.ts:135:13","logs":["[Command] Request: {\n \"merchantName\": \"SAVY\",\n \"floorName\": \"L29\",\n \"unitNumber\": \"E\",\n \"deviceName\": \"BL\",\n \"roomName\": \"LV\",\n \"deviceType\": \"S\",\n \"commandType\": \"C\",\n \"towerNumber\": \"T2\",\n \"payload\": {\n \"action\": \"Open\"\n }\n}\n","[Command] Response Status: 200\n","[Command] Response Body: {\n \"status\": \"success\",\n \"message\": \"Command accepted\",\n \"receivedAt\": \"2026-01-13T10:17:42.289Z\"\n}\n","---\n"],"timestamps":[1768299461974,1768299462232],"duration":258,"tags":[],"timeout":30000,"retry":0,"status":"passed","stepNum":7,"stepFailed":0,"stepSubs":true,"subs":[{"id":"oh97k400pjfwdtjd8ne1","title":"Before Hooks","type":"step","stepType":"hook","startTime":"2026-01-13T10:17:41.979Z","annotations":[],"duration":12,"location":"","subs":[{"id":"xm9pdp5tupz0dwal8ncf","title":"Fixture \"request\"","type":"step","stepType":"fixture","startTime":"2026-01-13T10:17:41.987Z","annotations":[],"duration":4,"location":"","subs":[{"id":"7q0ghvuw458odcxsd1i1","title":"Create request context","type":"step","stepType":"pw:api","startTime":"2026-01-13T10:17:41.989Z","annotations":[],"duration":2,"location":""}]}]},{"id":"cslbfu1o82quial578i8","title":"POST \"/device/v1/command\"","type":"step","stepType":"pw:api","startTime":"2026-01-13T10:17:41.994Z","annotations":[],"duration":224,"location":"tests/api-command.spec.ts:140:42"},{"id":"kck4z2qgvc5ekqbmfm1i","title":"Expect \"toBe\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:42.221Z","annotations":[],"duration":1,"location":"tests/api-command.spec.ts:156:37"},{"id":"hlvpwg4fam7qlzc5cack","title":"After Hooks","type":"step","stepType":"hook","startTime":"2026-01-13T10:17:42.222Z","annotations":[],"duration":9,"location":"","subs":[{"id":"05nnl27pvd7g1k0q9py1","title":"Fixture \"request\"","type":"step","stepType":"fixture","startTime":"2026-01-13T10:17:42.223Z","annotations":[],"duration":2,"location":""}]}]},{"id":"d6efc586d91d1299405d","title":"POST Command: BL (S) - L29_E - MS","type":"case","caseType":"passed","ok":true,"outcome":"expected","expectedStatus":"passed","location":"tests/api-command.spec.ts:135:13","logs":["[Command] Request: {\n \"merchantName\": \"SAVY\",\n \"floorName\": \"L29\",\n \"unitNumber\": \"E\",\n \"deviceName\": \"BL\",\n \"roomName\": \"MS\",\n \"deviceType\": \"S\",\n \"commandType\": \"C\",\n \"towerNumber\": \"T2\",\n \"payload\": {\n \"action\": \"Open\"\n }\n}\n","[Command] Response Status: 200\n","[Command] Response Body: {\n \"status\": \"success\",\n \"message\": \"Command accepted\",\n \"receivedAt\": \"2026-01-13T10:17:42.383Z\"\n}\n","---\n"],"timestamps":[1768299462235,1768299462297],"duration":62,"tags":[],"timeout":30000,"retry":0,"status":"passed","stepNum":7,"stepFailed":0,"stepSubs":true,"subs":[{"id":"yx3svivxd2spc014nkm3","title":"Before Hooks","type":"step","stepType":"hook","startTime":"2026-01-13T10:17:42.235Z","annotations":[],"duration":8,"location":"","subs":[{"id":"6k87pg3spugfmfbq3cfl","title":"Fixture \"request\"","type":"step","stepType":"fixture","startTime":"2026-01-13T10:17:42.239Z","annotations":[],"duration":4,"location":"","subs":[{"id":"j5wgrhv74caxmaoe2wxb","title":"Create request context","type":"step","stepType":"pw:api","startTime":"2026-01-13T10:17:42.239Z","annotations":[],"duration":4,"location":""}]}]},{"id":"1fzmevmn29sl2b7ckksd","title":"POST \"/device/v1/command\"","type":"step","stepType":"pw:api","startTime":"2026-01-13T10:17:42.244Z","annotations":[],"duration":47,"location":"tests/api-command.spec.ts:140:42"},{"id":"k3562cr273m6i5b5wr17","title":"Expect \"toBe\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:42.292Z","annotations":[],"duration":0,"location":"tests/api-command.spec.ts:156:37"},{"id":"azyomv443pnd0qug5ox6","title":"After Hooks","type":"step","stepType":"hook","startTime":"2026-01-13T10:17:42.292Z","annotations":[],"duration":5,"location":"","subs":[{"id":"shejdgsdmnm8jx36n65d","title":"Fixture \"request\"","type":"step","stepType":"fixture","startTime":"2026-01-13T10:17:42.293Z","annotations":[],"duration":0,"location":""}]}]},{"id":"f82a46626b4babb900fe","title":"POST Command: AC (S) - L29_E - LV","type":"case","caseType":"passed","ok":true,"outcome":"expected","expectedStatus":"passed","location":"tests/api-command.spec.ts:135:13","logs":["[Command] Request: {\n \"merchantName\": \"SAVY\",\n \"floorName\": \"L29\",\n \"unitNumber\": \"E\",\n \"deviceName\": \"AC\",\n \"roomName\": \"LV\",\n \"deviceType\": \"S\",\n \"commandType\": \"C\",\n \"towerNumber\": \"T2\",\n \"payload\": {\n \"action\": \"On\"\n }\n}\n","[Command] Response Status: 200\n","[Command] Response Body: {\n \"status\": \"success\",\n \"message\": \"Command accepted\",\n \"receivedAt\": \"2026-01-13T10:17:42.459Z\"\n}\n","---\n"],"timestamps":[1768299462298,1768299462370],"duration":72,"tags":[],"timeout":30000,"retry":0,"status":"passed","stepNum":7,"stepFailed":0,"stepSubs":true,"subs":[{"id":"vj2wwl4iuxnzs6493j4v","title":"Before Hooks","type":"step","stepType":"hook","startTime":"2026-01-13T10:17:42.299Z","annotations":[],"duration":5,"location":"","subs":[{"id":"1avtuynmvultdu27citn","title":"Fixture \"request\"","type":"step","stepType":"fixture","startTime":"2026-01-13T10:17:42.303Z","annotations":[],"duration":1,"location":"","subs":[{"id":"yyaxwsf9ylwksy9u7k29","title":"Create request context","type":"step","stepType":"pw:api","startTime":"2026-01-13T10:17:42.303Z","annotations":[],"duration":1,"location":""}]}]},{"id":"xn8s9ed98lnvmfqphg81","title":"POST \"/device/v1/command\"","type":"step","stepType":"pw:api","startTime":"2026-01-13T10:17:42.305Z","annotations":[],"duration":61,"location":"tests/api-command.spec.ts:140:42"},{"id":"w88d4wzdtuic46azm3mv","title":"Expect \"toBe\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:42.367Z","annotations":[],"duration":0,"location":"tests/api-command.spec.ts:156:37"},{"id":"1q1c398ik38410kthhe5","title":"After Hooks","type":"step","stepType":"hook","startTime":"2026-01-13T10:17:42.367Z","annotations":[],"duration":3,"location":"","subs":[{"id":"405kwdmecd3h1f2me6ym","title":"Fixture \"request\"","type":"step","stepType":"fixture","startTime":"2026-01-13T10:17:42.367Z","annotations":[],"duration":1,"location":""}]}]},{"id":"66d985cfdeadefb7ddc4","title":"POST Command: AC (A) - L29_E - LV","type":"case","caseType":"passed","ok":true,"outcome":"expected","expectedStatus":"passed","location":"tests/api-command.spec.ts:135:13","logs":["[Command] Request: {\n \"merchantName\": \"SAVY\",\n \"floorName\": \"L29\",\n \"unitNumber\": \"E\",\n \"deviceName\": \"AC\",\n \"roomName\": \"LV\",\n \"deviceType\": \"A\",\n \"commandType\": \"C\",\n \"towerNumber\": \"T2\",\n \"payload\": {\n \"action\": \"On\"\n }\n}\n","[Command] Response Status: 200\n","[Command] Response Body: {\n \"status\": \"success\",\n \"message\": \"Command accepted\",\n \"receivedAt\": \"2026-01-13T10:17:42.530Z\"\n}\n","---\n"],"timestamps":[1768299462371,1768299462462],"duration":91,"tags":[],"timeout":30000,"retry":0,"status":"passed","stepNum":7,"stepFailed":0,"stepSubs":true,"subs":[{"id":"ujtspsmzkhtlzdchvbrg","title":"Before Hooks","type":"step","stepType":"hook","startTime":"2026-01-13T10:17:42.371Z","annotations":[],"duration":3,"location":"","subs":[{"id":"xeh8uzrrs64rnattv4rd","title":"Fixture \"request\"","type":"step","stepType":"fixture","startTime":"2026-01-13T10:17:42.373Z","annotations":[],"duration":1,"location":"","subs":[{"id":"eqfumvsv1xn9g7ck627p","title":"Create request context","type":"step","stepType":"pw:api","startTime":"2026-01-13T10:17:42.373Z","annotations":[],"duration":1,"location":""}]}]},{"id":"arhi03gg3bcitsqmue1j","title":"POST \"/device/v1/command\"","type":"step","stepType":"pw:api","startTime":"2026-01-13T10:17:42.374Z","annotations":[],"duration":81,"location":"tests/api-command.spec.ts:140:42"},{"id":"20n9sqss1u899jbhirxg","title":"Expect \"toBe\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:42.456Z","annotations":[],"duration":0,"location":"tests/api-command.spec.ts:156:37"},{"id":"11msrkezgkaoesta3l2u","title":"After Hooks","type":"step","stepType":"hook","startTime":"2026-01-13T10:17:42.456Z","annotations":[],"duration":6,"location":"","subs":[{"id":"c5inbreltozp1iql10hd","title":"Fixture \"request\"","type":"step","stepType":"fixture","startTime":"2026-01-13T10:17:42.457Z","annotations":[],"duration":1,"location":""}]}]},{"id":"e1495246d4d6dff02047","title":"POST Command: AC (S) - L29_E - BR1","type":"case","caseType":"passed","ok":true,"outcome":"expected","expectedStatus":"passed","location":"tests/api-command.spec.ts:135:13","logs":["[Command] Request: {\n \"merchantName\": \"SAVY\",\n \"floorName\": \"L29\",\n \"unitNumber\": \"E\",\n \"deviceName\": \"AC\",\n \"roomName\": \"BR1\",\n \"deviceType\": \"S\",\n \"commandType\": \"C\",\n \"towerNumber\": \"T2\",\n \"payload\": {\n \"action\": \"On\"\n }\n}\n","[Command] Response Status: 200\n","[Command] Response Body: {\n \"status\": \"success\",\n \"message\": \"Command accepted\",\n \"receivedAt\": \"2026-01-13T10:17:42.636Z\"\n}\n","---\n"],"timestamps":[1768299462469,1768299462572],"duration":103,"tags":[],"timeout":30000,"retry":0,"status":"passed","stepNum":7,"stepFailed":0,"stepSubs":true,"subs":[{"id":"qi21emh0yk9es4q63eha","title":"Before Hooks","type":"step","stepType":"hook","startTime":"2026-01-13T10:17:42.469Z","annotations":[],"duration":4,"location":"","subs":[{"id":"xw2bgcmix5kcvjdbik1n","title":"Fixture \"request\"","type":"step","stepType":"fixture","startTime":"2026-01-13T10:17:42.472Z","annotations":[],"duration":1,"location":"","subs":[{"id":"szm401boq5icjv994nc0","title":"Create request context","type":"step","stepType":"pw:api","startTime":"2026-01-13T10:17:42.472Z","annotations":[],"duration":0,"location":""}]}]},{"id":"sj7vfypswfuxr05iqt07","title":"POST \"/device/v1/command\"","type":"step","stepType":"pw:api","startTime":"2026-01-13T10:17:42.473Z","annotations":[],"duration":94,"location":"tests/api-command.spec.ts:140:42"},{"id":"rok1gtaiy0duv2a1oiul","title":"Expect \"toBe\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:42.568Z","annotations":[],"duration":1,"location":"tests/api-command.spec.ts:156:37"},{"id":"4fr668pb14lyrw9b3prs","title":"After Hooks","type":"step","stepType":"hook","startTime":"2026-01-13T10:17:42.569Z","annotations":[],"duration":3,"location":"","subs":[{"id":"eirco9zb4o7nn3fnat1h","title":"Fixture \"request\"","type":"step","stepType":"fixture","startTime":"2026-01-13T10:17:42.569Z","annotations":[],"duration":1,"location":""}]}]},{"id":"684e826b3fe90595fac6","title":"POST Command: AC (A) - L29_E - BR1","type":"case","caseType":"passed","ok":true,"outcome":"expected","expectedStatus":"passed","location":"tests/api-command.spec.ts:135:13","logs":["[Command] Request: {\n \"merchantName\": \"SAVY\",\n \"floorName\": \"L29\",\n \"unitNumber\": \"E\",\n \"deviceName\": \"AC\",\n \"roomName\": \"BR1\",\n \"deviceType\": \"A\",\n \"commandType\": \"C\",\n \"towerNumber\": \"T2\",\n \"payload\": {\n \"action\": \"On\"\n }\n}\n","[Command] Response Status: 200\n","[Command] Response Body: {\n \"status\": \"success\",\n \"message\": \"Command accepted\",\n \"receivedAt\": \"2026-01-13T10:17:42.718Z\"\n}\n","---\n"],"timestamps":[1768299462573,1768299462651],"duration":78,"tags":[],"timeout":30000,"retry":0,"status":"passed","stepNum":7,"stepFailed":0,"stepSubs":true,"subs":[{"id":"l7rupmbfom5t2t612uv7","title":"Before Hooks","type":"step","stepType":"hook","startTime":"2026-01-13T10:17:42.573Z","annotations":[],"duration":6,"location":"","subs":[{"id":"p258ynh4rtg1dnmlxdj8","title":"Fixture \"request\"","type":"step","stepType":"fixture","startTime":"2026-01-13T10:17:42.575Z","annotations":[],"duration":4,"location":"","subs":[{"id":"g0d56inc4uh9c6tf9fpy","title":"Create request context","type":"step","stepType":"pw:api","startTime":"2026-01-13T10:17:42.576Z","annotations":[],"duration":3,"location":""}]}]},{"id":"5fyi6gs6pc0pi6vcyzy7","title":"POST \"/device/v1/command\"","type":"step","stepType":"pw:api","startTime":"2026-01-13T10:17:42.579Z","annotations":[],"duration":66,"location":"tests/api-command.spec.ts:140:42"},{"id":"vtbwiix0jb1hjceahsdf","title":"Expect \"toBe\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:42.647Z","annotations":[],"duration":0,"location":"tests/api-command.spec.ts:156:37"},{"id":"u6i71gabydvvcj90w43r","title":"After Hooks","type":"step","stepType":"hook","startTime":"2026-01-13T10:17:42.647Z","annotations":[],"duration":4,"location":"","subs":[{"id":"8bjfc22d5ccjyp3fe86f","title":"Fixture \"request\"","type":"step","stepType":"fixture","startTime":"2026-01-13T10:17:42.647Z","annotations":[],"duration":1,"location":""}]}]},{"id":"8a17c0e22a9dee41c290","title":"POST Command: AC (S) - L29_E - BR2","type":"case","caseType":"passed","ok":true,"outcome":"expected","expectedStatus":"passed","location":"tests/api-command.spec.ts:135:13","logs":["[Command] Request: {\n \"merchantName\": \"SAVY\",\n \"floorName\": \"L29\",\n \"unitNumber\": \"E\",\n \"deviceName\": \"AC\",\n \"roomName\": \"BR2\",\n \"deviceType\": \"S\",\n \"commandType\": \"C\",\n \"towerNumber\": \"T2\",\n \"payload\": {\n \"action\": \"On\"\n }\n}\n","[Command] Response Status: 200\n","[Command] Response Body: {\n \"status\": \"success\",\n \"message\": \"Command accepted\",\n \"receivedAt\": \"2026-01-13T10:17:42.799Z\"\n}\n","---\n"],"timestamps":[1768299462652,1768299462716],"duration":64,"tags":[],"timeout":30000,"retry":0,"status":"passed","stepNum":7,"stepFailed":0,"stepSubs":true,"subs":[{"id":"ht2wr6b2gtp1r8zobyyj","title":"Before Hooks","type":"step","stepType":"hook","startTime":"2026-01-13T10:17:42.652Z","annotations":[],"duration":4,"location":"","subs":[{"id":"xedx0ktokjla146suvt0","title":"Fixture \"request\"","type":"step","stepType":"fixture","startTime":"2026-01-13T10:17:42.655Z","annotations":[],"duration":1,"location":"","subs":[{"id":"4nym9cxigp32094lr7qu","title":"Create request context","type":"step","stepType":"pw:api","startTime":"2026-01-13T10:17:42.655Z","annotations":[],"duration":0,"location":""}]}]},{"id":"qcjeue2b4t3nk1mywotn","title":"POST \"/device/v1/command\"","type":"step","stepType":"pw:api","startTime":"2026-01-13T10:17:42.656Z","annotations":[],"duration":53,"location":"tests/api-command.spec.ts:140:42"},{"id":"dl2urwmt4z6gzrpwwd3g","title":"Expect \"toBe\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:42.710Z","annotations":[],"duration":0,"location":"tests/api-command.spec.ts:156:37"},{"id":"c9ky9sdhdutycybyu1fa","title":"After Hooks","type":"step","stepType":"hook","startTime":"2026-01-13T10:17:42.710Z","annotations":[],"duration":6,"location":"","subs":[{"id":"tedrbk0l9vfzzgiu9q4r","title":"Fixture \"request\"","type":"step","stepType":"fixture","startTime":"2026-01-13T10:17:42.711Z","annotations":[],"duration":2,"location":""}]}]},{"id":"d12f70250e85942d044a","title":"POST Command: AC (A) - L29_E - BR2","type":"case","caseType":"passed","ok":true,"outcome":"expected","expectedStatus":"passed","location":"tests/api-command.spec.ts:135:13","logs":["[Command] Request: {\n \"merchantName\": \"SAVY\",\n \"floorName\": \"L29\",\n \"unitNumber\": \"E\",\n \"deviceName\": \"AC\",\n \"roomName\": \"BR2\",\n \"deviceType\": \"A\",\n \"commandType\": \"C\",\n \"towerNumber\": \"T2\",\n \"payload\": {\n \"action\": \"On\"\n }\n}\n","[Command] Response Status: 200\n","[Command] Response Body: {\n \"status\": \"success\",\n \"message\": \"Command accepted\",\n \"receivedAt\": \"2026-01-13T10:17:42.877Z\"\n}\n","---\n"],"timestamps":[1768299462717,1768299462804],"duration":87,"tags":[],"timeout":30000,"retry":0,"status":"passed","stepNum":7,"stepFailed":0,"stepSubs":true,"subs":[{"id":"1zvhff36p7puegebk04f","title":"Before Hooks","type":"step","stepType":"hook","startTime":"2026-01-13T10:17:42.717Z","annotations":[],"duration":3,"location":"","subs":[{"id":"c9jzonjdobf6vd0lrjxn","title":"Fixture \"request\"","type":"step","stepType":"fixture","startTime":"2026-01-13T10:17:42.719Z","annotations":[],"duration":1,"location":"","subs":[{"id":"nplaskwwm5p21oqi7p3f","title":"Create request context","type":"step","stepType":"pw:api","startTime":"2026-01-13T10:17:42.720Z","annotations":[],"duration":0,"location":""}]}]},{"id":"mvrr6swf3hmzgb2ir43h","title":"POST \"/device/v1/command\"","type":"step","stepType":"pw:api","startTime":"2026-01-13T10:17:42.721Z","annotations":[],"duration":77,"location":"tests/api-command.spec.ts:140:42"},{"id":"3mxjztyzka9nm5td29tf","title":"Expect \"toBe\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:42.799Z","annotations":[],"duration":0,"location":"tests/api-command.spec.ts:156:37"},{"id":"975e55umca575kz5l655","title":"After Hooks","type":"step","stepType":"hook","startTime":"2026-01-13T10:17:42.799Z","annotations":[],"duration":5,"location":"","subs":[{"id":"jl2dseih4ahx8tdwrm1x","title":"Fixture \"request\"","type":"step","stepType":"fixture","startTime":"2026-01-13T10:17:42.799Z","annotations":[],"duration":1,"location":""}]}]},{"id":"eaa3e641a5c80939475f","title":"POST Command: AC (S) - L29_E - MS","type":"case","caseType":"passed","ok":true,"outcome":"expected","expectedStatus":"passed","location":"tests/api-command.spec.ts:135:13","logs":["[Command] Request: {\n \"merchantName\": \"SAVY\",\n \"floorName\": \"L29\",\n \"unitNumber\": \"E\",\n \"deviceName\": \"AC\",\n \"roomName\": \"MS\",\n \"deviceType\": \"S\",\n \"commandType\": \"C\",\n \"towerNumber\": \"T2\",\n \"payload\": {\n \"action\": \"On\"\n }\n}\n","[Command] Response Status: 200\n","[Command] Response Body: {\n \"status\": \"success\",\n \"message\": \"Command accepted\",\n \"receivedAt\": \"2026-01-13T10:17:42.955Z\"\n}\n","---\n"],"timestamps":[1768299462806,1768299462869],"duration":63,"tags":[],"timeout":30000,"retry":0,"status":"passed","stepNum":7,"stepFailed":0,"stepSubs":true,"subs":[{"id":"mb6gcp3byxu0bxsv2vxw","title":"Before Hooks","type":"step","stepType":"hook","startTime":"2026-01-13T10:17:42.806Z","annotations":[],"duration":5,"location":"","subs":[{"id":"wyyv0rr3qq6omuvi80oc","title":"Fixture \"request\"","type":"step","stepType":"fixture","startTime":"2026-01-13T10:17:42.809Z","annotations":[],"duration":2,"location":"","subs":[{"id":"kcvsgfaqfs7c4iqfdxt6","title":"Create request context","type":"step","stepType":"pw:api","startTime":"2026-01-13T10:17:42.809Z","annotations":[],"duration":2,"location":""}]}]},{"id":"xa46ej902frc8r6e9m01","title":"POST \"/device/v1/command\"","type":"step","stepType":"pw:api","startTime":"2026-01-13T10:17:42.812Z","annotations":[],"duration":50,"location":"tests/api-command.spec.ts:140:42"},{"id":"p3h8y2nf1txekm9kk0ln","title":"Expect \"toBe\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:42.862Z","annotations":[],"duration":1,"location":"tests/api-command.spec.ts:156:37"},{"id":"94nhblqlroyjo05kru24","title":"After Hooks","type":"step","stepType":"hook","startTime":"2026-01-13T10:17:42.863Z","annotations":[],"duration":6,"location":"","subs":[{"id":"86vaf6s1pltpfgsixxrn","title":"Fixture \"request\"","type":"step","stepType":"fixture","startTime":"2026-01-13T10:17:42.863Z","annotations":[],"duration":1,"location":""}]}]},{"id":"b91cd39fa7982ed85bca","title":"POST Command: AC (A) - L29_E - MS","type":"case","caseType":"passed","ok":true,"outcome":"expected","expectedStatus":"passed","location":"tests/api-command.spec.ts:135:13","logs":["[Command] Request: {\n \"merchantName\": \"SAVY\",\n \"floorName\": \"L29\",\n \"unitNumber\": \"E\",\n \"deviceName\": \"AC\",\n \"roomName\": \"MS\",\n \"deviceType\": \"A\",\n \"commandType\": \"C\",\n \"towerNumber\": \"T2\",\n \"payload\": {\n \"action\": \"On\"\n }\n}\n","[Command] Response Status: 200\n","[Command] Response Body: {\n \"status\": \"success\",\n \"message\": \"Command accepted\",\n \"receivedAt\": \"2026-01-13T10:17:43.029Z\"\n}\n","---\n"],"timestamps":[1768299462870,1768299462941],"duration":71,"tags":[],"timeout":30000,"retry":0,"status":"passed","stepNum":7,"stepFailed":0,"stepSubs":true,"subs":[{"id":"l3vnk9pfxslstgwzzjcl","title":"Before Hooks","type":"step","stepType":"hook","startTime":"2026-01-13T10:17:42.870Z","annotations":[],"duration":4,"location":"","subs":[{"id":"mdjnt1nli3n5fp1ksont","title":"Fixture \"request\"","type":"step","stepType":"fixture","startTime":"2026-01-13T10:17:42.873Z","annotations":[],"duration":1,"location":"","subs":[{"id":"rs55uq6r3p78mhzmy1c4","title":"Create request context","type":"step","stepType":"pw:api","startTime":"2026-01-13T10:17:42.873Z","annotations":[],"duration":1,"location":""}]}]},{"id":"6ntdw4yqzkrhr7h7ywc4","title":"POST \"/device/v1/command\"","type":"step","stepType":"pw:api","startTime":"2026-01-13T10:17:42.875Z","annotations":[],"duration":60,"location":"tests/api-command.spec.ts:140:42"},{"id":"7gajlj37cii0gs1cw8pn","title":"Expect \"toBe\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:42.936Z","annotations":[],"duration":0,"location":"tests/api-command.spec.ts:156:37"},{"id":"0xfsdw5lecjk6x5bz0c5","title":"After Hooks","type":"step","stepType":"hook","startTime":"2026-01-13T10:17:42.936Z","annotations":[],"duration":4,"location":"","subs":[{"id":"ibp2q5mw5zrbf7734eg4","title":"Fixture \"request\"","type":"step","stepType":"fixture","startTime":"2026-01-13T10:17:42.936Z","annotations":[],"duration":1,"location":""}]}]},{"id":"f94beee4da9a3f4e28ab","title":"POST Command: DL (S) - L29_E - KN","type":"case","caseType":"passed","ok":true,"outcome":"expected","expectedStatus":"passed","location":"tests/api-command.spec.ts:135:13","logs":["[Command] Request: {\n \"merchantName\": \"SAVY\",\n \"floorName\": \"L29\",\n \"unitNumber\": \"E\",\n \"deviceName\": \"DL\",\n \"roomName\": \"KN\",\n \"deviceType\": \"S\",\n \"commandType\": \"C\",\n \"towerNumber\": \"T2\",\n \"payload\": {\n \"action\": \"Lock\"\n }\n}\n","[Command] Response Status: 200\n","[Command] Response Body: {\n \"status\": \"success\",\n \"message\": \"Command accepted\",\n \"receivedAt\": \"2026-01-13T10:17:43.082Z\"\n}\n","---\n"],"timestamps":[1768299462941,1768299463006],"duration":65,"tags":[],"timeout":30000,"retry":0,"status":"passed","stepNum":7,"stepFailed":0,"stepSubs":true,"subs":[{"id":"4nox1t8ix1fgp5c23uzp","title":"Before Hooks","type":"step","stepType":"hook","startTime":"2026-01-13T10:17:42.941Z","annotations":[],"duration":5,"location":"","subs":[{"id":"abi1wj24xk3oy8078az4","title":"Fixture \"request\"","type":"step","stepType":"fixture","startTime":"2026-01-13T10:17:42.945Z","annotations":[],"duration":1,"location":"","subs":[{"id":"0w18d7sg5g043m1711il","title":"Create request context","type":"step","stepType":"pw:api","startTime":"2026-01-13T10:17:42.945Z","annotations":[],"duration":1,"location":""}]}]},{"id":"umhw6i1hl1qie4dpbd3e","title":"POST \"/device/v1/command\"","type":"step","stepType":"pw:api","startTime":"2026-01-13T10:17:42.947Z","annotations":[],"duration":53,"location":"tests/api-command.spec.ts:140:42"},{"id":"vgkiq45zhff76wsise6b","title":"Expect \"toBe\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:43.001Z","annotations":[],"duration":0,"location":"tests/api-command.spec.ts:156:37"},{"id":"cs9vbu2er8mltwdbz07g","title":"After Hooks","type":"step","stepType":"hook","startTime":"2026-01-13T10:17:43.001Z","annotations":[],"duration":5,"location":"","subs":[{"id":"mkp4ii5jm7prcn4yqnoy","title":"Fixture \"request\"","type":"step","stepType":"fixture","startTime":"2026-01-13T10:17:43.002Z","annotations":[],"duration":0,"location":""}]}]}],"location":"tests/api-command.spec.ts:116:8"},{"id":"677ea73e859b8834154f","title":"2. Status Check API Tests","type":"suite","suiteType":"describe","caseNum":11,"subs":[{"id":"da911117638a18b78656","title":"GET Status: BL (S) - L29_E - LV","type":"case","caseType":"passed","ok":true,"outcome":"expected","expectedStatus":"passed","location":"tests/api-command.spec.ts:169:13","logs":["[Status Check] Request URL: https://api-dev.vegacloud.id/device/v1/status?merchantName=SAVY&floorName=L29&unitNumber=E&deviceName=BL&roomName=LV&deviceType=S&commandType=S&towerNumber=T2\n","[Status Check] Response Status: 200\n","[Status Check] Response Body: {\n \"status\": \"success\",\n \"message\": \"command accepted\",\n \"data\": {\n \"floorName\": \"L29\",\n \"unitNumber\": \"E\",\n \"deviceName\": \"BL\",\n \"roomName\": \"LV\",\n \"deviceType\": \"S\",\n \"code\": \"S\",\n \"towerNumber\": \"T2\",\n \"payload\": \"Open\"\n }\n}\n","---\n"],"timestamps":[1768299463007,1768299463067],"duration":60,"tags":[],"timeout":30000,"retry":0,"status":"passed","stepNum":16,"stepFailed":0,"stepSubs":true,"subs":[{"id":"pqy33y87pztwuswonexi","title":"Before Hooks","type":"step","stepType":"hook","startTime":"2026-01-13T10:17:43.007Z","annotations":[],"duration":4,"location":"","subs":[{"id":"uy99efgnkz4b6zj12mb5","title":"Fixture \"request\"","type":"step","stepType":"fixture","startTime":"2026-01-13T10:17:43.010Z","annotations":[],"duration":1,"location":"","subs":[{"id":"7w88aw6f9yn4jjyvaji2","title":"Create request context","type":"step","stepType":"pw:api","startTime":"2026-01-13T10:17:43.010Z","annotations":[],"duration":0,"location":""}]}]},{"id":"qv7xjwinregkfeqtsw5p","title":"GET \"/device/v1/status?merchantName=SAVY&floorName=L29&unitNumber=E&deviceName=BL&roomName=LV&deviceType=S&commandType=S&towerNumber=T2\"","type":"step","stepType":"pw:api","startTime":"2026-01-13T10:17:43.012Z","annotations":[],"duration":44,"location":"tests/api-command.spec.ts:187:42"},{"id":"ibriacmi4uez95ssvux0","title":"Expect \"toBe\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:43.057Z","annotations":[],"duration":0,"location":"tests/api-command.spec.ts:201:37"},{"id":"blq74ldw6tr1lv0zsf6e","title":"Expect \"not toBeNull\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:43.057Z","annotations":[],"duration":1,"location":"tests/api-command.spec.ts:202:41"},{"id":"cnzt374e0qh4kr9ih5s4","title":"Expect \"toBe\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:43.058Z","annotations":[],"duration":0,"location":"tests/api-command.spec.ts:205:47"},{"id":"hfur3d0nzqinr7yhpozw","title":"Expect \"toBe\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:43.058Z","annotations":[],"duration":0,"location":"tests/api-command.spec.ts:206:48"},{"id":"68afeplwik04sd9twwk4","title":"Expect \"toBe\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:43.059Z","annotations":[],"duration":0,"location":"tests/api-command.spec.ts:207:48"},{"id":"tnubstx0indfjrd8npnj","title":"Expect \"toBe\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:43.059Z","annotations":[],"duration":0,"location":"tests/api-command.spec.ts:208:46"},{"id":"o4tnwyvo3dcc6584e9jj","title":"Expect \"toBe\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:43.060Z","annotations":[],"duration":0,"location":"tests/api-command.spec.ts:209:48"},{"id":"j1s1pubwxprfrvghemju","title":"Expect \"toBe\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:43.060Z","annotations":[],"duration":0,"location":"tests/api-command.spec.ts:210:42"},{"id":"0sm2h8f2a8oo4a80l5fi","title":"Expect \"toBe\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:43.060Z","annotations":[],"duration":0,"location":"tests/api-command.spec.ts:211:49"},{"id":"fximk9jm2dkik5a4cr6u","title":"Expect \"toHaveProperty\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:43.061Z","annotations":[],"duration":0,"location":"tests/api-command.spec.ts:212:37"},{"id":"fh30diq2tgwtnnx1hkmo","title":"After Hooks","type":"step","stepType":"hook","startTime":"2026-01-13T10:17:43.061Z","annotations":[],"duration":6,"location":"","subs":[{"id":"k1q4k4tw76r7dk8h3eem","title":"Fixture \"request\"","type":"step","stepType":"fixture","startTime":"2026-01-13T10:17:43.062Z","annotations":[],"duration":1,"location":""}]}]},{"id":"cd91623c43621ada4ad3","title":"GET Status: BL (S) - L29_E - MS","type":"case","caseType":"passed","ok":true,"outcome":"expected","expectedStatus":"passed","location":"tests/api-command.spec.ts:169:13","logs":["[Status Check] Request URL: https://api-dev.vegacloud.id/device/v1/status?merchantName=SAVY&floorName=L29&unitNumber=E&deviceName=BL&roomName=MS&deviceType=S&commandType=S&towerNumber=T2\n","[Status Check] Response Status: 200\n","[Status Check] Response Body: {\n \"status\": \"success\",\n \"message\": \"command accepted\",\n \"data\": {\n \"floorName\": \"L29\",\n \"unitNumber\": \"E\",\n \"deviceName\": \"BL\",\n \"roomName\": \"MS\",\n \"deviceType\": \"S\",\n \"code\": \"S\",\n \"towerNumber\": \"T2\",\n \"payload\": \"Open\"\n }\n}\n","---\n"],"timestamps":[1768299463068,1768299463127],"duration":59,"tags":[],"timeout":30000,"retry":0,"status":"passed","stepNum":16,"stepFailed":0,"stepSubs":true,"subs":[{"id":"9etaoi0kiqp96id8nlfe","title":"Before Hooks","type":"step","stepType":"hook","startTime":"2026-01-13T10:17:43.068Z","annotations":[],"duration":4,"location":"","subs":[{"id":"ham4dcuknsc1zf4elz4l","title":"Fixture \"request\"","type":"step","stepType":"fixture","startTime":"2026-01-13T10:17:43.071Z","annotations":[],"duration":1,"location":"","subs":[{"id":"rnnadm4yve23nhw1cubi","title":"Create request context","type":"step","stepType":"pw:api","startTime":"2026-01-13T10:17:43.072Z","annotations":[],"duration":0,"location":""}]}]},{"id":"e86j4qndvxs08m4cksia","title":"GET \"/device/v1/status?merchantName=SAVY&floorName=L29&unitNumber=E&deviceName=BL&roomName=MS&deviceType=S&commandType=S&towerNumber=T2\"","type":"step","stepType":"pw:api","startTime":"2026-01-13T10:17:43.073Z","annotations":[],"duration":43,"location":"tests/api-command.spec.ts:187:42"},{"id":"3nqlttjq39z3zp8xrsdj","title":"Expect \"toBe\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:43.117Z","annotations":[],"duration":0,"location":"tests/api-command.spec.ts:201:37"},{"id":"7l8x8fvc1aisbf26bjmj","title":"Expect \"not toBeNull\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:43.118Z","annotations":[],"duration":0,"location":"tests/api-command.spec.ts:202:41"},{"id":"j2doi96gqf8sx3f9jchk","title":"Expect \"toBe\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:43.118Z","annotations":[],"duration":1,"location":"tests/api-command.spec.ts:205:47"},{"id":"sb6ax9zqqlqusiivimo4","title":"Expect \"toBe\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:43.119Z","annotations":[],"duration":0,"location":"tests/api-command.spec.ts:206:48"},{"id":"8h740fi5v01yhgeuo3h9","title":"Expect \"toBe\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:43.119Z","annotations":[],"duration":0,"location":"tests/api-command.spec.ts:207:48"},{"id":"tl0dffozcaasqx81d1ma","title":"Expect \"toBe\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:43.120Z","annotations":[],"duration":0,"location":"tests/api-command.spec.ts:208:46"},{"id":"4av2in1qzytheun74dd4","title":"Expect \"toBe\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:43.120Z","annotations":[],"duration":0,"location":"tests/api-command.spec.ts:209:48"},{"id":"wyn6yf6v6we1fyv007st","title":"Expect \"toBe\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:43.121Z","annotations":[],"duration":0,"location":"tests/api-command.spec.ts:210:42"},{"id":"pw65iazcl73ca6spazhk","title":"Expect \"toBe\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:43.121Z","annotations":[],"duration":0,"location":"tests/api-command.spec.ts:211:49"},{"id":"v1zm0uc8h75nsosrg983","title":"Expect \"toHaveProperty\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:43.122Z","annotations":[],"duration":0,"location":"tests/api-command.spec.ts:212:37"},{"id":"3f6jtihs9v1y6yhbxzc8","title":"After Hooks","type":"step","stepType":"hook","startTime":"2026-01-13T10:17:43.122Z","annotations":[],"duration":5,"location":"","subs":[{"id":"xsl009g46q5cku1v7ou8","title":"Fixture \"request\"","type":"step","stepType":"fixture","startTime":"2026-01-13T10:17:43.122Z","annotations":[],"duration":1,"location":""}]}]},{"id":"d721efdde91cf0029d36","title":"GET Status: AC (S) - L29_E - LV","type":"case","caseType":"passed","ok":true,"outcome":"expected","expectedStatus":"passed","location":"tests/api-command.spec.ts:169:13","logs":["[Status Check] Request URL: https://api-dev.vegacloud.id/device/v1/status?merchantName=SAVY&floorName=L29&unitNumber=E&deviceName=AC&roomName=LV&deviceType=S&commandType=S&towerNumber=T2\n","[Status Check] Response Status: 200\n","[Status Check] Response Body: {\n \"status\": \"success\",\n \"message\": \"command accepted\",\n \"data\": {\n \"floorName\": \"L29\",\n \"unitNumber\": \"E\",\n \"deviceName\": \"AC\",\n \"roomName\": \"LV\",\n \"deviceType\": \"S\",\n \"code\": \"S\",\n \"towerNumber\": \"T2\",\n \"payload\": \"On\"\n }\n}\n","---\n"],"timestamps":[1768299463128,1768299463182],"duration":54,"tags":[],"timeout":30000,"retry":0,"status":"passed","stepNum":16,"stepFailed":0,"stepSubs":true,"subs":[{"id":"l4c1m2saylo1k8lqc1x3","title":"Before Hooks","type":"step","stepType":"hook","startTime":"2026-01-13T10:17:43.129Z","annotations":[],"duration":4,"location":"","subs":[{"id":"vypgtzsw9ccc2pf5fzk3","title":"Fixture \"request\"","type":"step","stepType":"fixture","startTime":"2026-01-13T10:17:43.132Z","annotations":[],"duration":1,"location":"","subs":[{"id":"w0xhiluc49h86ixcbw9b","title":"Create request context","type":"step","stepType":"pw:api","startTime":"2026-01-13T10:17:43.132Z","annotations":[],"duration":1,"location":""}]}]},{"id":"f5q1927ygm3959mo02go","title":"GET \"/device/v1/status?merchantName=SAVY&floorName=L29&unitNumber=E&deviceName=AC&roomName=LV&deviceType=S&commandType=S&towerNumber=T2\"","type":"step","stepType":"pw:api","startTime":"2026-01-13T10:17:43.134Z","annotations":[],"duration":38,"location":"tests/api-command.spec.ts:187:42"},{"id":"8rp56fcrpu6d7425e8ij","title":"Expect \"toBe\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:43.172Z","annotations":[],"duration":0,"location":"tests/api-command.spec.ts:201:37"},{"id":"r2vwz1vfqqwtydq3z8ta","title":"Expect \"not toBeNull\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:43.173Z","annotations":[],"duration":0,"location":"tests/api-command.spec.ts:202:41"},{"id":"f6unsd88sbrddsg3xdh3","title":"Expect \"toBe\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:43.173Z","annotations":[],"duration":0,"location":"tests/api-command.spec.ts:205:47"},{"id":"8ps36ao3eglns7dfoip9","title":"Expect \"toBe\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:43.174Z","annotations":[],"duration":0,"location":"tests/api-command.spec.ts:206:48"},{"id":"p6zl1b425tlt2drdjrs6","title":"Expect \"toBe\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:43.174Z","annotations":[],"duration":0,"location":"tests/api-command.spec.ts:207:48"},{"id":"7wsrl9i6cdum266vvzed","title":"Expect \"toBe\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:43.175Z","annotations":[],"duration":0,"location":"tests/api-command.spec.ts:208:46"},{"id":"8a9oq5eam4wr3gh930a9","title":"Expect \"toBe\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:43.175Z","annotations":[],"duration":0,"location":"tests/api-command.spec.ts:209:48"},{"id":"kwq2rhdft0gmfszcdolr","title":"Expect \"toBe\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:43.175Z","annotations":[],"duration":0,"location":"tests/api-command.spec.ts:210:42"},{"id":"tgn9q6elgzvobbsnd28o","title":"Expect \"toBe\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:43.176Z","annotations":[],"duration":0,"location":"tests/api-command.spec.ts:211:49"},{"id":"p5rkl9i0y7cf20ovlb9d","title":"Expect \"toHaveProperty\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:43.176Z","annotations":[],"duration":0,"location":"tests/api-command.spec.ts:212:37"},{"id":"kkmfbasko9wblh1qfgkf","title":"After Hooks","type":"step","stepType":"hook","startTime":"2026-01-13T10:17:43.177Z","annotations":[],"duration":5,"location":"","subs":[{"id":"73kms3ffndijkrekn19f","title":"Fixture \"request\"","type":"step","stepType":"fixture","startTime":"2026-01-13T10:17:43.177Z","annotations":[],"duration":1,"location":""}]}]},{"id":"337b01fb6409677a6077","title":"GET Status: AC (A) - L29_E - LV","type":"case","caseType":"failed","ok":false,"outcome":"unexpected","expectedStatus":"passed","location":"tests/api-command.spec.ts:169:13","logs":["[Status Check] Request URL: https://api-dev.vegacloud.id/device/v1/status?merchantName=SAVY&floorName=L29&unitNumber=E&deviceName=AC&roomName=LV&deviceType=A&commandType=S&towerNumber=T2\n","[Status Check] Response Status: 404\n","[Status Check] Response Body: {\n \"status\": \"not_found\",\n \"message\": \"Device not found\",\n \"data\": null\n}\n","---\n"],"timestamps":[1768299463183,1768299463299],"duration":116,"tags":[],"timeout":30000,"retry":0,"status":"failed","stepNum":8,"stepFailed":1,"stepSubs":true,"subs":[{"id":"vkm42yeu8t9bkab9same","title":"Before Hooks","type":"step","stepType":"hook","startTime":"2026-01-13T10:17:43.183Z","annotations":[],"duration":5,"location":"","subs":[{"id":"m8vq42oyt4thchzylbe5","title":"Fixture \"request\"","type":"step","stepType":"fixture","startTime":"2026-01-13T10:17:43.186Z","annotations":[],"duration":2,"location":"","subs":[{"id":"itpcufq0k63yixwjo680","title":"Create request context","type":"step","stepType":"pw:api","startTime":"2026-01-13T10:17:43.187Z","annotations":[],"duration":1,"location":""}]}]},{"id":"xh05s3ij5ryxm5tenkdk","title":"GET \"/device/v1/status?merchantName=SAVY&floorName=L29&unitNumber=E&deviceName=AC&roomName=LV&deviceType=A&commandType=S&towerNumber=T2\"","type":"step","stepType":"pw:api","startTime":"2026-01-13T10:17:43.189Z","annotations":[],"duration":94,"location":"tests/api-command.spec.ts:187:42"},{"id":"zcx5drdu0e5mpc00awlq","title":"Expect \"toBe\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:43.285Z","annotations":[],"duration":3,"location":"tests/api-command.spec.ts:201:37","errors":["Error: \u001b[2mexpect(\u001b[22m\u001b[31mreceived\u001b[39m\u001b[2m).\u001b[22mtoBe\u001b[2m(\u001b[22m\u001b[32mexpected\u001b[39m\u001b[2m) // Object.is equality\u001b[22m\n\nExpected: \u001b[32m200\u001b[39m\nReceived: \u001b[31m404\u001b[39m\n\n\u001b[0m \u001b[90m 199 |\u001b[39m console\u001b[33m.\u001b[39mlog(\u001b[32m'---'\u001b[39m)\n \u001b[90m 200 |\u001b[39m\n\u001b[31m\u001b[1m>\u001b[22m\u001b[39m\u001b[90m 201 |\u001b[39m expect(response\u001b[33m.\u001b[39mstatus())\u001b[33m.\u001b[39mtoBe(\u001b[35m200\u001b[39m)\n \u001b[90m |\u001b[39m \u001b[31m\u001b[1m^\u001b[22m\u001b[39m\u001b[0m\n\n at /Users/nuralan/skyrain/savy/playwright/tests/api-command.spec.ts:201:37"],"errorNum":1},{"id":"as974chgiw3j3wm7lzuk","title":"After Hooks","type":"step","stepType":"hook","startTime":"2026-01-13T10:17:43.289Z","annotations":[],"duration":6,"location":"","subs":[{"id":"0e8utv70wg5kqwf99urx","title":"Fixture \"request\"","type":"step","stepType":"fixture","startTime":"2026-01-13T10:17:43.289Z","annotations":[],"duration":1,"location":""}]},{"id":"r3uck6mdknzsfk4jafs1","title":"Worker Cleanup","type":"step","stepType":"hook","startTime":"2026-01-13T10:17:43.295Z","annotations":[],"duration":1,"location":""}],"errorNum":1,"errorId":"zcx5drdu0e5mpc00awlq"},{"id":"46f31440ee5942e8295d","title":"GET Status: AC (S) - L29_E - BR1","type":"case","caseType":"passed","ok":true,"outcome":"expected","expectedStatus":"passed","location":"tests/api-command.spec.ts:169:13","logs":["[Status Check] Request URL: https://api-dev.vegacloud.id/device/v1/status?merchantName=SAVY&floorName=L29&unitNumber=E&deviceName=AC&roomName=BR1&deviceType=S&commandType=S&towerNumber=T2\n","[Status Check] Response Status: 200\n","[Status Check] Response Body: {\n \"status\": \"success\",\n \"message\": \"command accepted\",\n \"data\": {\n \"floorName\": \"L29\",\n \"unitNumber\": \"E\",\n \"deviceName\": \"AC\",\n \"roomName\": \"BR1\",\n \"deviceType\": \"S\",\n \"code\": \"S\",\n \"towerNumber\": \"T2\",\n \"payload\": \"On\"\n }\n}\n","---\n"],"timestamps":[1768299463657,1768299463830],"duration":173,"tags":[],"timeout":30000,"retry":0,"status":"passed","stepNum":16,"stepFailed":0,"stepSubs":true,"subs":[{"id":"z75yw7mrmiuyv4z6iz5t","title":"Before Hooks","type":"step","stepType":"hook","startTime":"2026-01-13T10:17:43.658Z","annotations":[],"duration":8,"location":"","subs":[{"id":"menb06zrjmcghvuzk3ep","title":"Fixture \"request\"","type":"step","stepType":"fixture","startTime":"2026-01-13T10:17:43.663Z","annotations":[],"duration":3,"location":"","subs":[{"id":"ka8w9mutykxy09r36k84","title":"Create request context","type":"step","stepType":"pw:api","startTime":"2026-01-13T10:17:43.664Z","annotations":[],"duration":2,"location":""}]}]},{"id":"dc56ox13h7tgxc0mzoka","title":"GET \"/device/v1/status?merchantName=SAVY&floorName=L29&unitNumber=E&deviceName=AC&roomName=BR1&deviceType=S&commandType=S&towerNumber=T2\"","type":"step","stepType":"pw:api","startTime":"2026-01-13T10:17:43.667Z","annotations":[],"duration":147,"location":"tests/api-command.spec.ts:187:42"},{"id":"howi1re0va2ff2imclp5","title":"Expect \"toBe\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:43.817Z","annotations":[],"duration":0,"location":"tests/api-command.spec.ts:201:37"},{"id":"oktuccjns61ddkmobipu","title":"Expect \"not toBeNull\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:43.818Z","annotations":[],"duration":0,"location":"tests/api-command.spec.ts:202:41"},{"id":"50inl905h2mv6z8wzwmk","title":"Expect \"toBe\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:43.818Z","annotations":[],"duration":0,"location":"tests/api-command.spec.ts:205:47"},{"id":"t2i0d13akrpry5h0gxp2","title":"Expect \"toBe\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:43.819Z","annotations":[],"duration":0,"location":"tests/api-command.spec.ts:206:48"},{"id":"cac9jqcaeex2g1iznfhb","title":"Expect \"toBe\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:43.819Z","annotations":[],"duration":0,"location":"tests/api-command.spec.ts:207:48"},{"id":"pfq639x5ivx6yjs2q9rh","title":"Expect \"toBe\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:43.820Z","annotations":[],"duration":0,"location":"tests/api-command.spec.ts:208:46"},{"id":"td05kjot54hyo9xhgm1p","title":"Expect \"toBe\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:43.821Z","annotations":[],"duration":0,"location":"tests/api-command.spec.ts:209:48"},{"id":"85ecosdip7fzxc40fvlh","title":"Expect \"toBe\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:43.821Z","annotations":[],"duration":0,"location":"tests/api-command.spec.ts:210:42"},{"id":"5icjlkmx9avw8iwxwbbr","title":"Expect \"toBe\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:43.822Z","annotations":[],"duration":0,"location":"tests/api-command.spec.ts:211:49"},{"id":"ix82tagna2u0cvd1vngq","title":"Expect \"toHaveProperty\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:43.823Z","annotations":[],"duration":0,"location":"tests/api-command.spec.ts:212:37"},{"id":"taipe1z5g1cr0t7hpy8m","title":"After Hooks","type":"step","stepType":"hook","startTime":"2026-01-13T10:17:43.823Z","annotations":[],"duration":7,"location":"","subs":[{"id":"08xm4dtjhi01lz0bl1me","title":"Fixture \"request\"","type":"step","stepType":"fixture","startTime":"2026-01-13T10:17:43.824Z","annotations":[],"duration":1,"location":""}]}]},{"id":"19eb170dd569cd788304","title":"GET Status: AC (A) - L29_E - BR1","type":"case","caseType":"failed","ok":false,"outcome":"unexpected","expectedStatus":"passed","location":"tests/api-command.spec.ts:169:13","logs":["[Status Check] Request URL: https://api-dev.vegacloud.id/device/v1/status?merchantName=SAVY&floorName=L29&unitNumber=E&deviceName=AC&roomName=BR1&deviceType=A&commandType=S&towerNumber=T2\n","[Status Check] Response Status: 404\n","[Status Check] Response Body: {\n \"status\": \"not_found\",\n \"message\": \"Device not found\",\n \"data\": null\n}\n","---\n"],"timestamps":[1768299463833,1768299463923],"duration":90,"tags":[],"timeout":30000,"retry":0,"status":"failed","stepNum":8,"stepFailed":1,"stepSubs":true,"subs":[{"id":"fkdqav1r5o5ikdhgjjkc","title":"Before Hooks","type":"step","stepType":"hook","startTime":"2026-01-13T10:17:43.833Z","annotations":[],"duration":5,"location":"","subs":[{"id":"qjyb5jcyx6xtxzjl1u1z","title":"Fixture \"request\"","type":"step","stepType":"fixture","startTime":"2026-01-13T10:17:43.837Z","annotations":[],"duration":1,"location":"","subs":[{"id":"9faewjp9m9q5zvfuxty2","title":"Create request context","type":"step","stepType":"pw:api","startTime":"2026-01-13T10:17:43.837Z","annotations":[],"duration":0,"location":""}]}]},{"id":"yobpalloa1ikppl2786u","title":"GET \"/device/v1/status?merchantName=SAVY&floorName=L29&unitNumber=E&deviceName=AC&roomName=BR1&deviceType=A&commandType=S&towerNumber=T2\"","type":"step","stepType":"pw:api","startTime":"2026-01-13T10:17:43.838Z","annotations":[],"duration":75,"location":"tests/api-command.spec.ts:187:42"},{"id":"ypoadhber2olop1scczn","title":"Expect \"toBe\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:43.914Z","annotations":[],"duration":2,"location":"tests/api-command.spec.ts:201:37","errors":["Error: \u001b[2mexpect(\u001b[22m\u001b[31mreceived\u001b[39m\u001b[2m).\u001b[22mtoBe\u001b[2m(\u001b[22m\u001b[32mexpected\u001b[39m\u001b[2m) // Object.is equality\u001b[22m\n\nExpected: \u001b[32m200\u001b[39m\nReceived: \u001b[31m404\u001b[39m\n\n\u001b[0m \u001b[90m 199 |\u001b[39m console\u001b[33m.\u001b[39mlog(\u001b[32m'---'\u001b[39m)\n \u001b[90m 200 |\u001b[39m\n\u001b[31m\u001b[1m>\u001b[22m\u001b[39m\u001b[90m 201 |\u001b[39m expect(response\u001b[33m.\u001b[39mstatus())\u001b[33m.\u001b[39mtoBe(\u001b[35m200\u001b[39m)\n \u001b[90m |\u001b[39m \u001b[31m\u001b[1m^\u001b[22m\u001b[39m\u001b[0m\n\n at /Users/nuralan/skyrain/savy/playwright/tests/api-command.spec.ts:201:37"],"errorNum":1},{"id":"cyp3d31ok44m4yd9f630","title":"After Hooks","type":"step","stepType":"hook","startTime":"2026-01-13T10:17:43.916Z","annotations":[],"duration":5,"location":"","subs":[{"id":"5la6x0f6b1j6a97bt2f1","title":"Fixture \"request\"","type":"step","stepType":"fixture","startTime":"2026-01-13T10:17:43.916Z","annotations":[],"duration":1,"location":""}]},{"id":"sua9olmnguw34l4m1w8t","title":"Worker Cleanup","type":"step","stepType":"hook","startTime":"2026-01-13T10:17:43.921Z","annotations":[],"duration":1,"location":""}],"errorNum":1,"errorId":"ypoadhber2olop1scczn"},{"id":"de038ae7a3e9522a5666","title":"GET Status: AC (S) - L29_E - BR2","type":"case","caseType":"passed","ok":true,"outcome":"expected","expectedStatus":"passed","location":"tests/api-command.spec.ts:169:13","logs":["[Status Check] Request URL: https://api-dev.vegacloud.id/device/v1/status?merchantName=SAVY&floorName=L29&unitNumber=E&deviceName=AC&roomName=BR2&deviceType=S&commandType=S&towerNumber=T2\n","[Status Check] Response Status: 200\n","[Status Check] Response Body: {\n \"status\": \"success\",\n \"message\": \"command accepted\",\n \"data\": {\n \"floorName\": \"L29\",\n \"unitNumber\": \"E\",\n \"deviceName\": \"AC\",\n \"roomName\": \"BR2\",\n \"deviceType\": \"S\",\n \"code\": \"S\",\n \"towerNumber\": \"T2\",\n \"payload\": \"On\"\n }\n}\n","---\n"],"timestamps":[1768299464291,1768299464470],"duration":179,"tags":[],"timeout":30000,"retry":0,"status":"passed","stepNum":16,"stepFailed":0,"stepSubs":true,"subs":[{"id":"vgo69cu93dvpdwr94mpt","title":"Before Hooks","type":"step","stepType":"hook","startTime":"2026-01-13T10:17:44.292Z","annotations":[],"duration":8,"location":"","subs":[{"id":"fcj9x02l8q7op4d6udxs","title":"Fixture \"request\"","type":"step","stepType":"fixture","startTime":"2026-01-13T10:17:44.297Z","annotations":[],"duration":3,"location":"","subs":[{"id":"lwzdmo805z0t70xwyu3c","title":"Create request context","type":"step","stepType":"pw:api","startTime":"2026-01-13T10:17:44.298Z","annotations":[],"duration":2,"location":""}]}]},{"id":"g5lks4osin0w3h8whuj1","title":"GET \"/device/v1/status?merchantName=SAVY&floorName=L29&unitNumber=E&deviceName=AC&roomName=BR2&deviceType=S&commandType=S&towerNumber=T2\"","type":"step","stepType":"pw:api","startTime":"2026-01-13T10:17:44.302Z","annotations":[],"duration":150,"location":"tests/api-command.spec.ts:187:42"},{"id":"vj8ofdythfwz2pbwivm7","title":"Expect \"toBe\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:44.455Z","annotations":[],"duration":0,"location":"tests/api-command.spec.ts:201:37"},{"id":"1pdhsnb33ao0w9937t20","title":"Expect \"not toBeNull\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:44.456Z","annotations":[],"duration":0,"location":"tests/api-command.spec.ts:202:41"},{"id":"hewg2so0q94q1isv2qq7","title":"Expect \"toBe\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:44.457Z","annotations":[],"duration":0,"location":"tests/api-command.spec.ts:205:47"},{"id":"lhwcgcgvbp9bnoa5jwjg","title":"Expect \"toBe\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:44.457Z","annotations":[],"duration":0,"location":"tests/api-command.spec.ts:206:48"},{"id":"znr0nk8uev3nooe9nngv","title":"Expect \"toBe\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:44.458Z","annotations":[],"duration":0,"location":"tests/api-command.spec.ts:207:48"},{"id":"q3m5vaey9xdkoen9n77y","title":"Expect \"toBe\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:44.459Z","annotations":[],"duration":0,"location":"tests/api-command.spec.ts:208:46"},{"id":"xamlfd9tpxo36kni3m6f","title":"Expect \"toBe\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:44.459Z","annotations":[],"duration":1,"location":"tests/api-command.spec.ts:209:48"},{"id":"02ab73idy8f40hdni1xx","title":"Expect \"toBe\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:44.460Z","annotations":[],"duration":0,"location":"tests/api-command.spec.ts:210:42"},{"id":"phyb7v71aqx2fyu8di18","title":"Expect \"toBe\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:44.464Z","annotations":[],"duration":0,"location":"tests/api-command.spec.ts:211:49"},{"id":"q65gnxcnfrcebl2q69ei","title":"Expect \"toHaveProperty\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:44.464Z","annotations":[],"duration":1,"location":"tests/api-command.spec.ts:212:37"},{"id":"mpexcgu3gwqmwyln6mgb","title":"After Hooks","type":"step","stepType":"hook","startTime":"2026-01-13T10:17:44.465Z","annotations":[],"duration":4,"location":"","subs":[{"id":"mwr8eeeb49cj8w4wfngr","title":"Fixture \"request\"","type":"step","stepType":"fixture","startTime":"2026-01-13T10:17:44.465Z","annotations":[],"duration":1,"location":""}]}]},{"id":"50659f71d91abeb8af18","title":"GET Status: AC (A) - L29_E - BR2","type":"case","caseType":"failed","ok":false,"outcome":"unexpected","expectedStatus":"passed","location":"tests/api-command.spec.ts:169:13","logs":["[Status Check] Request URL: https://api-dev.vegacloud.id/device/v1/status?merchantName=SAVY&floorName=L29&unitNumber=E&deviceName=AC&roomName=BR2&deviceType=A&commandType=S&towerNumber=T2\n","[Status Check] Response Status: 404\n","[Status Check] Response Body: {\n \"status\": \"not_found\",\n \"message\": \"Device not found\",\n \"data\": null\n}\n","---\n"],"timestamps":[1768299464470,1768299464568],"duration":98,"tags":[],"timeout":30000,"retry":0,"status":"failed","stepNum":8,"stepFailed":1,"stepSubs":true,"subs":[{"id":"hylva49vdhf1a2ud8l1r","title":"Before Hooks","type":"step","stepType":"hook","startTime":"2026-01-13T10:17:44.470Z","annotations":[],"duration":9,"location":"","subs":[{"id":"h6uy08wuw5bxtbxefpex","title":"Fixture \"request\"","type":"step","stepType":"fixture","startTime":"2026-01-13T10:17:44.474Z","annotations":[],"duration":5,"location":"","subs":[{"id":"urtogz8h2s0su9i1mgey","title":"Create request context","type":"step","stepType":"pw:api","startTime":"2026-01-13T10:17:44.475Z","annotations":[],"duration":4,"location":""}]}]},{"id":"k5jovqepu2a6g774u15q","title":"GET \"/device/v1/status?merchantName=SAVY&floorName=L29&unitNumber=E&deviceName=AC&roomName=BR2&deviceType=A&commandType=S&towerNumber=T2\"","type":"step","stepType":"pw:api","startTime":"2026-01-13T10:17:44.480Z","annotations":[],"duration":81,"location":"tests/api-command.spec.ts:187:42"},{"id":"qprv1rm42xjhpj6i5hg1","title":"Expect \"toBe\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:44.562Z","annotations":[],"duration":1,"location":"tests/api-command.spec.ts:201:37","errors":["Error: \u001b[2mexpect(\u001b[22m\u001b[31mreceived\u001b[39m\u001b[2m).\u001b[22mtoBe\u001b[2m(\u001b[22m\u001b[32mexpected\u001b[39m\u001b[2m) // Object.is equality\u001b[22m\n\nExpected: \u001b[32m200\u001b[39m\nReceived: \u001b[31m404\u001b[39m\n\n\u001b[0m \u001b[90m 199 |\u001b[39m console\u001b[33m.\u001b[39mlog(\u001b[32m'---'\u001b[39m)\n \u001b[90m 200 |\u001b[39m\n\u001b[31m\u001b[1m>\u001b[22m\u001b[39m\u001b[90m 201 |\u001b[39m expect(response\u001b[33m.\u001b[39mstatus())\u001b[33m.\u001b[39mtoBe(\u001b[35m200\u001b[39m)\n \u001b[90m |\u001b[39m \u001b[31m\u001b[1m^\u001b[22m\u001b[39m\u001b[0m\n\n at /Users/nuralan/skyrain/savy/playwright/tests/api-command.spec.ts:201:37"],"errorNum":1},{"id":"c5v6oyptygcu9rl8v6pu","title":"After Hooks","type":"step","stepType":"hook","startTime":"2026-01-13T10:17:44.563Z","annotations":[],"duration":3,"location":"","subs":[{"id":"re5s4vk8trnlq9rau78c","title":"Fixture \"request\"","type":"step","stepType":"fixture","startTime":"2026-01-13T10:17:44.563Z","annotations":[],"duration":1,"location":""}]},{"id":"fon7xwklsragbtjwn5p3","title":"Worker Cleanup","type":"step","stepType":"hook","startTime":"2026-01-13T10:17:44.566Z","annotations":[],"duration":1,"location":""}],"errorNum":1,"errorId":"qprv1rm42xjhpj6i5hg1"},{"id":"c147dab815a14eb8d5d8","title":"GET Status: AC (S) - L29_E - MS","type":"case","caseType":"passed","ok":true,"outcome":"expected","expectedStatus":"passed","location":"tests/api-command.spec.ts:169:13","logs":["[Status Check] Request URL: https://api-dev.vegacloud.id/device/v1/status?merchantName=SAVY&floorName=L29&unitNumber=E&deviceName=AC&roomName=MS&deviceType=S&commandType=S&towerNumber=T2\n","[Status Check] Response Status: 200\n","[Status Check] Response Body: {\n \"status\": \"success\",\n \"message\": \"command accepted\",\n \"data\": {\n \"floorName\": \"L29\",\n \"unitNumber\": \"E\",\n \"deviceName\": \"AC\",\n \"roomName\": \"MS\",\n \"deviceType\": \"S\",\n \"code\": \"S\",\n \"towerNumber\": \"T2\",\n \"payload\": \"On\"\n }\n}\n","---\n"],"timestamps":[1768299464923,1768299465146],"duration":223,"tags":[],"timeout":30000,"retry":0,"status":"passed","stepNum":16,"stepFailed":0,"stepSubs":true,"subs":[{"id":"6c7tfjmeol2abip2mre9","title":"Before Hooks","type":"step","stepType":"hook","startTime":"2026-01-13T10:17:44.924Z","annotations":[],"duration":8,"location":"","subs":[{"id":"mh7rjhyxi2i3idi2rkgv","title":"Fixture \"request\"","type":"step","stepType":"fixture","startTime":"2026-01-13T10:17:44.929Z","annotations":[],"duration":3,"location":"","subs":[{"id":"uzp19ik3xfuz0lej94ue","title":"Create request context","type":"step","stepType":"pw:api","startTime":"2026-01-13T10:17:44.930Z","annotations":[],"duration":2,"location":""}]}]},{"id":"znevxb8165nlqosh5qak","title":"GET \"/device/v1/status?merchantName=SAVY&floorName=L29&unitNumber=E&deviceName=AC&roomName=MS&deviceType=S&commandType=S&towerNumber=T2\"","type":"step","stepType":"pw:api","startTime":"2026-01-13T10:17:44.934Z","annotations":[],"duration":192,"location":"tests/api-command.spec.ts:187:42"},{"id":"9mj4yo185ibp7ftwlpg5","title":"Expect \"toBe\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:45.129Z","annotations":[],"duration":1,"location":"tests/api-command.spec.ts:201:37"},{"id":"29sneak7kwvny4gf8lrb","title":"Expect \"not toBeNull\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:45.131Z","annotations":[],"duration":0,"location":"tests/api-command.spec.ts:202:41"},{"id":"4vjagakmnovjtf9sg2mq","title":"Expect \"toBe\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:45.132Z","annotations":[],"duration":0,"location":"tests/api-command.spec.ts:205:47"},{"id":"kkv9ujupag2nq3i5deoz","title":"Expect \"toBe\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:45.132Z","annotations":[],"duration":1,"location":"tests/api-command.spec.ts:206:48"},{"id":"7x8vzie464wb73v9tk5t","title":"Expect \"toBe\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:45.133Z","annotations":[],"duration":0,"location":"tests/api-command.spec.ts:207:48"},{"id":"sia0gnvil90eiyy9kdwk","title":"Expect \"toBe\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:45.134Z","annotations":[],"duration":0,"location":"tests/api-command.spec.ts:208:46"},{"id":"0x4xtesh7cv7n7n5ywx9","title":"Expect \"toBe\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:45.135Z","annotations":[],"duration":0,"location":"tests/api-command.spec.ts:209:48"},{"id":"yvy2c62d8fhhxbkcrnpp","title":"Expect \"toBe\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:45.135Z","annotations":[],"duration":0,"location":"tests/api-command.spec.ts:210:42"},{"id":"o0vddz7flibmtex9mqga","title":"Expect \"toBe\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:45.136Z","annotations":[],"duration":0,"location":"tests/api-command.spec.ts:211:49"},{"id":"6d17k021wnasf9ssckj2","title":"Expect \"toHaveProperty\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:45.137Z","annotations":[],"duration":0,"location":"tests/api-command.spec.ts:212:37"},{"id":"hcgh9hp4khmtqla0eb7k","title":"After Hooks","type":"step","stepType":"hook","startTime":"2026-01-13T10:17:45.138Z","annotations":[],"duration":8,"location":"","subs":[{"id":"uwo3h0f27by69g0fgwyl","title":"Fixture \"request\"","type":"step","stepType":"fixture","startTime":"2026-01-13T10:17:45.138Z","annotations":[],"duration":2,"location":""}]}]},{"id":"4eef833e4bdce4410e38","title":"GET Status: AC (A) - L29_E - MS","type":"case","caseType":"failed","ok":false,"outcome":"unexpected","expectedStatus":"passed","location":"tests/api-command.spec.ts:169:13","logs":["[Status Check] Request URL: https://api-dev.vegacloud.id/device/v1/status?merchantName=SAVY&floorName=L29&unitNumber=E&deviceName=AC&roomName=MS&deviceType=A&commandType=S&towerNumber=T2\n","[Status Check] Response Status: 404\n","[Status Check] Response Body: {\n \"status\": \"not_found\",\n \"message\": \"Device not found\",\n \"data\": null\n}\n","---\n"],"timestamps":[1768299465150,1768299465246],"duration":96,"tags":[],"timeout":30000,"retry":0,"status":"failed","stepNum":8,"stepFailed":1,"stepSubs":true,"subs":[{"id":"3ukpjb3ls8m4ivmv3uny","title":"Before Hooks","type":"step","stepType":"hook","startTime":"2026-01-13T10:17:45.150Z","annotations":[],"duration":6,"location":"","subs":[{"id":"1c4v50eiv4ig6b9m9fmg","title":"Fixture \"request\"","type":"step","stepType":"fixture","startTime":"2026-01-13T10:17:45.154Z","annotations":[],"duration":1,"location":"","subs":[{"id":"hryyk5oitz99kznn37pt","title":"Create request context","type":"step","stepType":"pw:api","startTime":"2026-01-13T10:17:45.155Z","annotations":[],"duration":0,"location":""}]}]},{"id":"kiebh89t0a266smir927","title":"GET \"/device/v1/status?merchantName=SAVY&floorName=L29&unitNumber=E&deviceName=AC&roomName=MS&deviceType=A&commandType=S&towerNumber=T2\"","type":"step","stepType":"pw:api","startTime":"2026-01-13T10:17:45.156Z","annotations":[],"duration":83,"location":"tests/api-command.spec.ts:187:42"},{"id":"20h7r63rcdejmxso7pzm","title":"Expect \"toBe\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:45.240Z","annotations":[],"duration":1,"location":"tests/api-command.spec.ts:201:37","errors":["Error: \u001b[2mexpect(\u001b[22m\u001b[31mreceived\u001b[39m\u001b[2m).\u001b[22mtoBe\u001b[2m(\u001b[22m\u001b[32mexpected\u001b[39m\u001b[2m) // Object.is equality\u001b[22m\n\nExpected: \u001b[32m200\u001b[39m\nReceived: \u001b[31m404\u001b[39m\n\n\u001b[0m \u001b[90m 199 |\u001b[39m console\u001b[33m.\u001b[39mlog(\u001b[32m'---'\u001b[39m)\n \u001b[90m 200 |\u001b[39m\n\u001b[31m\u001b[1m>\u001b[22m\u001b[39m\u001b[90m 201 |\u001b[39m expect(response\u001b[33m.\u001b[39mstatus())\u001b[33m.\u001b[39mtoBe(\u001b[35m200\u001b[39m)\n \u001b[90m |\u001b[39m \u001b[31m\u001b[1m^\u001b[22m\u001b[39m\u001b[0m\n\n at /Users/nuralan/skyrain/savy/playwright/tests/api-command.spec.ts:201:37"],"errorNum":1},{"id":"0saahuwqir3fvkm5haru","title":"After Hooks","type":"step","stepType":"hook","startTime":"2026-01-13T10:17:45.241Z","annotations":[],"duration":4,"location":"","subs":[{"id":"hyto7ws9myatw52mb34p","title":"Fixture \"request\"","type":"step","stepType":"fixture","startTime":"2026-01-13T10:17:45.241Z","annotations":[],"duration":1,"location":""}]},{"id":"hxzpbdbpykforq0szj5v","title":"Worker Cleanup","type":"step","stepType":"hook","startTime":"2026-01-13T10:17:45.245Z","annotations":[],"duration":0,"location":""}],"errorNum":1,"errorId":"20h7r63rcdejmxso7pzm"},{"id":"76215751f0f3967e7490","title":"GET Status: DL (S) - L29_E - KN","type":"case","caseType":"passed","ok":true,"outcome":"expected","expectedStatus":"passed","location":"tests/api-command.spec.ts:169:13","logs":["[Status Check] Request URL: https://api-dev.vegacloud.id/device/v1/status?merchantName=SAVY&floorName=L29&unitNumber=E&deviceName=DL&roomName=KN&deviceType=S&commandType=S&towerNumber=T2\n","[Status Check] Response Status: 200\n","[Status Check] Response Body: {\n \"status\": \"success\",\n \"message\": \"command accepted\",\n \"data\": {\n \"floorName\": \"L29\",\n \"unitNumber\": \"E\",\n \"deviceName\": \"DL\",\n \"roomName\": \"KN\",\n \"deviceType\": \"S\",\n \"code\": \"S\",\n \"towerNumber\": \"T2\",\n \"payload\": \"Lock\"\n }\n}\n","---\n"],"timestamps":[1768299465596,1768299465784],"duration":188,"tags":[],"timeout":30000,"retry":0,"status":"passed","stepNum":16,"stepFailed":0,"stepSubs":true,"subs":[{"id":"2lv2trkx0lrgt4dpkx35","title":"Before Hooks","type":"step","stepType":"hook","startTime":"2026-01-13T10:17:45.597Z","annotations":[],"duration":8,"location":"","subs":[{"id":"81zobj7xtv4f7uij1vnq","title":"Fixture \"request\"","type":"step","stepType":"fixture","startTime":"2026-01-13T10:17:45.602Z","annotations":[],"duration":3,"location":"","subs":[{"id":"d6e7is7715hpj56w6igt","title":"Create request context","type":"step","stepType":"pw:api","startTime":"2026-01-13T10:17:45.603Z","annotations":[],"duration":1,"location":""}]}]},{"id":"7tlvii9x5r0cdjbua45s","title":"GET \"/device/v1/status?merchantName=SAVY&floorName=L29&unitNumber=E&deviceName=DL&roomName=KN&deviceType=S&commandType=S&towerNumber=T2\"","type":"step","stepType":"pw:api","startTime":"2026-01-13T10:17:45.606Z","annotations":[],"duration":159,"location":"tests/api-command.spec.ts:187:42"},{"id":"vvtasfdogf5xdtxynd9x","title":"Expect \"toBe\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:45.769Z","annotations":[],"duration":0,"location":"tests/api-command.spec.ts:201:37"},{"id":"tfexbc9obgn0ln4iemr9","title":"Expect \"not toBeNull\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:45.770Z","annotations":[],"duration":0,"location":"tests/api-command.spec.ts:202:41"},{"id":"p6f736i6qpatcfofb6ia","title":"Expect \"toBe\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:45.770Z","annotations":[],"duration":0,"location":"tests/api-command.spec.ts:205:47"},{"id":"joe5pbi4ogvavqy5tow7","title":"Expect \"toBe\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:45.771Z","annotations":[],"duration":0,"location":"tests/api-command.spec.ts:206:48"},{"id":"o7f9uth437sie9xzdxae","title":"Expect \"toBe\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:45.771Z","annotations":[],"duration":0,"location":"tests/api-command.spec.ts:207:48"},{"id":"bosv5a4duhjfs1mpp5b7","title":"Expect \"toBe\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:45.772Z","annotations":[],"duration":0,"location":"tests/api-command.spec.ts:208:46"},{"id":"ol31idg0y06d4pah1l39","title":"Expect \"toBe\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:45.773Z","annotations":[],"duration":0,"location":"tests/api-command.spec.ts:209:48"},{"id":"ppotkl6o36u32tohya22","title":"Expect \"toBe\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:45.773Z","annotations":[],"duration":0,"location":"tests/api-command.spec.ts:210:42"},{"id":"voyv9tguuogflke0ps8i","title":"Expect \"toBe\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:45.776Z","annotations":[],"duration":0,"location":"tests/api-command.spec.ts:211:49"},{"id":"6vd72cxnoul9ex9xwqf0","title":"Expect \"toHaveProperty\"","type":"step","stepType":"expect","startTime":"2026-01-13T10:17:45.777Z","annotations":[],"duration":0,"location":"tests/api-command.spec.ts:212:37"},{"id":"d6buaybjqvzj5mitz0ws","title":"After Hooks","type":"step","stepType":"hook","startTime":"2026-01-13T10:17:45.778Z","annotations":[],"duration":6,"location":"","subs":[{"id":"gt9zgtk3c2hhb9u0h9dh","title":"Fixture \"request\"","type":"step","stepType":"fixture","startTime":"2026-01-13T10:17:45.778Z","annotations":[],"duration":2,"location":""}]}]}],"location":"tests/api-command.spec.ts:162:8"}],"location":"tests/api-command.spec.ts:107:6"}],"location":"tests/api-command.spec.ts:0:0"}]}],"formatters":{},"suiteTypes":["project","file","describe","shard"],"caseTypes":["failed","flaky","skipped","passed"],"traceViewerUrl":"https://trace.playwright.dev/?trace={traceUrl}","mermaid":null,"groupOptions":null,"tags":{},"summary":{"tests":{"name":"Tests","value":22,"nav":true,"id":"tests"},"failed":{"name":"Failed","value":4,"color":"#d00","nav":true,"id":"failed","percent":"18.2%"},"flaky":{"name":"Flaky","value":0,"color":"orange","nav":true,"id":"flaky","percent":"0.0%"},"skipped":{"name":"Skipped","value":0,"color":"gray","nav":true,"id":"skipped","percent":"0.0%"},"passed":{"name":"Passed","value":18,"color":"green","nav":true,"id":"passed","percent":"81.8%"},"steps":{"name":"Steps","value":221,"id":"steps"},"suites":{"name":"Suites","value":2,"id":"suites"},"projects":{"name":"Projects","description":"Suite type is project","value":1,"id":"projects"},"files":{"name":"Files","description":"Suite type is file","value":1,"id":"files"},"describes":{"name":"Describes","description":"Suite type is describe","value":3,"id":"describes"},"shards":{"name":"Shards","description":"Suite type is shard (only in shading mode)","value":0,"id":"shards"},"errors":{"name":"Errors","icon":"error","value":4,"id":"errors"},"retries":{"name":"Retries","icon":"retry","value":0,"id":"retries"},"logs":{"name":"Logs","icon":"log","value":88,"id":"logs"},"attachments":{"name":"Attachments","icon":"attachment","value":0,"id":"attachments"},"artifacts":{"name":"Artifacts","value":0}},"pieChart":{"ns":"mcr-pie","width":360,"height":150,"margin":10,"svg":"Failed418.2%Flaky00.0%Skipped00.0%Passed1881.8%Total22"},"htmlPath":"monocart-report/index.html"} diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..a01e48d --- /dev/null +++ b/package-lock.json @@ -0,0 +1,861 @@ +{ + "name": "playwright", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "playwright", + "version": "1.0.0", + "license": "ISC", + "devDependencies": { + "@playwright/test": "^1.57.0", + "@types/node": "^25.0.3", + "monocart-reporter": "^2.9.23" + } + }, + "node_modules/@playwright/test": { + "version": "1.57.0", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.57.0.tgz", + "integrity": "sha512-6TyEnHgd6SArQO8UO2OMTxshln3QMWBtPGrOCgs3wVEmQmwyuNtB10IZMfmYDE0riwNR1cu4q+pPcxMVtaG3TA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "playwright": "1.57.0" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@types/node": { + "version": "25.0.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-25.0.3.tgz", + "integrity": "sha512-W609buLVRVmeW693xKfzHeIV6nJGGz98uCPfeXI1ELMLXVeKYZ9m15fAMSaUPBHYLGFsVRcMmSCksQOrZV9BYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~7.16.0" + } + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/accepts/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/accepts/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-loose": { + "version": "8.5.2", + "resolved": "https://registry.npmjs.org/acorn-loose/-/acorn-loose-8.5.2.tgz", + "integrity": "sha512-PPvV6g8UGMGgjrMu+n/f9E/tCSkNQ2Y97eFvuVdJfG11+xdIeDcLyNdC8SHcrHbRqkfwLASdplyR6B6sKM1U4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.15.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", + "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/commander": { + "version": "14.0.2", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.2.tgz", + "integrity": "sha512-TywoWNNRbhoD0BXs1P3ZEScW8W5iKrnbithIl0YH+uCmBd0QpPOA8yc82DS3BIE5Ma6FnBVUsJ7wVUDz4dvOWQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "node_modules/console-grid": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/console-grid/-/console-grid-2.2.3.tgz", + "integrity": "sha512-+mecFacaFxGl+1G31IsCx41taUXuW2FxX+4xIE0TIPhgML+Jb9JFcBWGhhWerd1/vhScubdmHqTwOhB0KCUUAg==", + "dev": true, + "license": "MIT" + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookies": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/cookies/-/cookies-0.9.1.tgz", + "integrity": "sha512-TG2hpqe4ELx54QER/S3HQ9SRVnQnGBtKUz5bLQWtYAQ+o6GpgMs6sYUvaiJjVxb+UXwhRhAEP3m7LbsIZ77Hmw==", + "dev": true, + "license": "MIT", + "dependencies": { + "depd": "~2.0.0", + "keygrip": "~1.1.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/deep-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", + "integrity": "sha512-bHtC0iYvWhyaTzvV3CZgPeZQqCOBGyGsVV7v4eevpdkLHfiSrXUdBG+qAuSz4RI70sszvjQ1QSZ98An1yNwpSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "dev": true, + "license": "MIT" + }, + "node_modules/eight-colors": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/eight-colors/-/eight-colors-1.3.1.tgz", + "integrity": "sha512-7nXPYDeKh6DgJDR/mpt2G7N/hCNSGwwoPVmoI3+4TEwOb07VFN1WMPG0DFf6nMEjrkgdj8Og7l7IaEEk3VE6Zg==", + "dev": true, + "license": "MIT" + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "dev": true, + "license": "MIT" + }, + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "dev": true, + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true, + "license": "MIT" + }, + "node_modules/http-assert": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/http-assert/-/http-assert-1.5.0.tgz", + "integrity": "sha512-uPpH7OKX4H25hBmU6G1jWNaqJGpTXxey+YOUizJUAgu0AjLUeC8D73hTrhvDS5D+GJN1DN1+hhc/eF/wpxtp0w==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-equal": "~1.0.1", + "http-errors": "~1.8.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-assert/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/http-assert/node_modules/http-errors": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", + "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/http-assert/node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-reports": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz", + "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/keygrip": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/keygrip/-/keygrip-1.1.0.tgz", + "integrity": "sha512-iYSchDJ+liQ8iwbSI2QqsQOvqv58eJCEanyJPJi+Khyu8smkcKSFUCbPwzFcL7YVtZ6eONjqRX/38caJ7QjRAQ==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "dev": true, + "license": "MIT", + "dependencies": { + "tsscmp": "1.0.6" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/koa": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/koa/-/koa-3.1.1.tgz", + "integrity": "sha512-KDDuvpfqSK0ZKEO2gCPedNjl5wYpfj+HNiuVRlbhd1A88S3M0ySkdf2V/EJ4NWt5dwh5PXCdcenrKK2IQJAxsg==", + "dev": true, + "license": "MIT", + "dependencies": { + "accepts": "^1.3.8", + "content-disposition": "~0.5.4", + "content-type": "^1.0.5", + "cookies": "~0.9.1", + "delegates": "^1.0.0", + "destroy": "^1.2.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "fresh": "~0.5.2", + "http-assert": "^1.5.0", + "http-errors": "^2.0.0", + "koa-compose": "^4.1.0", + "mime-types": "^3.0.1", + "on-finished": "^2.4.1", + "parseurl": "^1.3.3", + "statuses": "^2.0.1", + "type-is": "^2.0.1", + "vary": "^1.1.2" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/koa-compose": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/koa-compose/-/koa-compose-4.1.0.tgz", + "integrity": "sha512-8ODW8TrDuMYvXRwra/Kh7/rJo9BtOfPc6qO8eAfC80CnCvSjSl0bkRM24X6/XBBEyj0v1nRUQ1LyOy3dbqOWXw==", + "dev": true, + "license": "MIT" + }, + "node_modules/koa-static-resolver": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/koa-static-resolver/-/koa-static-resolver-1.0.6.tgz", + "integrity": "sha512-ZX5RshSzH8nFn05/vUNQzqw32nEigsPa67AVUr6ZuQxuGdnCcTLcdgr4C81+YbJjpgqKHfacMBd7NmJIbj7fXw==", + "dev": true, + "license": "MIT" + }, + "node_modules/lz-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/lz-utils/-/lz-utils-2.1.0.tgz", + "integrity": "sha512-CMkfimAypidTtWjNDxY8a1bc1mJdyEh04V2FfEQ5Zh8Nx4v7k850EYa+dOWGn9hKG5xOyHP5MkuduAZCTHRvJw==", + "dev": true, + "license": "MIT" + }, + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/media-typer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", + "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz", + "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-db": "^1.54.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/monocart-coverage-reports": { + "version": "2.12.9", + "resolved": "https://registry.npmjs.org/monocart-coverage-reports/-/monocart-coverage-reports-2.12.9.tgz", + "integrity": "sha512-vtFqbC3Egl4nVa1FSIrQvMPO6HZtb9lo+3IW7/crdvrLNW2IH8lUsxaK0TsKNmMO2mhFWwqQywLV2CZelqPgwA==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.15.0", + "acorn-loose": "^8.5.2", + "acorn-walk": "^8.3.4", + "commander": "^14.0.0", + "console-grid": "^2.2.3", + "eight-colors": "^1.3.1", + "foreground-child": "^3.3.1", + "istanbul-lib-coverage": "^3.2.2", + "istanbul-lib-report": "^3.0.1", + "istanbul-reports": "^3.2.0", + "lz-utils": "^2.1.0", + "monocart-locator": "^1.0.2" + }, + "bin": { + "mcr": "lib/cli.js" + } + }, + "node_modules/monocart-locator": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/monocart-locator/-/monocart-locator-1.0.2.tgz", + "integrity": "sha512-v8W5hJLcWMIxLCcSi/MHh+VeefI+ycFmGz23Froer9QzWjrbg4J3gFJBuI/T1VLNoYxF47bVPPxq8ZlNX4gVCw==", + "dev": true, + "license": "MIT" + }, + "node_modules/monocart-reporter": { + "version": "2.9.23", + "resolved": "https://registry.npmjs.org/monocart-reporter/-/monocart-reporter-2.9.23.tgz", + "integrity": "sha512-FSz8908/2FIBJRMD9OdoVXcg7ndGmgiB3GmK2tojeMMrp5OSDt02ksv88GehlLRRzoL2jjf8fuSIHhi8u3QFxw==", + "dev": true, + "license": "MIT", + "dependencies": { + "console-grid": "^2.2.3", + "eight-colors": "^1.3.1", + "koa": "^3.0.1", + "koa-static-resolver": "^1.0.6", + "lz-utils": "^2.1.0", + "monocart-coverage-reports": "^2.12.9", + "monocart-locator": "^1.0.2", + "nodemailer": "^7.0.6" + }, + "bin": { + "monocart": "lib/cli.js" + } + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/nodemailer": { + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-7.0.12.tgz", + "integrity": "sha512-H+rnK5bX2Pi/6ms3sN4/jRQvYSMltV6vqup/0SFOrxYYY/qoNvhXPlYq3e+Pm9RFJRwrMGbMIwi81M4dxpomhA==", + "dev": true, + "license": "MIT-0", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/playwright": { + "version": "1.57.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.57.0.tgz", + "integrity": "sha512-ilYQj1s8sr2ppEJ2YVadYBN0Mb3mdo9J0wQ+UuDhzYqURwSoW4n1Xs5vs7ORwgDGmyEh33tRMeS8KhdkMoLXQw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "playwright-core": "1.57.0" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/playwright-core": { + "version": "1.57.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.57.0.tgz", + "integrity": "sha512-agTcKlMw/mjBWOnD6kFZttAAGHgi/Nw0CZ2o6JqWSbMlI219lAFLZZCyqByTsvVAJq5XA5H8cA6PrvBRpBWEuQ==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "dev": true, + "license": "ISC" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/tsscmp": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.6.tgz", + "integrity": "sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.6.x" + } + }, + "node_modules/type-is": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", + "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", + "dev": true, + "license": "MIT", + "dependencies": { + "content-type": "^1.0.5", + "media-typer": "^1.1.0", + "mime-types": "^3.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/undici-types": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", + "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", + "dev": true, + "license": "MIT" + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..a6f413b --- /dev/null +++ b/package.json @@ -0,0 +1,17 @@ +{ + "name": "playwright", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "npx playwright test", + "report": "npx monocart show-report monocart-report/index.html" + }, + "author": "", + "license": "ISC", + "devDependencies": { + "@playwright/test": "^1.57.0", + "@types/node": "^25.0.3", + "monocart-reporter": "^2.9.23" + } +} diff --git a/playwright.config.ts b/playwright.config.ts new file mode 100644 index 0000000..a1e0b92 --- /dev/null +++ b/playwright.config.ts @@ -0,0 +1,85 @@ +import { defineConfig, devices } from '@playwright/test' + +/** + * Read environment variables from file. + * https://github.com/motdotla/dotenv + */ +// import dotenv from 'dotenv'; +// import path from 'path'; +// dotenv.config({ path: path.resolve(__dirname, '.env') }); + +/** + * See https://playwright.dev/docs/test-configuration. + */ +export default defineConfig({ + testDir: './tests', + /* Run tests in files in parallel */ + fullyParallel: true, + /* Fail the build on CI if you accidentally left test.only in the source code. */ + forbidOnly: !!process.env.CI, + /* Retry on CI only */ + retries: process.env.CI ? 2 : 0, + /* Opt out of parallel tests on CI. */ + workers: process.env.CI ? 1 : undefined, + /* Reporter to use. See https://playwright.dev/docs/test-reporters */ + reporter: [ + ['html'], + ['monocart-reporter', { + name: "Savy API Test Report", + outputFile: './monocart-report/index.html' + }] + ], + /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ + use: { + /* Base URL to use in actions like `await page.goto('')`. */ + // baseURL: 'http://localhost:3000', + + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: 'on-first-retry', + }, + + /* Configure projects for major browsers */ + projects: [ + { + name: 'Tower-2_Floor-3_Unit-A', + use: { ...devices['Desktop Chrome'] }, + }, + + { + name: 'firefox', + use: { ...devices['Desktop Firefox'] }, + }, + + { + name: 'webkit', + use: { ...devices['Desktop Safari'] }, + }, + + /* Test against mobile viewports. */ + // { + // name: 'Mobile Chrome', + // use: { ...devices['Pixel 5'] }, + // }, + // { + // name: 'Mobile Safari', + // use: { ...devices['iPhone 12'] }, + // }, + + /* Test against branded browsers. */ + // { + // name: 'Microsoft Edge', + // use: { ...devices['Desktop Edge'], channel: 'msedge' }, + // }, + // { + // name: 'Google Chrome', + // use: { ...devices['Desktop Chrome'], channel: 'chrome' }, + // }, + ], + + /* Run your local dev server before starting the tests */ + // webServer: { + // command: 'npm run start', + // url: 'http://localhost:3000', + // reuseExistingServer: !process.env.CI, + // }, +}) diff --git a/tepineo:tepi-dev/test-case/index.html b/tepineo:tepi-dev/test-case/index.html new file mode 100644 index 0000000..3ac9db6 --- /dev/null +++ b/tepineo:tepi-dev/test-case/index.html @@ -0,0 +1,85 @@ + + + + + + + + + Playwright Test Report + + + + +
+ + + \ No newline at end of file diff --git a/tests/api-command.spec.ts b/tests/api-command.spec.ts new file mode 100644 index 0000000..cf988f1 --- /dev/null +++ b/tests/api-command.spec.ts @@ -0,0 +1,217 @@ +import { test, expect } from '@playwright/test' +import topics from '../topic.json' +import crypto from 'crypto' + +// Configuration +const API_URL = 'https://api-dev.vegacloud.id' +const API_COMMAND_PATH = '/device/v1/command' +const API_STATUS_PATH = '/device/v1/status' +const API_KEY = 'ak_sdbx:N8Xbvb4OYprJ-Mtw4QO6xw' +const SECRET_KEY = 'sk_sdbx:zyJteO7W3szL41fWWB8WZEmKpp8KyJzi-9o9OovbpT4' + +// Convert "01" -> "A", "02" -> "B", etc. +function numToAlpha(numStr: string): string { + const num = parseInt(numStr, 10) + if (isNaN(num)) return numStr + return String.fromCharCode(64 + num) +} + +// Helper function to sort keys deeply +function sortKeysDeep(obj: any): any { + if (Array.isArray(obj)) { + return obj.map(sortKeysDeep) + } + if (obj !== null && typeof obj === 'object') { + return Object.keys(obj) + .sort() + .reduce((acc: any, key) => { + acc[key] = sortKeysDeep(obj[key]) + return acc + }, {}) + } + return obj +} + +// Generate signature for POST request +function generateSignatureForPost(body: any): { timestamp: number; nonce: string; signature: string } { + const timestamp = Math.floor(Date.now() / 1000) + const nonce = crypto.randomUUID() + const sortedBody = sortKeysDeep(body) + const jsonBody = JSON.stringify({ + timestamp, + nonce, + body: JSON.stringify(sortedBody) + }) + + const signature = crypto + .createHmac('sha256', SECRET_KEY) + .update(jsonBody) + .digest('hex') + + return { timestamp, nonce, signature } +} + +// Parse query params from URL manually (matching Postman logic) +function parseQueryParamsManual(url: string): Record { + const resultObject: Record = {} + const queryStartIndex = url.indexOf('?') + + if (queryStartIndex === -1 || queryStartIndex === url.length - 1) { + return resultObject + } + + const queryString = url.substring(queryStartIndex + 1) + const pairs = queryString.split('&') + + for (let i = 0; i < pairs.length; i++) { + const pair = pairs[i] + const parts = pair.split('=') + + if (parts.length === 2) { + const key = decodeURIComponent(parts[0].replace(/\+/g, ' ')) + const value = decodeURIComponent(parts[1].replace(/\+/g, ' ')) + resultObject[key] = value + } + } + + return resultObject +} + +// Generate signature for GET request +function generateSignatureForGet(url: string): { timestamp: number; nonce: string; signature: string } { + const timestamp = Math.floor(Date.now() / 1000) + const nonce = crypto.randomUUID() + + const params = parseQueryParamsManual(url) + const sortedParams = Object.keys(params) + .sort() + .reduce((acc: any, key) => { + acc[key] = params[key] + return acc + }, {}) + + const jsonBody = JSON.stringify({ + timestamp, + nonce, + body: JSON.stringify(sortedParams) + }) + + const signature = crypto + .createHmac('sha256', SECRET_KEY) + .update(jsonBody) + .digest('hex') + + return { timestamp, nonce, signature } +} + +test.describe('Device Command & Status Tests', () => { + + const getPayload = (deviceName: string) => { + if (deviceName === 'AC') return 'On' + if (deviceName === 'BL') return 'Open' + if (deviceName === 'DL') return 'Lock' + return null + } + + test.describe('1. Command API Tests', () => { + for (const item of topics) { + const { towerNumber, floorName, unitNumber: originalUnit, deviceName, deviceRoom, deviceType } = item + const action = getPayload(deviceName) + + if (action) { + const unitNumber = numToAlpha(originalUnit) + const payload = { + merchantName: 'SAVY', + floorName, + unitNumber, + deviceName, + roomName: deviceRoom, + deviceType, + commandType: 'C', + towerNumber, + payload: { action } + } + + test(`POST Command: ${deviceName} (${deviceType}) - ${floorName}_${unitNumber} - ${deviceRoom}`, async ({ request }) => { + const { timestamp, nonce, signature } = generateSignatureForPost(payload) + + console.log(`[Command] Request: ${JSON.stringify(payload, null, 2)}`) + + const response = await request.post(`${API_URL}${API_COMMAND_PATH}`, { + headers: { + 'Content-Type': 'application/json', + 'X-API-Key': API_KEY, + 'X-Timestamp': timestamp.toString(), + 'X-Nonce': nonce, + 'X-Signature': signature + }, + data: payload + }) + + const responseBody = await response.json() + console.log(`[Command] Response Status: ${response.status()}`) + console.log(`[Command] Response Body: ${JSON.stringify(responseBody, null, 2)}`) + console.log('---') + + expect(response.status()).toBe(200) + }) + } + } + }) + + test.describe('2. Status Check API Tests', () => { + for (const item of topics) { + const { towerNumber, floorName, unitNumber: originalUnit, deviceName, deviceRoom, deviceType } = item + const action = getPayload(deviceName) + + if (action) { + const unitNumber = numToAlpha(originalUnit) + test(`GET Status: ${deviceName} (${deviceType}) - ${floorName}_${unitNumber} - ${deviceRoom}`, async ({ request }) => { + const params = { + merchantName: 'SAVY', + floorName, + unitNumber, + deviceName, + roomName: deviceRoom, + deviceType, + commandType: 'S', + towerNumber + } + + const queryString = new URLSearchParams(params).toString() + const url = `${API_URL}${API_STATUS_PATH}?${queryString}` + const { timestamp, nonce, signature } = generateSignatureForGet(url) + + console.log(`[Status Check] Request URL: ${url}`) + + const response = await request.get(url, { + headers: { + 'X-API-Key': API_KEY, + 'X-Timestamp': timestamp.toString(), + 'X-Nonce': nonce, + 'X-Signature': signature + } + }) + + const responseBody = await response.json() + console.log(`[Status Check] Response Status: ${response.status()}`) + console.log(`[Status Check] Response Body: ${JSON.stringify(responseBody, null, 2)}`) + console.log('---') + + expect(response.status()).toBe(200) + expect(responseBody.data).not.toBeNull() + + // Strict Validation + expect(responseBody.data.floorName).toBe(floorName) + expect(responseBody.data.unitNumber).toBe(unitNumber) + expect(responseBody.data.deviceName).toBe(deviceName) + expect(responseBody.data.roomName).toBe(deviceRoom) + expect(responseBody.data.deviceType).toBe(deviceType) + expect(responseBody.data.code).toBe('S') + expect(responseBody.data.towerNumber).toBe(towerNumber) + expect(responseBody.data).toHaveProperty('payload') + }) + } + } + }) +}) diff --git a/tests/command-api.spec.ts b/tests/command-api.spec.ts new file mode 100644 index 0000000..ac8e17e --- /dev/null +++ b/tests/command-api.spec.ts @@ -0,0 +1,77 @@ +import { test, expect } from '@playwright/test' +import topics from '../topic.json' + +test.describe('Savy API Automation', () => { + + // Helper to determine payload + const getPayload = (deviceName: string) => { + if (deviceName === 'AC') return 'AC=On' + if (deviceName === 'BL') return 'Bind=Open' + if (deviceName === 'DL') return 'Doorlock=Lock' + return null + } + + test.describe('1. Command API Tests', () => { + for (const item of topics) { + const { towerNumber, floorName, unitNumber, deviceName, deviceRoom, deviceType } = item + const payload = getPayload(deviceName) + + if (payload) { + const topic = `SAVY/${floorName}_${unitNumber}-${deviceName}-${deviceRoom}-${deviceType}-C-${towerNumber}` + + test(`Send command for ${deviceName} - ${topic}`, async ({ request }) => { + const requestData = { topic, payload } + + console.log(`[Command] Request: ${JSON.stringify(requestData, null, 2)}`) + + const response = await request.post('http://savy.vegacloud.id/command', { + headers: { + 'Content-Type': 'application/json', + 'Authorization': 'Basic e3thdXRodXNlckhUVFB9fTp7e2F1dGhwd2RIVFRQfX0=', + }, + data: requestData + }) + + const responseBody = await response.json() + console.log(`[Command] Response Status: ${response.status()}`) + console.log(`[Command] Response Body: ${JSON.stringify(responseBody, null, 2)}`) + console.log('---') + + expect(response.status()).toBe(200) + }) + } + } + }) + + test.describe('2. State Reply API Tests', () => { + for (const item of topics) { + const { towerNumber, floorName, unitNumber, deviceName, deviceRoom, deviceType } = item + const payload = getPayload(deviceName) + + if (payload) { + const topic = `SAVY/${floorName}_${unitNumber}-${deviceName}-${deviceRoom}-${deviceType}-S-${towerNumber}` + + test(`Check state for ${deviceName} - ${topic}`, async ({ request }) => { + const requestData = { topic } + + console.log(`[State Reply] Request: ${JSON.stringify(requestData, null, 2)}`) + + const response = await request.post('http://savy.vegacloud.id/state-reply', { + headers: { + 'Content-Type': 'application/json' + }, + data: requestData + }) + + const responseBody = await response.json() + console.log(`[State Reply] Response Status: ${response.status()}`) + console.log(`[State Reply] Response Body: ${JSON.stringify(responseBody, null, 2)}`) + console.log('---') + + expect(response.status()).toBe(200) + expect(responseBody.data).not.toBeNull() + }) + } + } + }) +}) diff --git a/tests/example.spec.ts b/tests/example.spec.ts new file mode 100644 index 0000000..54a906a --- /dev/null +++ b/tests/example.spec.ts @@ -0,0 +1,18 @@ +import { test, expect } from '@playwright/test'; + +test('has title', async ({ page }) => { + await page.goto('https://playwright.dev/'); + + // Expect a title "to contain" a substring. + await expect(page).toHaveTitle(/Playwright/); +}); + +test('get started link', async ({ page }) => { + await page.goto('https://playwright.dev/'); + + // Click the get started link. + await page.getByRole('link', { name: 'Get started' }).click(); + + // Expects page to have a heading with the name of Installation. + await expect(page.getByRole('heading', { name: 'Installation' })).toBeVisible(); +}); diff --git a/topic.json b/topic.json new file mode 100644 index 0000000..6dcd28e --- /dev/null +++ b/topic.json @@ -0,0 +1,154 @@ +[ + { + "towerNumber": "T2", + "floorName": "L29", + "unitNumber": "05", + "deviceName": "L", + "deviceRoom": "LV", + "deviceType": "S" + }, + { + "towerNumber": "T2", + "floorName": "L29", + "unitNumber": "05", + "deviceName": "L", + "deviceRoom": "MS", + "deviceType": "S" + }, + { + "towerNumber": "T2", + "floorName": "L29", + "unitNumber": "05", + "deviceName": "L", + "deviceRoom": "BT", + "deviceType": "S" + }, + { + "towerNumber": "T2", + "floorName": "L29", + "unitNumber": "05", + "deviceName": "L", + "deviceRoom": "WIC", + "deviceType": "S" + }, + { + "towerNumber": "T2", + "floorName": "L29", + "unitNumber": "05", + "deviceName": "BL", + "deviceRoom": "LV", + "deviceType": "S" + }, + { + "towerNumber": "T2", + "floorName": "L29", + "unitNumber": "05", + "deviceName": "BL", + "deviceRoom": "MS", + "deviceType": "S" + }, + { + "towerNumber": "T2", + "floorName": "L29", + "unitNumber": "05", + "deviceName": "AC", + "deviceRoom": "LV", + "deviceType": "S" + }, + { + "towerNumber": "T2", + "floorName": "L29", + "unitNumber": "05", + "deviceName": "AC", + "deviceRoom": "LV", + "deviceType": "A" + }, + { + "towerNumber": "T2", + "floorName": "L29", + "unitNumber": "05", + "deviceName": "AC", + "deviceRoom": "BR1", + "deviceType": "S" + }, + { + "towerNumber": "T2", + "floorName": "L29", + "unitNumber": "05", + "deviceName": "AC", + "deviceRoom": "BR1", + "deviceType": "A" + }, + { + "towerNumber": "T2", + "floorName": "L29", + "unitNumber": "05", + "deviceName": "AC", + "deviceRoom": "BR2", + "deviceType": "S" + }, + { + "towerNumber": "T2", + "floorName": "L29", + "unitNumber": "05", + "deviceName": "AC", + "deviceRoom": "BR2", + "deviceType": "A" + }, + { + "towerNumber": "T2", + "floorName": "L29", + "unitNumber": "05", + "deviceName": "AC", + "deviceRoom": "MS", + "deviceType": "S" + }, + { + "towerNumber": "T2", + "floorName": "L29", + "unitNumber": "05", + "deviceName": "AC", + "deviceRoom": "MS", + "deviceType": "A" + }, + { + "towerNumber": "T2", + "floorName": "L29", + "unitNumber": "05", + "deviceName": "FT1", + "deviceRoom": "LV", + "deviceType": "A" + }, + { + "towerNumber": "T2", + "floorName": "L29", + "unitNumber": "05", + "deviceName": "FT2", + "deviceRoom": "LV", + "deviceType": "S" + }, + { + "towerNumber": "T2", + "floorName": "L29", + "unitNumber": "05", + "deviceName": "PM25", + "deviceRoom": "LV", + "deviceType": "S" + }, + { + "towerNumber": "T2", + "floorName": "L29", + "unitNumber": "05", + "deviceName": "DL", + "deviceRoom": "KN", + "deviceType": "S" + }, + { + "towerNumber": "T2", + "floorName": "L29", + "unitNumber": "05", + "deviceName": "KC", + "deviceRoom": "KN", + "deviceType": "S" + } +] \ No newline at end of file