[READ-ONLY] Mirror of https://github.com/vitest-dev/vitest. Next generation testing framework powered by Vite. vitest.dev
test testing-tools vite
12

Configure Feed

Select the types of activity you want to include in your feed.

fix(coverage): ignore generated TS decorators (#5206)

Co-authored-by: Vladimir <sleuths.slews0s@icloud.com>

authored by

Ari Perkkiö
Vladimir
and committed by
GitHub
(Feb 20, 2024, 2:05 PM +0100) a280451b 5376d5be

+1059 -66
+3
packages/coverage-istanbul/src/provider.ts
··· 114 114 const sourceMap = pluginCtx.getCombinedSourcemap() 115 115 sourceMap.sources = sourceMap.sources.map(removeQueryParameters) 116 116 117 + // Exclude SWC's decorators that are left in source maps 118 + sourceCode = sourceCode.replaceAll('_ts_decorate', '/* istanbul ignore next */_ts_decorate') 119 + 117 120 const code = this.instrumenter.instrumentSync(sourceCode, id, sourceMap as any) 118 121 const map = this.instrumenter.lastSourceMap() as any 119 122
+14 -10
packages/coverage-v8/src/provider.ts
··· 51 51 52 52 // Note that this needs to match the line ending as well 53 53 const VITE_EXPORTS_LINE_PATTERN = /Object\.defineProperty\(__vite_ssr_exports__.*\n/g 54 + const DECORATOR_METADATA_PATTERN = /_ts_metadata\("design:paramtypes"(\s|.)+?]\),/g 54 55 const DEFAULT_PROJECT = Symbol.for('default-project') 55 56 56 57 const debug = createDebug('vitest:coverage') ··· 312 313 originalSource: sourcesContent, 313 314 source: code || sourcesContent, 314 315 sourceMap: { 315 - sourcemap: removeViteHelpersFromSourceMaps(code, { 316 + sourcemap: excludeGeneratedCode(code, { 316 317 ...map, 317 318 version: 3, 318 319 sources: [url], ··· 363 364 /** 364 365 * Remove generated code from the source maps: 365 366 * - Vite's export helpers: e.g. `Object.defineProperty(__vite_ssr_exports__, "sum", { enumerable: true, configurable: true, get(){ return sum }});` 367 + * - SWC's decorator metadata: e.g. `_ts_metadata("design:paramtypes", [\ntypeof Request === "undefined" ? Object : Request\n]),` 366 368 */ 367 - function removeViteHelpersFromSourceMaps(source: string | undefined, map: EncodedSourceMap) { 368 - if (!source || !source.match(VITE_EXPORTS_LINE_PATTERN)) 369 + function excludeGeneratedCode(source: string | undefined, map: EncodedSourceMap) { 370 + if (!source) 371 + return map 372 + 373 + if (!source.match(VITE_EXPORTS_LINE_PATTERN) && !source.match(DECORATOR_METADATA_PATTERN)) 369 374 return map 370 375 371 - const sourceWithoutHelpers = new MagicString(source) 372 - sourceWithoutHelpers.replaceAll(VITE_EXPORTS_LINE_PATTERN, '\n') 376 + const trimmed = new MagicString(source) 377 + trimmed.replaceAll(VITE_EXPORTS_LINE_PATTERN, '\n') 378 + trimmed.replaceAll(DECORATOR_METADATA_PATTERN, match => '\n'.repeat(match.split('\n').length - 1)) 373 379 374 - const mapWithoutHelpers = sourceWithoutHelpers.generateMap({ 375 - hires: 'boundary', 376 - }) 380 + const trimmedMap = trimmed.generateMap({ hires: 'boundary' }) 377 381 378 - // A merged source map where the first one excludes helpers 382 + // A merged source map where the first one excludes generated parts 379 383 const combinedMap = remapping( 380 - [{ ...mapWithoutHelpers, version: 3 }, map], 384 + [{ ...trimmedMap, version: 3 }, map], 381 385 () => null, 382 386 ) 383 387
+172
pnpm-lock.yaml
··· 1675 1675 magicast: 1676 1676 specifier: ^0.3.3 1677 1677 version: 0.3.3 1678 + unplugin-swc: 1679 + specifier: ^1.4.4 1680 + version: 1.4.4(@swc/core@1.4.1)(rollup@4.9.6) 1678 1681 vite: 1679 1682 specifier: ^5.0.12 1680 1683 version: 5.0.12(@types/node@20.11.5)(less@4.1.3) ··· 7073 7076 picomatch: 2.3.1 7074 7077 rollup: 4.9.6 7075 7078 7079 + /@rollup/pluginutils@5.1.0(rollup@4.9.6): 7080 + resolution: {integrity: sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==} 7081 + engines: {node: '>=14.0.0'} 7082 + peerDependencies: 7083 + rollup: ^4.9.6 7084 + peerDependenciesMeta: 7085 + rollup: 7086 + optional: true 7087 + dependencies: 7088 + '@types/estree': 1.0.5 7089 + estree-walker: 2.0.2 7090 + picomatch: 2.3.1 7091 + rollup: 4.9.6 7092 + dev: true 7093 + 7076 7094 /@rollup/rollup-android-arm-eabi@4.9.6: 7077 7095 resolution: {integrity: sha512-MVNXSSYN6QXOulbHpLMKYi60ppyO13W9my1qogeiAqtjb2yR4LSmfU2+POvDkLzhjYLXz9Rf9+9a3zFHW1Lecg==} 7078 7096 cpu: [arm] ··· 8839 8857 - supports-color 8840 8858 dev: true 8841 8859 8860 + /@swc/core-darwin-arm64@1.4.1: 8861 + resolution: {integrity: sha512-ePyfx0348UbR4DOAW24TedeJbafnzha8liXFGuQ4bdXtEVXhLfPngprrxKrAddCuv42F9aTxydlF6+adD3FBhA==} 8862 + engines: {node: '>=10'} 8863 + cpu: [arm64] 8864 + os: [darwin] 8865 + requiresBuild: true 8866 + dev: true 8867 + optional: true 8868 + 8869 + /@swc/core-darwin-x64@1.4.1: 8870 + resolution: {integrity: sha512-eLf4JSe6VkCMdDowjM8XNC5rO+BrgfbluEzAVtKR8L2HacNYukieumN7EzpYCi0uF1BYwu1ku6tLyG2r0VcGxA==} 8871 + engines: {node: '>=10'} 8872 + cpu: [x64] 8873 + os: [darwin] 8874 + requiresBuild: true 8875 + dev: true 8876 + optional: true 8877 + 8878 + /@swc/core-linux-arm-gnueabihf@1.4.1: 8879 + resolution: {integrity: sha512-K8VtTLWMw+rkN/jDC9o/Q9SMmzdiHwYo2CfgkwVT29NsGccwmNhCQx6XoYiPKyKGIFKt4tdQnJHKUFzxUqQVtQ==} 8880 + engines: {node: '>=10'} 8881 + cpu: [arm] 8882 + os: [linux] 8883 + requiresBuild: true 8884 + dev: true 8885 + optional: true 8886 + 8887 + /@swc/core-linux-arm64-gnu@1.4.1: 8888 + resolution: {integrity: sha512-0e8p4g0Bfkt8lkiWgcdiENH3RzkcqKtpRXIVNGOmVc0OBkvc2tpm2WTx/eoCnes2HpTT4CTtR3Zljj4knQ4Fvw==} 8889 + engines: {node: '>=10'} 8890 + cpu: [arm64] 8891 + os: [linux] 8892 + requiresBuild: true 8893 + dev: true 8894 + optional: true 8895 + 8896 + /@swc/core-linux-arm64-musl@1.4.1: 8897 + resolution: {integrity: sha512-b/vWGQo2n7lZVUnSQ7NBq3Qrj85GrAPPiRbpqaIGwOytiFSk8VULFihbEUwDe0rXgY4LDm8z8wkgADZcLnmdUA==} 8898 + engines: {node: '>=10'} 8899 + cpu: [arm64] 8900 + os: [linux] 8901 + requiresBuild: true 8902 + dev: true 8903 + optional: true 8904 + 8905 + /@swc/core-linux-x64-gnu@1.4.1: 8906 + resolution: {integrity: sha512-AFMQlvkKEdNi1Vk2GFTxxJzbICttBsOQaXa98kFTeWTnFFIyiIj2w7Sk8XRTEJ/AjF8ia8JPKb1zddBWr9+bEQ==} 8907 + engines: {node: '>=10'} 8908 + cpu: [x64] 8909 + os: [linux] 8910 + requiresBuild: true 8911 + dev: true 8912 + optional: true 8913 + 8914 + /@swc/core-linux-x64-musl@1.4.1: 8915 + resolution: {integrity: sha512-QX2MxIECX1gfvUVZY+jk528/oFkS9MAl76e3ZRvG2KC/aKlCQL0KSzcTSm13mOxkDKS30EaGRDRQWNukGpMeRg==} 8916 + engines: {node: '>=10'} 8917 + cpu: [x64] 8918 + os: [linux] 8919 + requiresBuild: true 8920 + dev: true 8921 + optional: true 8922 + 8923 + /@swc/core-win32-arm64-msvc@1.4.1: 8924 + resolution: {integrity: sha512-OklkJYXXI/tntD2zaY8i3iZldpyDw5q+NAP3k9OlQ7wXXf37djRsHLV0NW4+ZNHBjE9xp2RsXJ0jlOJhfgGoFA==} 8925 + engines: {node: '>=10'} 8926 + cpu: [arm64] 8927 + os: [win32] 8928 + requiresBuild: true 8929 + dev: true 8930 + optional: true 8931 + 8932 + /@swc/core-win32-ia32-msvc@1.4.1: 8933 + resolution: {integrity: sha512-MBuc3/QfKX9FnLOU7iGN+6yHRTQaPQ9WskiC8s8JFiKQ+7I2p25tay2RplR9dIEEGgVAu6L7auv96LbNTh+FaA==} 8934 + engines: {node: '>=10'} 8935 + cpu: [ia32] 8936 + os: [win32] 8937 + requiresBuild: true 8938 + dev: true 8939 + optional: true 8940 + 8941 + /@swc/core-win32-x64-msvc@1.4.1: 8942 + resolution: {integrity: sha512-lu4h4wFBb/bOK6N2MuZwg7TrEpwYXgpQf5R7ObNSXL65BwZ9BG8XRzD+dLJmALu8l5N08rP/TrpoKRoGT4WSxw==} 8943 + engines: {node: '>=10'} 8944 + cpu: [x64] 8945 + os: [win32] 8946 + requiresBuild: true 8947 + dev: true 8948 + optional: true 8949 + 8950 + /@swc/core@1.4.1: 8951 + resolution: {integrity: sha512-3y+Y8js+e7BbM16iND+6Rcs3jdiL28q3iVtYsCviYSSpP2uUVKkp5sJnCY4pg8AaVvyN7CGQHO7gLEZQ5ByozQ==} 8952 + engines: {node: '>=10'} 8953 + requiresBuild: true 8954 + peerDependencies: 8955 + '@swc/helpers': ^0.5.0 8956 + peerDependenciesMeta: 8957 + '@swc/helpers': 8958 + optional: true 8959 + dependencies: 8960 + '@swc/counter': 0.1.3 8961 + '@swc/types': 0.1.5 8962 + optionalDependencies: 8963 + '@swc/core-darwin-arm64': 1.4.1 8964 + '@swc/core-darwin-x64': 1.4.1 8965 + '@swc/core-linux-arm-gnueabihf': 1.4.1 8966 + '@swc/core-linux-arm64-gnu': 1.4.1 8967 + '@swc/core-linux-arm64-musl': 1.4.1 8968 + '@swc/core-linux-x64-gnu': 1.4.1 8969 + '@swc/core-linux-x64-musl': 1.4.1 8970 + '@swc/core-win32-arm64-msvc': 1.4.1 8971 + '@swc/core-win32-ia32-msvc': 1.4.1 8972 + '@swc/core-win32-x64-msvc': 1.4.1 8973 + dev: true 8974 + 8975 + /@swc/counter@0.1.3: 8976 + resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==} 8977 + dev: true 8978 + 8979 + /@swc/types@0.1.5: 8980 + resolution: {integrity: sha512-myfUej5naTBWnqOCc/MdVOLVjXUXtIA+NpDrDBKJtLLg2shUjBu3cZmB/85RyitKc55+lUUyl7oRfLOvkr2hsw==} 8981 + dev: true 8982 + 8842 8983 /@szmarczak/http-timer@5.0.1: 8843 8984 resolution: {integrity: sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==} 8844 8985 engines: {node: '>=14.16'} ··· 19847 19988 dev: true 19848 19989 optional: true 19849 19990 19991 + /load-tsconfig@0.2.5: 19992 + resolution: {integrity: sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==} 19993 + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} 19994 + dev: true 19995 + 19850 19996 /loader-runner@2.4.0: 19851 19997 resolution: {integrity: sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==} 19852 19998 engines: {node: '>=4.3.0 <5.0.0 || >=5.10'} ··· 25831 25977 - rollup 25832 25978 dev: true 25833 25979 25980 + /unplugin-swc@1.4.4(@swc/core@1.4.1)(rollup@4.9.6): 25981 + resolution: {integrity: sha512-S2mgLIQVNR1+UGIk379/wD3tmkTJfm9QJFyZgXutMDNsSJrcPNJUdSXUNGE/+1Zde9i/I0r0BvDqxGgTkg+eJQ==} 25982 + peerDependencies: 25983 + '@swc/core': ^1.2.108 25984 + dependencies: 25985 + '@rollup/pluginutils': 5.1.0(rollup@4.9.6) 25986 + '@swc/core': 1.4.1 25987 + load-tsconfig: 0.2.5 25988 + unplugin: 1.7.1 25989 + transitivePeerDependencies: 25990 + - rollup 25991 + dev: true 25992 + 25834 25993 /unplugin-vue-components@0.25.2(rollup@4.9.6)(vue@3.3.8): 25835 25994 resolution: {integrity: sha512-OVmLFqILH6w+eM8fyt/d/eoJT9A6WO51NZLf1vC5c1FZ4rmq2bbGxTy8WP2Jm7xwFdukaIdv819+UI7RClPyCA==} 25836 25995 engines: {node: '>=14'} ··· 25867 26026 chokidar: 3.5.3 25868 26027 webpack-sources: 3.2.3 25869 26028 webpack-virtual-modules: 0.5.0 26029 + dev: true 26030 + 26031 + /unplugin@1.7.1: 26032 + resolution: {integrity: sha512-JqzORDAPxxs8ErLV4x+LL7bk5pk3YlcWqpSNsIkAZj972KzFZLClc/ekppahKkOczGkwIG6ElFgdOgOlK4tXZw==} 26033 + dependencies: 26034 + acorn: 8.11.3 26035 + chokidar: 3.5.3 26036 + webpack-sources: 3.2.3 26037 + webpack-virtual-modules: 0.6.1 25870 26038 dev: true 25871 26039 25872 26040 /unset-value@1.0.0: ··· 26851 27019 26852 27020 /webpack-virtual-modules@0.5.0: 26853 27021 resolution: {integrity: sha512-kyDivFZ7ZM0BVOUteVbDFhlRt7Ah/CSPwJdi8hBpkK7QLumUqdLtVfm/PX/hkcnrvr0i77fO5+TjZ94Pe+C9iw==} 27022 + dev: true 27023 + 27024 + /webpack-virtual-modules@0.6.1: 27025 + resolution: {integrity: sha512-poXpCylU7ExuvZK8z+On3kX+S8o/2dQ/SVYueKA0D4WEMXROXgY8Ez50/bQEUmvoSMMrWcrJqCHuhAbsiwg7Dg==} 26854 27026 dev: true 26855 27027 26856 27028 /webpack@4.46.0:
+1
test/coverage-test/coverage-report-tests/__snapshots__/custom.report.test.ts.snap
··· 20 20 "<process-cwd>/src/Defined.vue", 21 21 "<process-cwd>/src/Hello.vue", 22 22 "<process-cwd>/src/another-setup.ts", 23 + "<process-cwd>/src/decorators.ts", 23 24 "<process-cwd>/src/dynamic-file-esm.ignore.js", 24 25 "<process-cwd>/src/dynamic-files.ts", 25 26 "<process-cwd>/src/function-count.ts",
+209
test/coverage-test/coverage-report-tests/__snapshots__/istanbul.report.test.ts.snap
··· 530 530 }, 531 531 }, 532 532 }, 533 + "<process-cwd>/src/decorators.ts": { 534 + "b": { 535 + "0": [ 536 + 1, 537 + 0, 538 + ], 539 + "1": [ 540 + 0, 541 + 1, 542 + ], 543 + }, 544 + "branchMap": { 545 + "0": { 546 + "loc": { 547 + "end": { 548 + "column": null, 549 + "line": 8, 550 + }, 551 + "start": { 552 + "column": 4, 553 + "line": 5, 554 + }, 555 + }, 556 + "locations": [ 557 + { 558 + "end": { 559 + "column": null, 560 + "line": 8, 561 + }, 562 + "start": { 563 + "column": 4, 564 + "line": 5, 565 + }, 566 + }, 567 + { 568 + "end": { 569 + "column": null, 570 + "line": 8, 571 + }, 572 + "start": { 573 + "column": 4, 574 + "line": 5, 575 + }, 576 + }, 577 + ], 578 + "type": "if", 579 + }, 580 + "1": { 581 + "loc": { 582 + "end": { 583 + "column": null, 584 + "line": 13, 585 + }, 586 + "start": { 587 + "column": 4, 588 + "line": 10, 589 + }, 590 + }, 591 + "locations": [ 592 + { 593 + "end": { 594 + "column": null, 595 + "line": 13, 596 + }, 597 + "start": { 598 + "column": 4, 599 + "line": 10, 600 + }, 601 + }, 602 + { 603 + "end": { 604 + "column": null, 605 + "line": 13, 606 + }, 607 + "start": { 608 + "column": 4, 609 + "line": 10, 610 + }, 611 + }, 612 + ], 613 + "type": "if", 614 + }, 615 + }, 616 + "f": { 617 + "0": 1, 618 + "1": 1, 619 + "2": 1, 620 + }, 621 + "fnMap": { 622 + "0": { 623 + "decl": { 624 + "end": { 625 + "column": 9, 626 + "line": 4, 627 + }, 628 + "start": { 629 + "column": 2, 630 + "line": 4, 631 + }, 632 + }, 633 + "loc": { 634 + "end": { 635 + "column": null, 636 + "line": 14, 637 + }, 638 + "start": { 639 + "column": 46, 640 + "line": 4, 641 + }, 642 + }, 643 + "name": "(anonymous_4)", 644 + }, 645 + "1": { 646 + "decl": { 647 + "end": { 648 + "column": null, 649 + "line": 17, 650 + }, 651 + "start": { 652 + "column": 9, 653 + "line": 17, 654 + }, 655 + }, 656 + "loc": { 657 + "end": { 658 + "column": null, 659 + "line": 21, 660 + }, 661 + "start": { 662 + "column": 25, 663 + "line": 20, 664 + }, 665 + }, 666 + "name": "SomeDecorator", 667 + }, 668 + "2": { 669 + "decl": { 670 + "end": { 671 + "column": 17, 672 + "line": 25, 673 + }, 674 + "start": { 675 + "column": 9, 676 + "line": 25, 677 + }, 678 + }, 679 + "loc": { 680 + "end": { 681 + "column": null, 682 + "line": 27, 683 + }, 684 + "start": { 685 + "column": 33, 686 + "line": 25, 687 + }, 688 + }, 689 + "name": "noop", 690 + }, 691 + }, 692 + "path": "<process-cwd>/src/decorators.ts", 693 + "s": { 694 + "0": 1, 695 + "1": 1, 696 + "2": 1, 697 + "3": 0, 698 + }, 699 + "statementMap": { 700 + "0": { 701 + "end": { 702 + "column": null, 703 + "line": 8, 704 + }, 705 + "start": { 706 + "column": 4, 707 + "line": 5, 708 + }, 709 + }, 710 + "1": { 711 + "end": { 712 + "column": null, 713 + "line": 7, 714 + }, 715 + "start": { 716 + "column": 6, 717 + "line": 7, 718 + }, 719 + }, 720 + "2": { 721 + "end": { 722 + "column": null, 723 + "line": 13, 724 + }, 725 + "start": { 726 + "column": 4, 727 + "line": 10, 728 + }, 729 + }, 730 + "3": { 731 + "end": { 732 + "column": null, 733 + "line": 12, 734 + }, 735 + "start": { 736 + "column": 6, 737 + "line": 12, 738 + }, 739 + }, 740 + }, 741 + }, 533 742 "<process-cwd>/src/dynamic-files.ts": { 534 743 "b": { 535 744 "0": [
+504
test/coverage-test/coverage-report-tests/__snapshots__/v8.report.test.ts.snap
··· 1231 1231 }, 1232 1232 }, 1233 1233 }, 1234 + "<process-cwd>/src/decorators.ts": { 1235 + "all": false, 1236 + "b": { 1237 + "0": [ 1238 + 1, 1239 + ], 1240 + "1": [ 1241 + 0, 1242 + ], 1243 + "2": [ 1244 + 1, 1245 + ], 1246 + "3": [ 1247 + 1, 1248 + ], 1249 + }, 1250 + "branchMap": { 1251 + "0": { 1252 + "line": 4, 1253 + "loc": { 1254 + "end": { 1255 + "column": 3, 1256 + "line": 14, 1257 + }, 1258 + "start": { 1259 + "column": 2, 1260 + "line": 4, 1261 + }, 1262 + }, 1263 + "locations": [ 1264 + { 1265 + "end": { 1266 + "column": 3, 1267 + "line": 14, 1268 + }, 1269 + "start": { 1270 + "column": 2, 1271 + "line": 4, 1272 + }, 1273 + }, 1274 + ], 1275 + "type": "branch", 1276 + }, 1277 + "1": { 1278 + "line": 10, 1279 + "loc": { 1280 + "end": { 1281 + "column": 5, 1282 + "line": 13, 1283 + }, 1284 + "start": { 1285 + "column": 35, 1286 + "line": 10, 1287 + }, 1288 + }, 1289 + "locations": [ 1290 + { 1291 + "end": { 1292 + "column": 5, 1293 + "line": 13, 1294 + }, 1295 + "start": { 1296 + "column": 35, 1297 + "line": 10, 1298 + }, 1299 + }, 1300 + ], 1301 + "type": "branch", 1302 + }, 1303 + "2": { 1304 + "line": 17, 1305 + "loc": { 1306 + "end": { 1307 + "column": 4, 1308 + "line": 21, 1309 + }, 1310 + "start": { 1311 + "column": 0, 1312 + "line": 17, 1313 + }, 1314 + }, 1315 + "locations": [ 1316 + { 1317 + "end": { 1318 + "column": 4, 1319 + "line": 21, 1320 + }, 1321 + "start": { 1322 + "column": 0, 1323 + "line": 17, 1324 + }, 1325 + }, 1326 + ], 1327 + "type": "branch", 1328 + }, 1329 + "3": { 1330 + "line": 25, 1331 + "loc": { 1332 + "end": { 1333 + "column": 1, 1334 + "line": 27, 1335 + }, 1336 + "start": { 1337 + "column": 0, 1338 + "line": 25, 1339 + }, 1340 + }, 1341 + "locations": [ 1342 + { 1343 + "end": { 1344 + "column": 1, 1345 + "line": 27, 1346 + }, 1347 + "start": { 1348 + "column": 0, 1349 + "line": 25, 1350 + }, 1351 + }, 1352 + ], 1353 + "type": "branch", 1354 + }, 1355 + }, 1356 + "f": { 1357 + "0": 1, 1358 + "1": 1, 1359 + "2": 1, 1360 + }, 1361 + "fnMap": { 1362 + "0": { 1363 + "decl": { 1364 + "end": { 1365 + "column": 3, 1366 + "line": 14, 1367 + }, 1368 + "start": { 1369 + "column": 2, 1370 + "line": 4, 1371 + }, 1372 + }, 1373 + "line": 4, 1374 + "loc": { 1375 + "end": { 1376 + "column": 3, 1377 + "line": 14, 1378 + }, 1379 + "start": { 1380 + "column": 2, 1381 + "line": 4, 1382 + }, 1383 + }, 1384 + "name": "method", 1385 + }, 1386 + "1": { 1387 + "decl": { 1388 + "end": { 1389 + "column": 4, 1390 + "line": 21, 1391 + }, 1392 + "start": { 1393 + "column": 0, 1394 + "line": 17, 1395 + }, 1396 + }, 1397 + "line": 17, 1398 + "loc": { 1399 + "end": { 1400 + "column": 4, 1401 + "line": 21, 1402 + }, 1403 + "start": { 1404 + "column": 0, 1405 + "line": 17, 1406 + }, 1407 + }, 1408 + "name": "SomeDecorator", 1409 + }, 1410 + "2": { 1411 + "decl": { 1412 + "end": { 1413 + "column": 1, 1414 + "line": 27, 1415 + }, 1416 + "start": { 1417 + "column": 0, 1418 + "line": 25, 1419 + }, 1420 + }, 1421 + "line": 25, 1422 + "loc": { 1423 + "end": { 1424 + "column": 1, 1425 + "line": 27, 1426 + }, 1427 + "start": { 1428 + "column": 0, 1429 + "line": 25, 1430 + }, 1431 + }, 1432 + "name": "noop", 1433 + }, 1434 + }, 1435 + "path": "<process-cwd>/src/decorators.ts", 1436 + "s": { 1437 + "0": 1, 1438 + "1": 1, 1439 + "10": 0, 1440 + "11": 0, 1441 + "12": 0, 1442 + "13": 1, 1443 + "14": 1, 1444 + "15": 1, 1445 + "16": 1, 1446 + "17": 1, 1447 + "18": 1, 1448 + "19": 1, 1449 + "2": 1, 1450 + "20": 1, 1451 + "21": 1, 1452 + "22": 1, 1453 + "23": 1, 1454 + "24": 1, 1455 + "25": 1, 1456 + "26": 1, 1457 + "3": 1, 1458 + "4": 1, 1459 + "5": 1, 1460 + "6": 1, 1461 + "7": 1, 1462 + "8": 1, 1463 + "9": 1, 1464 + }, 1465 + "statementMap": { 1466 + "0": { 1467 + "end": { 1468 + "column": 85, 1469 + "line": 1, 1470 + }, 1471 + "start": { 1472 + "column": 0, 1473 + "line": 1, 1474 + }, 1475 + }, 1476 + "1": { 1477 + "end": { 1478 + "column": 14, 1479 + "line": 2, 1480 + }, 1481 + "start": { 1482 + "column": 0, 1483 + "line": 2, 1484 + }, 1485 + }, 1486 + "10": { 1487 + "end": { 1488 + "column": 23, 1489 + "line": 11, 1490 + }, 1491 + "start": { 1492 + "column": 0, 1493 + "line": 11, 1494 + }, 1495 + }, 1496 + "11": { 1497 + "end": { 1498 + "column": 21, 1499 + "line": 12, 1500 + }, 1501 + "start": { 1502 + "column": 0, 1503 + "line": 12, 1504 + }, 1505 + }, 1506 + "12": { 1507 + "end": { 1508 + "column": 5, 1509 + "line": 13, 1510 + }, 1511 + "start": { 1512 + "column": 0, 1513 + "line": 13, 1514 + }, 1515 + }, 1516 + "13": { 1517 + "end": { 1518 + "column": 3, 1519 + "line": 14, 1520 + }, 1521 + "start": { 1522 + "column": 0, 1523 + "line": 14, 1524 + }, 1525 + }, 1526 + "14": { 1527 + "end": { 1528 + "column": 1, 1529 + "line": 15, 1530 + }, 1531 + "start": { 1532 + "column": 0, 1533 + "line": 15, 1534 + }, 1535 + }, 1536 + "15": { 1537 + "end": { 1538 + "column": 0, 1539 + "line": 16, 1540 + }, 1541 + "start": { 1542 + "column": 0, 1543 + "line": 16, 1544 + }, 1545 + }, 1546 + "16": { 1547 + "end": { 1548 + "column": 23, 1549 + "line": 17, 1550 + }, 1551 + "start": { 1552 + "column": 0, 1553 + "line": 17, 1554 + }, 1555 + }, 1556 + "17": { 1557 + "end": { 1558 + "column": 18, 1559 + "line": 18, 1560 + }, 1561 + "start": { 1562 + "column": 0, 1563 + "line": 18, 1564 + }, 1565 + }, 1566 + "18": { 1567 + "end": { 1568 + "column": 32, 1569 + "line": 19, 1570 + }, 1571 + "start": { 1572 + "column": 0, 1573 + "line": 19, 1574 + }, 1575 + }, 1576 + "19": { 1577 + "end": { 1578 + "column": 26, 1579 + "line": 20, 1580 + }, 1581 + "start": { 1582 + "column": 0, 1583 + "line": 20, 1584 + }, 1585 + }, 1586 + "2": { 1587 + "end": { 1588 + "column": 31, 1589 + "line": 3, 1590 + }, 1591 + "start": { 1592 + "column": 0, 1593 + "line": 3, 1594 + }, 1595 + }, 1596 + "20": { 1597 + "end": { 1598 + "column": 4, 1599 + "line": 21, 1600 + }, 1601 + "start": { 1602 + "column": 0, 1603 + "line": 21, 1604 + }, 1605 + }, 1606 + "21": { 1607 + "end": { 1608 + "column": 0, 1609 + "line": 22, 1610 + }, 1611 + "start": { 1612 + "column": 0, 1613 + "line": 22, 1614 + }, 1615 + }, 1616 + "22": { 1617 + "end": { 1618 + "column": 24, 1619 + "line": 23, 1620 + }, 1621 + "start": { 1622 + "column": 0, 1623 + "line": 23, 1624 + }, 1625 + }, 1626 + "23": { 1627 + "end": { 1628 + "column": 0, 1629 + "line": 24, 1630 + }, 1631 + "start": { 1632 + "column": 0, 1633 + "line": 24, 1634 + }, 1635 + }, 1636 + "24": { 1637 + "end": { 1638 + "column": 36, 1639 + "line": 25, 1640 + }, 1641 + "start": { 1642 + "column": 0, 1643 + "line": 25, 1644 + }, 1645 + }, 1646 + "25": { 1647 + "end": { 1648 + "column": 0, 1649 + "line": 26, 1650 + }, 1651 + "start": { 1652 + "column": 0, 1653 + "line": 26, 1654 + }, 1655 + }, 1656 + "26": { 1657 + "end": { 1658 + "column": 1, 1659 + "line": 27, 1660 + }, 1661 + "start": { 1662 + "column": 0, 1663 + "line": 27, 1664 + }, 1665 + }, 1666 + "3": { 1667 + "end": { 1668 + "column": 47, 1669 + "line": 4, 1670 + }, 1671 + "start": { 1672 + "column": 0, 1673 + "line": 4, 1674 + }, 1675 + }, 1676 + "4": { 1677 + "end": { 1678 + "column": 20, 1679 + "line": 5, 1680 + }, 1681 + "start": { 1682 + "column": 0, 1683 + "line": 5, 1684 + }, 1685 + }, 1686 + "5": { 1687 + "end": { 1688 + "column": 21, 1689 + "line": 6, 1690 + }, 1691 + "start": { 1692 + "column": 0, 1693 + "line": 6, 1694 + }, 1695 + }, 1696 + "6": { 1697 + "end": { 1698 + "column": 21, 1699 + "line": 7, 1700 + }, 1701 + "start": { 1702 + "column": 0, 1703 + "line": 7, 1704 + }, 1705 + }, 1706 + "7": { 1707 + "end": { 1708 + "column": 5, 1709 + "line": 8, 1710 + }, 1711 + "start": { 1712 + "column": 0, 1713 + "line": 8, 1714 + }, 1715 + }, 1716 + "8": { 1717 + "end": { 1718 + "column": 0, 1719 + "line": 9, 1720 + }, 1721 + "start": { 1722 + "column": 0, 1723 + "line": 9, 1724 + }, 1725 + }, 1726 + "9": { 1727 + "end": { 1728 + "column": 36, 1729 + "line": 10, 1730 + }, 1731 + "start": { 1732 + "column": 0, 1733 + "line": 10, 1734 + }, 1735 + }, 1736 + }, 1737 + }, 1234 1738 "<process-cwd>/src/dynamic-file-cjs.ignore.cjs": { 1235 1739 "all": false, 1236 1740 "b": {
+24
test/coverage-test/coverage-report-tests/generic.report.test.ts
··· 185 185 expect(lineCoverage[30]).toBe(2) 186 186 }) 187 187 188 + test('decorators generated metadata is ignored', async () => { 189 + const coverageJson = await readCoverageJson() 190 + const coverageMap = libCoverage.createCoverageMap(coverageJson as any) 191 + const fileCoverage = coverageMap.fileCoverageFor('<process-cwd>/src/decorators.ts') 192 + const lineCoverage = fileCoverage.getLineCoverage() 193 + const branchCoverage = fileCoverage.getBranchCoverageByLine() 194 + 195 + // Decorator should not be uncovered - on V8 this is marked as covered, on Istanbul it's excluded from report 196 + if (process.env.COVERAGE_PROVIDER === 'v8') { 197 + expect(lineCoverage['4']).toBe(1) 198 + expect(branchCoverage['4'].coverage).toBe(100) 199 + } 200 + else { 201 + expect(lineCoverage['4']).toBeUndefined() 202 + expect(branchCoverage['4']).toBeUndefined() 203 + } 204 + 205 + // Covered branch should be marked correctly 206 + expect(lineCoverage['7']).toBe(1) 207 + 208 + // Uncovered branch should be marked correctly 209 + expect(lineCoverage['12']).toBe(0) 210 + }) 211 + 188 212 test('temporary files are removed after test', async () => { 189 213 const coveragePath = resolve('./coverage') 190 214 const files = fs.readdirSync(coveragePath)
+1
test/coverage-test/package.json
··· 24 24 "istanbul-lib-coverage": "^3.2.0", 25 25 "istanbul-lib-report": "^3.0.1", 26 26 "magicast": "^0.3.3", 27 + "unplugin-swc": "^1.4.4", 27 28 "vite": "latest", 28 29 "vitest": "workspace:*", 29 30 "vue": "latest",
+27
test/coverage-test/src/decorators.ts
··· 1 + // eslint-disable-next-line ts/ban-ts-comment -- so that typecheck doesn't include it 2 + // @ts-nocheck 3 + export class DecoratorsTester { 4 + method(@SomeDecorator parameter: Something) { 5 + if (parameter) { 6 + // Covered line 7 + noop(parameter) 8 + } 9 + 10 + if (parameter === 'uncovered') { 11 + // Uncovered line 12 + noop(parameter) 13 + } 14 + } 15 + } 16 + 17 + function SomeDecorator( 18 + _target: Object, 19 + _propertyKey: string | symbol, 20 + _parameterIndex: number, 21 + ) {} 22 + 23 + type Something = unknown 24 + 25 + function noop(..._args: unknown[]) { 26 + 27 + }
+5
test/coverage-test/test/coverage.test.ts
··· 7 7 import { useImportEnv } from '../src/importEnv' 8 8 import { second } from '../src/function-count' 9 9 import MultiSuite from '../src/multi-suite' 10 + import { DecoratorsTester } from '../src/decorators' 10 11 11 12 // @ts-expect-error -- untyped virtual file provided by custom plugin 12 13 import virtualFile2 from '\0vitest-custom-virtual-file-2' ··· 71 72 expect(virtualFile1).toBe('This file should be excluded from coverage report #1') 72 73 expect(virtualFile2).toBe('This file should be excluded from coverage report #2') 73 74 }) 75 + 76 + test('decorators', () => { 77 + new DecoratorsTester().method('cover line') 78 + })
+2 -2
test/coverage-test/testing.mjs
··· 8 8 const isCI = process.env.GITHUB_ACTIONS 9 9 process.env.COVERAGE_PROVIDER = provider 10 10 11 - // TODO: Fix flakiness and enable on CI -- browser picks test files that don't exist and fails, some tests fail because of the multi environment mismatch 12 - if (isCI) 11 + // TODO: Fix flakiness and enable on CI -- browser picks test files that don't exist and fails, issue #5165 12 + if (isCI && isBrowser) 13 13 process.exit(0) 14 14 15 15 const poolConfigs = [
+6
test/coverage-test/tsconfig.json
··· 1 + { 2 + "extends": "../../tsconfig.base.json", 3 + "compilerOptions": { 4 + "experimentalDecorators": true 5 + } 6 + }
+91 -54
test/coverage-test/vitest.config.ts
··· 1 1 import { resolve } from 'pathe' 2 + import swc from 'unplugin-swc' 2 3 import { defineConfig } from 'vitest/config' 3 4 import vue from '@vitejs/plugin-vue' 4 5 import MagicString from 'magic-string' 5 6 import remapping from '@ampproject/remapping' 7 + import type { Plugin } from 'vite' 6 8 7 9 const provider = process.argv[1 + process.argv.indexOf('--provider')] 8 10 9 - export default defineConfig(() => ({ 11 + export default defineConfig(_ => ({ 10 12 plugins: [ 11 13 vue(), 12 - /* 13 - * Transforms `multi-environment.ts` differently based on test environment (JSDOM/Node) 14 - * so that there are multiple different source maps for a single file. 15 - * This causes a case where coverage report is incorrect if sourcemaps are not picked based on transform mode. 16 - */ 17 - { 18 - name: 'vitest-custom-multi-transform', 19 - enforce: 'pre', 20 - transform(code, id, options) { 21 - if (id.includes('src/multi-environment')) { 22 - const ssr = options?.ssr || false 23 - const transforMode = `transformMode is ${ssr ? 'ssr' : 'csr'}` 24 - const padding = '\n*****'.repeat(ssr ? 0 : 15) 25 - 26 - const transformed = new MagicString(code) 27 - transformed.replace('\'default-padding\'', `\`${transforMode} ${padding}\``) 28 - 29 - const map = remapping( 30 - [transformed.generateMap({ hires: true }), this.getCombinedSourcemap() as any], 31 - () => null, 32 - ) as any 33 - 34 - return { code: transformed.toString(), map } 35 - } 36 - }, 37 - }, 38 - { 39 - // Simulates Vite's virtual files: https://vitejs.dev/guide/api-plugin.html#virtual-modules-convention 40 - name: 'vitest-custom-virtual-files', 41 - resolveId(id) { 42 - if (id === 'virtual:vitest-custom-virtual-file-1') 43 - return 'src/virtual:vitest-custom-virtual-file-1.ts' 44 - 45 - if (id === '\0vitest-custom-virtual-file-2') 46 - return 'src/\0vitest-custom-virtual-file-2.ts' 47 - }, 48 - load(id) { 49 - if (id === 'src/virtual:vitest-custom-virtual-file-1.ts') { 50 - return ` 51 - const virtualFile = "This file should be excluded from coverage report #1" 52 - export default virtualFile; 53 - ` 54 - } 55 - 56 - // Vitest browser resolves this as "\x00", Node as "__x00__" 57 - if (id === 'src/__x00__vitest-custom-virtual-file-2.ts' || id === 'src/\x00vitest-custom-virtual-file-2.ts') { 58 - return ` 59 - const virtualFile = "This file should be excluded from coverage report #2" 60 - export default virtualFile; 61 - ` 62 - } 63 - }, 64 - }, 14 + MultiTransformPlugin(), 15 + VirtualFilesPlugin(), 16 + DecoratorsPlugin(), 65 17 ], 66 18 define: { 67 19 MY_CONSTANT: '"my constant"', ··· 105 57 ], 106 58 }, 107 59 })) 60 + 61 + /* 62 + * Transforms `multi-environment.ts` differently based on test environment (JSDOM/Node) 63 + * so that there are multiple different source maps for a single file. 64 + * This causes a case where coverage report is incorrect if sourcemaps are not picked based on transform mode. 65 + */ 66 + function MultiTransformPlugin(): Plugin { 67 + return { 68 + name: 'vitest-custom-multi-transform', 69 + enforce: 'pre', 70 + transform(code, id, options) { 71 + if (id.includes('src/multi-environment')) { 72 + const ssr = options?.ssr || false 73 + const transforMode = `transformMode is ${ssr ? 'ssr' : 'csr'}` 74 + const padding = '\n*****'.repeat(ssr ? 0 : 15) 75 + 76 + const transformed = new MagicString(code) 77 + transformed.replace('\'default-padding\'', `\`${transforMode} ${padding}\``) 78 + 79 + const map = remapping( 80 + [transformed.generateMap({ hires: true }), this.getCombinedSourcemap() as any], 81 + () => null, 82 + ) as any 83 + 84 + return { code: transformed.toString(), map } 85 + } 86 + }, 87 + } 88 + } 89 + 90 + // Simulates Vite's virtual files: https://vitejs.dev/guide/api-plugin.html#virtual-modules-convention 91 + function VirtualFilesPlugin(): Plugin { 92 + return { 93 + name: 'vitest-custom-virtual-files', 94 + resolveId(id) { 95 + if (id === 'virtual:vitest-custom-virtual-file-1') 96 + return 'src/virtual:vitest-custom-virtual-file-1.ts' 97 + 98 + if (id === '\0vitest-custom-virtual-file-2') 99 + return 'src/\0vitest-custom-virtual-file-2.ts' 100 + }, 101 + load(id) { 102 + if (id === 'src/virtual:vitest-custom-virtual-file-1.ts') { 103 + return ` 104 + const virtualFile = "This file should be excluded from coverage report #1" 105 + export default virtualFile; 106 + ` 107 + } 108 + 109 + // Vitest browser resolves this as "\x00", Node as "__x00__" 110 + if (id === 'src/__x00__vitest-custom-virtual-file-2.ts' || id === 'src/\x00vitest-custom-virtual-file-2.ts') { 111 + return ` 112 + const virtualFile = "This file should be excluded from coverage report #2" 113 + export default virtualFile; 114 + ` 115 + } 116 + }, 117 + } 118 + } 119 + 120 + function DecoratorsPlugin(): Plugin { 121 + const plugin = swc.vite({ 122 + jsc: { 123 + target: 'esnext', 124 + parser: { 125 + syntax: 'typescript', 126 + decorators: true, 127 + }, 128 + transform: { 129 + legacyDecorator: true, 130 + decoratorMetadata: true, 131 + }, 132 + }, 133 + }) 134 + 135 + return { 136 + name: 'custom-swc-decorator', 137 + enforce: 'pre', 138 + transform(code, id, options) { 139 + if (id.endsWith('decorators.ts')) 140 + // @ts-expect-error -- Ignore complex type 141 + return plugin.transform(code, id, options) 142 + }, 143 + } 144 + }