I need to make a JavaScript script available as a global script tag for a unit test in Jest.
I understand that Jest uses jsdom and in jsdom there is an api that allows to initialize the DOM and load script but I cannot seem to find a way on how to do this in Jest?
If you do not need to test the script itself, which, given the fact it is an external library, you shouldn't, you can mock it globally.
First of all you need to setup a jest setupFile, this file will be executed before test execution and the mocks available there should remain available for each test file, to do so write something like this in package.json or, better, in jest.config.js
"jest": {
"setupFiles": [
"<rootDir>/jest/globals.js"
]
}
Then create that file and write your global mocks there.
Now you will say "'Duh'? How do I mock the external library imported through the tag script?" Well, what I found useful for this and a number of other reason is to wrap the imported library in a separate module, this way you can use the wrapper throughout your code instead of using directly the globally imported external library, which will give you the possibility to mock the said module globally and voilĂ , it is done!
You can simply use require to load your script.
However, keep in mind that the script must be saved locally.
require('relative/path/to/your/script')
Some more interesting information here :
https://info343.github.io/jest.html
Related
In Node you can make an importText function fairly easily, and then use it in another file like so:
import importText from 'importText'
const css = await importText('./someFile.css')
// (This isn't technically possible yet, but top-level await is coming someday)
By using Webpack or a similar tool, you can also do the same thing, only with a more convenient syntax:
import css from './someFile.css';
Node used to have a way to do the same thing without Webpack, but the API for it, "require extensions", was deprecated (emphasis added):
Deprecated. In the past, this list has been used to load non-JavaScript modules into Node.js by compiling them on-demand. However, in practice, there are much better ways to do this, such as loading modules via some other Node.js program, or compiling them to JavaScript ahead of time.
https://nodejs.org/api/modules.html#modules_require_extensions
My question is: what are the "much better ways"?
They mention "compiling them to JavaScript ahead of time", which I would assume is the Webpack approach. But how would one "load a module via some other Node.js program" ... or solve the problem any other way (the text I quoted implied those two weren't the only options)?
If in my package.json I define a yarn script test that only calls nightwatch command; It seems as it is that it'll run both the scenarios that are found in the features folder as well as any test that is not necessarily a test made with Cucumber (plain nightwatch tests under the tests/ folder).
Is there a way for me to distinguish the execution of only the "cucumber+nightwatch" tests from the plain nightwatch ones, so I filter and only run from one of the two sets?
The author of nightwatch-cucumber suggested this approach via e-mail:
use an environment variable in nightwatch configuration (JS based).
This environment variable can decide the source of the tests.
One note: this package will be deprecated if nightwatch 1.x will come
out. So I suggest not to invest to much time with it instead use the
new nightwatch-api package.
A quick workaround to filter out plain nightwatch tests from the cucumber+nightwatch ones was to edit the src_folders in the nightwatch.json file to an empty array, like this:
{
"src_folders" : [],
...
}
I have a TypeScript project that compiles down to a single JS file in /dist.
I have Jasmine tests, also written in TypeScript, that reference the various classes they test with references like:
/// <reference path="../../../src/script/classUnderTest.ts" />
When I compile the tests the TypeScript compiler pulls in all the referenced classes and I get a single JS file containing the test code and the code under test.
This actually works fine for just running the tests, but now I'd like code coverage too. From what I can tell, to get Istanbul to work I need to have the code under test separate from the test code. Also it would be nice to be testing exactly the JS file that will be live.
So, how can I get the type safety and autocomplete benefits of "/// reference" whilst using my compiled JS file when the tests are actually run?
(Or am I barking up the wrong tree entirely?)
Note, I am building this on a Mac, so from what I've read Chutzpah is not currently an option. I'm also currently using only npm scripts to do builds. I'd prefer to not bring in grunt or gulp unless it's absolutely necessary.
So, how can I get the type safety and autocomplete benefits of "/// reference" whilst using my compiled JS file when the tests are actually run?
Don't using TypeScript's --outFile option (few other reasons). Instead use modules e.g. --module commonsjs and a module loader e.g. webpack.
More
Browser quickstart : https://basarat.gitbooks.io/typescript/content/docs/quick/browser.html
Modules:
https://basarat.gitbooks.io/typescript/content/docs/project/modules.html
Is there a clever way to create a module that can both be run with index.js arg1 arg2 as well as exporting itself to be used by others, ie. module.exports?
Say I have a script that kickstart a proxy server, while I can do proxy.js host port, I can't think of an easy way to export it as well. Should I look at process.argv to decide whether to exports or run itself? Or is there a better pattern?
PS: I was trying to write test cases for it but realize without module.exports, it's kinda hard to provide proper test coverage. Just curious how one would tackle this.
Backstory:
I've currently got a Require.js and jQuery/Backbone.js using site. Until now, jQuery and Backbone have stayed outside of Require, letting me do:
define([], function() {
// NOTE: Using Backbone and $ without an import!
new Backbone.View(el: $('#foo');
});
That's worked really well: without that approach, just about every module in my site would have to add a Backbone/jQuery dependency.
But then the other day I needed to package up a portion of our code as an external library. I made a separate require config file for it, and everything seemed great, until I compiled ("optimized") all the files in to a single library file, and realized that Backbone/jQuery (and related plug-ins/libraries) weren't getting included.
So, I added a bunch of shims, and got Backbone, jQuery, and all the related libraries in to Require. However, I still have a ton of modules that expect $ and Backbone to just exist. That should be ok, because Backbone/jQuery both register their variables globally, but it's not because of Require's load order.
Basically, any module without dependencies is broken, because they load before Require loads the jQuery/Backbone shim. Any modules that have dependencies don't have this issue, because jQuery/Backbone have already been loaded by the time they get loaded.
It seems like my only option is to add an explicit Backbone/jQuery to every module without dependencies. I've got a bunch of modules like that though, and ideally I'd prefer not to have to import jQuery/Backbone anywhere.
Question
So, my question is: is there any way to tell Require "load these X modules/shims before you load everything else"? Or, to put it another way, is there any way to tell Require that all of my modules depend on certain other modules?
I thought putting Backbone at the top of my initial require:
require(['backbone', ...
but that didn't help; the other dependency-less modules still load before it.
I see no reason this would not work:
require(['backbone', 'jquery'], function () {
require(['main']);
});
The idea is to wrap what was your initial entry point to your application in a require call that loads Backbone and jQuery. If the modules of your application are loaded only because main is required (that is, if there is no require call elsewhere that loads any module needed by main), then with the code above both Backbone and jQuery are guaranteed to be loaded before any of the modules used by main are.