Compare commits

...

4 Commits

12 changed files with 224 additions and 152 deletions

View File

@@ -1,5 +1,25 @@
# Changelog
## 2025-10-17 - 2.6.0 - feat(runtime-adapters)
Add runtime environment availability check and logger output; normalize runtime version strings
- Introduce checkEnvironment() in TsTest and invoke it at the start of run() to detect available runtimes before executing tests.
- Add environmentCheck(availability) to TsTestLogger to print a human-friendly environment summary (with JSON and quiet-mode handling).
- Normalize reported runtime version strings from adapters: prefix Deno and Bun versions with 'v' and simplify Chromium version text.
- Display runtime availability information to the user before moving previous logs or running tests.
- Includes addition of local .claude/settings.local.json (local dev/tooling settings).
## 2025-10-17 - 2.5.2 - fix(runtime.node)
Improve Node runtime adapter to use tsrun.spawnPath, strengthen tsrun detection, and improve process lifecycle and loader handling; update tsrun dependency.
- Use tsrun.spawnPath to spawn Node test processes and pass structured spawn options (cwd, env, args, stdio).
- Detect tsrun availability via plugins.tsrun and require spawnPath; provide a clearer error message when tsrun is missing or outdated.
- Pass --web via spawn args and set TSTEST_FILTER_TAGS on the spawned process env instead of mutating the parent process.env.
- When a 00init.ts exists, create a temporary loader that imports both 00init.ts and the test file, run the loader via tsrun.spawnPath, and clean up the loader after execution.
- Use tsrunProcess.terminate()/kill for timeouts to ensure proper process termination and improve cleanup handling.
- Export tsrun from ts/tstest.plugins.ts so runtime code can access tsrun APIs via the plugins object.
- Bump dependency @git.zone/tsrun from ^1.3.4 to ^1.6.2 in package.json.
## 2025-10-16 - 2.5.1 - fix(deps)
Bump dependencies and add local tooling settings

0
cli.js Normal file → Executable file
View File

View File

@@ -1,6 +1,6 @@
{
"name": "@git.zone/tstest",
"version": "2.5.1",
"version": "2.6.0",
"private": false,
"description": "a test utility to run tests that match test/**/*.ts",
"exports": {
@@ -30,7 +30,7 @@
"dependencies": {
"@api.global/typedserver": "^3.0.79",
"@git.zone/tsbundle": "^2.5.1",
"@git.zone/tsrun": "^1.3.4",
"@git.zone/tsrun": "^1.6.2",
"@push.rocks/consolecolor": "^2.0.3",
"@push.rocks/qenv": "^6.1.3",
"@push.rocks/smartbrowser": "^2.0.8",

226
pnpm-lock.yaml generated
View File

@@ -15,8 +15,8 @@ importers:
specifier: ^2.5.1
version: 2.5.1
'@git.zone/tsrun':
specifier: ^1.3.4
version: 1.3.4
specifier: ^1.6.2
version: 1.6.2
'@push.rocks/consolecolor':
specifier: ^2.0.3
version: 2.0.3
@@ -425,8 +425,8 @@ packages:
'@emnapi/wasi-threads@1.0.4':
resolution: {integrity: sha512-PJR+bOmMOPH8AtcTGAyYNiuJ3/Fcoj2XN/gBEWzDIKh254XO+mM9XoXHk5GNEhodxeMznbg7BlRojVbKN+gC6g==}
'@esbuild/aix-ppc64@0.25.10':
resolution: {integrity: sha512-0NFWnA+7l41irNuaSVlLfgNT12caWJVLzp5eAVhZ0z1qpxbockccEt3s+149rE64VUI3Ml2zt8Nv5JVc4QXTsw==}
'@esbuild/aix-ppc64@0.25.11':
resolution: {integrity: sha512-Xt1dOL13m8u0WE8iplx9Ibbm+hFAO0GsU2P34UNoDGvZYkY8ifSiy6Zuc1lYxfG7svWE2fzqCUmFp5HCn51gJg==}
engines: {node: '>=18'}
cpu: [ppc64]
os: [aix]
@@ -437,8 +437,8 @@ packages:
cpu: [ppc64]
os: [aix]
'@esbuild/android-arm64@0.25.10':
resolution: {integrity: sha512-LSQa7eDahypv/VO6WKohZGPSJDq5OVOo3UoFR1E4t4Gj1W7zEQMUhI+lo81H+DtB+kP+tDgBp+M4oNCwp6kffg==}
'@esbuild/android-arm64@0.25.11':
resolution: {integrity: sha512-9slpyFBc4FPPz48+f6jyiXOx/Y4v34TUeDDXJpZqAWQn/08lKGeD8aDp9TMn9jDz2CiEuHwfhRmGBvpnd/PWIQ==}
engines: {node: '>=18'}
cpu: [arm64]
os: [android]
@@ -449,8 +449,8 @@ packages:
cpu: [arm64]
os: [android]
'@esbuild/android-arm@0.25.10':
resolution: {integrity: sha512-dQAxF1dW1C3zpeCDc5KqIYuZ1tgAdRXNoZP7vkBIRtKZPYe2xVr/d3SkirklCHudW1B45tGiUlz2pUWDfbDD4w==}
'@esbuild/android-arm@0.25.11':
resolution: {integrity: sha512-uoa7dU+Dt3HYsethkJ1k6Z9YdcHjTrSb5NUy66ZfZaSV8hEYGD5ZHbEMXnqLFlbBflLsl89Zke7CAdDJ4JI+Gg==}
engines: {node: '>=18'}
cpu: [arm]
os: [android]
@@ -461,8 +461,8 @@ packages:
cpu: [arm]
os: [android]
'@esbuild/android-x64@0.25.10':
resolution: {integrity: sha512-MiC9CWdPrfhibcXwr39p9ha1x0lZJ9KaVfvzA0Wxwz9ETX4v5CHfF09bx935nHlhi+MxhA63dKRRQLiVgSUtEg==}
'@esbuild/android-x64@0.25.11':
resolution: {integrity: sha512-Sgiab4xBjPU1QoPEIqS3Xx+R2lezu0LKIEcYe6pftr56PqPygbB7+szVnzoShbx64MUupqoE0KyRlN7gezbl8g==}
engines: {node: '>=18'}
cpu: [x64]
os: [android]
@@ -473,8 +473,8 @@ packages:
cpu: [x64]
os: [android]
'@esbuild/darwin-arm64@0.25.10':
resolution: {integrity: sha512-JC74bdXcQEpW9KkV326WpZZjLguSZ3DfS8wrrvPMHgQOIEIG/sPXEN/V8IssoJhbefLRcRqw6RQH2NnpdprtMA==}
'@esbuild/darwin-arm64@0.25.11':
resolution: {integrity: sha512-VekY0PBCukppoQrycFxUqkCojnTQhdec0vevUL/EDOCnXd9LKWqD/bHwMPzigIJXPhC59Vd1WFIL57SKs2mg4w==}
engines: {node: '>=18'}
cpu: [arm64]
os: [darwin]
@@ -485,8 +485,8 @@ packages:
cpu: [arm64]
os: [darwin]
'@esbuild/darwin-x64@0.25.10':
resolution: {integrity: sha512-tguWg1olF6DGqzws97pKZ8G2L7Ig1vjDmGTwcTuYHbuU6TTjJe5FXbgs5C1BBzHbJ2bo1m3WkQDbWO2PvamRcg==}
'@esbuild/darwin-x64@0.25.11':
resolution: {integrity: sha512-+hfp3yfBalNEpTGp9loYgbknjR695HkqtY3d3/JjSRUyPg/xd6q+mQqIb5qdywnDxRZykIHs3axEqU6l1+oWEQ==}
engines: {node: '>=18'}
cpu: [x64]
os: [darwin]
@@ -497,8 +497,8 @@ packages:
cpu: [x64]
os: [darwin]
'@esbuild/freebsd-arm64@0.25.10':
resolution: {integrity: sha512-3ZioSQSg1HT2N05YxeJWYR+Libe3bREVSdWhEEgExWaDtyFbbXWb49QgPvFH8u03vUPX10JhJPcz7s9t9+boWg==}
'@esbuild/freebsd-arm64@0.25.11':
resolution: {integrity: sha512-CmKjrnayyTJF2eVuO//uSjl/K3KsMIeYeyN7FyDBjsR3lnSJHaXlVoAK8DZa7lXWChbuOk7NjAc7ygAwrnPBhA==}
engines: {node: '>=18'}
cpu: [arm64]
os: [freebsd]
@@ -509,8 +509,8 @@ packages:
cpu: [arm64]
os: [freebsd]
'@esbuild/freebsd-x64@0.25.10':
resolution: {integrity: sha512-LLgJfHJk014Aa4anGDbh8bmI5Lk+QidDmGzuC2D+vP7mv/GeSN+H39zOf7pN5N8p059FcOfs2bVlrRr4SK9WxA==}
'@esbuild/freebsd-x64@0.25.11':
resolution: {integrity: sha512-Dyq+5oscTJvMaYPvW3x3FLpi2+gSZTCE/1ffdwuM6G1ARang/mb3jvjxs0mw6n3Lsw84ocfo9CrNMqc5lTfGOw==}
engines: {node: '>=18'}
cpu: [x64]
os: [freebsd]
@@ -521,8 +521,8 @@ packages:
cpu: [x64]
os: [freebsd]
'@esbuild/linux-arm64@0.25.10':
resolution: {integrity: sha512-5luJWN6YKBsawd5f9i4+c+geYiVEw20FVW5x0v1kEMWNq8UctFjDiMATBxLvmmHA4bf7F6hTRaJgtghFr9iziQ==}
'@esbuild/linux-arm64@0.25.11':
resolution: {integrity: sha512-Qr8AzcplUhGvdyUF08A1kHU3Vr2O88xxP0Tm8GcdVOUm25XYcMPp2YqSVHbLuXzYQMf9Bh/iKx7YPqECs6ffLA==}
engines: {node: '>=18'}
cpu: [arm64]
os: [linux]
@@ -533,8 +533,8 @@ packages:
cpu: [arm64]
os: [linux]
'@esbuild/linux-arm@0.25.10':
resolution: {integrity: sha512-oR31GtBTFYCqEBALI9r6WxoU/ZofZl962pouZRTEYECvNF/dtXKku8YXcJkhgK/beU+zedXfIzHijSRapJY3vg==}
'@esbuild/linux-arm@0.25.11':
resolution: {integrity: sha512-TBMv6B4kCfrGJ8cUPo7vd6NECZH/8hPpBHHlYI3qzoYFvWu2AdTvZNuU/7hsbKWqu/COU7NIK12dHAAqBLLXgw==}
engines: {node: '>=18'}
cpu: [arm]
os: [linux]
@@ -545,8 +545,8 @@ packages:
cpu: [arm]
os: [linux]
'@esbuild/linux-ia32@0.25.10':
resolution: {integrity: sha512-NrSCx2Kim3EnnWgS4Txn0QGt0Xipoumb6z6sUtl5bOEZIVKhzfyp/Lyw4C1DIYvzeW/5mWYPBFJU3a/8Yr75DQ==}
'@esbuild/linux-ia32@0.25.11':
resolution: {integrity: sha512-TmnJg8BMGPehs5JKrCLqyWTVAvielc615jbkOirATQvWWB1NMXY77oLMzsUjRLa0+ngecEmDGqt5jiDC6bfvOw==}
engines: {node: '>=18'}
cpu: [ia32]
os: [linux]
@@ -557,8 +557,8 @@ packages:
cpu: [ia32]
os: [linux]
'@esbuild/linux-loong64@0.25.10':
resolution: {integrity: sha512-xoSphrd4AZda8+rUDDfD9J6FUMjrkTz8itpTITM4/xgerAZZcFW7Dv+sun7333IfKxGG8gAq+3NbfEMJfiY+Eg==}
'@esbuild/linux-loong64@0.25.11':
resolution: {integrity: sha512-DIGXL2+gvDaXlaq8xruNXUJdT5tF+SBbJQKbWy/0J7OhU8gOHOzKmGIlfTTl6nHaCOoipxQbuJi7O++ldrxgMw==}
engines: {node: '>=18'}
cpu: [loong64]
os: [linux]
@@ -569,8 +569,8 @@ packages:
cpu: [loong64]
os: [linux]
'@esbuild/linux-mips64el@0.25.10':
resolution: {integrity: sha512-ab6eiuCwoMmYDyTnyptoKkVS3k8fy/1Uvq7Dj5czXI6DF2GqD2ToInBI0SHOp5/X1BdZ26RKc5+qjQNGRBelRA==}
'@esbuild/linux-mips64el@0.25.11':
resolution: {integrity: sha512-Osx1nALUJu4pU43o9OyjSCXokFkFbyzjXb6VhGIJZQ5JZi8ylCQ9/LFagolPsHtgw6himDSyb5ETSfmp4rpiKQ==}
engines: {node: '>=18'}
cpu: [mips64el]
os: [linux]
@@ -581,8 +581,8 @@ packages:
cpu: [mips64el]
os: [linux]
'@esbuild/linux-ppc64@0.25.10':
resolution: {integrity: sha512-NLinzzOgZQsGpsTkEbdJTCanwA5/wozN9dSgEl12haXJBzMTpssebuXR42bthOF3z7zXFWH1AmvWunUCkBE4EA==}
'@esbuild/linux-ppc64@0.25.11':
resolution: {integrity: sha512-nbLFgsQQEsBa8XSgSTSlrnBSrpoWh7ioFDUmwo158gIm5NNP+17IYmNWzaIzWmgCxq56vfr34xGkOcZ7jX6CPw==}
engines: {node: '>=18'}
cpu: [ppc64]
os: [linux]
@@ -593,8 +593,8 @@ packages:
cpu: [ppc64]
os: [linux]
'@esbuild/linux-riscv64@0.25.10':
resolution: {integrity: sha512-FE557XdZDrtX8NMIeA8LBJX3dC2M8VGXwfrQWU7LB5SLOajfJIxmSdyL/gU1m64Zs9CBKvm4UAuBp5aJ8OgnrA==}
'@esbuild/linux-riscv64@0.25.11':
resolution: {integrity: sha512-HfyAmqZi9uBAbgKYP1yGuI7tSREXwIb438q0nqvlpxAOs3XnZ8RsisRfmVsgV486NdjD7Mw2UrFSw51lzUk1ww==}
engines: {node: '>=18'}
cpu: [riscv64]
os: [linux]
@@ -605,8 +605,8 @@ packages:
cpu: [riscv64]
os: [linux]
'@esbuild/linux-s390x@0.25.10':
resolution: {integrity: sha512-3BBSbgzuB9ajLoVZk0mGu+EHlBwkusRmeNYdqmznmMc9zGASFjSsxgkNsqmXugpPk00gJ0JNKh/97nxmjctdew==}
'@esbuild/linux-s390x@0.25.11':
resolution: {integrity: sha512-HjLqVgSSYnVXRisyfmzsH6mXqyvj0SA7pG5g+9W7ESgwA70AXYNpfKBqh1KbTxmQVaYxpzA/SvlB9oclGPbApw==}
engines: {node: '>=18'}
cpu: [s390x]
os: [linux]
@@ -617,8 +617,8 @@ packages:
cpu: [s390x]
os: [linux]
'@esbuild/linux-x64@0.25.10':
resolution: {integrity: sha512-QSX81KhFoZGwenVyPoberggdW1nrQZSvfVDAIUXr3WqLRZGZqWk/P4T8p2SP+de2Sr5HPcvjhcJzEiulKgnxtA==}
'@esbuild/linux-x64@0.25.11':
resolution: {integrity: sha512-HSFAT4+WYjIhrHxKBwGmOOSpphjYkcswF449j6EjsjbinTZbp8PJtjsVK1XFJStdzXdy/jaddAep2FGY+wyFAQ==}
engines: {node: '>=18'}
cpu: [x64]
os: [linux]
@@ -629,8 +629,8 @@ packages:
cpu: [x64]
os: [linux]
'@esbuild/netbsd-arm64@0.25.10':
resolution: {integrity: sha512-AKQM3gfYfSW8XRk8DdMCzaLUFB15dTrZfnX8WXQoOUpUBQ+NaAFCP1kPS/ykbbGYz7rxn0WS48/81l9hFl3u4A==}
'@esbuild/netbsd-arm64@0.25.11':
resolution: {integrity: sha512-hr9Oxj1Fa4r04dNpWr3P8QKVVsjQhqrMSUzZzf+LZcYjZNqhA3IAfPQdEh1FLVUJSiu6sgAwp3OmwBfbFgG2Xg==}
engines: {node: '>=18'}
cpu: [arm64]
os: [netbsd]
@@ -641,8 +641,8 @@ packages:
cpu: [arm64]
os: [netbsd]
'@esbuild/netbsd-x64@0.25.10':
resolution: {integrity: sha512-7RTytDPGU6fek/hWuN9qQpeGPBZFfB4zZgcz2VK2Z5VpdUxEI8JKYsg3JfO0n/Z1E/6l05n0unDCNc4HnhQGig==}
'@esbuild/netbsd-x64@0.25.11':
resolution: {integrity: sha512-u7tKA+qbzBydyj0vgpu+5h5AeudxOAGncb8N6C9Kh1N4n7wU1Xw1JDApsRjpShRpXRQlJLb9wY28ELpwdPcZ7A==}
engines: {node: '>=18'}
cpu: [x64]
os: [netbsd]
@@ -653,8 +653,8 @@ packages:
cpu: [x64]
os: [netbsd]
'@esbuild/openbsd-arm64@0.25.10':
resolution: {integrity: sha512-5Se0VM9Wtq797YFn+dLimf2Zx6McttsH2olUBsDml+lm0GOCRVebRWUvDtkY4BWYv/3NgzS8b/UM3jQNh5hYyw==}
'@esbuild/openbsd-arm64@0.25.11':
resolution: {integrity: sha512-Qq6YHhayieor3DxFOoYM1q0q1uMFYb7cSpLD2qzDSvK1NAvqFi8Xgivv0cFC6J+hWVw2teCYltyy9/m/14ryHg==}
engines: {node: '>=18'}
cpu: [arm64]
os: [openbsd]
@@ -665,8 +665,8 @@ packages:
cpu: [arm64]
os: [openbsd]
'@esbuild/openbsd-x64@0.25.10':
resolution: {integrity: sha512-XkA4frq1TLj4bEMB+2HnI0+4RnjbuGZfet2gs/LNs5Hc7D89ZQBHQ0gL2ND6Lzu1+QVkjp3x1gIcPKzRNP8bXw==}
'@esbuild/openbsd-x64@0.25.11':
resolution: {integrity: sha512-CN+7c++kkbrckTOz5hrehxWN7uIhFFlmS/hqziSFVWpAzpWrQoAG4chH+nN3Be+Kzv/uuo7zhX716x3Sn2Jduw==}
engines: {node: '>=18'}
cpu: [x64]
os: [openbsd]
@@ -677,8 +677,8 @@ packages:
cpu: [x64]
os: [openbsd]
'@esbuild/openharmony-arm64@0.25.10':
resolution: {integrity: sha512-AVTSBhTX8Y/Fz6OmIVBip9tJzZEUcY8WLh7I59+upa5/GPhh2/aM6bvOMQySspnCCHvFi79kMtdJS1w0DXAeag==}
'@esbuild/openharmony-arm64@0.25.11':
resolution: {integrity: sha512-rOREuNIQgaiR+9QuNkbkxubbp8MSO9rONmwP5nKncnWJ9v5jQ4JxFnLu4zDSRPf3x4u+2VN4pM4RdyIzDty/wQ==}
engines: {node: '>=18'}
cpu: [arm64]
os: [openharmony]
@@ -689,8 +689,8 @@ packages:
cpu: [arm64]
os: [openharmony]
'@esbuild/sunos-x64@0.25.10':
resolution: {integrity: sha512-fswk3XT0Uf2pGJmOpDB7yknqhVkJQkAQOcW/ccVOtfx05LkbWOaRAtn5SaqXypeKQra1QaEa841PgrSL9ubSPQ==}
'@esbuild/sunos-x64@0.25.11':
resolution: {integrity: sha512-nq2xdYaWxyg9DcIyXkZhcYulC6pQ2FuCgem3LI92IwMgIZ69KHeY8T4Y88pcwoLIjbed8n36CyKoYRDygNSGhA==}
engines: {node: '>=18'}
cpu: [x64]
os: [sunos]
@@ -701,8 +701,8 @@ packages:
cpu: [x64]
os: [sunos]
'@esbuild/win32-arm64@0.25.10':
resolution: {integrity: sha512-ah+9b59KDTSfpaCg6VdJoOQvKjI33nTaQr4UluQwW7aEwZQsbMCfTmfEO4VyewOxx4RaDT/xCy9ra2GPWmO7Kw==}
'@esbuild/win32-arm64@0.25.11':
resolution: {integrity: sha512-3XxECOWJq1qMZ3MN8srCJ/QfoLpL+VaxD/WfNRm1O3B4+AZ/BnLVgFbUV3eiRYDMXetciH16dwPbbHqwe1uU0Q==}
engines: {node: '>=18'}
cpu: [arm64]
os: [win32]
@@ -713,8 +713,8 @@ packages:
cpu: [arm64]
os: [win32]
'@esbuild/win32-ia32@0.25.10':
resolution: {integrity: sha512-QHPDbKkrGO8/cz9LKVnJU22HOi4pxZnZhhA2HYHez5Pz4JeffhDjf85E57Oyco163GnzNCVkZK0b/n4Y0UHcSw==}
'@esbuild/win32-ia32@0.25.11':
resolution: {integrity: sha512-3ukss6gb9XZ8TlRyJlgLn17ecsK4NSQTmdIXRASVsiS2sQ6zPPZklNJT5GR5tE/MUarymmy8kCEf5xPCNCqVOA==}
engines: {node: '>=18'}
cpu: [ia32]
os: [win32]
@@ -725,8 +725,8 @@ packages:
cpu: [ia32]
os: [win32]
'@esbuild/win32-x64@0.25.10':
resolution: {integrity: sha512-9KpxSVFCu0iK1owoez6aC/s/EdUQLDN3adTxGCqxMVhrPDj6bt5dbrHDXUuq+Bs2vATFBBrQS5vdQ/Ed2P+nbw==}
'@esbuild/win32-x64@0.25.11':
resolution: {integrity: sha512-D7Hpz6A2L4hzsRpPaCYkQnGOotdUpDzSGRIv9I+1ITdHROSFUWW95ZPZWQmGka1Fg7W3zFJowyn9WGwMJ0+KPA==}
engines: {node: '>=18'}
cpu: [x64]
os: [win32]
@@ -749,8 +749,8 @@ packages:
resolution: {integrity: sha512-o2/jvNsdLC8SRdH1kQ7JjNOQNu9el0FpJ/QOW3mgiC5C9reuTp18iU4kijsVVLgvw4KZv6Z289SoKPh3HPsS0g==}
hasBin: true
'@git.zone/tsrun@1.3.4':
resolution: {integrity: sha512-bAhlV5ORVyahl6ew1SC379qf48Gnc0HB5CVZbQZrqoVtOgXvUo9A47WynCyLOw+7sCeYMLYp3/yfwlgmuRoFPw==}
'@git.zone/tsrun@1.6.2':
resolution: {integrity: sha512-SOHbQqBg3/769/jPQcdpPCmugdEtIJINiG0O6aWx+su91GvGhheha5dAhccsCutJYErr+aJcBqBYuUYfhOfkFQ==}
hasBin: true
'@happy-dom/global-registrator@15.11.7':
@@ -2242,8 +2242,8 @@ packages:
resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==}
engines: {node: '>= 0.4'}
esbuild@0.25.10:
resolution: {integrity: sha512-9RiGKvCwaqxO2owP61uQ4BgNborAQskMR6QusfWzQqv7AZOg5oGehdY2pRJMTKuwxd1IDBP4rSbI5lHzU7SMsQ==}
esbuild@0.25.11:
resolution: {integrity: sha512-KohQwyzrKTQmhXDW1PjCv3Tyspn9n5GcY2RTDqeORIdIJY8yKIF7sTSopFmn/wpMPW4rdPXI0UE5LJLuq3bx0Q==}
engines: {node: '>=18'}
hasBin: true
@@ -5002,157 +5002,157 @@ snapshots:
tslib: 2.8.1
optional: true
'@esbuild/aix-ppc64@0.25.10':
'@esbuild/aix-ppc64@0.25.11':
optional: true
'@esbuild/aix-ppc64@0.25.9':
optional: true
'@esbuild/android-arm64@0.25.10':
'@esbuild/android-arm64@0.25.11':
optional: true
'@esbuild/android-arm64@0.25.9':
optional: true
'@esbuild/android-arm@0.25.10':
'@esbuild/android-arm@0.25.11':
optional: true
'@esbuild/android-arm@0.25.9':
optional: true
'@esbuild/android-x64@0.25.10':
'@esbuild/android-x64@0.25.11':
optional: true
'@esbuild/android-x64@0.25.9':
optional: true
'@esbuild/darwin-arm64@0.25.10':
'@esbuild/darwin-arm64@0.25.11':
optional: true
'@esbuild/darwin-arm64@0.25.9':
optional: true
'@esbuild/darwin-x64@0.25.10':
'@esbuild/darwin-x64@0.25.11':
optional: true
'@esbuild/darwin-x64@0.25.9':
optional: true
'@esbuild/freebsd-arm64@0.25.10':
'@esbuild/freebsd-arm64@0.25.11':
optional: true
'@esbuild/freebsd-arm64@0.25.9':
optional: true
'@esbuild/freebsd-x64@0.25.10':
'@esbuild/freebsd-x64@0.25.11':
optional: true
'@esbuild/freebsd-x64@0.25.9':
optional: true
'@esbuild/linux-arm64@0.25.10':
'@esbuild/linux-arm64@0.25.11':
optional: true
'@esbuild/linux-arm64@0.25.9':
optional: true
'@esbuild/linux-arm@0.25.10':
'@esbuild/linux-arm@0.25.11':
optional: true
'@esbuild/linux-arm@0.25.9':
optional: true
'@esbuild/linux-ia32@0.25.10':
'@esbuild/linux-ia32@0.25.11':
optional: true
'@esbuild/linux-ia32@0.25.9':
optional: true
'@esbuild/linux-loong64@0.25.10':
'@esbuild/linux-loong64@0.25.11':
optional: true
'@esbuild/linux-loong64@0.25.9':
optional: true
'@esbuild/linux-mips64el@0.25.10':
'@esbuild/linux-mips64el@0.25.11':
optional: true
'@esbuild/linux-mips64el@0.25.9':
optional: true
'@esbuild/linux-ppc64@0.25.10':
'@esbuild/linux-ppc64@0.25.11':
optional: true
'@esbuild/linux-ppc64@0.25.9':
optional: true
'@esbuild/linux-riscv64@0.25.10':
'@esbuild/linux-riscv64@0.25.11':
optional: true
'@esbuild/linux-riscv64@0.25.9':
optional: true
'@esbuild/linux-s390x@0.25.10':
'@esbuild/linux-s390x@0.25.11':
optional: true
'@esbuild/linux-s390x@0.25.9':
optional: true
'@esbuild/linux-x64@0.25.10':
'@esbuild/linux-x64@0.25.11':
optional: true
'@esbuild/linux-x64@0.25.9':
optional: true
'@esbuild/netbsd-arm64@0.25.10':
'@esbuild/netbsd-arm64@0.25.11':
optional: true
'@esbuild/netbsd-arm64@0.25.9':
optional: true
'@esbuild/netbsd-x64@0.25.10':
'@esbuild/netbsd-x64@0.25.11':
optional: true
'@esbuild/netbsd-x64@0.25.9':
optional: true
'@esbuild/openbsd-arm64@0.25.10':
'@esbuild/openbsd-arm64@0.25.11':
optional: true
'@esbuild/openbsd-arm64@0.25.9':
optional: true
'@esbuild/openbsd-x64@0.25.10':
'@esbuild/openbsd-x64@0.25.11':
optional: true
'@esbuild/openbsd-x64@0.25.9':
optional: true
'@esbuild/openharmony-arm64@0.25.10':
'@esbuild/openharmony-arm64@0.25.11':
optional: true
'@esbuild/openharmony-arm64@0.25.9':
optional: true
'@esbuild/sunos-x64@0.25.10':
'@esbuild/sunos-x64@0.25.11':
optional: true
'@esbuild/sunos-x64@0.25.9':
optional: true
'@esbuild/win32-arm64@0.25.10':
'@esbuild/win32-arm64@0.25.11':
optional: true
'@esbuild/win32-arm64@0.25.9':
optional: true
'@esbuild/win32-ia32@0.25.10':
'@esbuild/win32-ia32@0.25.11':
optional: true
'@esbuild/win32-ia32@0.25.9':
optional: true
'@esbuild/win32-x64@0.25.10':
'@esbuild/win32-x64@0.25.11':
optional: true
'@esbuild/win32-x64@0.25.9':
@@ -5209,7 +5209,7 @@ snapshots:
- aws-crt
- supports-color
'@git.zone/tsrun@1.3.4':
'@git.zone/tsrun@1.6.2':
dependencies:
'@push.rocks/smartfile': 11.2.7
'@push.rocks/smartshell': 3.3.0
@@ -7377,34 +7377,34 @@ snapshots:
has-tostringtag: 1.0.2
hasown: 2.0.2
esbuild@0.25.10:
esbuild@0.25.11:
optionalDependencies:
'@esbuild/aix-ppc64': 0.25.10
'@esbuild/android-arm': 0.25.10
'@esbuild/android-arm64': 0.25.10
'@esbuild/android-x64': 0.25.10
'@esbuild/darwin-arm64': 0.25.10
'@esbuild/darwin-x64': 0.25.10
'@esbuild/freebsd-arm64': 0.25.10
'@esbuild/freebsd-x64': 0.25.10
'@esbuild/linux-arm': 0.25.10
'@esbuild/linux-arm64': 0.25.10
'@esbuild/linux-ia32': 0.25.10
'@esbuild/linux-loong64': 0.25.10
'@esbuild/linux-mips64el': 0.25.10
'@esbuild/linux-ppc64': 0.25.10
'@esbuild/linux-riscv64': 0.25.10
'@esbuild/linux-s390x': 0.25.10
'@esbuild/linux-x64': 0.25.10
'@esbuild/netbsd-arm64': 0.25.10
'@esbuild/netbsd-x64': 0.25.10
'@esbuild/openbsd-arm64': 0.25.10
'@esbuild/openbsd-x64': 0.25.10
'@esbuild/openharmony-arm64': 0.25.10
'@esbuild/sunos-x64': 0.25.10
'@esbuild/win32-arm64': 0.25.10
'@esbuild/win32-ia32': 0.25.10
'@esbuild/win32-x64': 0.25.10
'@esbuild/aix-ppc64': 0.25.11
'@esbuild/android-arm': 0.25.11
'@esbuild/android-arm64': 0.25.11
'@esbuild/android-x64': 0.25.11
'@esbuild/darwin-arm64': 0.25.11
'@esbuild/darwin-x64': 0.25.11
'@esbuild/freebsd-arm64': 0.25.11
'@esbuild/freebsd-x64': 0.25.11
'@esbuild/linux-arm': 0.25.11
'@esbuild/linux-arm64': 0.25.11
'@esbuild/linux-ia32': 0.25.11
'@esbuild/linux-loong64': 0.25.11
'@esbuild/linux-mips64el': 0.25.11
'@esbuild/linux-ppc64': 0.25.11
'@esbuild/linux-riscv64': 0.25.11
'@esbuild/linux-s390x': 0.25.11
'@esbuild/linux-x64': 0.25.11
'@esbuild/netbsd-arm64': 0.25.11
'@esbuild/netbsd-x64': 0.25.11
'@esbuild/openbsd-arm64': 0.25.11
'@esbuild/openbsd-x64': 0.25.11
'@esbuild/openharmony-arm64': 0.25.11
'@esbuild/sunos-x64': 0.25.11
'@esbuild/win32-arm64': 0.25.11
'@esbuild/win32-ia32': 0.25.11
'@esbuild/win32-x64': 0.25.11
esbuild@0.25.9:
optionalDependencies:
@@ -9268,7 +9268,7 @@ snapshots:
tsx@4.20.6:
dependencies:
esbuild: 0.25.10
esbuild: 0.25.11
get-tsconfig: 4.12.0
optionalDependencies:
fsevents: 2.3.3

View File

@@ -3,6 +3,6 @@
*/
export const commitinfo = {
name: '@git.zone/tstest',
version: '2.5.1',
version: '2.6.0',
description: 'a test utility to run tests that match test/**/*.ts'
}

View File

@@ -47,11 +47,11 @@ export class BunRuntimeAdapter extends RuntimeAdapter {
}
// Bun version is just the version number
const version = result.stdout.trim();
const version = `v${result.stdout.trim()}`;
return {
available: true,
version: `Bun ${version}`,
version: version,
};
} catch (error) {
return {

View File

@@ -37,7 +37,7 @@ export class ChromiumRuntimeAdapter extends RuntimeAdapter {
// The browser binary is usually handled by @push.rocks/smartbrowser
return {
available: true,
version: 'Chromium (via smartbrowser)',
version: 'via smartbrowser',
};
} catch (error) {
return {

View File

@@ -67,11 +67,11 @@ export class DenoRuntimeAdapter extends RuntimeAdapter {
// Parse Deno version from output (first line is "deno X.Y.Z")
const versionMatch = result.stdout.match(/deno (\d+\.\d+\.\d+)/);
const version = versionMatch ? versionMatch[1] : 'unknown';
const version = versionMatch ? `v${versionMatch[1]}` : 'unknown';
return {
available: true,
version: `Deno ${version}`,
version: version,
};
} catch (error) {
return {

View File

@@ -35,18 +35,11 @@ export class NodeRuntimeAdapter extends RuntimeAdapter {
// Check Node.js version
const nodeVersion = process.version;
// Check if tsrun is available
const result = await this.smartshellInstance.exec('tsrun --version', {
cwd: process.cwd(),
onError: () => {
// Ignore error
}
});
if (result.exitCode !== 0) {
// Check if tsrun module is available (imported as dependency)
if (!plugins.tsrun || !plugins.tsrun.spawnPath) {
return {
available: false,
error: 'tsrun not found. Install with: pnpm install --save-dev @git.zone/tsrun',
error: 'tsrun module not found or outdated (requires version 1.6.0+)',
};
}
@@ -96,7 +89,7 @@ export class NodeRuntimeAdapter extends RuntimeAdapter {
}
/**
* Execute a test file in Node.js
* Execute a test file in Node.js using tsrun's spawnPath API
*/
async run(
testFile: string,
@@ -109,28 +102,35 @@ export class NodeRuntimeAdapter extends RuntimeAdapter {
const mergedOptions = this.mergeOptions(options);
// Build tsrun command
let tsrunOptions = '';
// Build spawn options
const spawnOptions: any = {
cwd: mergedOptions.cwd || process.cwd(),
env: { ...mergedOptions.env },
args: [] as string[],
stdio: 'pipe' as const,
};
// Add --web flag if needed
if (process.argv.includes('--web')) {
tsrunOptions += ' --web';
spawnOptions.args.push('--web');
}
// Set filter tags as environment variable
if (this.filterTags.length > 0) {
process.env.TSTEST_FILTER_TAGS = this.filterTags.join(',');
spawnOptions.env.TSTEST_FILTER_TAGS = this.filterTags.join(',');
}
// Check for 00init.ts file in test directory
const testDir = plugins.path.dirname(testFile);
const initFile = plugins.path.join(testDir, '00init.ts');
let runCommand = `tsrun ${testFile}${tsrunOptions}`;
const initFileExists = await plugins.smartfile.fs.fileExists(initFile);
// If 00init.ts exists, run it first
// Determine which file to run
let fileToRun = testFile;
let loaderPath: string | null = null;
// If 00init.ts exists, create a loader file
if (initFileExists) {
// Create a temporary loader file that imports both 00init.ts and the test file
const absoluteInitFile = plugins.path.resolve(initFile);
const absoluteTestFile = plugins.path.resolve(testFile);
const loaderContent = `
@@ -139,10 +139,12 @@ import '${absoluteTestFile.replace(/\\/g, '/')}';
`;
loaderPath = plugins.path.join(testDir, `.loader_${plugins.path.basename(testFile)}`);
await plugins.smartfile.memory.toFs(loaderContent, loaderPath);
runCommand = `tsrun ${loaderPath}${tsrunOptions}`;
fileToRun = loaderPath;
}
const execResultStreaming = await this.smartshellInstance.execStreamingSilent(runCommand);
// Spawn the test process using tsrun's spawnPath API
// Pass undefined for fromFileUrl since fileToRun is already an absolute path
const tsrunProcess = plugins.tsrun.spawnPath(fileToRun, undefined, spawnOptions);
// If we created a loader file, clean it up after test execution
if (loaderPath) {
@@ -156,8 +158,8 @@ import '${absoluteTestFile.replace(/\\/g, '/')}';
}
};
execResultStreaming.childProcess.on('exit', cleanup);
execResultStreaming.childProcess.on('error', cleanup);
tsrunProcess.childProcess.on('exit', cleanup);
tsrunProcess.childProcess.on('error', cleanup);
}
// Start warning timer if no timeout was specified
@@ -180,15 +182,15 @@ import '${absoluteTestFile.replace(/\\/g, '/')}';
const timeoutPromise = new Promise<void>((_resolve, reject) => {
timeoutId = setTimeout(async () => {
// Use smartshell's terminate() to kill entire process tree
await execResultStreaming.terminate();
// Use tsrun's terminate() to gracefully kill the process
await tsrunProcess.terminate();
reject(new Error(`Test file timed out after ${this.timeoutSeconds} seconds`));
}, timeoutMs);
});
try {
await Promise.race([
tapParser.handleTapProcess(execResultStreaming.childProcess),
tapParser.handleTapProcess(tsrunProcess.childProcess),
timeoutPromise
]);
// Clear timeout if test completed successfully
@@ -200,16 +202,16 @@ import '${absoluteTestFile.replace(/\\/g, '/')}';
}
// Handle timeout error
tapParser.handleTimeout(this.timeoutSeconds);
// Ensure entire process tree is killed if still running
// Ensure process is killed if still running
try {
await execResultStreaming.kill(); // This kills the entire process tree with SIGKILL
tsrunProcess.kill('SIGKILL');
} catch (killError) {
// Process tree might already be dead
// Process might already be dead
}
await tapParser.evaluateFinalResult();
}
} else {
await tapParser.handleTapProcess(execResultStreaming.childProcess);
await tapParser.handleTapProcess(tsrunProcess.childProcess);
}
// Clear warning timer if it was set

View File

@@ -62,7 +62,19 @@ export class TsTest {
);
}
/**
* Check and display available runtimes
*/
private async checkEnvironment() {
const availability = await this.runtimeRegistry.checkAvailability();
this.logger.environmentCheck(availability);
return availability;
}
async run() {
// Check and display environment
await this.checkEnvironment();
// Move previous log files if --logfile option is used
if (this.logger.options.logFile) {
await this.movePreviousLogFiles();

View File

@@ -138,6 +138,43 @@ export class TsTestLogger {
}
}
// Environment check - display available runtimes
environmentCheck(availability: Map<string, { available: boolean; version?: string; error?: string }>) {
if (this.options.json) {
const runtimes: any = {};
for (const [runtime, info] of availability) {
runtimes[runtime] = info;
}
this.logJson({ event: 'environmentCheck', runtimes });
return;
}
if (this.options.quiet) return;
this.log(this.format('\n🌍 Test Environment', 'bold'));
// Define runtime display names
const runtimeNames: Record<string, string> = {
node: 'Node.js',
deno: 'Deno',
bun: 'Bun',
chromium: 'Chrome/Chromium'
};
// Display each runtime
for (const [runtime, info] of availability) {
const displayName = runtimeNames[runtime] || runtime;
if (info.available) {
const versionStr = info.version ? ` ${info.version}` : '';
this.log(this.format(`${displayName}${versionStr}`, 'green'));
} else {
const errorStr = info.error ? ` (${info.error})` : '';
this.log(this.format(`${displayName}${errorStr}`, 'dim'));
}
}
}
// Test execution
testFileStart(filename: string, runtime: string, index: number, total: number) {
this.currentFileResult = {

View File

@@ -37,8 +37,9 @@ export {
// @git.zone scope
import * as tsbundle from '@git.zone/tsbundle';
import * as tsrun from '@git.zone/tsrun';
export { tsbundle };
export { tsbundle, tsrun };
// sindresorhus
import figures from 'figures';