feat - allow other extensions to register test runner (#1705)

This commit is contained in:
Sheng Chen 2024-07-04 09:57:24 +08:00 коммит произвёл GitHub
Родитель afe9114e39
Коммит 696e31ab2a
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
28 изменённых файлов: 808 добавлений и 350 удалений

264
package-lock.json сгенерированный
Просмотреть файл

@ -150,61 +150,61 @@
"dev": true
},
"node_modules/@jridgewell/gen-mapping": {
"version": "0.3.3",
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz",
"integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==",
"version": "0.3.5",
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz",
"integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==",
"dev": true,
"dependencies": {
"@jridgewell/set-array": "^1.0.1",
"@jridgewell/set-array": "^1.2.1",
"@jridgewell/sourcemap-codec": "^1.4.10",
"@jridgewell/trace-mapping": "^0.3.9"
"@jridgewell/trace-mapping": "^0.3.24"
},
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/@jridgewell/resolve-uri": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz",
"integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==",
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
"integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
"dev": true,
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/@jridgewell/set-array": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz",
"integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==",
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz",
"integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==",
"dev": true,
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/@jridgewell/source-map": {
"version": "0.3.5",
"resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz",
"integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==",
"version": "0.3.6",
"resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz",
"integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==",
"dev": true,
"dependencies": {
"@jridgewell/gen-mapping": "^0.3.0",
"@jridgewell/trace-mapping": "^0.3.9"
"@jridgewell/gen-mapping": "^0.3.5",
"@jridgewell/trace-mapping": "^0.3.25"
}
},
"node_modules/@jridgewell/sourcemap-codec": {
"version": "1.4.14",
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz",
"integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==",
"version": "1.4.15",
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
"integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==",
"dev": true
},
"node_modules/@jridgewell/trace-mapping": {
"version": "0.3.18",
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz",
"integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==",
"version": "0.3.25",
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz",
"integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==",
"dev": true,
"dependencies": {
"@jridgewell/resolve-uri": "3.1.0",
"@jridgewell/sourcemap-codec": "1.4.14"
"@jridgewell/resolve-uri": "^3.1.0",
"@jridgewell/sourcemap-codec": "^1.4.14"
}
},
"node_modules/@microsoft/1ds-core-js": {
@ -430,9 +430,9 @@
}
},
"node_modules/@types/estree": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.1.tgz",
"integrity": "sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==",
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz",
"integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==",
"dev": true
},
"node_modules/@types/fs-extra": {
@ -744,9 +744,9 @@
}
},
"node_modules/@webassemblyjs/ast": {
"version": "1.11.6",
"resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz",
"integrity": "sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==",
"version": "1.12.1",
"resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz",
"integrity": "sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==",
"dev": true,
"dependencies": {
"@webassemblyjs/helper-numbers": "1.11.6",
@ -766,9 +766,9 @@
"dev": true
},
"node_modules/@webassemblyjs/helper-buffer": {
"version": "1.11.6",
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz",
"integrity": "sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==",
"version": "1.12.1",
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz",
"integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==",
"dev": true
},
"node_modules/@webassemblyjs/helper-numbers": {
@ -789,15 +789,15 @@
"dev": true
},
"node_modules/@webassemblyjs/helper-wasm-section": {
"version": "1.11.6",
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz",
"integrity": "sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==",
"version": "1.12.1",
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz",
"integrity": "sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==",
"dev": true,
"dependencies": {
"@webassemblyjs/ast": "1.11.6",
"@webassemblyjs/helper-buffer": "1.11.6",
"@webassemblyjs/ast": "1.12.1",
"@webassemblyjs/helper-buffer": "1.12.1",
"@webassemblyjs/helper-wasm-bytecode": "1.11.6",
"@webassemblyjs/wasm-gen": "1.11.6"
"@webassemblyjs/wasm-gen": "1.12.1"
}
},
"node_modules/@webassemblyjs/ieee754": {
@ -825,28 +825,28 @@
"dev": true
},
"node_modules/@webassemblyjs/wasm-edit": {
"version": "1.11.6",
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz",
"integrity": "sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==",
"version": "1.12.1",
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz",
"integrity": "sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==",
"dev": true,
"dependencies": {
"@webassemblyjs/ast": "1.11.6",
"@webassemblyjs/helper-buffer": "1.11.6",
"@webassemblyjs/ast": "1.12.1",
"@webassemblyjs/helper-buffer": "1.12.1",
"@webassemblyjs/helper-wasm-bytecode": "1.11.6",
"@webassemblyjs/helper-wasm-section": "1.11.6",
"@webassemblyjs/wasm-gen": "1.11.6",
"@webassemblyjs/wasm-opt": "1.11.6",
"@webassemblyjs/wasm-parser": "1.11.6",
"@webassemblyjs/wast-printer": "1.11.6"
"@webassemblyjs/helper-wasm-section": "1.12.1",
"@webassemblyjs/wasm-gen": "1.12.1",
"@webassemblyjs/wasm-opt": "1.12.1",
"@webassemblyjs/wasm-parser": "1.12.1",
"@webassemblyjs/wast-printer": "1.12.1"
}
},
"node_modules/@webassemblyjs/wasm-gen": {
"version": "1.11.6",
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz",
"integrity": "sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==",
"version": "1.12.1",
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz",
"integrity": "sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==",
"dev": true,
"dependencies": {
"@webassemblyjs/ast": "1.11.6",
"@webassemblyjs/ast": "1.12.1",
"@webassemblyjs/helper-wasm-bytecode": "1.11.6",
"@webassemblyjs/ieee754": "1.11.6",
"@webassemblyjs/leb128": "1.11.6",
@ -854,24 +854,24 @@
}
},
"node_modules/@webassemblyjs/wasm-opt": {
"version": "1.11.6",
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz",
"integrity": "sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==",
"version": "1.12.1",
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz",
"integrity": "sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==",
"dev": true,
"dependencies": {
"@webassemblyjs/ast": "1.11.6",
"@webassemblyjs/helper-buffer": "1.11.6",
"@webassemblyjs/wasm-gen": "1.11.6",
"@webassemblyjs/wasm-parser": "1.11.6"
"@webassemblyjs/ast": "1.12.1",
"@webassemblyjs/helper-buffer": "1.12.1",
"@webassemblyjs/wasm-gen": "1.12.1",
"@webassemblyjs/wasm-parser": "1.12.1"
}
},
"node_modules/@webassemblyjs/wasm-parser": {
"version": "1.11.6",
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz",
"integrity": "sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==",
"version": "1.12.1",
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz",
"integrity": "sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==",
"dev": true,
"dependencies": {
"@webassemblyjs/ast": "1.11.6",
"@webassemblyjs/ast": "1.12.1",
"@webassemblyjs/helper-api-error": "1.11.6",
"@webassemblyjs/helper-wasm-bytecode": "1.11.6",
"@webassemblyjs/ieee754": "1.11.6",
@ -880,12 +880,12 @@
}
},
"node_modules/@webassemblyjs/wast-printer": {
"version": "1.11.6",
"resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz",
"integrity": "sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==",
"version": "1.12.1",
"resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz",
"integrity": "sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==",
"dev": true,
"dependencies": {
"@webassemblyjs/ast": "1.11.6",
"@webassemblyjs/ast": "1.12.1",
"@xtuc/long": "4.2.2"
}
},
@ -949,10 +949,10 @@
"node": ">=0.4.0"
}
},
"node_modules/acorn-import-assertions": {
"version": "1.9.0",
"resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz",
"integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==",
"node_modules/acorn-import-attributes": {
"version": "1.9.5",
"resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz",
"integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==",
"dev": true,
"peerDependencies": {
"acorn": "^8"
@ -1447,9 +1447,9 @@
"dev": true
},
"node_modules/enhanced-resolve": {
"version": "5.15.0",
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz",
"integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==",
"version": "5.17.0",
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.0.tgz",
"integrity": "sha512-dwDPwZL0dmye8Txp2gzFmA6sxALaSvdRDjPH0viLcKrtlOL3tw62nWWweVD1SdILDTJrbrL6tdWVN58Wo6U3eA==",
"dev": true,
"dependencies": {
"graceful-fs": "^4.2.4",
@ -1460,9 +1460,9 @@
}
},
"node_modules/envinfo": {
"version": "7.10.0",
"resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.10.0.tgz",
"integrity": "sha512-ZtUjZO6l5mwTHvc1L9+1q5p/R3wTopcfqMW8r5t8SJSKqeVI/LtajORwRFEKpEFuekjD0VBjwu1HMxL4UalIRw==",
"version": "7.13.0",
"resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.13.0.tgz",
"integrity": "sha512-cvcaMr7KqXVh4nyzGTVqTum+gAiL265x5jUWQIDLq//zOGbW+gSW/C+OWLleY/rs9Qole6AZLMXPbtIFQbqu+Q==",
"dev": true,
"bin": {
"envinfo": "dist/cli.js"
@ -1886,10 +1886,13 @@
}
},
"node_modules/function-bind": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
"dev": true
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
"dev": true,
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/get-caller-file": {
"version": "2.0.5",
@ -2001,18 +2004,6 @@
"node": ">=4.x"
}
},
"node_modules/has": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
"integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
"dev": true,
"dependencies": {
"function-bind": "^1.1.1"
},
"engines": {
"node": ">= 0.4.0"
}
},
"node_modules/has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@ -2022,6 +2013,18 @@
"node": ">=8"
}
},
"node_modules/hasown": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
"dev": true,
"dependencies": {
"function-bind": "^1.1.2"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/he": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
@ -2166,12 +2169,15 @@
}
},
"node_modules/is-core-module": {
"version": "2.12.1",
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.1.tgz",
"integrity": "sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==",
"version": "2.14.0",
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.14.0.tgz",
"integrity": "sha512-a5dFJih5ZLYlRtDc0dZWP7RiKr6xIKzmn/oAYCDvdLThadVgyJwlaoQPmRtMSpz+rk0OGAgIu+TcM9HUF0fk1A==",
"dev": true,
"dependencies": {
"has": "^1.0.3"
"hasown": "^2.0.2"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
@ -3064,12 +3070,12 @@
}
},
"node_modules/resolve": {
"version": "1.22.2",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz",
"integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==",
"version": "1.22.8",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz",
"integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==",
"dev": true,
"dependencies": {
"is-core-module": "^2.11.0",
"is-core-module": "^2.13.0",
"path-parse": "^1.0.7",
"supports-preserve-symlinks-flag": "^1.0.0"
},
@ -3397,9 +3403,9 @@
}
},
"node_modules/terser": {
"version": "5.19.2",
"resolved": "https://registry.npmjs.org/terser/-/terser-5.19.2.tgz",
"integrity": "sha512-qC5+dmecKJA4cpYxRa5aVkKehYsQKc+AHeKl0Oe62aYjBL8ZA33tTljktDHJSaxxMnbI5ZYw+o/S2DxxLu8OfA==",
"version": "5.31.1",
"resolved": "https://registry.npmjs.org/terser/-/terser-5.31.1.tgz",
"integrity": "sha512-37upzU1+viGvuFtBo9NPufCb9dwM0+l9hMxYyWfBA+fbwrPqNJAhbZ6W47bBFnZHKHTUBnMvi87434qq+qnxOg==",
"dev": true,
"dependencies": {
"@jridgewell/source-map": "^0.3.3",
@ -3415,16 +3421,16 @@
}
},
"node_modules/terser-webpack-plugin": {
"version": "5.3.9",
"resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz",
"integrity": "sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==",
"version": "5.3.10",
"resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz",
"integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==",
"dev": true,
"dependencies": {
"@jridgewell/trace-mapping": "^0.3.17",
"@jridgewell/trace-mapping": "^0.3.20",
"jest-worker": "^27.4.5",
"schema-utils": "^3.1.1",
"serialize-javascript": "^6.0.1",
"terser": "^5.16.8"
"terser": "^5.26.0"
},
"engines": {
"node": ">= 10.13.0"
@ -3449,9 +3455,9 @@
}
},
"node_modules/terser-webpack-plugin/node_modules/serialize-javascript": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz",
"integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==",
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz",
"integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==",
"dev": true,
"dependencies": {
"randombytes": "^2.1.0"
@ -3684,9 +3690,9 @@
}
},
"node_modules/watchpack": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz",
"integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==",
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.1.tgz",
"integrity": "sha512-8wrBCMtVhqcXP2Sup1ctSkga6uc2Bx0IIvKyT7yTFier5AXHooSI+QyQQAtTb7+E0IUCCKyTFmXqdqgum2XWGg==",
"dev": true,
"dependencies": {
"glob-to-regexp": "^0.4.1",
@ -3697,34 +3703,34 @@
}
},
"node_modules/webpack": {
"version": "5.88.2",
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.88.2.tgz",
"integrity": "sha512-JmcgNZ1iKj+aiR0OvTYtWQqJwq37Pf683dY9bVORwVbUrDhLhdn/PlO2sHsFHPkj7sHNQF3JwaAkp49V+Sq1tQ==",
"version": "5.92.1",
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.92.1.tgz",
"integrity": "sha512-JECQ7IwJb+7fgUFBlrJzbyu3GEuNBcdqr1LD7IbSzwkSmIevTm8PF+wej3Oxuz/JFBUZ6O1o43zsPkwm1C4TmA==",
"dev": true,
"dependencies": {
"@types/eslint-scope": "^3.7.3",
"@types/estree": "^1.0.0",
"@webassemblyjs/ast": "^1.11.5",
"@webassemblyjs/wasm-edit": "^1.11.5",
"@webassemblyjs/wasm-parser": "^1.11.5",
"@types/estree": "^1.0.5",
"@webassemblyjs/ast": "^1.12.1",
"@webassemblyjs/wasm-edit": "^1.12.1",
"@webassemblyjs/wasm-parser": "^1.12.1",
"acorn": "^8.7.1",
"acorn-import-assertions": "^1.9.0",
"browserslist": "^4.14.5",
"acorn-import-attributes": "^1.9.5",
"browserslist": "^4.21.10",
"chrome-trace-event": "^1.0.2",
"enhanced-resolve": "^5.15.0",
"enhanced-resolve": "^5.17.0",
"es-module-lexer": "^1.2.1",
"eslint-scope": "5.1.1",
"events": "^3.2.0",
"glob-to-regexp": "^0.4.1",
"graceful-fs": "^4.2.9",
"graceful-fs": "^4.2.11",
"json-parse-even-better-errors": "^2.3.1",
"loader-runner": "^4.2.0",
"mime-types": "^2.1.27",
"neo-async": "^2.6.2",
"schema-utils": "^3.2.0",
"tapable": "^2.1.1",
"terser-webpack-plugin": "^5.3.7",
"watchpack": "^2.4.0",
"terser-webpack-plugin": "^5.3.10",
"watchpack": "^2.4.1",
"webpack-sources": "^3.2.3"
},
"bin": {

Просмотреть файл

@ -8,7 +8,7 @@ import { loadChildren, runTests, testController } from '../controller/testContro
import { loadJavaProjects, updateItemForDocument } from '../controller/utils';
import { IProgressReporter } from '../debugger.api';
import { progressProvider } from '../extension';
import { TestLevel } from '../types';
import { TestLevel } from '../java-test-runner.api';
export async function runTestsFromJavaProjectExplorer(node: any, isDebug: boolean): Promise<void> {
const testLevel: TestLevel = getTestLevel(node._nodeData);

Просмотреть файл

@ -9,11 +9,12 @@ import * as fse from 'fs-extra';
import * as _ from 'lodash';
import * as os from 'os';
import { getJavaProjects, getProjectType } from '../controller/utils';
import { IJavaTestItem, ProjectType, TestKind } from '../types';
import { IJavaTestItem, ProjectType } from '../types';
import { createWriteStream, WriteStream } from 'fs';
import { URL } from 'url';
import { ClientRequest, IncomingMessage } from 'http';
import { sendError } from 'vscode-extension-telemetry-wrapper';
import { TestKind } from '../java-test-runner.api';
export async function enableTests(testKind?: TestKind): Promise<void> {
const project: IJavaTestItem | undefined = await getTargetProject();

Просмотреть файл

@ -3,22 +3,25 @@
import * as _ from 'lodash';
import * as path from 'path';
import { CancellationToken, DebugConfiguration, Disposable, FileCoverage, FileCoverageDetail, FileSystemWatcher, RelativePattern, TestController, TestItem, TestRun, TestRunProfileKind, TestRunRequest, tests, TestTag, Uri, window, workspace, WorkspaceFolder } from 'vscode';
import { CancellationToken, DebugConfiguration, Disposable, FileCoverage, FileCoverageDetail, FileSystemWatcher, Location, MarkdownString, RelativePattern, TestController, TestItem, TestMessage, TestRun, TestRunProfileKind, TestRunRequest, tests, TestTag, Uri, window, workspace, WorkspaceFolder } from 'vscode';
import { instrumentOperation, sendError, sendInfo } from 'vscode-extension-telemetry-wrapper';
import { refreshExplorer } from '../commands/testExplorerCommands';
import { IProgressReporter } from '../debugger.api';
import { progressProvider } from '../extension';
import { testSourceProvider } from '../provider/testSourceProvider';
import { IExecutionConfig } from '../runConfigs';
import { BaseRunner } from '../runners/baseRunner/BaseRunner';
import { JUnitRunner } from '../runners/junitRunner/JunitRunner';
import { TestNGRunner } from '../runners/testngRunner/TestNGRunner';
import { IJavaTestItem, IRunTestContext, TestKind, TestLevel } from '../types';
import { IJavaTestItem } from '../types';
import { loadRunConfig } from '../utils/configUtils';
import { resolveLaunchConfigurationForRunner } from '../utils/launchUtils';
import { dataCache, ITestItemData } from './testItemDataCache';
import { findDirectTestChildrenForClass, findTestPackagesAndTypes, findTestTypesAndMethods, loadJavaProjects, resolvePath, synchronizeItemsRecursively, updateItemForDocumentWithDebounce } from './utils';
import { createTestItem, findDirectTestChildrenForClass, findTestPackagesAndTypes, findTestTypesAndMethods, loadJavaProjects, resolvePath, synchronizeItemsRecursively, updateItemForDocumentWithDebounce } from './utils';
import { JavaTestCoverageProvider } from '../provider/JavaTestCoverageProvider';
import { testRunnerService } from './testRunnerService';
import { IRunTestContext, TestRunner, TestFinishEvent, TestItemStatusChangeEvent, TestKind, TestLevel, TestResultState, TestIdParts } from '../java-test-runner.api';
import { processStackTraceLine } from '../runners/utils';
import { parsePartsFromTestId } from '../utils/testItemUtils';
export let testController: TestController | undefined;
export const watchers: Disposable[] = [];
@ -43,6 +46,10 @@ export function createTestController(): void {
startWatchingWorkspace();
}
export function creatTestProfile(name: string, kind: TestRunProfileKind): void {
testController?.createRunProfile(name, kind, runHandler, false, runnableTag);
}
export const loadChildren: (item: TestItem, token?: CancellationToken) => any = instrumentOperation('java.test.explorer.loadChildren', async (_operationId: string, item: TestItem, token?: CancellationToken) => {
if (!item) {
await loadJavaProjects();
@ -178,12 +185,15 @@ export const runTests: (request: TestRunRequest, option: IRunOption) => any = in
try {
await new Promise<void>(async (resolve: () => void): Promise<void> => {
const token: CancellationToken = option.token ?? run.token;
let disposables: Disposable[] = [];
token.onCancellationRequested(() => {
option.progressReporter?.done();
run.end();
disposables.forEach((d: Disposable) => d.dispose());
return resolve();
});
enqueueTestMethods(testItems, run);
// TODO: first group by project, then merge test methods.
const queue: TestItem[][] = mergeTestMethods(testItems);
for (const testsInQueue of queue) {
if (testsInQueue.length === 0) {
@ -191,8 +201,32 @@ export const runTests: (request: TestRunRequest, option: IRunOption) => any = in
}
const testProjectMapping: Map<string, TestItem[]> = mapTestItemsByProject(testsInQueue);
for (const [projectName, itemsPerProject] of testProjectMapping.entries()) {
const workspaceFolder: WorkspaceFolder | undefined = workspace.getWorkspaceFolder(itemsPerProject[0].uri!);
if (!workspaceFolder) {
window.showErrorMessage(`Failed to get workspace folder from test item: ${itemsPerProject[0].label}.`);
continue;
}
const testContext: IRunTestContext = {
isDebug: option.isDebug,
kind: TestKind.None,
projectName,
testItems: itemsPerProject,
testRun: run,
workspaceFolder,
profile: request.profile,
testConfig: await loadRunConfig(itemsPerProject, workspaceFolder),
};
const testRunner: TestRunner | undefined = testRunnerService.getRunner(request.profile?.label, request.profile?.kind);
if (testRunner) {
await executeWithTestRunner(option, testRunner, testContext, run, disposables);
disposables.forEach((d: Disposable) => d.dispose());
disposables = [];
continue;
}
const testKindMapping: Map<TestKind, TestItem[]> = mapTestItemsByKind(itemsPerProject);
for (const [kind, items] of testKindMapping.entries()) {
testContext.kind = kind;
testContext.testItems = items;
if (option.progressReporter?.isCancelled()) {
option.progressReporter = progressProvider?.createProgressReporter(option.isDebug ? 'Debug Tests' : 'Run Tests');
}
@ -208,25 +242,9 @@ export const runTests: (request: TestRunRequest, option: IRunOption) => any = in
return resolve();
});
option.progressReporter?.report('Resolving launch configuration...');
// TODO: improve the config experience
const workspaceFolder: WorkspaceFolder | undefined = workspace.getWorkspaceFolder(items[0].uri!);
if (!workspaceFolder) {
window.showErrorMessage(`Failed to get workspace folder from test item: ${items[0].label}.`);
if (!testContext.testConfig) {
continue;
}
const config: IExecutionConfig | undefined = await loadRunConfig(items, workspaceFolder);
if (!config) {
continue;
}
const testContext: IRunTestContext = {
isDebug: option.isDebug,
kind,
projectName,
testItems: items,
testRun: run,
workspaceFolder,
profile: request.profile,
};
const runner: BaseRunner | undefined = getRunnerByContext(testContext);
if (!runner) {
window.showErrorMessage(`Failed to get suitable runner for the test kind: ${testContext.kind}.`);
@ -234,7 +252,7 @@ export const runTests: (request: TestRunRequest, option: IRunOption) => any = in
}
try {
await runner.setup();
const resolvedConfiguration: DebugConfiguration = mergeConfigurations(option.launchConfiguration, config) ?? await resolveLaunchConfigurationForRunner(runner, testContext, config);
const resolvedConfiguration: DebugConfiguration = mergeConfigurations(option.launchConfiguration, testContext.testConfig) ?? await resolveLaunchConfigurationForRunner(runner, testContext, testContext.testConfig);
resolvedConfiguration.__progressId = option.progressReporter?.getId();
delegatedToDebugger = true;
trackTestFrameworkVersion(testContext.kind, resolvedConfiguration.classPaths, resolvedConfiguration.modulePaths);
@ -258,6 +276,133 @@ export const runTests: (request: TestRunRequest, option: IRunOption) => any = in
}
});
async function executeWithTestRunner(option: IRunOption, testRunner: TestRunner, testContext: IRunTestContext, run: TestRun, disposables: Disposable[]) {
option.progressReporter?.done();
await new Promise<void>(async (resolve: () => void): Promise<void> => {
disposables.push(testRunner.onDidChangeTestItemStatus((event: TestItemStatusChangeEvent) => {
const parts: TestIdParts = parsePartsFromTestId(event.testId);
let parentItem: TestItem;
try {
parentItem = findTestClass(parts);
} catch (e) {
sendError(e);
window.showErrorMessage(e.message);
return resolve();
}
let currentItem: TestItem | undefined;
const invocations: string[] | undefined = parts.invocations;
if (invocations?.length) {
let i: number = 0;
for (; i < invocations.length; i++) {
currentItem = parentItem.children.get(`${parentItem.id}#${invocations[i]}`);
if (!currentItem) {
break;
}
parentItem = currentItem;
}
if (i < invocations.length - 1) {
window.showErrorMessage('Test not found:' + event.testId);
sendError(new Error('Test not found:' + event.testId));
return resolve();
}
if (!currentItem) {
currentItem = createTestItem({
children: [],
uri: parentItem.uri?.toString(),
range: parentItem.range,
jdtHandler: '',
fullName: `${parentItem.id}#${invocations[invocations.length - 1]}`,
label: event.displayName || invocations[invocations.length - 1],
id: `${parentItem.id}#${invocations[invocations.length - 1]}`,
projectName: testContext.projectName,
testKind: TestKind.None,
testLevel: TestLevel.Invocation,
}, parentItem);
}
} else {
currentItem = parentItem;
}
if (event.displayName && getLabelWithoutCodicon(currentItem.label) !== event.displayName) {
currentItem.description = event.displayName;
}
switch (event.state) {
case TestResultState.Running:
run.started(currentItem);
break;
case TestResultState.Passed:
run.passed(currentItem);
break;
case TestResultState.Failed:
case TestResultState.Errored:
const testMessages: TestMessage[] = [];
if (event.message) {
const markdownTrace: MarkdownString = new MarkdownString();
markdownTrace.supportHtml = true;
markdownTrace.isTrusted = true;
const testMessage: TestMessage = new TestMessage(markdownTrace);
testMessages.push(testMessage);
const lines: string[] = event.message.split(/\r?\n/);
for (const line of lines) {
const location: Location | undefined = processStackTraceLine(line, markdownTrace, currentItem, testContext.projectName);
if (location) {
testMessage.location = location;
}
}
}
run.failed(currentItem, testMessages);
break;
case TestResultState.Skipped:
run.skipped(currentItem);
break;
default:
break;
}
}));
disposables.push(testRunner.onDidFinishTestRun((_event: TestFinishEvent) => {
return resolve();
}));
testRunner.launch(testContext);
});
function findTestClass(parts: TestIdParts): TestItem {
const projectItem: TestItem | undefined = testController?.items.get(parts.project);
if (!projectItem) {
throw new Error('Failed to get the project test item.');
}
if (parts.package === undefined) { // '' means default package
throw new Error('package is undefined in the id parts.');
}
const packageItem: TestItem | undefined = projectItem.children.get(`${projectItem.id}@${parts.package}`);
if (!packageItem) {
throw new Error('Failed to get the package test item.');
}
if (!parts.class) {
throw new Error('class is undefined in the id parts.');
}
const classes: string[] = parts.class.split('$'); // handle nested classes
let current: TestItem | undefined = packageItem.children.get(`${projectItem.id}@${classes[0]}`);
if (!current) {
throw new Error('Failed to get the class test item.');
}
for (let i: number = 1; i < classes.length; i++) {
current = current.children.get(`${current.id}$${classes[i]}`);
if (!current) {
throw new Error('Failed to get the class test item.');
}
}
return current;
}
}
function mergeConfigurations(launchConfiguration: DebugConfiguration | undefined, config: any): DebugConfiguration | undefined {
if (!launchConfiguration) {
return undefined;
@ -586,6 +731,18 @@ function trackTestFrameworkVersion(testKind: TestKind, classpaths: string[], mod
});
}
function getLabelWithoutCodicon(name: string): string {
if (name.includes('#')) {
name = name.substring(name.indexOf('#') + 1);
}
const result: RegExpMatchArray | null = name.match(/(?:\$\(.+\) )?(.*)/);
if (result?.length === 2) {
return result[1];
}
return name;
}
interface IRunOption {
isDebug: boolean;
progressReporter?: IProgressReporter;

Просмотреть файл

@ -2,7 +2,7 @@
// Licensed under the MIT license.
import { TestItem } from 'vscode';
import { TestKind, TestLevel } from '../types';
import { TestKind, TestLevel } from '../java-test-runner.api';
/**
* A map cache to save the metadata of the test item.

Просмотреть файл

@ -0,0 +1,35 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import { TestRunProfileKind } from 'vscode';
import { creatTestProfile } from './testController';
import { TestRunner } from '../java-test-runner.api';
// TODO: this should be refactored. The test controller should be extended and hosting the registered runners.
class TestRunnerService {
private registeredRunners: Map<string, TestRunner>;
constructor() {
this.registeredRunners = new Map<string, TestRunner>();
}
public registerTestRunner(name: string, kind: TestRunProfileKind, runner: TestRunner) {
const key: string = `${name}:${kind}`;
if (this.registeredRunners.has(key)) {
throw new Error(`Runner ${key} has already been registered.`);
}
creatTestProfile(name, kind);
this.registeredRunners.set(key, runner);
}
public getRunner(name: string | undefined, kind: TestRunProfileKind | undefined): TestRunner | undefined {
if (!name || !kind) {
return undefined;
}
const key: string = `${name}:${kind}`;
return this.registeredRunners.get(key);
}
}
export const testRunnerService: TestRunnerService = new TestRunnerService();

Просмотреть файл

@ -8,11 +8,12 @@ import { performance } from 'perf_hooks';
import { CancellationToken, commands, Range, TestItem, Uri, workspace, WorkspaceFolder } from 'vscode';
import { sendError } from 'vscode-extension-telemetry-wrapper';
import { JavaTestRunnerDelegateCommands } from '../constants';
import { IJavaTestItem, ProjectType, TestKind, TestLevel } from '../types';
import { IJavaTestItem, ProjectType } from '../types';
import { executeJavaLanguageServerCommand } from '../utils/commandUtils';
import { getRequestDelay, lruCache, MovingAverage } from './debouncing';
import { runnableTag, testController } from './testController';
import { dataCache } from './testItemDataCache';
import { TestKind, TestLevel } from '../java-test-runner.api';
/**
* Load the Java projects, which are the root nodes of the test explorer
@ -129,8 +130,8 @@ function updateTestItem(testItem: TestItem, metaInfo: IJavaTestItem): void {
/**
* Create test item which will be shown in the test explorer
* @param metaInfo The data from the server side of the test item
* @param parent The parent node of the test item (if it has)
* @param metaInfo The data from the server side of the test item.
* @param parent The parent node of the test item (if it has).
* @returns The created test item
*/
export function createTestItem(metaInfo: IJavaTestItem, parent?: TestItem): TestItem {
@ -139,7 +140,7 @@ export function createTestItem(metaInfo: IJavaTestItem, parent?: TestItem): Test
}
const item: TestItem = testController.createTestItem(
metaInfo.id,
`${getCodiconLabel(metaInfo.testLevel)} ${metaInfo.label}`,
`${getCodiconLabel(metaInfo.testLevel)} ${metaInfo.label}`.trim(),
metaInfo.uri ? Uri.parse(metaInfo.uri) : undefined,
);
item.range = asRange(metaInfo.range);

Просмотреть файл

@ -2,7 +2,7 @@
// Licensed under the MIT license.
import * as path from 'path';
import { commands, DebugConfiguration, Event, Extension, ExtensionContext, extensions, TestItem, TextDocument, TextDocumentChangeEvent, TextEditor, Uri, window, workspace, WorkspaceFoldersChangeEvent } from 'vscode';
import { commands, DebugConfiguration, Event, Extension, ExtensionContext, extensions, TestItem, TestRunProfileKind, TextDocument, TextDocumentChangeEvent, TextEditor, Uri, window, workspace, WorkspaceFoldersChangeEvent } from 'vscode';
import { dispose as disposeTelemetryWrapper, initializeFromJsonFile, instrumentOperation, instrumentOperationAsVsCodeCommand } from 'vscode-extension-telemetry-wrapper';
import { navigateToTestOrTarget } from './commands/navigation/navigationCommands';
import { generateTests } from './commands/generationCommands';
@ -18,11 +18,14 @@ import { disposeCodeActionProvider, registerTestCodeActionProvider } from './pro
import { testSourceProvider } from './provider/testSourceProvider';
import { registerAskForChoiceCommand, registerAdvanceAskForChoice, registerAskForInputCommand } from './commands/askForOptionCommands';
import { enableTests } from './commands/testDependenciesCommands';
import { testRunnerService } from './controller/testRunnerService';
import { TestRunner } from './java-test-runner.api';
import { parsePartsFromTestId, parseTestIdFromParts } from './utils/testItemUtils';
export let extensionContext: ExtensionContext;
let componentsRegistered: boolean = false;
export async function activate(context: ExtensionContext): Promise<void> {
export async function activate(context: ExtensionContext): Promise<any> {
extensionContext = context;
await initializeFromJsonFile(context.asAbsolutePath('./package.json'), { replacementOptions: [{
lookup: /path must include project and resource name: \/.*/gi,
@ -30,6 +33,13 @@ export async function activate(context: ExtensionContext): Promise<void> {
}]});
await initExpService(context);
await instrumentOperation('activation', doActivate)(context);
return {
registerTestProfile: (name: string, kind: TestRunProfileKind, runner: TestRunner) => {
testRunnerService.registerTestRunner(name, kind, runner);
},
parseTestIdFromParts,
parsePartsFromTestId,
};
}
export async function deactivate(): Promise<void> {

356
src/java-test-runner.api.ts Normal file
Просмотреть файл

@ -0,0 +1,356 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import * as vscode from 'vscode';
/**
* @todo Proposed API
* Register a test profile to the test runner service.
*/
export type registerTestProfile = (name: string, kind: vscode.TestRunProfileKind, runner: TestRunner) => void;
/**
* @todo Proposed API
* Parse the test id from the parts.
*/
export type parseTestIdFromParts = (parts: TestIdParts) => string;
/**
* @todo Proposed API
* Parse the test id parts from the id.
*/
export type parsePartsFromTestId = (id: string) => TestIdParts;
/**
* @todo Proposed API
* The parts that compose a test id.
*/
export interface TestIdParts {
/**
* The project name.
*/
project: string;
/**
* The package fully qualified name.
*/
package?: string;
/**
* The class fully qualified name.
*/
class?: string;
/**
* The method name or the invocation names(for example, the dynamic tests in JUnit Jupiter).
*/
invocations?: string[];
}
/**
* @todo Proposed API
* The test runner.
*/
export interface TestRunner {
/**
* launch test test execution.
* @param context the context for this test run.
*/
launch(context: IRunTestContext): void;
/**
* Event that should be emitted when the status of a test item changes.
*/
onDidChangeTestItemStatus: vscode.Event<TestItemStatusChangeEvent>;
/**
* Event that should be emitted when the test run is finished.
*/
onDidFinishTestRun: vscode.Event<TestFinishEvent>;
}
/**
* @todo Proposed API
* The event that should be emitted when the status of a test item changes.
*/
export interface TestItemStatusChangeEvent {
/**
* An identifier representing the test item in the test explorer.
* The identifier must follow the following format:
* <package name>.<class name>[#<method or invocation name>]*
*
* Please note that:
*
* 1. The test controller will split the identifier to multiple parts according
* to the above example, and find the target test item using this hierarchy in the test explorer.
* 2. The class fully qualified name must be a valid one which exists in the test explorer.
* 3. Only the last part of the invocation or method name of the item is allowed to be non-existent
* in the explorer. In such case, the test controller will create a new test item in the test explorer.
*
* @example 'org.junit.Test#testMethod'
* @example 'foo.bar#test(String, String)#1 + 1 = 2'
*/
testId: string;
/**
* The new state of the test item.
*/
state: TestResultState;
/**
* The display name of the test item which will be displayed as description in the test explorer.
*/
displayName?: string;
/**
* The message of the test item. It can be used to show the error stacktrace for failed items.
*/
message?: string;
/**
* Execution duration for this test item in milliseconds.
*/
duration?: number;
}
/**
* @todo Proposed API
* The state of a test item.
*/
export enum TestResultState {
/**
* Test will be run, but is not currently running.
*/
Queued = 1,
/**
* Test is currently running.
*/
Running = 2,
/**
* Test run has passed.
*/
Passed = 3,
/**
* Test run has failed (on an assertion).
*/
Failed = 4,
/**
* Test run has been skipped.
*/
Skipped = 5,
/**
* Test run failed for some other reason (compilation error, timeout, etc).
*/
Errored = 6,
}
/**
* @todo Proposed API
* The event that should be emitted when the test run is finished.
*/
export interface TestFinishEvent {
/**
* The status of the test run.
*/
statusCode: number;
/**
* The message of the test run.
*/
message?: string;
}
/**
* @todo Proposed API
* The context for running tests.
*/
export interface IRunTestContext {
/**
* The flag to indicate whether the test run is in debug mode.
*/
isDebug: boolean;
/**
* The kind of the test.
*/
kind: TestKind;
/**
* The name of the project.
*/
projectName: string;
/**
* The test items to run.
*/
testItems: vscode.TestItem[];
/**
* VS Code's TestRun object for this test execution.
*/
testRun: vscode.TestRun;
/**
* The workspace folder where the tests are run.
*/
workspaceFolder: vscode.WorkspaceFolder;
/**
* The profile for this test run.
*/
profile?: vscode.TestRunProfile;
/**
* The configuration for this test run.
*/
testConfig?: IExecutionConfig;
}
/**
* @todo Proposed API
* The test kind.
*/
export enum TestKind {
JUnit5 = 0,
JUnit = 1,
TestNG = 2,
None = 100,
}
/**
* @todo Proposed API
* The test level.
*/
export enum TestLevel {
Root = 0,
Workspace = 1,
WorkspaceFolder = 2,
Project = 3,
Package = 4,
Class = 5,
Method = 6,
Invocation = 7,
}
/**
* @todo Proposed API
* The configuration for running tests.
*/
export interface IExecutionConfig {
/**
* The name of the configuration item.
* @since 0.14.0
*/
name?: string;
/**
* The working directory when running the tests.
* @since 0.14.0
*/
workingDirectory?: string;
/**
* The classpaths defined in this setting will be appended to the resolved classpaths.
* @since 0.33.0
*/
classPaths?: string[]
/**
* The modulepaths defined in this setting will be appended to the resolved modulepaths
* @since 0.33.0
*/
modulePaths?: string[]
/**
* The command line arguments which will be passed to the test runner.
* @since 0.14.0
*/
args?: any[];
/**
* The path to java executable to use. If undefined project JDK's java executable is used.
* @since 0.40.0
*/
javaExec?: string;
/**
* the extra options and system properties for the JVM.
* @since 0.14.0
*/
vmArgs?: any[];
/**
* The extra environment variables when running the tests.
* @since 0.25.0
*/
env?: { [key: string]: string; };
/**
* The absolute path to a file containing environment variable definitions.
* @since 0.33.0
*/
envFile?: string;
/**
* The extra source paths when debugging the tests
* @since 0.22.4
*/
sourcePaths?: string[];
/**
* The label of a task specified in tasks.json.
* @since 0.33.0
*/
preLaunchTask?: string;
/**
* The label of a task specified in tasks.json.
* @since 0.39.0
*/
postDebugTask?: string;
/**
* the test framework kind of this test configuration.
* @since 0.37.0
*/
testKind?: string;
/**
* The configurations for test filters.
* @since 0.37.0
*/
filters?: {
/**
* The test tags which will be included or excluded when running tests.
* This field will only take effect on JUnit 5 tests and user needs to
* explicitly set `testKind` to `junit`.
* @since 0.37.0
*/
tags?: string[]
};
/**
* The coverage configuration.
* @since 0.41.0
*/
coverage?: {
/**
* Whether the coverage result is appended. For Jacoco, it means the execution data
* is appended to the existing data file if it already exists.
* @since 0.41.0
*/
appendResult?: boolean;
}
/**
* The when clause for matching tests by to determine if the configuration should be run with.
* @since 0.41.0
*/
when?: string
}

Просмотреть файл

@ -2,126 +2,7 @@
// Licensed under the MIT license.
import { Configurations } from './constants';
export interface IExecutionConfig {
/**
* The name of the configuration item.
* @since 0.14.0
*/
name?: string;
/**
* The working directory when running the tests.
* @since 0.14.0
*/
workingDirectory?: string;
/**
* The classpaths defined in this setting will be appended to the resolved classpaths.
* @since 0.33.0
*/
classPaths?: string[]
/**
* The modulepaths defined in this setting will be appended to the resolved modulepaths
* @since 0.33.0
*/
modulePaths?: string[]
/**
* The command line arguments which will be passed to the test runner.
* @since 0.14.0
*/
args?: any[];
/**
* The path to java executable to use. If undefined project JDK's java executable is used.
* @since 0.40.0
*/
javaExec?: string;
/**
* the extra options and system properties for the JVM.
* It's deprecated, we should align with the debug launch configuration, which is 'vmArgs'.
* @since 0.14.0
*/
vmargs?: any[];
/**
* the extra options and system properties for the JVM.
* @since 0.14.0
*/
vmArgs?: any[];
/**
* The extra environment variables when running the tests.
* @since 0.25.0
*/
env?: { [key: string]: string; };
/**
* The absolute path to a file containing environment variable definitions.
* @since 0.33.0
*/
envFile?: string;
/**
* The extra source paths when debugging the tests
* @since 0.22.4
*/
sourcePaths?: string[];
/**
* The label of a task specified in tasks.json.
* @since 0.33.0
*/
preLaunchTask?: string;
/**
* The label of a task specified in tasks.json.
* @since 0.39.0
*/
postDebugTask?: string;
/**
* the test framework kind of this test configuration.
* @since 0.37.0
*/
testKind?: string;
/**
* The configurations for test filters.
* @since 0.37.0
*/
filters?: {
/**
* The test tags which will be included or excluded when running tests.
* This field will only take effect on JUnit 5 tests and user needs to
* explicitly set `testKind` to `junit`.
* @since 0.37.0
*/
tags?: string[]
};
/**
* The coverage configuration.
* @since 0.41.0
*/
coverage?: {
/**
* Whether the coverage result is appended. For Jacoco, it means the execution data
* is appended to the existing data file if it already exists.
* @since 0.41.0
*/
appendResult?: boolean;
}
/**
* The when clause for matching tests by to determine if the configuration should be run with.
* @since 0.41.0
*/
when?: string
}
import { IExecutionConfig } from './java-test-runner.api';
export function getBuiltinConfig(): IExecutionConfig {
return Object.assign({}, BUILTIN_CONFIG);

Просмотреть файл

@ -3,9 +3,9 @@
import { CancellationToken, DebugConfiguration } from 'vscode';
import { IProgressReporter } from '../debugger.api';
import { IRunTestContext } from '../types';
import { IRunTestContext } from '../java-test-runner.api';
export interface ITestRunner {
export interface ITestRunnerInternal {
setup(context: IRunTestContext): Promise<void>;
run(launchConfiguration: DebugConfiguration, token: CancellationToken, progressReporter?: IProgressReporter): Promise<void>;
tearDown(isCancel: boolean): Promise<void>;

Просмотреть файл

@ -9,12 +9,11 @@ import { CancellationToken, debug, DebugConfiguration, DebugSession, Disposable
import { sendError } from 'vscode-extension-telemetry-wrapper';
import { Configurations } from '../../constants';
import { IProgressReporter } from '../../debugger.api';
import { IExecutionConfig } from '../../runConfigs';
import { IRunTestContext } from '../../types';
import { ITestRunner } from '../ITestRunner';
import { ITestRunnerInternal } from '../ITestRunner';
import { RunnerResultAnalyzer } from './RunnerResultAnalyzer';
import { IExecutionConfig, IRunTestContext } from '../../java-test-runner.api';
export abstract class BaseRunner implements ITestRunner {
export abstract class BaseRunner implements ITestRunnerInternal {
protected server: Server;
protected socket: Socket;
protected runnerResultAnalyzer: RunnerResultAnalyzer;

Просмотреть файл

@ -2,7 +2,7 @@
// Licensed under the MIT license.
import { Location, MarkdownString, TestItem } from 'vscode';
import { IRunTestContext } from '../../types';
import { IRunTestContext } from '../../java-test-runner.api';
import { processStackTraceLine } from '../utils';
export abstract class RunnerResultAnalyzer {

Просмотреть файл

@ -4,10 +4,11 @@
import { Location, MarkdownString, TestItem, TestMessage } from 'vscode';
import { dataCache, ITestItemData } from '../../controller/testItemDataCache';
import { createTestItem, updateOrCreateTestItem } from '../../controller/utils';
import { IJavaTestItem, IRunTestContext, TestKind, TestLevel } from '../../types';
import { IJavaTestItem } from '../../types';
import { RunnerResultAnalyzer } from '../baseRunner/RunnerResultAnalyzer';
import { findTestLocation, setTestState, TestResultState } from '../utils';
import { findTestLocation, setTestState } from '../utils';
import { JUnitTestPart } from '../../constants';
import { IRunTestContext, TestKind, TestLevel, TestResultState } from '../../java-test-runner.api';
export class JUnitRunnerResultAnalyzer extends RunnerResultAnalyzer {

Просмотреть файл

@ -3,10 +3,10 @@
import { TestItem } from 'vscode';
import { dataCache } from '../../controller/testItemDataCache';
import { TestLevel } from '../../types';
import { BaseRunner } from '../baseRunner/BaseRunner';
import { RunnerResultAnalyzer } from '../baseRunner/RunnerResultAnalyzer';
import { TestNGRunnerResultAnalyzer } from './TestNGRunnerResultAnalyzer';
import { TestLevel } from '../../java-test-runner.api';
export class TestNGRunner extends BaseRunner {

Просмотреть файл

@ -3,9 +3,9 @@
import { Location, MarkdownString, TestItem, TestMessage } from 'vscode';
import { dataCache } from '../../controller/testItemDataCache';
import { IRunTestContext, TestLevel } from '../../types';
import { RunnerResultAnalyzer } from '../baseRunner/RunnerResultAnalyzer';
import { setTestState, TestResultState } from '../utils';
import { setTestState } from '../utils';
import { IRunTestContext, TestLevel, TestResultState } from '../../java-test-runner.api';
const TEST_START: string = 'testStarted';
const TEST_FAIL: string = 'testFailed';

Просмотреть файл

@ -6,6 +6,7 @@ import { JavaTestRunnerCommands } from '../constants';
import { asRange } from '../controller/utils';
import { executeJavaLanguageServerCommand } from '../utils/commandUtils';
import * as path from 'path';
import { TestResultState } from '../java-test-runner.api';
export async function findTestLocation(fullName: string): Promise<Location | undefined> {
const location: any | undefined = await executeJavaLanguageServerCommand<any>(
@ -38,22 +39,6 @@ export function setTestState(testRun: TestRun, item: TestItem, result: TestResul
}
}
// Copied from the proposed part of the API
export enum TestResultState {
// Test will be run, but is not currently running.
Queued = 1,
// Test is currently running
Running = 2,
// Test run has passed
Passed = 3,
// Test run has failed (on an assertion)
Failed = 4,
// Test run has been skipped
Skipped = 5,
// Test run failed for some other reason (compilation error, timeout, etc)
Errored = 6,
}
/**
* Append the line of stack trace to the traces.
* @param lineOfMessage line of stack trace.

Просмотреть файл

@ -1,8 +1,8 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import { Range, TestItem, TestRun, TestRunProfile } from 'vscode';
import * as vscode from 'vscode';
import { Range } from 'vscode';
import { TestKind, TestLevel } from './java-test-runner.api';
export interface IJavaTestItem {
children: IJavaTestItem[];
@ -31,34 +31,6 @@ export interface IJavaTestItem {
natureIds?: string[];
}
export enum TestKind {
JUnit5 = 0,
JUnit = 1,
TestNG = 2,
None = 100,
}
export enum TestLevel {
Root = 0,
Workspace = 1,
WorkspaceFolder = 2,
Project = 3,
Package = 4,
Class = 5,
Method = 6,
Invocation = 7,
}
export interface IRunTestContext {
isDebug: boolean;
kind: TestKind;
projectName: string;
testItems: TestItem[];
testRun: TestRun;
workspaceFolder: vscode.WorkspaceFolder;
profile?: TestRunProfile;
}
export enum ProjectType {
Gradle,
Maven,

Просмотреть файл

@ -8,7 +8,8 @@ import { sendInfo } from 'vscode-extension-telemetry-wrapper';
import { Configurations, Dialog } from '../constants';
import { dataCache } from '../controller/testItemDataCache';
import { extensionContext } from '../extension';
import { getBuiltinConfig, IExecutionConfig } from '../runConfigs';
import { getBuiltinConfig } from '../runConfigs';
import { IExecutionConfig } from '../java-test-runner.api';
export async function loadRunConfig(testItems: TestItem[], workspaceFolder: WorkspaceFolder): Promise<IExecutionConfig | undefined> {
const configSetting: IExecutionConfig[] | IExecutionConfig = workspace.getConfiguration(undefined, workspaceFolder.uri).get<IExecutionConfig[] | IExecutionConfig>(Configurations.CONFIG_SETTING_KEY, {});

Просмотреть файл

@ -8,19 +8,19 @@ import { sendError, sendInfo } from 'vscode-extension-telemetry-wrapper';
import { JavaTestRunnerDelegateCommands } from '../constants';
import { dataCache } from '../controller/testItemDataCache';
import { extensionContext } from '../extension';
import { IExecutionConfig } from '../runConfigs';
import { BaseRunner, IJUnitLaunchArguments, Response } from '../runners/baseRunner/BaseRunner';
import { IRunTestContext, TestKind, TestLevel } from '../types';
import { executeJavaLanguageServerCommand } from './commandUtils';
import { getJacocoAgentPath, getJacocoDataFilePath } from './coverageUtils';
import { IExecutionConfig, IRunTestContext, TestKind, TestLevel } from '../java-test-runner.api';
export async function resolveLaunchConfigurationForRunner(runner: BaseRunner, testContext: IRunTestContext, config?: IExecutionConfig): Promise<DebugConfiguration> {
const launchArguments: IJUnitLaunchArguments = await getLaunchArguments(testContext);
if (config && config.vmArgs) {
launchArguments.vmArguments.push(...config.vmArgs.filter(Boolean));
} else if (config && config.vmargs) {
launchArguments.vmArguments.push(...config.vmargs.filter(Boolean));
} else if (config && (config as any).vmargs) { // to support the deprecated property name.
launchArguments.vmArguments.push(...(config as any).vmargs.filter(Boolean));
sendInfo('', {'deprecatedPropertyUsed': 'vmargs'});
}
let debugConfiguration: DebugConfiguration;

Просмотреть файл

@ -0,0 +1,53 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import { TestIdParts } from '../java-test-runner.api';
export function parseTestIdFromParts(parts: TestIdParts): string {
let testId: string = parts.project;
if (parts.class) {
testId += `@${parts.class}`;
} else if (parts.package) {
testId += `@${parts.package}`;
}
if (parts.invocations?.length) {
testId += `#${parts.invocations.join('#')}`;
}
return testId;
}
export function parsePartsFromTestId(testId: string): TestIdParts {
const idxOfProjectSeparator: number = testId.indexOf('@');
if (idxOfProjectSeparator < 0) {
return { project: testId };
}
const project: string = testId.substring(0, idxOfProjectSeparator);
testId = testId.substring(idxOfProjectSeparator + 1);
const idxOfMethodStart: number = testId.indexOf('#');
let classFullyQualifiedName: string;
if (idxOfMethodStart > 0) {
classFullyQualifiedName = testId.substring(0, idxOfMethodStart);
} else {
classFullyQualifiedName = testId;
}
const idxOfLastDot: number = classFullyQualifiedName.lastIndexOf('.');
const packageName: string = idxOfLastDot > 0 ? classFullyQualifiedName.substring(0, idxOfLastDot) : '';
let invocations: string[] | undefined;
if (idxOfMethodStart > 0) {
testId = testId.substring(idxOfMethodStart + 1);
invocations = [...testId.split('#')];
}
return {
project,
package: packageName,
class: classFullyQualifiedName,
invocations,
}
}

Просмотреть файл

@ -6,8 +6,8 @@
import * as sinon from 'sinon';
import { Range, TestController, TestItem, TestMessage, TestRunRequest, tests, workspace } from 'vscode';
import { JUnitRunnerResultAnalyzer } from '../../src/runners/junitRunner/JUnitRunnerResultAnalyzer';
import { TestKind } from '../../src/types';
import { generateTestItem } from './utils';
import { TestKind } from '../../src/java-test-runner.api';
// tslint:disable: only-arrow-functions
// tslint:disable: no-object-literal-type-assertion

Просмотреть файл

@ -7,8 +7,8 @@ import * as assert from 'assert';
import * as sinon from 'sinon';
import { MarkdownString, Range, TestController, TestMessage, TestRunRequest, tests, workspace } from 'vscode';
import { JUnitRunnerResultAnalyzer } from '../../src/runners/junitRunner/JUnitRunnerResultAnalyzer';
import { IRunTestContext, TestKind } from '../../src/types';
import { generateTestItem } from './utils';
import { TestKind, IRunTestContext } from '../../src/java-test-runner.api';
// tslint:disable: only-arrow-functions
// tslint:disable: no-object-literal-type-assertion

Просмотреть файл

@ -6,9 +6,9 @@
import * as assert from 'assert';
import { TestController, TestRunRequest, tests, workspace } from 'vscode';
import { JUnitRunner } from '../../src/runners/junitRunner/JunitRunner';
import { IRunTestContext, TestKind } from '../../src/types';
import { resolveLaunchConfigurationForRunner } from '../../src/utils/launchUtils';
import { generateTestItem, setupTestEnv } from './utils';
import { TestKind, IRunTestContext } from '../../src/java-test-runner.api';
// tslint:disable: only-arrow-functions
// tslint:disable: no-object-literal-type-assertion

Просмотреть файл

@ -6,10 +6,10 @@
import * as assert from 'assert';
import { JavaTestRunnerDelegateCommands } from "../../src/constants";
import { IJUnitLaunchArguments, Response } from "../../src/runners/baseRunner/BaseRunner";
import { TestKind, TestLevel } from "../../src/types";
import { executeJavaLanguageServerCommand } from "../../src/utils/commandUtils";
import { setupTestEnv } from "./utils";
import { exportedForTesting } from "../../src/utils/launchUtils";
import { TestLevel, TestKind } from '../../src/java-test-runner.api';
// tslint:disable: only-arrow-functions
// tslint:disable: no-object-literal-type-assertion

Просмотреть файл

@ -3,8 +3,8 @@ import * as sinon from 'sinon';
import { TestController, TestItem, tests, window } from "vscode";
import { handleInvocations } from '../../src/controller/testController';
import { dataCache } from "../../src/controller/testItemDataCache";
import { TestKind, TestLevel } from "../../src/types";
import { setupTestEnv } from './utils';
import { TestKind, TestLevel } from '../../src/java-test-runner.api';
function generateTestItem(testController: TestController, id: string, testKind: TestKind, testLevel: TestLevel, uniqueId?: string): TestItem {
const testItem = testController.createTestItem(id, id + '_label');

Просмотреть файл

@ -7,7 +7,7 @@ import * as fse from 'fs-extra';
import * as path from 'path';
import { commands, extensions, Range, TestController, TestItem, Uri, workspace } from "vscode";
import { dataCache } from "../../src/controller/testItemDataCache";
import { TestKind, TestLevel } from "../../src/types";
import { TestKind, TestLevel } from '../../src/java-test-runner.api';
export function generateTestItem(testController: TestController, id: string, testKind: TestKind,
range?: Range, jdtHandler?: string, uri: string = '/mock/test/TestAnnotation.java'): TestItem {

Просмотреть файл

@ -8,8 +8,8 @@ import * as path from 'path';
import * as fse from 'fs-extra';
import { Uri, window } from 'vscode';
import { enableTests } from '../../src/commands/testDependenciesCommands';
import { TestKind } from '../../src/types';
import { setupTestEnv, sleep } from '../suite/utils';
import { TestKind } from '../../src/java-test-runner.api';
// tslint:disable: only-arrow-functions
// tslint:disable: no-object-literal-type-assertion