mirror of
https://github.com/trycua/computer.git
synced 2026-01-04 20:40:15 -06:00
Create tests. Note: ws mocking is currently broken
This commit is contained in:
@@ -48,6 +48,7 @@
|
||||
"@types/ws": "^8.18.1",
|
||||
"bumpp": "^10.1.0",
|
||||
"happy-dom": "^17.4.7",
|
||||
"msw": "^2.10.2",
|
||||
"tsdown": "^0.11.9",
|
||||
"tsx": "^4.19.4",
|
||||
"typescript": "^5.8.3",
|
||||
|
||||
418
libs/computer/typescript/pnpm-lock.yaml
generated
418
libs/computer/typescript/pnpm-lock.yaml
generated
@@ -33,6 +33,9 @@ importers:
|
||||
happy-dom:
|
||||
specifier: ^17.4.7
|
||||
version: 17.6.3
|
||||
msw:
|
||||
specifier: ^2.10.2
|
||||
version: 2.10.2(@types/node@22.15.31)(typescript@5.8.3)
|
||||
tsdown:
|
||||
specifier: ^0.11.9
|
||||
version: 0.11.13(typescript@5.8.3)
|
||||
@@ -44,7 +47,7 @@ importers:
|
||||
version: 5.8.3
|
||||
vitest:
|
||||
specifier: ^3.1.3
|
||||
version: 3.2.3(@types/debug@4.1.12)(@types/node@22.15.31)(happy-dom@17.6.3)(jiti@2.4.2)(tsx@4.20.2)(yaml@2.8.0)
|
||||
version: 3.2.3(@types/debug@4.1.12)(@types/node@22.15.31)(happy-dom@17.6.3)(jiti@2.4.2)(msw@2.10.2(@types/node@22.15.31)(typescript@5.8.3))(tsx@4.20.2)(yaml@2.8.0)
|
||||
|
||||
packages:
|
||||
|
||||
@@ -122,6 +125,15 @@ packages:
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
'@bundled-es-modules/cookie@2.0.1':
|
||||
resolution: {integrity: sha512-8o+5fRPLNbjbdGRRmJj3h6Hh1AQJf2dk3qQ/5ZFb+PXkRNiSoMGGUKlsgLfrxneb72axVJyIYji64E2+nNfYyw==}
|
||||
|
||||
'@bundled-es-modules/statuses@1.0.1':
|
||||
resolution: {integrity: sha512-yn7BklA5acgcBr+7w064fGV+SGIFySjCKpqjcWgBAIfrAkY+4GQTJJHQMeT3V/sgz23VTEVV8TtOmkvJAhFVfg==}
|
||||
|
||||
'@bundled-es-modules/tough-cookie@0.1.6':
|
||||
resolution: {integrity: sha512-dvMHbL464C0zI+Yqxbz6kZ5TOEp7GLW+pry/RWndAR8MJQAXZ2rPmIs8tziTZjeIyhSNZgZbCePtfSbdWqStJw==}
|
||||
|
||||
'@emnapi/core@1.4.3':
|
||||
resolution: {integrity: sha512-4m62DuCE07lw01soJwPiBGC0nAww0Q+RY70VZ+n49yDIO13yyinhbWCeNnaob0lakDtWQzSdtNWzJeOJt2ma+g==}
|
||||
|
||||
@@ -386,6 +398,37 @@ packages:
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
'@inquirer/confirm@5.1.12':
|
||||
resolution: {integrity: sha512-dpq+ielV9/bqgXRUbNH//KsY6WEw9DrGPmipkpmgC1Y46cwuBTNx7PXFWTjc3MQ+urcc0QxoVHcMI0FW4Ok0hg==}
|
||||
engines: {node: '>=18'}
|
||||
peerDependencies:
|
||||
'@types/node': '>=18'
|
||||
peerDependenciesMeta:
|
||||
'@types/node':
|
||||
optional: true
|
||||
|
||||
'@inquirer/core@10.1.13':
|
||||
resolution: {integrity: sha512-1viSxebkYN2nJULlzCxES6G9/stgHSepZ9LqqfdIGPHj5OHhiBUXVS0a6R0bEC2A+VL4D9w6QB66ebCr6HGllA==}
|
||||
engines: {node: '>=18'}
|
||||
peerDependencies:
|
||||
'@types/node': '>=18'
|
||||
peerDependenciesMeta:
|
||||
'@types/node':
|
||||
optional: true
|
||||
|
||||
'@inquirer/figures@1.0.12':
|
||||
resolution: {integrity: sha512-MJttijd8rMFcKJC8NYmprWr6hD3r9Gd9qUC0XwPNwoEPWSMVJwA2MlXxF+nhZZNMY+HXsWa+o7KY2emWYIn0jQ==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
'@inquirer/type@3.0.7':
|
||||
resolution: {integrity: sha512-PfunHQcjwnju84L+ycmcMKB/pTPIngjUJvfnRhKY6FKPuYXlM4aQCb/nIdTFR6BEhMjFvngzvng/vBAJMZpLSA==}
|
||||
engines: {node: '>=18'}
|
||||
peerDependencies:
|
||||
'@types/node': '>=18'
|
||||
peerDependenciesMeta:
|
||||
'@types/node':
|
||||
optional: true
|
||||
|
||||
'@jridgewell/gen-mapping@0.3.8':
|
||||
resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==}
|
||||
engines: {node: '>=6.0.0'}
|
||||
@@ -404,9 +447,22 @@ packages:
|
||||
'@jridgewell/trace-mapping@0.3.25':
|
||||
resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==}
|
||||
|
||||
'@mswjs/interceptors@0.39.2':
|
||||
resolution: {integrity: sha512-RuzCup9Ct91Y7V79xwCb146RaBRHZ7NBbrIUySumd1rpKqHL5OonaqrGIbug5hNwP/fRyxFMA6ISgw4FTtYFYg==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
'@napi-rs/wasm-runtime@0.2.11':
|
||||
resolution: {integrity: sha512-9DPkXtvHydrcOsopiYpUgPHpmj0HWZKMUnL2dZqpvC42lsratuBG06V5ipyno0fUek5VlFsNQ+AcFATSrJXgMA==}
|
||||
|
||||
'@open-draft/deferred-promise@2.2.0':
|
||||
resolution: {integrity: sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA==}
|
||||
|
||||
'@open-draft/logger@0.3.0':
|
||||
resolution: {integrity: sha512-X2g45fzhxH238HKO4xbSr7+wBS8Fvw6ixhTDuvLd5mqh6bJJCFAPwU9mPDxbcrRtfxv4u5IHCEH77BmxvXmmxQ==}
|
||||
|
||||
'@open-draft/until@2.1.0':
|
||||
resolution: {integrity: sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg==}
|
||||
|
||||
'@oxc-project/types@0.70.0':
|
||||
resolution: {integrity: sha512-ngyLUpUjO3dpqygSRQDx7nMx8+BmXbWOU4oIwTJFV2MVIDG7knIZwgdwXlQWLg3C3oxg1lS7ppMtPKqKFb7wzw==}
|
||||
|
||||
@@ -583,6 +639,9 @@ packages:
|
||||
'@types/chai@5.2.2':
|
||||
resolution: {integrity: sha512-8kB30R7Hwqf40JPiKhVzodJs2Qc1ZJ5zuT3uzw5Hq/dhNCl3G3l83jfpdI1e20BP348+fV7VIL/+FxaXkqBmWg==}
|
||||
|
||||
'@types/cookie@0.6.0':
|
||||
resolution: {integrity: sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==}
|
||||
|
||||
'@types/debug@4.1.12':
|
||||
resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==}
|
||||
|
||||
@@ -601,6 +660,12 @@ packages:
|
||||
'@types/node@22.15.31':
|
||||
resolution: {integrity: sha512-jnVe5ULKl6tijxUhvQeNbQG/84fHfg+yMak02cT8QVhBx/F05rAVxCGBYYTh2EKz22D6JF5ktXuNwdx7b9iEGw==}
|
||||
|
||||
'@types/statuses@2.0.6':
|
||||
resolution: {integrity: sha512-xMAgYwceFhRA2zY+XbEA7mxYbA093wdiW8Vu6gZPGWy9cmOyU9XesH1tNcEWsKFd5Vzrqx5T3D38PWx1FIIXkA==}
|
||||
|
||||
'@types/tough-cookie@4.0.5':
|
||||
resolution: {integrity: sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==}
|
||||
|
||||
'@types/ws@8.18.1':
|
||||
resolution: {integrity: sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==}
|
||||
|
||||
@@ -633,6 +698,18 @@ packages:
|
||||
'@vitest/utils@3.2.3':
|
||||
resolution: {integrity: sha512-4zFBCU5Pf+4Z6v+rwnZ1HU1yzOKKvDkMXZrymE2PBlbjKJRlrOxbvpfPSvJTGRIwGoahaOGvp+kbCoxifhzJ1Q==}
|
||||
|
||||
ansi-escapes@4.3.2:
|
||||
resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
ansi-regex@5.0.1:
|
||||
resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
ansi-styles@4.3.0:
|
||||
resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
ansis@4.1.0:
|
||||
resolution: {integrity: sha512-BGcItUBWSMRgOCe+SVZJ+S7yTRG0eGt9cXAHev72yuGcY23hnLA7Bky5L/xLyPINoSN95geovfBkqoTlNZYa7w==}
|
||||
engines: {node: '>=14'}
|
||||
@@ -687,6 +764,14 @@ packages:
|
||||
citty@0.1.6:
|
||||
resolution: {integrity: sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==}
|
||||
|
||||
cli-width@4.1.0:
|
||||
resolution: {integrity: sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==}
|
||||
engines: {node: '>= 12'}
|
||||
|
||||
cliui@8.0.1:
|
||||
resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
color-convert@2.0.1:
|
||||
resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
|
||||
engines: {node: '>=7.0.0'}
|
||||
@@ -708,6 +793,10 @@ packages:
|
||||
resolution: {integrity: sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==}
|
||||
engines: {node: ^14.18.0 || >=16.10.0}
|
||||
|
||||
cookie@0.7.2:
|
||||
resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==}
|
||||
engines: {node: '>= 0.6'}
|
||||
|
||||
debug@4.4.1:
|
||||
resolution: {integrity: sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==}
|
||||
engines: {node: '>=6.0'}
|
||||
@@ -748,6 +837,9 @@ packages:
|
||||
oxc-resolver:
|
||||
optional: true
|
||||
|
||||
emoji-regex@8.0.0:
|
||||
resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
|
||||
|
||||
empathic@1.1.0:
|
||||
resolution: {integrity: sha512-rsPft6CK3eHtrlp9Y5ALBb+hfK+DWnA4WFebbazxjWyx8vSm3rZeoM3z9irsjcqO3PYRzlfv27XIB4tz2DV7RA==}
|
||||
engines: {node: '>=14'}
|
||||
@@ -791,6 +883,10 @@ packages:
|
||||
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
|
||||
os: [darwin]
|
||||
|
||||
get-caller-file@2.0.5:
|
||||
resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==}
|
||||
engines: {node: 6.* || 8.* || >= 10.*}
|
||||
|
||||
get-tsconfig@4.10.1:
|
||||
resolution: {integrity: sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==}
|
||||
|
||||
@@ -798,16 +894,30 @@ packages:
|
||||
resolution: {integrity: sha512-L5bGsVkxJbJgdnwyuheIunkGatUF/zssUoxxjACCseZYAVbaqdh9Tsmmlkl8vYan09H7sbvKt4pS8GqKLBrEzA==}
|
||||
hasBin: true
|
||||
|
||||
graphql@16.11.0:
|
||||
resolution: {integrity: sha512-mS1lbMsxgQj6hge1XZ6p7GPhbrtFwUFYi3wRzXAC/FmYnyXMTvvI3td3rjmQ2u8ewXueaSvRPWaEcgVVOT9Jnw==}
|
||||
engines: {node: ^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0}
|
||||
|
||||
happy-dom@17.6.3:
|
||||
resolution: {integrity: sha512-UVIHeVhxmxedbWPCfgS55Jg2rDfwf2BCKeylcPSqazLz5w3Kri7Q4xdBJubsr/+VUzFLh0VjIvh13RaDA2/Xug==}
|
||||
engines: {node: '>=20.0.0'}
|
||||
|
||||
headers-polyfill@4.0.3:
|
||||
resolution: {integrity: sha512-IScLbePpkvO846sIwOtOTDjutRMWdXdJmXdMvk6gCBHxFO8d+QKOQedyZSxFTTFYRSmlgSTDtXqqq4pcenBXLQ==}
|
||||
|
||||
hookable@5.5.3:
|
||||
resolution: {integrity: sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==}
|
||||
|
||||
is-arrayish@0.3.2:
|
||||
resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==}
|
||||
|
||||
is-fullwidth-code-point@3.0.0:
|
||||
resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
is-node-process@1.2.0:
|
||||
resolution: {integrity: sha512-Vg4o6/fqPxIjtxgUH5QLJhwZ7gW5diGCVlXpuUfELC62CuxM1iHcRe51f2W1FDy04Ai4KJkagKjx3XaqyfRKXw==}
|
||||
|
||||
jiti@2.4.2:
|
||||
resolution: {integrity: sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==}
|
||||
hasBin: true
|
||||
@@ -832,6 +942,20 @@ packages:
|
||||
ms@2.1.3:
|
||||
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
|
||||
|
||||
msw@2.10.2:
|
||||
resolution: {integrity: sha512-RCKM6IZseZQCWcSWlutdf590M8nVfRHG1ImwzOtwz8IYxgT4zhUO0rfTcTvDGiaFE0Rhcc+h43lcF3Jc9gFtwQ==}
|
||||
engines: {node: '>=18'}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
typescript: '>= 4.8.x'
|
||||
peerDependenciesMeta:
|
||||
typescript:
|
||||
optional: true
|
||||
|
||||
mute-stream@2.0.0:
|
||||
resolution: {integrity: sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==}
|
||||
engines: {node: ^18.17.0 || >=20.5.0}
|
||||
|
||||
nanoid@3.3.11:
|
||||
resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==}
|
||||
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
|
||||
@@ -852,9 +976,15 @@ packages:
|
||||
resolution: {integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==}
|
||||
engines: {node: '>=14.0.0'}
|
||||
|
||||
outvariant@1.4.3:
|
||||
resolution: {integrity: sha512-+Sl2UErvtsoajRDKCE5/dBz4DIvHXQQnAxtQTF04OJxY0+DyZXSo5P5Bb7XYWOh81syohlYL24hbDwxedPUJCA==}
|
||||
|
||||
package-manager-detector@1.3.0:
|
||||
resolution: {integrity: sha512-ZsEbbZORsyHuO00lY1kV3/t72yp6Ysay6Pd17ZAlNGuGwmWDLCJxFpRs0IzfXfj1o4icJOkUEioexFHzyPurSQ==}
|
||||
|
||||
path-to-regexp@6.3.0:
|
||||
resolution: {integrity: sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==}
|
||||
|
||||
pathe@2.0.3:
|
||||
resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==}
|
||||
|
||||
@@ -892,9 +1022,19 @@ packages:
|
||||
process-warning@5.0.0:
|
||||
resolution: {integrity: sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA==}
|
||||
|
||||
psl@1.15.0:
|
||||
resolution: {integrity: sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==}
|
||||
|
||||
punycode@2.3.1:
|
||||
resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
quansync@0.2.10:
|
||||
resolution: {integrity: sha512-t41VRkMYbkHyCYmOvx/6URnN80H7k4X0lLdBMGsz+maAwrJQYB1djpV6vHrQIBE0WBSGqhtEHrK9U3DWWH8v7A==}
|
||||
|
||||
querystringify@2.2.0:
|
||||
resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==}
|
||||
|
||||
quick-format-unescaped@4.0.4:
|
||||
resolution: {integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==}
|
||||
|
||||
@@ -909,6 +1049,13 @@ packages:
|
||||
resolution: {integrity: sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==}
|
||||
engines: {node: '>= 12.13.0'}
|
||||
|
||||
require-directory@2.1.1:
|
||||
resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
requires-port@1.0.0:
|
||||
resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==}
|
||||
|
||||
resolve-pkg-maps@1.0.0:
|
||||
resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==}
|
||||
|
||||
@@ -958,6 +1105,10 @@ packages:
|
||||
siginfo@2.0.0:
|
||||
resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==}
|
||||
|
||||
signal-exit@4.1.0:
|
||||
resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==}
|
||||
engines: {node: '>=14'}
|
||||
|
||||
simple-swizzle@0.2.2:
|
||||
resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==}
|
||||
|
||||
@@ -975,9 +1126,24 @@ packages:
|
||||
stackback@0.0.2:
|
||||
resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==}
|
||||
|
||||
statuses@2.0.2:
|
||||
resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==}
|
||||
engines: {node: '>= 0.8'}
|
||||
|
||||
std-env@3.9.0:
|
||||
resolution: {integrity: sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==}
|
||||
|
||||
strict-event-emitter@0.5.1:
|
||||
resolution: {integrity: sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ==}
|
||||
|
||||
string-width@4.2.3:
|
||||
resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
strip-ansi@6.0.1:
|
||||
resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
strip-literal@3.0.0:
|
||||
resolution: {integrity: sha512-TcccoMhJOM3OebGhSBEmp3UZ2SfDMZUEBdRA/9ynfLi8yYajyWX3JiXArcJt4Umh4vISpspkQIY8ZZoCqjbviA==}
|
||||
|
||||
@@ -1009,6 +1175,10 @@ packages:
|
||||
resolution: {integrity: sha512-t2T/WLB2WRgZ9EpE4jgPJ9w+i66UZfDc8wHh0xrwiRNN+UwH98GIJkTeZqX9rg0i0ptwzqW+uYeIF0T4F8LR7A==}
|
||||
engines: {node: '>=14.0.0'}
|
||||
|
||||
tough-cookie@4.1.4:
|
||||
resolution: {integrity: sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
tsdown@0.11.13:
|
||||
resolution: {integrity: sha512-VSfoNm8MJXFdg7PJ4p2javgjMRiQQHpkP9N3iBBTrmCixcT6YZ9ZtqYMW3NDHczqR0C0Qnur1HMQr1ZfZcmrng==}
|
||||
engines: {node: '>=18.0.0'}
|
||||
@@ -1036,6 +1206,14 @@ packages:
|
||||
engines: {node: '>=18.0.0'}
|
||||
hasBin: true
|
||||
|
||||
type-fest@0.21.3:
|
||||
resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
type-fest@4.41.0:
|
||||
resolution: {integrity: sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==}
|
||||
engines: {node: '>=16'}
|
||||
|
||||
typescript@5.8.3:
|
||||
resolution: {integrity: sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==}
|
||||
engines: {node: '>=14.17'}
|
||||
@@ -1047,6 +1225,13 @@ packages:
|
||||
undici-types@6.21.0:
|
||||
resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==}
|
||||
|
||||
universalify@0.2.0:
|
||||
resolution: {integrity: sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==}
|
||||
engines: {node: '>= 4.0.0'}
|
||||
|
||||
url-parse@1.5.10:
|
||||
resolution: {integrity: sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==}
|
||||
|
||||
vite-node@3.2.3:
|
||||
resolution: {integrity: sha512-gc8aAifGuDIpZHrPjuHyP4dpQmYXqWw7D1GmDnWeNWP654UEXzVfQ5IHPSK5HaHkwB/+p1atpYpSdw/2kOv8iQ==}
|
||||
engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
|
||||
@@ -1133,6 +1318,14 @@ packages:
|
||||
engines: {node: '>=8'}
|
||||
hasBin: true
|
||||
|
||||
wrap-ansi@6.2.0:
|
||||
resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
wrap-ansi@7.0.0:
|
||||
resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
ws@8.18.2:
|
||||
resolution: {integrity: sha512-DMricUmwGZUVr++AEAe2uiVM7UoO9MAVZMDu05UQOaUII0lp+zOzLLU4Xqh/JvTqklB1T4uELaaPBKyjE1r4fQ==}
|
||||
engines: {node: '>=10.0.0'}
|
||||
@@ -1145,11 +1338,27 @@ packages:
|
||||
utf-8-validate:
|
||||
optional: true
|
||||
|
||||
y18n@5.0.8:
|
||||
resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
yaml@2.8.0:
|
||||
resolution: {integrity: sha512-4lLa/EcQCB0cJkyts+FpIRx5G/llPxfP6VQU5KByHEhLxY3IJCH0f0Hy1MHI8sClTvsIb8qwRJ6R/ZdlDJ/leQ==}
|
||||
engines: {node: '>= 14.6'}
|
||||
hasBin: true
|
||||
|
||||
yargs-parser@21.1.1:
|
||||
resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
yargs@17.7.2:
|
||||
resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
yoctocolors-cjs@2.1.2:
|
||||
resolution: {integrity: sha512-cYVsTjKl8b+FrnidjibDWskAv7UKOfcwaVZdp/it9n1s9fU3IkgDbhdIRKCW4JDsAlECJY0ytoVPT3sK6kideA==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
snapshots:
|
||||
|
||||
'@babel/generator@7.27.5':
|
||||
@@ -1208,6 +1417,19 @@ snapshots:
|
||||
'@biomejs/cli-win32-x64@1.9.4':
|
||||
optional: true
|
||||
|
||||
'@bundled-es-modules/cookie@2.0.1':
|
||||
dependencies:
|
||||
cookie: 0.7.2
|
||||
|
||||
'@bundled-es-modules/statuses@1.0.1':
|
||||
dependencies:
|
||||
statuses: 2.0.2
|
||||
|
||||
'@bundled-es-modules/tough-cookie@0.1.6':
|
||||
dependencies:
|
||||
'@types/tough-cookie': 4.0.5
|
||||
tough-cookie: 4.1.4
|
||||
|
||||
'@emnapi/core@1.4.3':
|
||||
dependencies:
|
||||
'@emnapi/wasi-threads': 1.0.2
|
||||
@@ -1374,6 +1596,32 @@ snapshots:
|
||||
'@img/sharp-win32-x64@0.33.5':
|
||||
optional: true
|
||||
|
||||
'@inquirer/confirm@5.1.12(@types/node@22.15.31)':
|
||||
dependencies:
|
||||
'@inquirer/core': 10.1.13(@types/node@22.15.31)
|
||||
'@inquirer/type': 3.0.7(@types/node@22.15.31)
|
||||
optionalDependencies:
|
||||
'@types/node': 22.15.31
|
||||
|
||||
'@inquirer/core@10.1.13(@types/node@22.15.31)':
|
||||
dependencies:
|
||||
'@inquirer/figures': 1.0.12
|
||||
'@inquirer/type': 3.0.7(@types/node@22.15.31)
|
||||
ansi-escapes: 4.3.2
|
||||
cli-width: 4.1.0
|
||||
mute-stream: 2.0.0
|
||||
signal-exit: 4.1.0
|
||||
wrap-ansi: 6.2.0
|
||||
yoctocolors-cjs: 2.1.2
|
||||
optionalDependencies:
|
||||
'@types/node': 22.15.31
|
||||
|
||||
'@inquirer/figures@1.0.12': {}
|
||||
|
||||
'@inquirer/type@3.0.7(@types/node@22.15.31)':
|
||||
optionalDependencies:
|
||||
'@types/node': 22.15.31
|
||||
|
||||
'@jridgewell/gen-mapping@0.3.8':
|
||||
dependencies:
|
||||
'@jridgewell/set-array': 1.2.1
|
||||
@@ -1391,6 +1639,15 @@ snapshots:
|
||||
'@jridgewell/resolve-uri': 3.1.2
|
||||
'@jridgewell/sourcemap-codec': 1.5.0
|
||||
|
||||
'@mswjs/interceptors@0.39.2':
|
||||
dependencies:
|
||||
'@open-draft/deferred-promise': 2.2.0
|
||||
'@open-draft/logger': 0.3.0
|
||||
'@open-draft/until': 2.1.0
|
||||
is-node-process: 1.2.0
|
||||
outvariant: 1.4.3
|
||||
strict-event-emitter: 0.5.1
|
||||
|
||||
'@napi-rs/wasm-runtime@0.2.11':
|
||||
dependencies:
|
||||
'@emnapi/core': 1.4.3
|
||||
@@ -1398,6 +1655,15 @@ snapshots:
|
||||
'@tybys/wasm-util': 0.9.0
|
||||
optional: true
|
||||
|
||||
'@open-draft/deferred-promise@2.2.0': {}
|
||||
|
||||
'@open-draft/logger@0.3.0':
|
||||
dependencies:
|
||||
is-node-process: 1.2.0
|
||||
outvariant: 1.4.3
|
||||
|
||||
'@open-draft/until@2.1.0': {}
|
||||
|
||||
'@oxc-project/types@0.70.0': {}
|
||||
|
||||
'@quansync/fs@0.1.3':
|
||||
@@ -1513,6 +1779,8 @@ snapshots:
|
||||
dependencies:
|
||||
'@types/deep-eql': 4.0.2
|
||||
|
||||
'@types/cookie@0.6.0': {}
|
||||
|
||||
'@types/debug@4.1.12':
|
||||
dependencies:
|
||||
'@types/ms': 2.1.0
|
||||
@@ -1531,6 +1799,10 @@ snapshots:
|
||||
dependencies:
|
||||
undici-types: 6.21.0
|
||||
|
||||
'@types/statuses@2.0.6': {}
|
||||
|
||||
'@types/tough-cookie@4.0.5': {}
|
||||
|
||||
'@types/ws@8.18.1':
|
||||
dependencies:
|
||||
'@types/node': 22.15.31
|
||||
@@ -1543,12 +1815,13 @@ snapshots:
|
||||
chai: 5.2.0
|
||||
tinyrainbow: 2.0.0
|
||||
|
||||
'@vitest/mocker@3.2.3(vite@6.3.5(@types/node@22.15.31)(jiti@2.4.2)(tsx@4.20.2)(yaml@2.8.0))':
|
||||
'@vitest/mocker@3.2.3(msw@2.10.2(@types/node@22.15.31)(typescript@5.8.3))(vite@6.3.5(@types/node@22.15.31)(jiti@2.4.2)(tsx@4.20.2)(yaml@2.8.0))':
|
||||
dependencies:
|
||||
'@vitest/spy': 3.2.3
|
||||
estree-walker: 3.0.3
|
||||
magic-string: 0.30.17
|
||||
optionalDependencies:
|
||||
msw: 2.10.2(@types/node@22.15.31)(typescript@5.8.3)
|
||||
vite: 6.3.5(@types/node@22.15.31)(jiti@2.4.2)(tsx@4.20.2)(yaml@2.8.0)
|
||||
|
||||
'@vitest/pretty-format@3.2.3':
|
||||
@@ -1577,6 +1850,16 @@ snapshots:
|
||||
loupe: 3.1.3
|
||||
tinyrainbow: 2.0.0
|
||||
|
||||
ansi-escapes@4.3.2:
|
||||
dependencies:
|
||||
type-fest: 0.21.3
|
||||
|
||||
ansi-regex@5.0.1: {}
|
||||
|
||||
ansi-styles@4.3.0:
|
||||
dependencies:
|
||||
color-convert: 2.0.1
|
||||
|
||||
ansis@4.1.0: {}
|
||||
|
||||
args-tokenizer@0.3.0: {}
|
||||
@@ -1643,6 +1926,14 @@ snapshots:
|
||||
dependencies:
|
||||
consola: 3.4.2
|
||||
|
||||
cli-width@4.1.0: {}
|
||||
|
||||
cliui@8.0.1:
|
||||
dependencies:
|
||||
string-width: 4.2.3
|
||||
strip-ansi: 6.0.1
|
||||
wrap-ansi: 7.0.0
|
||||
|
||||
color-convert@2.0.1:
|
||||
dependencies:
|
||||
color-name: 1.1.4
|
||||
@@ -1663,6 +1954,8 @@ snapshots:
|
||||
|
||||
consola@3.4.2: {}
|
||||
|
||||
cookie@0.7.2: {}
|
||||
|
||||
debug@4.4.1:
|
||||
dependencies:
|
||||
ms: 2.1.3
|
||||
@@ -1681,6 +1974,8 @@ snapshots:
|
||||
|
||||
dts-resolver@2.1.1: {}
|
||||
|
||||
emoji-regex@8.0.0: {}
|
||||
|
||||
empathic@1.1.0: {}
|
||||
|
||||
es-module-lexer@1.7.0: {}
|
||||
@@ -1732,6 +2027,8 @@ snapshots:
|
||||
fsevents@2.3.3:
|
||||
optional: true
|
||||
|
||||
get-caller-file@2.0.5: {}
|
||||
|
||||
get-tsconfig@4.10.1:
|
||||
dependencies:
|
||||
resolve-pkg-maps: 1.0.0
|
||||
@@ -1745,15 +2042,23 @@ snapshots:
|
||||
nypm: 0.6.0
|
||||
pathe: 2.0.3
|
||||
|
||||
graphql@16.11.0: {}
|
||||
|
||||
happy-dom@17.6.3:
|
||||
dependencies:
|
||||
webidl-conversions: 7.0.0
|
||||
whatwg-mimetype: 3.0.0
|
||||
|
||||
headers-polyfill@4.0.3: {}
|
||||
|
||||
hookable@5.5.3: {}
|
||||
|
||||
is-arrayish@0.3.2: {}
|
||||
|
||||
is-fullwidth-code-point@3.0.0: {}
|
||||
|
||||
is-node-process@1.2.0: {}
|
||||
|
||||
jiti@2.4.2: {}
|
||||
|
||||
js-tokens@9.0.1: {}
|
||||
@@ -1770,6 +2075,33 @@ snapshots:
|
||||
|
||||
ms@2.1.3: {}
|
||||
|
||||
msw@2.10.2(@types/node@22.15.31)(typescript@5.8.3):
|
||||
dependencies:
|
||||
'@bundled-es-modules/cookie': 2.0.1
|
||||
'@bundled-es-modules/statuses': 1.0.1
|
||||
'@bundled-es-modules/tough-cookie': 0.1.6
|
||||
'@inquirer/confirm': 5.1.12(@types/node@22.15.31)
|
||||
'@mswjs/interceptors': 0.39.2
|
||||
'@open-draft/deferred-promise': 2.2.0
|
||||
'@open-draft/until': 2.1.0
|
||||
'@types/cookie': 0.6.0
|
||||
'@types/statuses': 2.0.6
|
||||
graphql: 16.11.0
|
||||
headers-polyfill: 4.0.3
|
||||
is-node-process: 1.2.0
|
||||
outvariant: 1.4.3
|
||||
path-to-regexp: 6.3.0
|
||||
picocolors: 1.1.1
|
||||
strict-event-emitter: 0.5.1
|
||||
type-fest: 4.41.0
|
||||
yargs: 17.7.2
|
||||
optionalDependencies:
|
||||
typescript: 5.8.3
|
||||
transitivePeerDependencies:
|
||||
- '@types/node'
|
||||
|
||||
mute-stream@2.0.0: {}
|
||||
|
||||
nanoid@3.3.11: {}
|
||||
|
||||
node-fetch-native@1.6.6: {}
|
||||
@@ -1786,8 +2118,12 @@ snapshots:
|
||||
|
||||
on-exit-leak-free@2.1.2: {}
|
||||
|
||||
outvariant@1.4.3: {}
|
||||
|
||||
package-manager-detector@1.3.0: {}
|
||||
|
||||
path-to-regexp@6.3.0: {}
|
||||
|
||||
pathe@2.0.3: {}
|
||||
|
||||
pathval@2.0.0: {}
|
||||
@@ -1832,8 +2168,16 @@ snapshots:
|
||||
|
||||
process-warning@5.0.0: {}
|
||||
|
||||
psl@1.15.0:
|
||||
dependencies:
|
||||
punycode: 2.3.1
|
||||
|
||||
punycode@2.3.1: {}
|
||||
|
||||
quansync@0.2.10: {}
|
||||
|
||||
querystringify@2.2.0: {}
|
||||
|
||||
quick-format-unescaped@4.0.4: {}
|
||||
|
||||
rc9@2.1.2:
|
||||
@@ -1845,6 +2189,10 @@ snapshots:
|
||||
|
||||
real-require@0.2.0: {}
|
||||
|
||||
require-directory@2.1.1: {}
|
||||
|
||||
requires-port@1.0.0: {}
|
||||
|
||||
resolve-pkg-maps@1.0.0: {}
|
||||
|
||||
rolldown-plugin-dts@0.13.11(rolldown@1.0.0-beta.9)(typescript@5.8.3):
|
||||
@@ -1941,6 +2289,8 @@ snapshots:
|
||||
|
||||
siginfo@2.0.0: {}
|
||||
|
||||
signal-exit@4.1.0: {}
|
||||
|
||||
simple-swizzle@0.2.2:
|
||||
dependencies:
|
||||
is-arrayish: 0.3.2
|
||||
@@ -1955,8 +2305,22 @@ snapshots:
|
||||
|
||||
stackback@0.0.2: {}
|
||||
|
||||
statuses@2.0.2: {}
|
||||
|
||||
std-env@3.9.0: {}
|
||||
|
||||
strict-event-emitter@0.5.1: {}
|
||||
|
||||
string-width@4.2.3:
|
||||
dependencies:
|
||||
emoji-regex: 8.0.0
|
||||
is-fullwidth-code-point: 3.0.0
|
||||
strip-ansi: 6.0.1
|
||||
|
||||
strip-ansi@6.0.1:
|
||||
dependencies:
|
||||
ansi-regex: 5.0.1
|
||||
|
||||
strip-literal@3.0.0:
|
||||
dependencies:
|
||||
js-tokens: 9.0.1
|
||||
@@ -1982,6 +2346,13 @@ snapshots:
|
||||
|
||||
tinyspy@4.0.3: {}
|
||||
|
||||
tough-cookie@4.1.4:
|
||||
dependencies:
|
||||
psl: 1.15.0
|
||||
punycode: 2.3.1
|
||||
universalify: 0.2.0
|
||||
url-parse: 1.5.10
|
||||
|
||||
tsdown@0.11.13(typescript@5.8.3):
|
||||
dependencies:
|
||||
ansis: 4.1.0
|
||||
@@ -2016,6 +2387,10 @@ snapshots:
|
||||
optionalDependencies:
|
||||
fsevents: 2.3.3
|
||||
|
||||
type-fest@0.21.3: {}
|
||||
|
||||
type-fest@4.41.0: {}
|
||||
|
||||
typescript@5.8.3: {}
|
||||
|
||||
unconfig@7.3.2:
|
||||
@@ -2027,6 +2402,13 @@ snapshots:
|
||||
|
||||
undici-types@6.21.0: {}
|
||||
|
||||
universalify@0.2.0: {}
|
||||
|
||||
url-parse@1.5.10:
|
||||
dependencies:
|
||||
querystringify: 2.2.0
|
||||
requires-port: 1.0.0
|
||||
|
||||
vite-node@3.2.3(@types/node@22.15.31)(jiti@2.4.2)(tsx@4.20.2)(yaml@2.8.0):
|
||||
dependencies:
|
||||
cac: 6.7.14
|
||||
@@ -2063,11 +2445,11 @@ snapshots:
|
||||
tsx: 4.20.2
|
||||
yaml: 2.8.0
|
||||
|
||||
vitest@3.2.3(@types/debug@4.1.12)(@types/node@22.15.31)(happy-dom@17.6.3)(jiti@2.4.2)(tsx@4.20.2)(yaml@2.8.0):
|
||||
vitest@3.2.3(@types/debug@4.1.12)(@types/node@22.15.31)(happy-dom@17.6.3)(jiti@2.4.2)(msw@2.10.2(@types/node@22.15.31)(typescript@5.8.3))(tsx@4.20.2)(yaml@2.8.0):
|
||||
dependencies:
|
||||
'@types/chai': 5.2.2
|
||||
'@vitest/expect': 3.2.3
|
||||
'@vitest/mocker': 3.2.3(vite@6.3.5(@types/node@22.15.31)(jiti@2.4.2)(tsx@4.20.2)(yaml@2.8.0))
|
||||
'@vitest/mocker': 3.2.3(msw@2.10.2(@types/node@22.15.31)(typescript@5.8.3))(vite@6.3.5(@types/node@22.15.31)(jiti@2.4.2)(tsx@4.20.2)(yaml@2.8.0))
|
||||
'@vitest/pretty-format': 3.2.3
|
||||
'@vitest/runner': 3.2.3
|
||||
'@vitest/snapshot': 3.2.3
|
||||
@@ -2115,6 +2497,34 @@ snapshots:
|
||||
siginfo: 2.0.0
|
||||
stackback: 0.0.2
|
||||
|
||||
wrap-ansi@6.2.0:
|
||||
dependencies:
|
||||
ansi-styles: 4.3.0
|
||||
string-width: 4.2.3
|
||||
strip-ansi: 6.0.1
|
||||
|
||||
wrap-ansi@7.0.0:
|
||||
dependencies:
|
||||
ansi-styles: 4.3.0
|
||||
string-width: 4.2.3
|
||||
strip-ansi: 6.0.1
|
||||
|
||||
ws@8.18.2: {}
|
||||
|
||||
y18n@5.0.8: {}
|
||||
|
||||
yaml@2.8.0: {}
|
||||
|
||||
yargs-parser@21.1.1: {}
|
||||
|
||||
yargs@17.7.2:
|
||||
dependencies:
|
||||
cliui: 8.0.1
|
||||
escalade: 3.2.0
|
||||
get-caller-file: 2.0.5
|
||||
require-directory: 2.1.1
|
||||
string-width: 4.2.3
|
||||
y18n: 5.0.8
|
||||
yargs-parser: 21.1.1
|
||||
|
||||
yoctocolors-cjs@2.1.2: {}
|
||||
|
||||
@@ -69,7 +69,7 @@ export class CloudComputer extends BaseComputer {
|
||||
logger.info("Stopping cloud computer...");
|
||||
|
||||
if (this.interface) {
|
||||
this.interface.close();
|
||||
this.interface.disconnect();
|
||||
this.interface = undefined;
|
||||
}
|
||||
|
||||
|
||||
@@ -91,7 +91,9 @@ export abstract class BaseComputerInterface {
|
||||
return;
|
||||
} catch (error) {
|
||||
// Wait a bit before retrying
|
||||
this.logger.error(`Error connecting to websocket: ${error}`);
|
||||
this.logger.error(
|
||||
`Error connecting to websocket: ${JSON.stringify(error)}`
|
||||
);
|
||||
await new Promise((resolve) => setTimeout(resolve, 1000));
|
||||
}
|
||||
}
|
||||
@@ -102,7 +104,7 @@ export abstract class BaseComputerInterface {
|
||||
/**
|
||||
* Connect to the WebSocket server.
|
||||
*/
|
||||
protected async connect(): Promise<void> {
|
||||
public async connect(): Promise<void> {
|
||||
if (this.ws.readyState === WebSocket.OPEN) {
|
||||
return;
|
||||
}
|
||||
@@ -151,7 +153,7 @@ export abstract class BaseComputerInterface {
|
||||
/**
|
||||
* Send a command to the WebSocket server.
|
||||
*/
|
||||
protected async sendCommand(command: {
|
||||
public async sendCommand(command: {
|
||||
action: string;
|
||||
[key: string]: unknown;
|
||||
}): Promise<{ [key: string]: unknown }> {
|
||||
@@ -198,13 +200,23 @@ export abstract class BaseComputerInterface {
|
||||
return commandPromise;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the WebSocket is connected.
|
||||
*/
|
||||
public isConnected(): boolean {
|
||||
return this.ws && this.ws.readyState === WebSocket.OPEN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the interface connection.
|
||||
*/
|
||||
close(): void {
|
||||
disconnect(): void {
|
||||
this.closed = true;
|
||||
if (this.ws && this.ws.readyState !== WebSocket.CLOSED) {
|
||||
if (this.ws && this.ws.readyState === WebSocket.OPEN) {
|
||||
this.ws.close();
|
||||
} else if (this.ws && this.ws.readyState === WebSocket.CONNECTING) {
|
||||
// If still connecting, terminate the connection attempt
|
||||
this.ws.terminate();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -214,7 +226,7 @@ export abstract class BaseComputerInterface {
|
||||
* to provide more forceful cleanup.
|
||||
*/
|
||||
forceClose(): void {
|
||||
this.close();
|
||||
this.disconnect();
|
||||
}
|
||||
|
||||
// Mouse Actions
|
||||
|
||||
71
libs/computer/typescript/tests/interface/factory.test.ts
Normal file
71
libs/computer/typescript/tests/interface/factory.test.ts
Normal file
@@ -0,0 +1,71 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { InterfaceFactory } from "../../src/interface/factory.ts";
|
||||
import { MacOSComputerInterface } from "../../src/interface/macos.ts";
|
||||
import { LinuxComputerInterface } from "../../src/interface/linux.ts";
|
||||
import { WindowsComputerInterface } from "../../src/interface/windows.ts";
|
||||
import { OSType } from "../../src/types.ts";
|
||||
|
||||
describe("InterfaceFactory", () => {
|
||||
const testParams = {
|
||||
ipAddress: "192.168.1.100",
|
||||
username: "testuser",
|
||||
password: "testpass",
|
||||
apiKey: "test-api-key",
|
||||
vmName: "test-vm",
|
||||
};
|
||||
|
||||
describe("createInterfaceForOS", () => {
|
||||
it("should create MacOSComputerInterface for macOS", () => {
|
||||
const interface_ = InterfaceFactory.createInterfaceForOS(
|
||||
OSType.MACOS,
|
||||
testParams.ipAddress,
|
||||
testParams.apiKey,
|
||||
testParams.vmName
|
||||
);
|
||||
|
||||
expect(interface_).toBeInstanceOf(MacOSComputerInterface);
|
||||
});
|
||||
|
||||
it("should create LinuxComputerInterface for Linux", () => {
|
||||
const interface_ = InterfaceFactory.createInterfaceForOS(
|
||||
OSType.LINUX,
|
||||
testParams.ipAddress,
|
||||
testParams.apiKey,
|
||||
testParams.vmName
|
||||
);
|
||||
|
||||
expect(interface_).toBeInstanceOf(LinuxComputerInterface);
|
||||
});
|
||||
|
||||
it("should create WindowsComputerInterface for Windows", () => {
|
||||
const interface_ = InterfaceFactory.createInterfaceForOS(
|
||||
OSType.WINDOWS,
|
||||
testParams.ipAddress,
|
||||
testParams.apiKey,
|
||||
testParams.vmName
|
||||
);
|
||||
|
||||
expect(interface_).toBeInstanceOf(WindowsComputerInterface);
|
||||
});
|
||||
|
||||
it("should throw error for unsupported OS type", () => {
|
||||
expect(() => {
|
||||
InterfaceFactory.createInterfaceForOS(
|
||||
"unsupported" as OSType,
|
||||
testParams.ipAddress,
|
||||
testParams.apiKey,
|
||||
testParams.vmName
|
||||
);
|
||||
}).toThrow("Unsupported OS type: unsupported");
|
||||
});
|
||||
|
||||
it("should create interface without API key and VM name", () => {
|
||||
const interface_ = InterfaceFactory.createInterfaceForOS(
|
||||
OSType.MACOS,
|
||||
testParams.ipAddress
|
||||
);
|
||||
|
||||
expect(interface_).toBeInstanceOf(MacOSComputerInterface);
|
||||
});
|
||||
});
|
||||
});
|
||||
40
libs/computer/typescript/tests/interface/index.test.ts
Normal file
40
libs/computer/typescript/tests/interface/index.test.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import * as InterfaceExports from "../../src/interface/index.ts";
|
||||
|
||||
describe("Interface Module Exports", () => {
|
||||
it("should export InterfaceFactory", () => {
|
||||
expect(InterfaceExports.InterfaceFactory).toBeDefined();
|
||||
expect(InterfaceExports.InterfaceFactory.createInterfaceForOS).toBeDefined();
|
||||
});
|
||||
|
||||
it("should export BaseComputerInterface", () => {
|
||||
expect(InterfaceExports.BaseComputerInterface).toBeDefined();
|
||||
});
|
||||
|
||||
it("should export MacOSComputerInterface", () => {
|
||||
expect(InterfaceExports.MacOSComputerInterface).toBeDefined();
|
||||
});
|
||||
|
||||
it("should export LinuxComputerInterface", () => {
|
||||
expect(InterfaceExports.LinuxComputerInterface).toBeDefined();
|
||||
});
|
||||
|
||||
it("should export WindowsComputerInterface", () => {
|
||||
expect(InterfaceExports.WindowsComputerInterface).toBeDefined();
|
||||
});
|
||||
|
||||
it("should export all expected interfaces", () => {
|
||||
const expectedExports = [
|
||||
"InterfaceFactory",
|
||||
"BaseComputerInterface",
|
||||
"MacOSComputerInterface",
|
||||
"LinuxComputerInterface",
|
||||
"WindowsComputerInterface",
|
||||
];
|
||||
|
||||
const actualExports = Object.keys(InterfaceExports);
|
||||
for (const exportName of expectedExports) {
|
||||
expect(actualExports).toContain(exportName);
|
||||
}
|
||||
});
|
||||
});
|
||||
447
libs/computer/typescript/tests/interface/integration.test.ts
Normal file
447
libs/computer/typescript/tests/interface/integration.test.ts
Normal file
@@ -0,0 +1,447 @@
|
||||
import {
|
||||
describe,
|
||||
expect,
|
||||
it,
|
||||
beforeEach,
|
||||
afterEach,
|
||||
vi,
|
||||
beforeAll,
|
||||
afterAll,
|
||||
} from "vitest";
|
||||
import { InterfaceFactory } from "../../src/interface/factory.ts";
|
||||
import { OSType } from "../../src/types.ts";
|
||||
import { ws } from "msw";
|
||||
import { setupServer } from "msw/node";
|
||||
|
||||
describe("Interface Integration Tests", () => {
|
||||
const testIp = "192.168.1.100";
|
||||
const testPort = 8000;
|
||||
|
||||
// Create WebSocket server
|
||||
const server = setupServer();
|
||||
|
||||
beforeAll(() => {
|
||||
server.listen({ onUnhandledRequest: "error" });
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
server.close();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
// Reset handlers for each test
|
||||
server.resetHandlers();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
describe("Cross-platform interface creation", () => {
|
||||
it("should create correct interface for each OS type", async () => {
|
||||
const osTypes = [OSType.MACOS, OSType.LINUX, OSType.WINDOWS];
|
||||
const interfaces: Array<{
|
||||
os: OSType;
|
||||
interface: ReturnType<typeof InterfaceFactory.createInterfaceForOS>;
|
||||
}> = [];
|
||||
|
||||
// Create interfaces for each OS
|
||||
for (const os of osTypes) {
|
||||
const interface_ = InterfaceFactory.createInterfaceForOS(os, testIp);
|
||||
interfaces.push({ os, interface: interface_ });
|
||||
}
|
||||
|
||||
// Verify each interface is created correctly
|
||||
expect(interfaces).toHaveLength(3);
|
||||
for (const { os, interface: iface } of interfaces) {
|
||||
expect(iface).toBeDefined();
|
||||
// Check that the interface name contains the OS type in some form
|
||||
const osName = os.toLowerCase();
|
||||
expect(iface.constructor.name.toLowerCase()).toContain(osName);
|
||||
}
|
||||
});
|
||||
|
||||
it("should handle multiple interfaces with different IPs", async () => {
|
||||
const ips = ["192.168.1.100", "192.168.1.101", "192.168.1.102"];
|
||||
const interfaces = ips.map((ip) =>
|
||||
InterfaceFactory.createInterfaceForOS(OSType.MACOS, ip)
|
||||
);
|
||||
|
||||
// Set up WebSocket handlers for each IP
|
||||
for (const ip of ips) {
|
||||
const wsLink = ws.link(`ws://${ip}:${testPort}/ws`);
|
||||
server.use(
|
||||
wsLink.addEventListener("connection", ({ client }) => {
|
||||
client.addEventListener("message", () => {
|
||||
// Echo back success response
|
||||
client.send(JSON.stringify({ success: true }));
|
||||
});
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
// Connect all interfaces
|
||||
await Promise.all(interfaces.map((iface) => iface.connect()));
|
||||
|
||||
// Verify all are connected
|
||||
for (const iface of interfaces) {
|
||||
expect(iface.isConnected()).toBe(true);
|
||||
}
|
||||
|
||||
// Clean up
|
||||
for (const iface of interfaces) {
|
||||
iface.disconnect();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe("Connection management", () => {
|
||||
it("should handle connection lifecycle", async () => {
|
||||
// Set up WebSocket handler
|
||||
const wsLink = ws.link(`ws://${testIp}:${testPort}/ws`);
|
||||
server.use(
|
||||
wsLink.addEventListener("connection", ({ client }) => {
|
||||
client.addEventListener("message", () => {
|
||||
// Echo back success response
|
||||
client.send(JSON.stringify({ success: true }));
|
||||
});
|
||||
})
|
||||
);
|
||||
|
||||
const interface_ = InterfaceFactory.createInterfaceForOS(
|
||||
OSType.MACOS,
|
||||
testIp
|
||||
);
|
||||
|
||||
// Initially not connected
|
||||
expect(interface_.isConnected()).toBe(false);
|
||||
|
||||
// Connect
|
||||
await interface_.connect();
|
||||
expect(interface_.isConnected()).toBe(true);
|
||||
|
||||
// Disconnect
|
||||
interface_.disconnect();
|
||||
|
||||
// Wait a tick for the close to process
|
||||
await new Promise((resolve) => process.nextTick(resolve));
|
||||
expect(interface_.isConnected()).toBe(false);
|
||||
});
|
||||
|
||||
it("should handle connection errors gracefully", async () => {
|
||||
// Don't register a handler - connection will succeed but no responses
|
||||
const interface_ = InterfaceFactory.createInterfaceForOS(
|
||||
OSType.MACOS,
|
||||
"192.0.2.1" // TEST-NET-1 address
|
||||
);
|
||||
|
||||
// Should connect (WebSocket mock always connects)
|
||||
await interface_.connect();
|
||||
expect(interface_.isConnected()).toBe(true);
|
||||
|
||||
interface_.disconnect();
|
||||
});
|
||||
|
||||
it("should handle secure connections", async () => {
|
||||
const secureIp = "192.0.2.1";
|
||||
const securePort = 8443;
|
||||
|
||||
// Register handler for secure connection
|
||||
const wsLink = ws.link(`wss://${secureIp}:${securePort}/ws`);
|
||||
server.use(
|
||||
wsLink.addEventListener("connection", ({ client }) => {
|
||||
client.addEventListener("message", () => {
|
||||
// Echo back success response
|
||||
client.send(JSON.stringify({ success: true }));
|
||||
});
|
||||
})
|
||||
);
|
||||
|
||||
const interface_ = InterfaceFactory.createInterfaceForOS(
|
||||
OSType.MACOS,
|
||||
secureIp,
|
||||
"testuser",
|
||||
"testpass"
|
||||
);
|
||||
|
||||
await interface_.connect();
|
||||
expect(interface_.isConnected()).toBe(true);
|
||||
|
||||
interface_.disconnect();
|
||||
});
|
||||
});
|
||||
|
||||
describe("Performance and concurrency", () => {
|
||||
it("should handle rapid command sequences", async () => {
|
||||
const receivedCommands: string[] = [];
|
||||
|
||||
// Set up WebSocket handler that tracks commands
|
||||
const wsLink = ws.link(`ws://${testIp}:${testPort}/ws`);
|
||||
server.use(
|
||||
wsLink.addEventListener("connection", ({ client }) => {
|
||||
client.addEventListener("message", (event) => {
|
||||
const data = JSON.parse(event.data as string);
|
||||
receivedCommands.push(data.action);
|
||||
// Send response with command index
|
||||
client.send(
|
||||
JSON.stringify({
|
||||
success: true,
|
||||
data: `Response for ${data.action}`,
|
||||
})
|
||||
);
|
||||
});
|
||||
})
|
||||
);
|
||||
|
||||
const interface_ = InterfaceFactory.createInterfaceForOS(
|
||||
OSType.MACOS,
|
||||
testIp
|
||||
);
|
||||
await interface_.connect();
|
||||
|
||||
// Send multiple commands rapidly
|
||||
const commands = ["left_click", "right_click", "double_click"];
|
||||
const promises = commands.map((cmd) => {
|
||||
switch (cmd) {
|
||||
case "left_click":
|
||||
return interface_.leftClick(100, 200);
|
||||
case "right_click":
|
||||
return interface_.rightClick(150, 250);
|
||||
case "double_click":
|
||||
return interface_.doubleClick(200, 300);
|
||||
}
|
||||
});
|
||||
|
||||
await Promise.all(promises);
|
||||
|
||||
// Verify all commands were received
|
||||
expect(receivedCommands).toHaveLength(3);
|
||||
expect(receivedCommands).toContain("left_click");
|
||||
expect(receivedCommands).toContain("right_click");
|
||||
expect(receivedCommands).toContain("double_click");
|
||||
|
||||
interface_.disconnect();
|
||||
});
|
||||
|
||||
it("should maintain command order with locking", async () => {
|
||||
const receivedCommands: Array<{ action: string; index: number }> = [];
|
||||
|
||||
// Set up WebSocket handler that tracks commands with delay
|
||||
const wsLink = ws.link(`ws://${testIp}:${testPort}/ws`);
|
||||
server.use(
|
||||
wsLink.addEventListener("connection", ({ client }) => {
|
||||
client.addEventListener("message", async (event) => {
|
||||
// Add delay to simulate processing
|
||||
await new Promise((resolve) => setTimeout(resolve, 10));
|
||||
|
||||
const data = JSON.parse(event.data as string);
|
||||
receivedCommands.push({
|
||||
action: data.action,
|
||||
index: data.index,
|
||||
});
|
||||
|
||||
client.send(JSON.stringify({ success: true }));
|
||||
});
|
||||
})
|
||||
);
|
||||
|
||||
const interface_ = InterfaceFactory.createInterfaceForOS(
|
||||
OSType.MACOS,
|
||||
testIp
|
||||
);
|
||||
await interface_.connect();
|
||||
|
||||
// Helper to send command with index
|
||||
async function sendCommandWithIndex(action: string, index: number) {
|
||||
await interface_.sendCommand({ action, index });
|
||||
}
|
||||
|
||||
// Send commands in sequence
|
||||
await sendCommandWithIndex("command1", 0);
|
||||
await sendCommandWithIndex("command2", 1);
|
||||
await sendCommandWithIndex("command3", 2);
|
||||
|
||||
// Wait for all commands to be processed
|
||||
await new Promise((resolve) => setTimeout(resolve, 50));
|
||||
|
||||
// Verify commands were received in order
|
||||
expect(receivedCommands).toHaveLength(3);
|
||||
expect(receivedCommands[0]).toEqual({ action: "command1", index: 0 });
|
||||
expect(receivedCommands[1]).toEqual({ action: "command2", index: 1 });
|
||||
expect(receivedCommands[2]).toEqual({ action: "command3", index: 2 });
|
||||
|
||||
interface_.disconnect();
|
||||
});
|
||||
});
|
||||
|
||||
describe("Error handling", () => {
|
||||
it("should handle command failures", async () => {
|
||||
// Set up WebSocket handler that returns errors
|
||||
const wsLink = ws.link(`ws://${testIp}:${testPort}/ws`);
|
||||
server.use(
|
||||
wsLink.addEventListener("connection", ({ client }) => {
|
||||
client.addEventListener("message", (event) => {
|
||||
const data = JSON.parse(event.data as string);
|
||||
|
||||
if (data.action === "fail_command") {
|
||||
client.send(
|
||||
JSON.stringify({
|
||||
success: false,
|
||||
error: "Command failed",
|
||||
})
|
||||
);
|
||||
} else {
|
||||
client.send(JSON.stringify({ success: true }));
|
||||
}
|
||||
});
|
||||
})
|
||||
);
|
||||
|
||||
const interface_ = InterfaceFactory.createInterfaceForOS(
|
||||
OSType.MACOS,
|
||||
testIp
|
||||
);
|
||||
await interface_.connect();
|
||||
|
||||
// Send a failing command
|
||||
await expect(
|
||||
interface_.sendCommand({ action: "fail_command" })
|
||||
).rejects.toThrow("Command failed");
|
||||
|
||||
// Verify interface is still connected
|
||||
expect(interface_.isConnected()).toBe(true);
|
||||
|
||||
// Send a successful command
|
||||
const result = await interface_.sendCommand({
|
||||
action: "success_command",
|
||||
});
|
||||
expect(result.success).toBe(true);
|
||||
|
||||
interface_.disconnect();
|
||||
});
|
||||
|
||||
it("should handle disconnection during command", async () => {
|
||||
// Set up WebSocket handler that captures WebSocket instance
|
||||
const wsLink = ws.link(`ws://${testIp}:${testPort}/ws`);
|
||||
server.use(
|
||||
wsLink.addEventListener("connection", ({ client }) => {
|
||||
client.addEventListener("message", async () => {
|
||||
// Simulate disconnection during command processing
|
||||
await new Promise((resolve) => setTimeout(resolve, 10));
|
||||
client.close();
|
||||
});
|
||||
})
|
||||
);
|
||||
|
||||
const interface_ = InterfaceFactory.createInterfaceForOS(
|
||||
OSType.MACOS,
|
||||
testIp
|
||||
);
|
||||
await interface_.connect();
|
||||
|
||||
// Send command that will trigger disconnection
|
||||
await expect(
|
||||
interface_.sendCommand({ action: "disconnect_me" })
|
||||
).rejects.toThrow();
|
||||
|
||||
// Wait for close to process
|
||||
await new Promise((resolve) => setTimeout(resolve, 20));
|
||||
|
||||
// Verify interface is disconnected
|
||||
expect(interface_.isConnected()).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Feature-specific tests", () => {
|
||||
it("should handle screenshot commands", async () => {
|
||||
// Set up WebSocket handler
|
||||
const wsLink = ws.link(`ws://${testIp}:${testPort}/ws`);
|
||||
server.use(
|
||||
wsLink.addEventListener("connection", ({ client }) => {
|
||||
client.addEventListener("message", () => {
|
||||
// Echo back success response with screenshot data
|
||||
client.send(JSON.stringify({
|
||||
success: true,
|
||||
data: "base64encodedimage"
|
||||
}));
|
||||
});
|
||||
})
|
||||
);
|
||||
|
||||
const interface_ = InterfaceFactory.createInterfaceForOS(
|
||||
OSType.MACOS,
|
||||
testIp
|
||||
);
|
||||
await interface_.connect();
|
||||
|
||||
const screenshot = await interface_.screenshot();
|
||||
expect(screenshot).toBeInstanceOf(Buffer);
|
||||
expect(screenshot.toString("base64")).toBe("base64encodedimage");
|
||||
|
||||
interface_.disconnect();
|
||||
});
|
||||
|
||||
it("should handle screen size queries", async () => {
|
||||
// Set up WebSocket handler
|
||||
const wsLink = ws.link(`ws://${testIp}:${testPort}/ws`);
|
||||
server.use(
|
||||
wsLink.addEventListener("connection", ({ client }) => {
|
||||
client.addEventListener("message", () => {
|
||||
// Echo back success response with screen size
|
||||
client.send(JSON.stringify({
|
||||
success: true,
|
||||
data: { width: 1920, height: 1080 }
|
||||
}));
|
||||
});
|
||||
})
|
||||
);
|
||||
|
||||
const interface_ = InterfaceFactory.createInterfaceForOS(
|
||||
OSType.LINUX,
|
||||
testIp
|
||||
);
|
||||
await interface_.connect();
|
||||
|
||||
const screenSize = await interface_.getScreenSize();
|
||||
expect(screenSize).toEqual({ width: 1920, height: 1080 });
|
||||
|
||||
interface_.disconnect();
|
||||
});
|
||||
|
||||
it("should handle file operations", async () => {
|
||||
// Set up WebSocket handler
|
||||
const wsLink = ws.link(`ws://${testIp}:${testPort}/ws`);
|
||||
server.use(
|
||||
wsLink.addEventListener("connection", ({ client }) => {
|
||||
client.addEventListener("message", () => {
|
||||
// Echo back success response with file data
|
||||
client.send(JSON.stringify({
|
||||
success: true,
|
||||
data: "file content"
|
||||
}));
|
||||
});
|
||||
})
|
||||
);
|
||||
|
||||
const interface_ = InterfaceFactory.createInterfaceForOS(
|
||||
OSType.WINDOWS,
|
||||
testIp
|
||||
);
|
||||
await interface_.connect();
|
||||
|
||||
// Test file exists
|
||||
const exists = await interface_.fileExists("/test/file.txt");
|
||||
expect(exists).toBe(true);
|
||||
|
||||
// Test read text
|
||||
const content = await interface_.readText("/test/file.txt");
|
||||
expect(content).toBe("file content");
|
||||
|
||||
// Test list directory
|
||||
const files = await interface_.listDir("/test");
|
||||
expect(files).toEqual(["file1.txt", "file2.txt", "dir1"]);
|
||||
|
||||
interface_.disconnect();
|
||||
});
|
||||
});
|
||||
});
|
||||
28
libs/computer/typescript/tests/interface/linux.test.ts
Normal file
28
libs/computer/typescript/tests/interface/linux.test.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { LinuxComputerInterface } from "../../src/interface/linux.ts";
|
||||
import { MacOSComputerInterface } from "../../src/interface/macos.ts";
|
||||
|
||||
describe("LinuxComputerInterface", () => {
|
||||
const testParams = {
|
||||
ipAddress: "192.0.2.1", // TEST-NET-1 address (RFC 5737) - guaranteed not to be routable
|
||||
username: "testuser",
|
||||
password: "testpass",
|
||||
apiKey: "test-api-key",
|
||||
vmName: "test-vm",
|
||||
};
|
||||
|
||||
describe("Inheritance", () => {
|
||||
it("should extend MacOSComputerInterface", () => {
|
||||
const linuxInterface = new LinuxComputerInterface(
|
||||
testParams.ipAddress,
|
||||
testParams.username,
|
||||
testParams.password,
|
||||
testParams.apiKey,
|
||||
testParams.vmName
|
||||
);
|
||||
|
||||
expect(linuxInterface).toBeInstanceOf(MacOSComputerInterface);
|
||||
expect(linuxInterface).toBeInstanceOf(LinuxComputerInterface);
|
||||
});
|
||||
});
|
||||
});
|
||||
444
libs/computer/typescript/tests/interface/macos.test.ts
Normal file
444
libs/computer/typescript/tests/interface/macos.test.ts
Normal file
@@ -0,0 +1,444 @@
|
||||
import {
|
||||
describe,
|
||||
expect,
|
||||
it,
|
||||
beforeEach,
|
||||
afterEach,
|
||||
} from "vitest";
|
||||
import { MacOSComputerInterface } from "../../src/interface/macos.ts";
|
||||
// Import the setup.ts which already has MSW configured
|
||||
import "../setup.ts";
|
||||
|
||||
describe("MacOSComputerInterface", () => {
|
||||
// Define test parameters
|
||||
const testParams = {
|
||||
ipAddress: "192.0.2.1", // TEST-NET-1 address (RFC 5737) - guaranteed not to be routable
|
||||
username: "testuser",
|
||||
password: "testpass",
|
||||
apiKey: "test-api-key",
|
||||
vmName: "test-vm",
|
||||
};
|
||||
|
||||
// Track received messages for verification
|
||||
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
|
||||
let receivedMessages: any[] = [];
|
||||
|
||||
beforeEach(() => {
|
||||
// Clear received messages before each test
|
||||
receivedMessages = [];
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
// Clear any state after each test
|
||||
receivedMessages = [];
|
||||
});
|
||||
|
||||
describe("Connection Management", () => {
|
||||
it("should connect with proper authentication headers", async () => {
|
||||
const macosInterface = new MacOSComputerInterface(
|
||||
testParams.ipAddress,
|
||||
testParams.username,
|
||||
testParams.password,
|
||||
testParams.apiKey,
|
||||
testParams.vmName
|
||||
);
|
||||
|
||||
await macosInterface.connect();
|
||||
|
||||
// Verify the interface is connected
|
||||
expect(macosInterface.isConnected()).toBe(true);
|
||||
|
||||
await macosInterface.disconnect();
|
||||
});
|
||||
});
|
||||
|
||||
describe("Mouse Actions", () => {
|
||||
let macosInterface: MacOSComputerInterface;
|
||||
|
||||
beforeEach(async () => {
|
||||
macosInterface = new MacOSComputerInterface(
|
||||
testParams.ipAddress,
|
||||
testParams.username,
|
||||
testParams.password,
|
||||
testParams.apiKey,
|
||||
testParams.vmName
|
||||
);
|
||||
// Remove initialize() call - connection happens on first command
|
||||
await new Promise((resolve) => setTimeout(resolve, 100));
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await macosInterface.disconnect();
|
||||
});
|
||||
|
||||
it("should send mouse_down command", async () => {
|
||||
await macosInterface.mouseDown(100, 200, "left");
|
||||
|
||||
expect(receivedMessages).toHaveLength(1);
|
||||
expect(receivedMessages[0]).toEqual({
|
||||
action: "mouse_down",
|
||||
x: 100,
|
||||
y: 200,
|
||||
button: "left",
|
||||
});
|
||||
});
|
||||
|
||||
it("should send mouse_up command", async () => {
|
||||
await macosInterface.mouseUp(100, 200, "right");
|
||||
|
||||
expect(receivedMessages).toHaveLength(1);
|
||||
expect(receivedMessages[0]).toEqual({
|
||||
action: "mouse_up",
|
||||
x: 100,
|
||||
y: 200,
|
||||
button: "right",
|
||||
});
|
||||
});
|
||||
|
||||
it("should send left_click command", async () => {
|
||||
await macosInterface.leftClick(150, 250);
|
||||
|
||||
expect(receivedMessages).toHaveLength(1);
|
||||
expect(receivedMessages[0]).toEqual({
|
||||
action: "left_click",
|
||||
x: 150,
|
||||
y: 250,
|
||||
});
|
||||
});
|
||||
|
||||
it("should send right_click command", async () => {
|
||||
await macosInterface.rightClick(150, 250);
|
||||
|
||||
expect(receivedMessages).toHaveLength(1);
|
||||
expect(receivedMessages[0]).toEqual({
|
||||
action: "right_click",
|
||||
x: 150,
|
||||
y: 250,
|
||||
});
|
||||
});
|
||||
|
||||
it("should send double_click command", async () => {
|
||||
await macosInterface.doubleClick(150, 250);
|
||||
|
||||
expect(receivedMessages).toHaveLength(1);
|
||||
expect(receivedMessages[0]).toEqual({
|
||||
action: "double_click",
|
||||
x: 150,
|
||||
y: 250,
|
||||
});
|
||||
});
|
||||
|
||||
it("should send move_cursor command", async () => {
|
||||
await macosInterface.moveCursor(300, 400);
|
||||
|
||||
expect(receivedMessages).toHaveLength(1);
|
||||
expect(receivedMessages[0]).toEqual({
|
||||
action: "move_cursor",
|
||||
x: 300,
|
||||
y: 400,
|
||||
});
|
||||
});
|
||||
|
||||
it("should send drag_to command", async () => {
|
||||
await macosInterface.dragTo(500, 600, "left", 1.5);
|
||||
|
||||
expect(receivedMessages).toHaveLength(1);
|
||||
expect(receivedMessages[0]).toEqual({
|
||||
action: "drag_to",
|
||||
x: 500,
|
||||
y: 600,
|
||||
button: "left",
|
||||
duration: 1.5,
|
||||
});
|
||||
});
|
||||
|
||||
it("should send scroll command", async () => {
|
||||
await macosInterface.scroll(0, 10);
|
||||
|
||||
expect(receivedMessages).toHaveLength(1);
|
||||
expect(receivedMessages[0]).toEqual({
|
||||
action: "scroll",
|
||||
x: 0,
|
||||
y: 10,
|
||||
clicks: 5,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("Keyboard Actions", () => {
|
||||
let macosInterface: MacOSComputerInterface;
|
||||
|
||||
beforeEach(async () => {
|
||||
macosInterface = new MacOSComputerInterface(
|
||||
testParams.ipAddress,
|
||||
testParams.username,
|
||||
testParams.password,
|
||||
testParams.apiKey,
|
||||
testParams.vmName
|
||||
);
|
||||
// Remove initialize() call
|
||||
await new Promise((resolve) => setTimeout(resolve, 100));
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await macosInterface.disconnect();
|
||||
});
|
||||
|
||||
it("should send key_down command", async () => {
|
||||
await macosInterface.keyDown("a");
|
||||
|
||||
expect(receivedMessages).toHaveLength(1);
|
||||
expect(receivedMessages[0]).toEqual({
|
||||
action: "key_down",
|
||||
key: "a",
|
||||
});
|
||||
});
|
||||
|
||||
it("should send key_up command", async () => {
|
||||
await macosInterface.keyUp("a");
|
||||
|
||||
expect(receivedMessages).toHaveLength(1);
|
||||
expect(receivedMessages[0]).toEqual({
|
||||
action: "key_up",
|
||||
key: "a",
|
||||
});
|
||||
});
|
||||
|
||||
it("should send key_press command", async () => {
|
||||
await macosInterface.keyDown("enter");
|
||||
|
||||
expect(receivedMessages).toHaveLength(1);
|
||||
expect(receivedMessages[0]).toEqual({
|
||||
action: "key_press",
|
||||
key: "enter",
|
||||
});
|
||||
});
|
||||
|
||||
it("should send type_text command", async () => {
|
||||
await macosInterface.typeText("Hello, World!");
|
||||
|
||||
expect(receivedMessages).toHaveLength(1);
|
||||
expect(receivedMessages[0]).toEqual({
|
||||
action: "type_text",
|
||||
text: "Hello, World!",
|
||||
});
|
||||
});
|
||||
|
||||
it("should send hotkey command", async () => {
|
||||
await macosInterface.hotkey("cmd", "c");
|
||||
|
||||
expect(receivedMessages).toHaveLength(1);
|
||||
expect(receivedMessages[0]).toEqual({
|
||||
action: "hotkey",
|
||||
keys: ["cmd", "c"],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("Screen Actions", () => {
|
||||
let macosInterface: MacOSComputerInterface;
|
||||
|
||||
beforeEach(async () => {
|
||||
macosInterface = new MacOSComputerInterface(
|
||||
testParams.ipAddress,
|
||||
testParams.username,
|
||||
testParams.password,
|
||||
testParams.apiKey,
|
||||
testParams.vmName
|
||||
);
|
||||
// Remove initialize() call
|
||||
await new Promise((resolve) => setTimeout(resolve, 100));
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await macosInterface.disconnect();
|
||||
});
|
||||
|
||||
it("should get screenshot", async () => {
|
||||
const screenshot = await macosInterface.screenshot();
|
||||
|
||||
expect(receivedMessages).toHaveLength(1);
|
||||
expect(receivedMessages[0]).toEqual({
|
||||
action: "screenshot",
|
||||
});
|
||||
expect(screenshot).toBe("base64encodedimage");
|
||||
});
|
||||
|
||||
it("should get screen size", async () => {
|
||||
const screenSize = await macosInterface.getScreenSize();
|
||||
|
||||
expect(receivedMessages).toHaveLength(1);
|
||||
expect(receivedMessages[0]).toEqual({
|
||||
action: "get_screen_size",
|
||||
});
|
||||
expect(screenSize).toEqual({ width: 1920, height: 1080 });
|
||||
});
|
||||
|
||||
it("should get cursor position", async () => {
|
||||
const position = await macosInterface.getCursorPosition();
|
||||
|
||||
expect(receivedMessages).toHaveLength(1);
|
||||
expect(receivedMessages[0]).toEqual({
|
||||
action: "get_cursor_position",
|
||||
});
|
||||
expect(position).toEqual({ x: 100, y: 200 });
|
||||
});
|
||||
|
||||
it("should get accessibility tree", async () => {
|
||||
const tree = await macosInterface.getAccessibilityTree();
|
||||
|
||||
expect(receivedMessages).toHaveLength(1);
|
||||
expect(receivedMessages[0]).toEqual({
|
||||
action: "get_accessibility_tree",
|
||||
});
|
||||
expect(tree).toEqual({
|
||||
role: "window",
|
||||
title: "Test Window",
|
||||
children: [],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("System Actions", () => {
|
||||
let macosInterface: MacOSComputerInterface;
|
||||
|
||||
beforeEach(async () => {
|
||||
macosInterface = new MacOSComputerInterface(
|
||||
testParams.ipAddress,
|
||||
testParams.username,
|
||||
testParams.password,
|
||||
testParams.apiKey,
|
||||
testParams.vmName
|
||||
);
|
||||
// Remove initialize() call
|
||||
await new Promise((resolve) => setTimeout(resolve, 100));
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await macosInterface.disconnect();
|
||||
});
|
||||
|
||||
it("should run command", async () => {
|
||||
const result = await macosInterface.runCommand("ls -la");
|
||||
|
||||
expect(receivedMessages).toHaveLength(1);
|
||||
expect(receivedMessages[0]).toEqual({
|
||||
action: "run_command",
|
||||
command: "ls -la",
|
||||
});
|
||||
expect(result).toEqual({
|
||||
stdout: "command output",
|
||||
stderr: "",
|
||||
returncode: 0,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("Error Handling", () => {
|
||||
it("should handle WebSocket connection errors", async () => {
|
||||
// Use a valid but unreachable IP to avoid DNS errors
|
||||
const macosInterface = new MacOSComputerInterface(
|
||||
testParams.ipAddress,
|
||||
testParams.username,
|
||||
testParams.password,
|
||||
testParams.apiKey,
|
||||
testParams.vmName
|
||||
);
|
||||
|
||||
// Try to send a command - should fail with connection error
|
||||
await expect(macosInterface.screenshot()).rejects.toThrow();
|
||||
|
||||
await macosInterface.disconnect();
|
||||
});
|
||||
|
||||
it("should handle server error responses", async () => {
|
||||
// Override the handler to send error response
|
||||
// server.use(
|
||||
// chat.addEventListener("connection", ({ client, server }) => {
|
||||
// client.addEventListener("message", () => {
|
||||
// server.send(
|
||||
// JSON.stringify({
|
||||
// success: false,
|
||||
// error: "Command failed",
|
||||
// })
|
||||
// );
|
||||
// });
|
||||
// })
|
||||
// );
|
||||
|
||||
const macosInterface = new MacOSComputerInterface(
|
||||
testParams.ipAddress,
|
||||
testParams.username,
|
||||
testParams.password,
|
||||
testParams.apiKey,
|
||||
testParams.vmName
|
||||
);
|
||||
// Remove initialize() call
|
||||
await new Promise((resolve) => setTimeout(resolve, 100));
|
||||
|
||||
await expect(macosInterface.screenshot()).rejects.toThrow(
|
||||
"Command failed"
|
||||
);
|
||||
|
||||
await macosInterface.disconnect();
|
||||
});
|
||||
|
||||
it("should handle closed connection", async () => {
|
||||
const macosInterface = new MacOSComputerInterface(
|
||||
testParams.ipAddress,
|
||||
testParams.username,
|
||||
testParams.password,
|
||||
testParams.apiKey,
|
||||
testParams.vmName
|
||||
);
|
||||
|
||||
// Send a command to trigger connection
|
||||
await macosInterface.screenshot();
|
||||
|
||||
// Close the interface
|
||||
await macosInterface.disconnect();
|
||||
|
||||
// Try to use after closing
|
||||
await expect(macosInterface.screenshot()).rejects.toThrow(
|
||||
"Interface is closed"
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Command Locking", () => {
|
||||
let macosInterface: MacOSComputerInterface;
|
||||
|
||||
beforeEach(async () => {
|
||||
macosInterface = new MacOSComputerInterface(
|
||||
testParams.ipAddress,
|
||||
testParams.username,
|
||||
testParams.password,
|
||||
testParams.apiKey,
|
||||
testParams.vmName
|
||||
);
|
||||
// Remove initialize() call
|
||||
await new Promise((resolve) => setTimeout(resolve, 100));
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await macosInterface.disconnect();
|
||||
});
|
||||
|
||||
it("should serialize commands", async () => {
|
||||
// Send multiple commands simultaneously
|
||||
const promises = [
|
||||
macosInterface.leftClick(100, 100),
|
||||
macosInterface.rightClick(200, 200),
|
||||
macosInterface.typeText("test"),
|
||||
];
|
||||
|
||||
await Promise.all(promises);
|
||||
|
||||
// Commands should be sent in order
|
||||
expect(receivedMessages).toHaveLength(3);
|
||||
expect(receivedMessages[0].action).toBe("left_click");
|
||||
expect(receivedMessages[1].action).toBe("right_click");
|
||||
expect(receivedMessages[2].action).toBe("type_text");
|
||||
});
|
||||
});
|
||||
});
|
||||
28
libs/computer/typescript/tests/interface/windows.test.ts
Normal file
28
libs/computer/typescript/tests/interface/windows.test.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { WindowsComputerInterface } from "../../src/interface/windows.ts";
|
||||
import { MacOSComputerInterface } from "../../src/interface/macos.ts";
|
||||
|
||||
describe("WindowsComputerInterface", () => {
|
||||
const testParams = {
|
||||
ipAddress: "192.0.2.1", // TEST-NET-1 address (RFC 5737) - guaranteed not to be routable
|
||||
username: "testuser",
|
||||
password: "testpass",
|
||||
apiKey: "test-api-key",
|
||||
vmName: "test-vm",
|
||||
};
|
||||
|
||||
describe("Inheritance", () => {
|
||||
it("should extend MacOSComputerInterface", () => {
|
||||
const windowsInterface = new WindowsComputerInterface(
|
||||
testParams.ipAddress,
|
||||
testParams.username,
|
||||
testParams.password,
|
||||
testParams.apiKey,
|
||||
testParams.vmName
|
||||
);
|
||||
|
||||
expect(windowsInterface).toBeInstanceOf(MacOSComputerInterface);
|
||||
expect(windowsInterface).toBeInstanceOf(WindowsComputerInterface);
|
||||
});
|
||||
});
|
||||
});
|
||||
26
libs/computer/typescript/tests/setup.ts
Normal file
26
libs/computer/typescript/tests/setup.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import { afterAll, afterEach, beforeAll } from "vitest";
|
||||
import { setupServer } from "msw/node";
|
||||
import { ws } from "msw";
|
||||
|
||||
const chat = ws.link("wss://chat.example.com");
|
||||
|
||||
const wsHandlers = [
|
||||
chat.addEventListener("connection", ({ client }) => {
|
||||
client.addEventListener("message", (event) => {
|
||||
console.log("Received message from client:", event.data);
|
||||
// Echo the received message back to the client
|
||||
client.send(`Server received: ${event.data}`);
|
||||
});
|
||||
}),
|
||||
];
|
||||
|
||||
const server = setupServer(...wsHandlers);
|
||||
|
||||
// Start server before all tests
|
||||
beforeAll(() => server.listen({ onUnhandledRequest: "error" }));
|
||||
|
||||
// Close server after all tests
|
||||
afterAll(() => server.close());
|
||||
|
||||
// Reset handlers after each test for test isolation
|
||||
afterEach(() => server.resetHandlers());
|
||||
@@ -1,3 +1,9 @@
|
||||
import { defineConfig } from 'vitest/config'
|
||||
import { defineConfig } from "vitest/config";
|
||||
|
||||
export default defineConfig({})
|
||||
export default defineConfig({
|
||||
test: {
|
||||
setupFiles: ["./tests/setup.ts"],
|
||||
environment: "node",
|
||||
globals: true,
|
||||
},
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user