Intellij Debugger Console for Javascript imported objects or functions - javascript

I have a Jest file that I am debugging in Intellij.
import { screen, waitFor } from '#testing-library/react';
import userEvent from '#testing-library/user-event';
describe('<SamplePage />', () => {
afterEach(() => {
jest.clearAllMocks();
});
it('Correct text in SampleForm', () => {
renderPage();
expect(screen.getByRole('heading')).toHaveTextContent(
"Text to check",
);
});
});
Then I normally put a breakpoint at the expect() line so that the view has been rendered by then. Once at the breakpoint, I open the Debugger Console and I start playing with the test api by testing various statements. However I immediately get an error in the Debugger console when trying to call the screen.debug():
Although the autocomplete is working in the debugger for the screen:
The workaround that I have been using is to assign the imported object screen into a variable x for example. Then when I get to the breakpoint I can play with the x variable as the screen and call various methods like debug or getByRole.
However this is cumbersome since there could be multiple imported objects that I want to explore and assigning each of them to a temporary variable is just not scalable. Does anybody know how to fix this in Intellij?

Undefined variables (screen in your case) while evaluating code during debugging is caused by the weird way imported objects are transpiled + missing name mappings in sourcemaps: if the variable is renamed while transpiling/obfuscating, and no appropriate name mapping is provided, the debugger won't be able to match variable in source code with the one in VM.
There are some known issues when evaluating ES6 imports in modules transpiled by babel/built by webpack. Please see https://github.com/webpack/webpack/issues/3957, https://github.com/babel/babel/issues/1468 for details. There is unfortunately no way to fix the issue on the IDE end.

Related

VS code extension for knowing where function is called from

I want VScode to inform where a defined function is being called from.
file utils.js
function counter(){
console.log('counter');
}
export default counter;
file index.js:
import counter from './utils';
counter();
I want to know in counter function definition in utils.js that it is being used at index.js
if the function counter is called in different files I want to get the information about where the function is being used | called from.
As stated by #hUwUtao, the callstack has the information about the callers of your counter() function when it is executing. If you want to find references without executing, VS Code can do this by right-clicking the function, then selecting Go to References, as seen in the following screenshot.
Thanks for the answers. I found that VScode has an inbuilt reference locater. Just right-click the function and select the option find all references, and VScode will locate all the references to that functions Shortcut: Alt + Shift + F12
Explain: Browser log should show the whole callstack where the error should throw

Webdriver.io - Unable to load spec files quite likely because they rely on `browser` object

I'm using Webdriver.io to run tests on a large number of pages. Because all the specs for the pages are in a JSON file, I have a special class that sets up the test. It looks like this:
module.exports = class PageTester {
suiteName = '';
browser = {};
constructor (suiteName, browser) {
this.suiteName = suiteName;
this.browser = browser;
}
testModel(currentModel) {
describe(this.suiteName + ' endpoint ' + currentModel.url, () => {
this.browser.url(currentModel.url);
/* it() statements for the test */
});
}
}
Then in my specs folder I have a file that loads the JSON and plugs it into the PageTester class, like this:
const PageTester = require('../modules/PageTester');
const models = require('/path/to/some/file.json');
const pageTester = new PageTester('Some Name', browser);
for (const modelName in models) {
pageTester.testModel(models[modelName]);
}
When I run this code, WebdriverIO gives me the following warning:
WARN #wdio/mocha-framework: Unable to load spec files quite likely because they rely on `browser` object that is not fully initialised.
`browser` object has only `capabilities` and some flags like `isMobile`.
Helper files that use other `browser` commands have to be moved to `before` hook.
Spec file(s): /suite/test/specs/test.js
All the tests seem to run fine, so I don't actually understand what this warning is complaining about and what negative consequences ignoring it may have. So I would like to a) understand why this is happening and b) how it would be possible to get rid of this warning given the way my code is set up.
In my case, I resolve it by fixing the path for the require files. I noticed that my path was wrong. But the error that wdio throws is not really helpful. :/
you can only interact with browser object inside it blocks because it is not fully accessible before the browser session is started.
See https://webdriver.io/blog/2019/11/01/spec-filtering.html for details.
You simply should ensure your spec file and respective page file are kept on a similar folder structure.

Unit tests in JavaScript with mocked objects

So I'm working with an enterprise tool where we have javascript scripts embedded throughout. These scripts have access to certain built-in objects.
Unfortunately, the tool doesn't give any good way to unit test these scripts. So my thinking was to maintain the scripts in a repo, mock the built-in objects, and then set up unit tests that run on my system.
I'm pretty ignorant to how JavaScript works in terms of building, class loading, etc. but I've been just trying things and seeing what works. I started by trying out Mocha by making it a node project (even though it's just a directory full of scripts, not a real node project). The default test works, but when I try and test functions from my code, I get compiler errors.
Here's what a sample script from my project looks like. I'm hoping to test the functions, not the entire script:
var thing = builtInObject.foo();
doStuff(thing);
doMoreStuff(thing);
function doStuff(thing) {
// Code
}
function doMoreStuff(thing) {
// More Code
}
Here's what a test file looks like:
var assert = require('assert');
var sampleScript = require('../scripts/sampleScript.js');
describe('SampleScript', function() {
describe('#doStuff()', function() {
it('should do stuff', function() {
assert.equal(-1, sampleScript.doStuff("input"));
});
});
});
Problem happens when I import ("require") the script. I get compilation errors, because it doesn't builtInObject. Is there any way I can "inject" those built in objects with mocks? So I define variables and functions that those objects contain, and the compiler knows what they are?
I'm open to alternative frameworks or ideas. Sorry for my ignorance, I'm not really a javascript guy. And I know this is a bit hacky, but it seems like the best option since I'm not getting out of the enterprise tool.
So if I get it right you want to do the unit tests for the frontened file in the Node.js environment.
There are some complications.
First, in terms of Node.js each file has it's own scope so the variables defined inside of the file won't be accessible even if you required the file. So you need to export the vars to use them.
module.exports.doStuff = doStuff; //in the end of sample script
Second, you you start using things like require/module.exports on the frontend they'll be undefined so you'll get an error.
The easiest way to run your code would be. Inside the sample script:
var isNode = typeof module !== 'undefined' && module.exports;
if (isNode) {
//So we are exporting only when we are running in Node env.
//After this doStuff and doMoreStuff will be avail. in the test
module.exports.doStuff = doStuff;
module.exports.doMoreStuff = doMoreStuff;
}
What for the builtInObject. The easies way to mock it would be inside the test before the require do the following:
global.builtInObject = {
foo: function () { return 'thing'; }
};
The test just passed for me. See the sources.
Global variables are not good anyway. But in this case seems you cannot avoid using them.
Or you can avoid using Node.js by configuring something like Karma. It physically launches browser and runs the tests in it. :)

Filter out React warnings caused by components in node_modules

Anyone knows a trick for filtering out React warnings in the browser console caused by some node module? They are making things harder to debug and at the moment I can't do anything about it.
Whilst not being specific to React:
If you are using Chrome there is an option in the console to filter out which messages are shown. It's the funnel like icon under the Console tab. Then you can choose to filter by Err, Warning, Info, etc...
One option is to overwrite the logging functions of the console object. For example, to filter out "warnings" about the invalid prop type notation that is raised from a package in node_modules, you can add this on top of your main index.jsx file:
const originalConsoleError = console.error;
console.error = (message, ...messageArgs) => {
// console.log({message, messageArgs}); // uncomment only to see what arguments you receive
if (
messageArgs[1] &&
messageArgs[1].includes("has invalid PropType notation inside")
) {
return;
}
originalConsoleError(message, ...messageArgs);
};
You can of course perform more complicated checks - uncomment the console.log to see what message format arguments you receive.

Weird Gecko behaviour (trying to pass an array of nsiDomWindows between js modules)

I'm writing a bootstrap firefox extension. Using firefox developer edition v36.2a
I have two problems that seem related, which I don't understand. The first one, mere annoyance:
my bootstrap Console.utils.imports a js file which loads my application (creates a namespace object and imports all other js files as properties on the namespace. All other files include this same namespace file and thus have access to each other. They even store state and everything works much similar to how node caches modules, eg it seems there is only one object of every class which is shared throughout the whole application. Now, this happens:
my namespace file does:
namespace.console = Components.utils.import( 'you know the one/console.jsm' )
namespace.Services = Components.utils.import( 'you know the one/Services.jsm')
namespace.Cu = Components.utils
Now in another file that imports this file, I get the namespace object, but namespace.Cu will be undefined. console.log( namespace ) is fine however and shows me Cu, that I can expand and see all its properties and so on... All other things (console, Services, my own classes) are fine, but trying Cc, Ci etc from Components -> undefined.
In another place in my app I have a function (in file A) which returns an array of nsiDomWindows. A function in file B calls it and when it arrives, similar story: in console all looks fine, Array with ChromeWidows that I can look at. But it's no longer an array actually and is of type object and array[ 0 ] is undefined. If I put both classes in the same file they're fine.
For further confusion, I think I have already used this method in another file and all was fine:
// A.js
//
function A()
{
b = new B()
c = new C()
let windows = b.windowList () // works fine, yields an actual valid array
// with valid windows inside
c.doSomething() // broken, see below
c.doSomething( windows ) // passing it as a parameter
// doesn't help, still broken
}
// B.js
//
function B()
{
this.windowList = function windowList()
{
let result = []
// get open windows from nsiWindowMediator
// foreach...
//
result.push( nsiDomWindow )
console.log( typeof result ) // Array -> it's completely valid here
return result
}
}
// C.js
//
function C()
{
this.b = new B()
this.doSomething = function doSomething( windows )
{
if( ! windows )
windows = this.b.windowList()
console.log( windows ) // in the console shows:
// Array[ ChromeWindow -> about:home ]
// I can inspect all it's properties, looks ok
console.log( typeof windows ) // object
console.log( windows.constructor.name ) // undefined
console.log( windows[ 0 ] ) // undefined
// looping over the object properties shows that it does
// have 1 property called '0' which points at undefined
// note: there was only one open window in the array.
}
}
// Note: the order in which I use Components.utils.import on these is B, C, A
I also wondered if this had to do with security measures in gecko, but no wrapper objects are to be seen anywhere, and afaik they should only shield content code from chrome code (this is all chrome code).
It's the kind of bugs that frustrates me, because I can't think of one sensible reason why the return value of a function shouldn't be the same thing on two sides of the call.
Lucky enough there is a workaround, I will have my make file concatenate all my js files and be done with Components.utils once and for all. Seems the less of the mozilla API I have to use, the happier and more productive I'll be.
I'm seeing errors from mozilla code as well. I just had an error saying "shouldLog is not a function" in Console.jsm. This function is clearly defined higher up in that file. The line that throws the error is an anonymous function that is being returned. That should inherit the scope without a doubt, but it doesn't. It might be that something is mangling return values and that this is related.
I filed a bug on bugzilla with a sample addon attached which demonstrates the first of the problems mentioned above.
update:
I'm sorry, I confused two things. I just figured out what happened in the first case of Cu not being available. I just loaded the file in which the problem happens before adding Cu to my namespace and since I did const { console, Services, Cu } = namespace on the global scope, this actually got evaluated before the property was made. The confusing part about it is that the console keeps references, not copies of the objects it shows you (an unfortunate design choice if you ask me) logging the namespace before the code in question gives you a view on it's state later on, which I missed to take into consideration.
That still doesn't explain how one function can return a perfectly sound value to a receiving function who receives something else, or how a function declared in Console.jsm doesn't seem to exist anymore in a function who inherits it's scope.
All in all, the first problem hasn't got anything to do with the others. I can't however create a reproducible small addon to illustrate the other 2. If I think of a way I'll upload it.
Btw: The pitfall by console can be easily seen (put the following in a javascript scratchpad):
let a = { some: "value" }
console.log( a )
delete a.some
// output: Object { }
For debugging purposes (usually it's main purpose) console has it's limits, and it usually better to set a breakpoint in a debugger or use JSON.stringify
I think I've narrowed all the fore mentioned problems to unloading uncorrectly. I had eventlisteners that I didn't remove and when they fired, objects or scopes can be invalidated.
Using the Extension Auto-Installer somewhat made these problems more severe because when reloading the addon when it hasn't properly unloaded creates an unreliable state of the addon code.
The shouldLog is not a function was because I thought that I had to unload all modules that I loaded with Components.utils.unload, so I unloaded Console.jsm.
After fixing that plus wrapping all the entry points into my software in try-catch blocks, things now run smoother. I now rarely have to uninstall the addon and restart firefox after updating the code.
There's nothing like a few fun days of debugging...
I didnt read it all but:
I think the first issue is you are importing it wrong.
If you want to bring it to a certain namespace to the exported var from Cu.import you should do it like this:
Cu.import('resource://gre/modules/ctypes.jsm', namespace);
No need for the var blah = Cu.import
Console.jsm and Services.jsm export a var named te same thing.
You can even just do Cu.import('rsource://gre/modules/ctypes.jsm') and start using it like ctypes.blah
Also to get access to Cu do this:
var {Cu: utils, Cr: results} = Components
Next i think if you change the module in one scope, it will not change in other scopes until you do Cu.import again in that scope.

Categories