-
-
Notifications
You must be signed in to change notification settings - Fork 4.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Help coverage instrumenters exclude compiler's helper functions #7824
Comments
Here is one example in details. Complete setup for inspecting the source maps of transpiled and instrumented code can be found at https://github.com/AriPerkkio/svelte-istanbul-reproduction, especially the debug-svelte-sourcemaps.mjs part should reveal the process of code coverage. Considering the line 13 of the following each block: 12 | {#each users as user}
13 | <li>{user}</li>
14 | {/each} When the Svelte code is transpiled to Javascript there will be following position in source map:
26 | let t_value = /*user*/ ctx[1] + "";
Mapping #1 | ^^^
39 | if (dirty & /*users*/ 1 && t_value !== (t_value = /*user*/ ctx[1] + "")) set_data(t, t_value);
Mapping #2 | ^^^ 13 | <li>{user}</li>
Mapping #1 | ^^^^
Mapping #2 | ^^^^ When the transpiled Javascript is instrumented, Istanbul will add the counters as below:
1878 | let t_value = ( /*user*/cov_208gup579f().s[3]++, ctx[1] + "");
Mapping #3 | ^^^
1899 | if ((cov_208gup579f().b[1][0]++, dirty & /*users*/1) && (cov_208gup579f().b[1][1]++, t_value !== (t_value = /*user*/ctx[1] + ""))) {
Mapping #4 | ^^^
1900 | cov_208gup579f().b[0][0]++;
Mapping #5 | ^ These map to the sources as below: 13 | <li>{user}</li>
Mapping #3 | ^^^^
Mapping #4 | ^^^^
Mapping #5 | ^ And now finally in the coverage report: 13 | <li>{user}</li>
statementMap["0"] | ^^^^^^^^^^
statementMap["1"] | ^
statementMap["2"] | ^^^^^^
branchMap["0"].locations[0] | ^^^^^^^^^^
branchMap["1"].locations[0] | ^^^^
branchMap["1"].locations[1] | ^^^^^^^^^^ ❗ Both entries in So the tricky part in transpiled code is this one: 39 | if (dirty & /*users*/ 1 && t_value !== (t_value = /*user*/ ctx[1] + "")) set_data(t, t_value); The "Mapping pair + 38 | /* istanbul ignore if */
39 | if (dirty & /*users*/ 1 && t_value !== (t_value = /*user*/ ctx[1] + "")) set_data(t, t_value); There are likely other similar cases that should be covered as well. |
Is there any movement on or at least acknowledgement of this issue from anyone in the svelte team? It makes coverage reporting for tests on svelte components all but meaningless currently, I'm surprised it's not a bigger pain point for more users. |
is there any update for this? |
I'm having the same problem here guys. Is there any update for this? |
What’s stopping those PRs being merged? If putting coverage-tool specific ignore comments in the compiled output for the two biggest tools (Istanbul and C8) is the only way to reasonably achieve this at the moment, then I think pragmatism has to win over ideals for now |
Should we expect for Svelte5 to have the same issues? What's the current expectation for this, given that a previous PR had been closed in favor of waiting for another major release and checking if that maybe fixes the issue. |
Svelte 5 has a completely different approach, which involves much less generated code with fewer |
I've updated the reproduction to use Svelte 5: https://github.com/AriPerkkio/svelte-istanbul-reproduction/blob/main/debug-svelte-sourcemaps.mjs It's definitely different. Maybe better but not perfect, e.g. line 17 is now excluded from source maps. In the picture it says Svelte 3 but it's actually 4.
On Vitest's side we'll be able to close issues like vitest-dev/vitest#1893 now. |
I think the issue is still happening in The code used is the one generated by the Testimport { render, screen } from "@testing-library/svelte";
import { describe, expect, test } from "vitest";
import userEvent from "@testing-library/user-event";
import Counter from "/src/dashboard/dashboard1/lib/Counter.svelte";
describe("Counter suite", () => {
test("should render", () => {
render(Counter);
const button = screen.getByRole("button");
expect(button).toBeInTheDocument();
expect(button).toHaveTextContent("clicks: 0");
});
test("should increment", async () => {
const user = userEvent.setup();
render(Counter);
const button = screen.getByRole("button");
await user.click(button);
expect(button).toHaveTextContent("clicks: 1");
});
}); |
Hi guys, is this issue still happening on svelte 5? any chance that this will be fixed on svelte 4? i'm happy to provide some help if needed |
This issue is still happening on Svelte 5.16.0 (check my previous comment), I have a template that uses istanbul https://codeberg.org/RiQuY/nodecg-vite-svelte-js-template/src/branch/feat/RiQuY-vite-6-upgrade showing this, although this can be tested with any code, even with the one generated by Can this be reopened please, or my example is suffering an unrelated issue? @Rich-Harris |
Describe the problem
When transpiled Svelte code is instrumented with
istanbul
, there are a lot of unrelated statements and branches in the coverage report. The source maps received fromsvelte/compiler
include mappings which I think are intended for debugging breakpoints. However when we instrument the transpiled svelte code withistanbul
, these unnecessary if-blocks and other statements end up getting instrumented. See vitest-dev/vitest#1893.For inspecting sourcemaps of transpiled and instrumented svelte file, see https://gist.github.com/AriPerkkio/8399007031cb747b2811c07358b8daa2.
Here is one example where the file is completely covered by a test. However statements and branches are not 100%. We can see uncovered code highlighted in results.
The reason why there is an if-block in middle of
<li>{user}</li>
is due to having an actual if-statement in transpiled code.Those other red-highlighted blocks are marked as uncovered, as source map points to a helper function which is not executed.
Describe the proposed solution
If those source mappings are unnecessary, those could be just removed from the mappings. But as I think those are indeed used for debugging, those cannot be simply removed.
But svelte compiler could be placing hints from instrumenters. I'm 99% sure I've seen some code transformation tools placing
/* istanbul ignore, c8 ignore */
comments around their internal helper functions. Could svelte do the same?Svelte is already adding some extra comments, e.g. variable names, in the transpiled code. Adding some more comments should not be an issue.
I have zero knowledge about svelte's internals so I'm not sure whether these cases can easily be identified.
Alternatives considered
I don't think any coverage tool is currently working perfectly for svelte.
Importance
nice to have
The text was updated successfully, but these errors were encountered: