Skip to content
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

Feature Request: Sourcemap support #491

Open
nicosommi opened this issue Jan 2, 2014 · 49 comments · Fixed by #1862
Open

Feature Request: Sourcemap support #491

nicosommi opened this issue Jan 2, 2014 · 49 comments · Fixed by #1862

Comments

@nicosommi
Copy link

It would be nice if the original line number of the error is displayed when developing in coffeescript.

For example for this error:
TypeError: entityCollection.get(...) is undefined in http://somehost:[someport]/somepath/SomeSpec.js (line 37)

It can be something like this (reading the sourcemap):
TypeError: entityCollection.get(...) is undefined in http://somehost:[someport]/somepath/Spec.coffee (line 15) (and line 37 on /somepath/SomeSpec.js)

I think this can be done reading the //@sourceMappingURL or the //#sourceMappingURL attribute of the compiled js and later the sourcemap itself (using the value of that attribute), then there is the sourcemap interpretation using https://github.com/mozilla/source-map

@infews
Copy link
Contributor

infews commented Jan 6, 2014

This code would belong in the reporters. The Jasmine team doesn't work in Coffee Script so we're not familiar with the pain points.

We'd be happy to look at a pull request that test-drove out this support for the HtmlReporter - and it should (naturally) support the spec and source files. Is this something you'd like to tackle?

@nicosommi
Copy link
Author

Yes just give me some time and I'll try to create a PR. Looking at the code I think that I need to modify the core/ExceptionFormatter.js around line 19. Im going to create a new js file and add the mozilla source-map dependency.

@Yona-Appletree
Copy link

I have the same issue, but from TypeScript. It's a bit of a pain to reverse-engineer the actual line numbers, esp. since IntelliJ does not make it all that easy to load the generated JS files. @nicosommi I'm curious what the status of PR is, as I might be interested in continuing work on it if you don't have the time.

@nicosommi
Copy link
Author

@Yona-Appletree yes, I've a simple (I mean really simple) example of an HTML loading a script, detecting the SourceMap, loading it and translating some line from the browser. There is still hard work to do: make it nicer and put it into the logic of jasmine. If you are interested I made a tar that you can download here http://ge.tt/6kj7GWP1/v/0?c It just proves that it can be done

@novocaine
Copy link

I feel this is probably out of scope of jasmine itself because it involves fetching and parsing sourcemaps.

I have pushed a module which does that part to https://github.com/novocaine/sourcemapped-stacktrace. I would like to integrate that with a Jasmine reporter, but I need an asynchronous hook for the reporter to do its work (as would any solution to the problem).

I have created a pull request for the hook in 6b7302f

Would also appreciate thoughts on whether a reporter that integrated sourcemapped-stacktrace is useful enough to go into jasmine source (and would only work if the developer had loaded sourcemapped-stacktrace) or whether that reporter in itself should be another module.

@infews
Copy link
Contributor

infews commented Jul 22, 2014

@novocaine you're bringing up an interesting idea.

Maybe instead of a reporter concern (and your pull request #630), it's an ExceptionFormatter concern? That forces the question of how to expose this functionality so that projects could provide a map, or turn on something.

@novocaine
Copy link

@infews, thanks for taking a look at this.

Would you accept a patch to make the ExceptionFormatter something customizable through env, similar to how you can customise the reporter? Or is this possible already?

I am imagining there could be a formatter you opt into if you want to use sourcemapped stacktraces. I don't feel strongly about whether such a formatter lives within jasmine or not, just that there should be a way to do this without hacking jasmine.

Also thinking that maybe sourcemapped-stacktrace could provide a sync interface to solve the problems with integrating async into the chain.

@infews
Copy link
Contributor

infews commented Aug 27, 2014

Ugh.

At the moment, the ExceptionFormatter is used in a factory that's defined in Env.js (see). We allow options to be passed into jasmine.getEnv() which is mostly used for testing.

So to make this happen, you'd have to be able to define the constructor of the formatter before the Env is created and pass it in during the boot.js process. You can't do that today without writing your own boot.js. Not awesome, but possible.

Do you want to play around with a PR for Env.js that allows the exception formatter to be passed in? I think we could take that and allow your formatter to work with a custom boot.js. And we could start a doc for all the improvements that need to happen at boot time for a Jasmine 3...

@infews infews added the waiting label Aug 27, 2014
@Zequez
Copy link

Zequez commented Dec 2, 2014

I think in-line sourcemaps would be more appropiate for this situation, as you wouldn't have to worry about fetching a different file for the sourcemap.

@alexeagle
Copy link

+1 this would be useful for running unit tests written in Typescript

@caseyhoward
Copy link

👍 I compile all my tests beforehand using typescript. Source map support would be really nice. I hate digging through the generated file.

guitarpoet added a commit to guitarpoet/lilium that referenced this issue Jun 27, 2015
@geddski
Copy link

geddski commented Aug 1, 2015

+1 as someone using webpack, I have no idea where the actual errors are without source map support.

@geddski
Copy link

geddski commented Aug 1, 2015

For anyone else needing this, I've found that adding ?catch=false to the URL at least lets the errors make it to the console so the browser can use source maps to show you where the errors are.

@cmdelatorre
Copy link

+1 to support tests in coffeescript
In the meanwhile, @novocaine , do you have some tips on how to integrate your module in my project without patching Jasmine?

@novocaine
Copy link

sorry, you definitely have to patch Jasmine..

@ghost
Copy link

ghost commented Nov 2, 2015

@geddski I tried out, but it does not work, because the error was rethrown by jasmine, so it points to the code of jasmine instead of my source code. (Btw. did anybody manage to use sourcemaps in firefox and chrome. I got proper support only in opera and msie.)

If somebody needs this feature, it works with karma + browserify + jasmine (tested with phantomjs). Here is a project template: https://github.com/inf3rno/javascript-project-template

@guncha
Copy link

guncha commented Dec 10, 2015

If anyone else is looking for a quick hack to get the source mapped stack traces working with Jasmine's HTML reporter while this is being figured out, here's a gist for you: https://gist.github.com/guncha/f45ceef6d483c384290a

@DanielSchuech
Copy link

thx @guncha

I am using it with karma jasmine html reporter and its working well! I haven't found another solution so I just can recommand that atm.

@guncha
Copy link

guncha commented Jan 21, 2016

I actually ended up using https://github.com/evanw/node-source-map-support which overwrites the native Error#stack to fetch the source maps and rewrite the stacktrace. It works with Jasmine as well as errors in the console. The only issue with testing is that is uses AJAX, so if you use jasmine-ajax, it will break in strange ways.

@ArnaudRinquin
Copy link

@guncha Thanks for the gist, I hacked it a little to make it work but that'll do for now. Do you know if there is a way to restore the stack traces before they get sent to karma/testem/initial loader?

EDIT: nevermind, I figured a way to have them using node-source-map-support. It only works for Chrome but I guess that's good enough and much better than the previous solution.

@geddski
Copy link

geddski commented Feb 4, 2016

This issue still makes using jasmine such a major pain when using something like webpack. Not knowing what line errors are coming from makes things impossible.

@andyl
Copy link

andyl commented Feb 4, 2016

Is there a different JavaScript test runner that handles sourcemaps??

@slackersoft
Copy link
Member

As @infews mentioned, we'd be happy to review a pull request that either:

  • Allows injection of an ExceptionFormatter, allowing a custom one that can deal with sourcemaps
  • Allows injection of some sort of filtering/rewriting function that the existing ExceptionReporter can use to accomplish this

This would also allow for a better solution to #801 and filtering lines out of the stacktrace of an error.

@leonadler
Copy link

@johngrogg for node, take a look at source-map-support

@rdy
Copy link

rdy commented Nov 22, 2017

@johngrogg I was able to get inline-source-maps working correctly with jasmine but I used a babel plugin to inject the source-maps for my tests.
https://www.npmjs.com/package/babel-plugin-stack-trace-sourcemap

It works the same way as described by @leonadler under the hood. I have mine working with devTool: 'cheap-module-source-map' in webpack. Seems to be the best solution though it the source map support only works in chrome and node.

@cancerberoSgx
Copy link

found this one for typescript, seems to obe working just fine and easy to install: https://github.com/SeanSobey/JasmineTSConsoleReporter

@klemenoslaj
Copy link

I think that the easiest solution is the following:

  • install source-map-support with npm or yarn.
  • add/modify test script in package.json
"test": "NODE_OPTIONS='-r source-map-support/register' jasmine ./src/**/*.spec.js",

@DamienCassou
Copy link
Contributor

DamienCassou commented Oct 19, 2018

@klemenoslaj said:

I think that the easiest solution is the following:
* install source-map-support with npm or yarn.

that doesn't work for me. I guess it's because Jasmine already does something with source-maps (#1598).

@slackersoft
Copy link
Member

Jasmine itself definitely doesn't know anything about sourcemaps. If there is another library included that is patching the Error prototype to provide a sourcemapped stacktrace, then Jasmine will end up using that.

@cancerberoSgx
Copy link

Just in case, for those using typescript, in node.js, what I do is execute typescript directly with (npm install) ts-node, basically just change all *.js with *.ts in your spec/support/jasine.json file and then run npx ts-node node_modules/jasmine/bin/jasmine.js . For actually debugging (like putting a breakpoint) it in node.js you will need to compile TS with sourcemap: true in tsconfig.json and that works fine though

@sgravrock
Copy link
Member

I'd like to get a sense of whether there is still a need for Jasmine to do anything with source maps in 2019, and if so how widespread it is. Jasmine has produced correct stack traces for TypeScript and Flow for at least a couple of years now, thanks to the sourcemap support that's built into those languages' toolchains. I suspect that the same is true for other languages that compile to JS.

If anyone still has this problem today despite using the latest version of their language's build system and (if necessary) turning on source maps in their language's configuration, I'd love to hear specifics.

@MarcusRiemer
Copy link

I am not sure whether this exactly fits this issue, but I am always frustrated by only partially helpful stacktraces of stacks in the debug.html-runner. I have an Angular (Typescript) application and get stacktrace entries like this:

<Jasmine>
./src/app/shared/multilingual-input.spec.ts/</</<@http://0.0.0.0:9876/_karma_webpack_/main.js:5309:61

The mentioned file is correct, but sadly there is no class name, method name or line number. I am not 100% certain that this would be solved via sourcemaps, but if this would be the case I would be more then glad for a fix.

@DamienCassou
Copy link
Contributor

@sgravrock Please read #1598 (comment) which contains an up-to-date way to reproduce a problem with stacktraces in Jasmine.

@sgravrock sgravrock removed the waiting label Aug 20, 2019
@sgravrock
Copy link
Member

Thanks. This helps. I played with the repro from @DamienCassou a bit and tried a few different source map configurations with a few different browsers. None of them resulted in Error objects with a correct stack property, which is what Jasmine uses to figure out where expectation failures come from. So it looks like while Node might be pretty well supported today, browsers aren't.

So I think there's a good case to be made for Jasmine to apply source maps to stack traces, especially since they're already processed to filter out Jasmine's own frames. But the prospect of changing all the code paths that touch stack traces to be async doesn't exactly fill my heart with joy. Maybe the source maps could be preloaded prior to the call to Env#execute and then processed synchronously when errors occur.

@sgravrock
Copy link
Member

A while ago, I finally had a chance to spend a solid block of focused time looking into this. I was able to get source mapped stack traces working in modern browsers using source-map without too much effort. See this spike for details (but keep in mind that it's not production-ready or architecturally anything like what I'd want to end up with).

IE is another matter entirely. I wasn't able to find a way to compile source-map to something that runs in IE without introducing polyfills in the process. That's something that we'd really like to avoid, since it can create a situation where tests pass because of the polyfills and the code under test fails when run outside of Jasmine.

It would be great if somebody who's better than I am with Webpack and Babel could come up with a solution. Alternately, I think it would be OK to let users bring their own build of source-map and have Jasmine use it if it's present. That would let uses make an informed choice about introducing polyfills and might open up some possibilities for frameworks like Angular that can make different assumptions about the environment they run in.

I can't rule out the possibility that I might give this another try in the future, but it's not anywhere near the top of my personal to-do list. If someone wants to step up and make a major contribution, this would be a great place to do it. I'd be happy to offer context & advice, review PRs, or provide other support.

@elliot-nelson
Copy link
Contributor

elliot-nelson commented Oct 1, 2020

After playing around with jasmine and nyc options, I was surprised to see how hard it was to get this working with a very basic setup, no webpack, babel, typescript or browsers involved.

My setup is: install jasmine and nyc in a local node project, have a failing test case. I'd like the line:column output to read 67:8 but instead it reads 10:35803. Does anyone know if there's a node module I can plug in that would fix this scenario?


Update: of course minutes after I ask I manage to get it working! 🤕

In case anyone else runs into this issue: to work properly, you must both tell nyc that it should produce source maps, and you need jasmine to be able to consume those source maps.

For the first, it's as simple as adding the command-line option produce-source-map, which will add an inline source map to the bottom of each instrumented file:

nyc --produce-source-map jasmine

For the second, you need to support inline source maps through source-map-support. Install the source-map-support npm module and then add the following line to the top of your spec/helpers/helpers.js:

require('source-map-support').install({ hookRequire: true });

That's it!

@JannesMeyer
Copy link
Contributor

JannesMeyer commented Nov 2, 2020

Node.js actually has (experimental) source map support since v12. It can be enabled with the --enable-source-maps flag. No additional dependencies required.

Unfortunately, it looks like Jasmine is swallowing the extra information in the stack trace that Node.js provides because it ignores stack frames where the file property is undefined. Presumably this happens in an attempt to filter out stack frames that are about Jasmine internals.

After testing with some compiled TypeScript, I get an additional stack frame that contains an arrow and the original file name in the raw field:

{
  raw: '        -> C:\\testing\\test.ts:15:40'
}

However, this doesn't have a file property so it is filtered out. The original JavaScript frame right above it has a bit more information (file property is populated):

{
  raw: '    at UserContext.test (file:///C:/testing/test.js:12:43)',
  file: 'file:///C:/testing/test.js',
  line: 12,
  func: 'UserContext.test'
}

I think I found the code that accidentally filters the source-mapped frames:

if (frame.file && frame.file !== jasmineFile) {

@JannesMeyer
Copy link
Contributor

JannesMeyer commented Nov 2, 2020

I forgot to mention how to run your tests with the flag enabled. You should be able to do it by setting the environment variable NODE_OPTIONS=--enable-source-maps and then running npm test.

By the way, Mocha seems to have some custom support for passing this flag to node: https://mochajs.org/#-enable-source-maps. And it can be activated via the .mocharc.js file, too.

@elliot-nelson
Copy link
Contributor

elliot-nelson commented Nov 2, 2020

Having it built-in would be very cool. The example you provided almost makes me think this is a bug in node and not Jasmine, though... the frame is clearly in a file, and it knows which file it is, so why wouldn't the file property be set?

(I'm not sure which frames are being filtered out by the undefined check, but in browsers I'd be worried that removing that check could surface a lot of useless per-browser core functions that Jasmine is intentionally hiding.)

@JannesMeyer JannesMeyer mentioned this issue Nov 2, 2020
9 tasks
@JannesMeyer
Copy link
Contributor

JannesMeyer commented Nov 2, 2020

I have just submitted a pull request that would show a lot of extra information on the stack trace (including source map support). You can see the before and after in my description in #1862.

@elliot-nelson I don't think I would call it a bug in Node or V8, because there is no standardised way of doing stack traces. Many JavaScript engines don't even come close to the amount of detail that V8 provides. I think other engines merely provide a big string object.

Keep in mind that Jasmine can be run in the browser, which means it has to deal with other JS engines, too. I think Jasmine should just expose the same amount of detail that the JS engine provides.

The Node.js documentation doesn't make any guarantees about what information is provided in a stack trace. It just defers to V8:

Stack traces are dependent on V8's stack trace API

Good luck convincing Google that the stack trace API should be even more detailed than it already is, just so that we can remove detail from the stack trace...

@sgravrock
Copy link
Member

Reopening. I'd never intended to close this. The above-linked PR helps with source maps on Node but doesn't change anything in browsers.

@sgravrock sgravrock reopened this Nov 28, 2020
sshyran pushed a commit to sshyran/Chromite-fresh-Dec-2022-source-import that referenced this issue Dec 28, 2022
Using source-map-support, we can make stacktrace from Jasmine unit tests
print Typescript filepaths.
I found this in jasmine/jasmine#491 (comment) .

BUG=b:230048048
TEST=manually let a test fail and checked the stacktrace

Change-Id: Icf6cbba3049576df8b04e96ab79aaa09502cdbea
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/chromite/+/3934909
Tested-by: Keigo Oka <oka@chromium.org>
Reviewed-by: Tomasz Tylenda <ttylenda@chromium.org>
Commit-Queue: Keigo Oka <oka@chromium.org>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.