Debug angular app from outside (browser console only) - javascript

I have this angular website which for some reason cannot be debugged when everything is concat together (not minified). Fo example, if I try to set a breakpoint, the breakpoint is placed somewhere else (at the bottom of an other file) :(
So, to overcome this I would like to set a breakpoint using the browser console (if possible of course).
In my current situation I need to set a breakpoint inside a service method. So I figured, I need the reference holding that service. But where does angular keep those. For example, I tried this
$> var myApp = angular.module('myApp');
$> debug(myApp.injector('someSevice').someMethod);
If this would work, I would expect the debugger to kick in when someMethod is called.
Here is an other failed attempt:
$> myApp.run((someService) => { debug(someService.someMethod)});
Any help on how to do this would be appreciated?
UPDATE: Find a way to access a service
$> angular.injector(['myApp']).get('someService').someMethod
However, in my case, this function is called initially only

If you're trying to debug a live production app, there might be a chance where the debug info is disabled for the website which is actually done to increase performance of the website. So use angular.reloadWithDebugInfo(); in console and then try to debug.

Related

Breakpoints in WebStorm not hitting for JavaScript debugging

I have the following configuration setup in WebStorm:
When I click debug, it launches Chrome fine and navigates to the page, but my breakpoints never get hit. It's connected somehow though because I see all of the console.log() output in WebStorm.
I'm trying to navigate to the URL specified in the screenshot and have breakpoints in main.js get hit, but it doesn't work as expected (see: at all). I'm not exactly sure what I'm missing. I've tried setting a remote URL for the specific main.js file in the Remote URLs section, but that didn't help either.
For reference I run the application via bra run and npm run watch.
Quick Update
So I've been able to actually get a breakpoint to hit, but it's in a different file (in a different path):
../public/app/core/routes/dashboard_loaders.ts allows me to stop at breakpoints, but ../public/dashboards doesn't.
When I navigate to http://localhost:3000/dashboard/script/main.js?orgId=1, it hits the route:
.when('/dashboard/:type/:slug', {
templateUrl: 'public/app/partials/dashboard.html',
controller : 'LoadDashboardCtrl',
reloadOnSearch: false,
pageClass: 'page-dashboard',
})
Which ultimately does load the file ../public/dashboards/multi.js -- but no breakpoints are hit.
Further Updates
It looks like the script is served via the following command (in ../public/app/features/dashboard/dashboardLoaderSrv.js):
/*jshint -W054 */
var script_func = new Function('ARGS','kbn','dateMath','_','moment','window','document','$','jQuery', 'services', result.data);
var script_result = script_func($routeParams, kbn, dateMath, _ , moment, window, document, $, $, services);
Where $routeParams are type:script and slug:main.js - If I step into this function, I get an anonymous(?) file that's identical to my actual main.js file, but the name is like 43550 instead of main.js -- I think this is boiling down to a fundamental lack of knowledge in how JavaScript handles something on my part. :)
Edit: I found this issue for using webstorm with grafana (second edit) looks like this is you.
I think what he linked solves it with declaring a sourceUrl then your file isn't "anonymous" or rather dynamic.
//# sourceURL=filename.js
I.E
//# sourceURL=main.js
Reference How to debug dynamically loaded JavaScript (with jQuery) in the browser's debugger itself?
Here is the documentation and video on debugging in webstorm to make sure everything is setup properly. (I.E My default setting were to debug my index file instead of my project). Make sure you have their Chrome extension or Firefox Extension
General JS Debugging in Webstorm
Debugging for Chrome in Webstorm
Debugging for Firefox in Webstorm
Debugging Node.JS in Webstorm

How to get javascript variables in a debugger when using webpack

I am developing a react application with the bundler Webpack.
I would like to debug this application with a browser console (here i use chrome).
I have used source-maps and equivalent in my webpack config:
devtool = 'inline-source-map';
Now errors are displayed with the exact line of the original file.
The problem is that i want to access to live variables with the console.
So far I found two ways to display them:
1- Add a library in webpack.config.js
output: {
library: "lib"
},
export variable in the code export var foo = 34; and finally inside the browser console use lib.foo.
2- use breakpoint and access to variable set in the file
Is there another solution to access live variables?
Thanks
There are other solutions, but that means defining global variables and that should be avoided as it can have side effects in the code you're trying to debug, so you might run into problems that are not identical with and without exposing the variables, which makes your debugging experience very frustrating.
Using breakpoints is the best you can do for debugging purposes. The browser debuggers, especially the Chrome devtools, are extremely powerful and it's absolutely worth spending some time to get familiar with them.
Because pausing the app at every breakpoint you set for getting to a certain point can be tedious, you can use conditional breakpoints. One way is to use the debugger statement in your code, in that case you can guard it by any JavaScript you like, for instance this will only pause when the input to the function is 5:
function debug(input) {
if (input === 5) {
debugger;
}
// Other code
}
Another way is to add conditional breakpoints in the Chrome devtools. As you've configure source maps, you can set the breakpoints in the original source under Sources > top > webpack:// > .
To set a conditional breakpoint you simply right-click a line and choose Add conditional breakpoint... and enter the condition, e.g. input === 5. You can also Edit breakpoint... to change or add a condition to an existing breakpoint. For more information about breakpoints in Chrome see Pause Your Code With Breakpoints.
In the Sources tab you can also right click anywhere and Add folder to workspace so you can edit the sources directly and save the changes to disk (in older versions of Chrome it's a bit more complicated to add a folder to the workspace). To let Chrome know that the source maps of webpack correspond to your workspace, you can right-click any webpack source map and select Map to File System Resource... and you simply choose the correct file of the workspace. After that, all the sources of webpack should automatically be mapped to the correct files. Now you can set the breakpoints there and when you change something and save it (Ctrl + S or Cmd + S), webpack will recompile it. See also Set Up Persistence with DevTools Workspaces.
Sometimes setting a breakpoint might be too much effort for only getting values of variables. With just console.log you probably end up with a lot of different messages. To make it easier to find the messages you need, you can use console.group which lets you put messages inside a group, that can be expanded and collapsed. The groups can also be nested. Use console.groupCollapsed if you want the group to be collapsed initially.

Debug remote mocha.js test with node-inspector?

I have a test file on a remote machine and I want to walk through it with node-inspector. So, on the remote machine (Vagrantfile):
node-inspector &
mocha --debug-brk foo.test.js
Then, on my dev machine I open Canary and go to:
http://127.0.0.1:8080/debug?ws=127.0.0.1:8080&port=5858
However, I'm not able to debug my test, since the debugger will break at the first line in node_modules/mocha/bin/_mocha, and my test file isn't visible in the Sources tab:
I tried setting a breakpoint inside _mocha, on line 398:
runner = mocha.run(program.exit ? exit : exitLater);
But when I try to 'step into', to see the run function execute, it doesn't step in. I can see output in the console, so it does execute though. If I set a breakpoint directly in the run function, it won't break there.
Also, the test file never appears in the "Sources" tab so I can't set breakpoints in it. I also tried adding a debugger statement to it but it still doesn't break there.
How can I make node-inspector show the test file, and step through it ?
node v0.12.0
node-inspector v0.10.0
mocha v2.2.4
I frequently run into this, and I don't know if there's a better solution (if there is I'll be glad to hear it), but I find I have to let the debugger advance to a point where it becomes aware of the additional files I want to debug. Without seeing more of your code I can't give a more specific suggestion about where to advance to, but try to figure out where the test files will be loaded in the source files that are available and advance to there. It'll gradually add more files to the Sources panel as code runs.
There are actually 2 problems:
breakpoints not respected
test files not visible
The first problem was fixed in the recently released node-inspector#v0.10.1. So, breakpoints will be respected anywhere.
There is still the second issue. As #JMM said, the list of files in the 'Sources' tab is dynamic, and test files won't appear there when the process breaks. What I ended up doing is setting a breakpoint just before the test function is run, in mocha/lib/runnable.js#266, on this line:
var result = fn.call(ctx);
fn is the test function. Once you step into it, the test file will appear in the Sources tab and the debugger's cursor will be on the first line of the test function.

How do I change the underlying Phantomjs object settings using Chutzpah?

We have some QUnit javascript tests running in Visual Studio using the Chutzpah test adapter. Everything was working fine until we changed our api (the one being tested by the js files) recently, and added some validations over the UserAgent http header. When I tried to update the tests to change/mock the user agent I realized it was not directly possible even by overriding the default browser property.
After a few days of scavenging, I finally found what exactly is happening. Chutzpah is creating a phantomjs page object for the test files to run on. This is being done on a base javascript file (chutzpahRunner.js) located at the Chutzpah adapter installation path. These are the last lines on the file, that effectively start the tests:
...
// Allows local files to make ajax calls to remote urls
page.settings.localToRemoteUrlAccessEnabled = true; //(default false)
// Stops all security (for example you can access content in other domain IFrames)
page.settings.webSecurityEnabled = false; //(default true)
page.open(testFile, pageOpenHandler);
...
Phatomjs supports changing the user agent header by specifying it in the page settings object. If I edit this chutzpahRunner.js file in my machine, and manually set the user agent there, like this:
page.settings.userAgent = "MyCustomUserAgent";
My tests start to work again. The problem is that this is not in the project itself, and thus cannot be shared with the rest of the team.
Is it possible to change the properties of the phantomjs objects created by Chutzpah to run the tests? I'd like to either change them from inside my own tests, or from another script file I could embed on the pipeline.
Without a code change in Chutzpah it is not possible to set those properties on the PhantomJS object. Please file an issue at https://github.com/mmanela/chutzpah asking for this functionality and then fork/patch Chutzpah to add it (or wait for a developer on the project to hopefully get to this).
Update:
I pushed a fix for this issue. Once this is released you can use the following in a Chutzpah.json file:
{
"userAgent": "myUserAgent"
}

Anchor element's pathname returns undefined in Rhino with env.js

I have run into an issue that I believe is rooted in the implementation of anchor tags in Rhino. Although I am utilizing env.js, I suspect perhaps I am not configuring something correctly.
In particular, my issue occurs while I am attempting to write unit tests against code written for an angularjs application. When I include angular.js (versions 1.2.1 to present), I get the following error:
TypeError: Cannot call method "charAt" of undefined
I am convinced the error is the result of this call to urlParsingNode.pathname since a console.log call reveals that the pathname object is undefined.
I traced the instantiation of the urlParsingNode to this line where we see that it is the result of a call to document.createElement("a"); Further down, we see that they set the href attribute in this line in hopes that the created anchor tag will utilize the browser to correctly parse the URL.
I have to believe I'm not the first to attempt JS unit testing for angular via Rhino, but thus far I've not successfully Googled myself to a solution. Any tips will be greatly appreciated.
Found it and fixed it. The pathname getter/setter simply was undefined for HTMLAnchorElement in env.js.
I submitted a pull request, but unfortunately the project looks all but abandoned. I also couldn't figure out how to build it out to a single file. It appears perhaps someone has taken it upon themselves to break it apart into require.js modules. Not a battle worth fighting for my use case.
So for anyone else who hits this issue, I have the code you need below. It belongs in the HTMLAnchorElement.prototype. In my copy of env.js 1.2, this prototype begins on line 8075. I added the following at line 8118.
get pathname() {
var uri = Envjs.urlsplit(this.href);
return uri.path;
},
set pathname(val) {
var uri = Envjs.urlsplit(this.href);
uri.path = val
this.href(uri.urlunsplit(uri));
},
FYI, my particular issue is resolved with this pull request.

Categories