Read a HTML file in a Karma+Jasmine test - javascript

I have an Angular controller that defines an array of over 50 field names. Each of these should occur in an HTML file as both the id and ng-model of an input are present. I would like to test if I made no typos by reading and parsing the HTML file. Since I need to get the array, a Karma+Jasmine test seems ideal (with protractor I can't get that). What would be a good way to test this?
For both the FileReader and $http.get neither enter the success or error function, and with XMLHttpRequest I just get an empty string.
I already added a line
pattern: 'app/views/*.html', watched: false, included: false, served: true}
to karma.conf.js, that matches the file I want to read.
Any help is greatly appreciated.

1.You can use following preprocessor to render html
npm install karma-ng-html2js-preprocessor --save-dev
Add following into karma.config.js:
ngHtml2JsPreprocessor : {
moduleName:'templates'
},
2.Use $compile service of angular and create html which you want to test and add it to dom. Then you can perform any test on that html
var $body=$('$body');
afterEach(
$body.empty();
);

You could load the HTML-snippets as fixtures with jasmine-jquery. Don't wonder about the name, it's because the library also adds lots of custom jasmine matchers which are useful in combination with jQuery.
To use it, add the following in your karma config file to the files array:
// this is the path to your library if installed via bower
'../bower_components/jasmine-jquery/lib/jasmine-jquery.js',
// make the views available to the locally by karma started webserver
{pattern: 'views/*.html', watched: true, served: true, included: false},
For your tests, you have to define the path to your views and load them explicitly:
beforeEach(function () {
jasmine.getFixtures().fixturesPath = "base/views"; // path to your templates
jasmine.getFixtures().load('myHtmlSnippet.html'); // load a template
});
This will load an div with the id jasmine-fixtures directly into the body of the browser in which the tests run. The loaded fixture will be inserted into the div#jasmine-fixtures. Then you can simply access them with jQuery or by vanilla javascript.

After I had such the sample problem to call the "server"-data and don't use a mockup service.
I stumble over this entry:
E2E mock $httpBackend doesn't actually passThrough for me
Works fine, with this you can use $http.get and check your data.
If you're working with promises try also this: https://github.com/ThomasBurleson/jasmine-as-promised

Related

Require file on runtime & unit test issue

I use require.js to load files at runtime like following
This is working as expected when I run the file in the right context(I mean when the call is coming from the right path.)
module1.js
define(["otherModule"], function(otherModule) {
working!!!
....
Now I want to create some unit test to this file (module1) from
other context (from folder of tests which is found in diffrent location in the project) and I get error
require.js:145 Uncaught Error: Script error for: otherModule
Since it tries to run the get on this path during the Unit Test
which is located in diffrent project structure ...
https://app/path1/path2/path3/otherModule.js
And in runtime which works (from different context) it find it in the path
https://app/path1/path2/path3/path4/path5/otherModule.js
There is additional path4 & path5 in the request that works,
How should I solve it to work on both cases (UT/Runtime) ?
http://requirejs.org
I think you should be able to get it working by applying a RequireJS configuration file, so that the module name is abstracted from its path:
E.g. in the test context, call something like this as initialization step:
require.config({
baseUrl: "/path1/path2/path3"
});
Alternatively, you can also remap single modules like so (this can also be used to inject a different implementation of a specific module for testing etc.):
require.config({
paths: {
"otherModule": "/path1/path2/path3/otherModule"
}
});
See here: http://requirejs.org/docs/api.html#config

Add files to watch-list in karma preprocessor

Here is a repository created to demonstrate the issue:
brianmhunt/karma-rollup-preprocessor-issue-3
I'm trying to get karma-rollup-preprocessor working with Karma's builtin watch i.e. solve showpad/karma-rollup-preprocessor#3
In other words, in a preprocessor, I want to add files to Karma's watch list.
It's easy to get the list of files Rollup uses to compile. Rollup returns a list of files that it reads (ones one wants to watch), so in the preprocessor I am trying to add files to the list karma watches.
Basically I want to add this (or the working equivalent) to the preprocessor:
bundle.modules.forEach((module) => {
files.unshift({
pattern: module.id, /* The full file path, from Rollup */
watched: true,
included: false,
nocache: false,
served: false,
})
})
Where files is Karma's config.files or fileList or whatever place one needs to put the files being watched.
Doing the above with config.files, the files are indeed being added to the watcher, but .on(fileList.changeFile) fails the _isIncluded.
So it looks like the files also (or alternatively) must be added to the fileList.
Unfortunately when I try to add the fileList to the $inject, I get the error:
Error: Can not resolve circular dependency! (Resolving: preprocess -> preprocessor:rollup -> fileList -> preprocess).
I've looked at basically all the other preprocessors that look like they could also add includes, but I have found no indication of how to do it.
Is there a canonical way to add files Karma should watch from a preprocessor? Or otherwise how might one do this? This seems pretty clutch for a preprocessor in Karma, so it's surprising that it's not documented, apparent, or problematic in the other preprocessors.
EDIT Here's some more attempts:
I tried to add the watched patterns to the config.files in karma.conf i.e.
files: [
"spec/**/*.js",
{pattern:"src/**/*.js", included: false, watched: true}
]
But the src/* doesn't recompile when changed. The tests just re-run.
So I tried chokidar like this:
var server = new karma.Server(options)...
chokidar.watch("src/**/*.js")
.on('add', server.refreshFiles.bind(server))
.on('change', server.refreshFiles.bind(server))
I also tried it with a debounce, in case Karma was slower on the refresh, but it seems the tests won't re-run.
I rooted around karma-browserify for inspiration but it was a bit too convoluted to pick up without delving in.
I've issued a pull request to resolve this.
Until it is merged one can use my repo i.e. put "karma-rollup-preprocessor": "brianmhunt/karma-rollup-preprocessor" in package.json dependencies or devDependencies.
EDIT: Superceded by https://github.com/Kflash/karma-rollup-plugin

Load Json Fixture in Karma/Mocha

I am using Karma with Mocha and karma-fixture. If I go into debug when I run tests, I can see the file is loaded in the server. If I changed the config included:true, then I can see it's loaded on the console. The extension is changed to .js (rather than .json) and if I view source on the file (in browser window) the json is wrapped in a function -- so it seems like everything is happening as described in the documentation. However, I get an error that the file cannot be found. I have included the relevant configs and errors below.
Update 1
I was able to load the fixture with require -- which I'm using anyway to manage and load dependencies. The data is assigned to an array like this: __json__['test/fixtures/json-data/querybrowser']. I would still be interested in knowing why I can't use the fixture.load() function. I feel like I am missing a simple detail here.
Thank you!
The configuration:
The file is located here, pathed from root of my project: \test\fixtures\json-data\querybrowser.json
Karma
files: [{pattern: 'test/fixtures/{,*/}*', watched: true, included: false, served: true}]
TEST spec
fixture.setBase('base/test/fixtures/json-data');
querybrowser_json = fixture.load('querybrowser.json');
The Error
Chrome 48.0.2564 (Windows 7 0.0.0) Query Browser Function Tests "before all" hook FAILED
ReferenceError: Cannot find fixture 'base/test/fixtures/json-data/querybrowser.js'
at Fixture._throwNoFixture (////node_modules/karma-fixture/lib/fixture.js:141:13)
Have you:
Made sure that you're including the JSON files in both your files array and your preprocessors array inside your karma config?
Made sure that you have transformPath property defined in jsonFixturesPreprocessor as per https://github.com/billtrik/karma-fixture/issues/10?
I had the same issue as you but doing these things fixed it for me.

Glob Syntax: Breadth first traversal to get all items in a folder using Karma

I'm writing Karma to test some AngularJS code. In order for the tests to run correctly, certain modules have to be run before others. Controllers and services come after the module instantiation.
The way my code is structured right now (grossly simplified) is I have an "app" folder which contains another folder called "controllers".
Inside "app", I have an app.js file. Inside "app/controllers", I have someController.js.
/root
--- /app
--- app.js
--- /controllers
--- someController.js
I'm using Karma to load all my files before I run tests. The tests are loaded after the source (app) files. But it's loading the source files in an order that's undesirable. It loads someController.js first before loading app.js. Probably because it does a depth-first traversal. I'm not looking for an algorithm or anything because that's all that Google seems to give me. Just a simple string glob pattern.
The syntax I'm using is "root/**/*.js" to get all the files in all sub-directories of "root".
How do I specify to Karma that I want to load all the files in "/app" before loading files in "app/controllers/"? (ie. breadth first traversal)
The example I'm following from Karma's documentation is here: http://karma-runner.github.io/0.13/plus/requirejs.html under the Configure Karma section.
Specifically:
files: [
{pattern: 'lib/**/*.js', included: false},
{pattern: 'src/**/*.js', included: false},
{pattern: 'test/**/*Spec.js', included: false},
'test/test-main.js'
],
Thanks!
I don't know of a way to explicitly control the traversal strategy of the globbing, but you can manually create multiple patterns which will force the desired order. If you use a simple dir/*.js pattern first, only the top level .js files will be matched, and then in a second pass you can go deeper with a more permissive dir/**/*.js pattern.
In your case, these patterns would be something like:
{pattern: 'app/*.js', included: false},
{pattern: 'app/**/*.js', included: false},
However, if you have several places where you need to specify the loading order, this can become cumbersome to maintain. For cases like this I found it very helpful to set up the build environment to generate the includes into the karma configuration file at the same time as generating the includes into the main .html file of the app - usually the same order restrictions apply to both. For example, if you're using something like grunt-wiredep, this can be as easy as adding a new target with a custom fileTypes entry to set up the proper syntax.

TypeScript: How do you test your client-side code?

When I write tests for my in-browser TS code, I hit the following problem. My "test" code files are located in a separate folder from the "application" code files (an arrangement that I am not willing to give up). Therefore, in order to import my "app" modules, I have to do this:
// tests/TS/SubComponent/Module.Test.ts
import m = module("../../Web/Scripts/SubComponent/Module");
This compiles just fine. But when loaded in browser, it will obviously not work, because from the standpoint of RequireJS running in the browser, the module is located at "app/SubComponent/Module" (after being remapped through web server and RequireJS config).
With TS 0.8.3 I was able to pull off this clever trick, but in 0.9.0 it no longer works, because now the compiler doesn't let me treat a module as an interface.
So the question is: how do you test your client-side code?
Clearly, I can't be the only person to be doing it, can I? :-)
I can't tell if you are using Visual Studio - this next bit is Visual Studio specific...
This is how I do it:
In my test project, I created a folder named "ReferencedScripts" and
referenced the scripts from the project being tested (add existing
item > add as link). Set the file to copy to the output folder.
Source: Include JavaScript and TypeScript tests in Visual Studio.
Using add-as-link makes the scripts available in your test project.
Not using Visual Studio? I recommend creating a task / job / batch file to copy the files into the test folder. You could even use tsc to do this task for you.
I am in the middle of a project where I have to migrate parts of a large javascript project to typescript and this is how I managed to keep the tests running:
Use grunt-typescript task to watch and compile all my .ts files from the source to a tmp folder (with their source-maps). If you only have to deal with typescript files, then you can use the tsc in watch mode to do it as well. The latter would be faster, but the former allowed me to simultaneous edit javascript and typescript files with livereload.
Include the .ts files in karma.conf but don't watch them or include them:
// list of files / patterns to load in the browser
files = [
JASMINE,
JASMINE_ADAPTER,
// ...
// We want the *.js to appear in in the window.__karma__.files list
{ pattern: 'app/**/*.ts', included: false, watched: false, served: true },
{ pattern: 'app/**/*.js', included: false },
// We do watch the folder where the typescript files are compiled
{ pattern: 'tmp/**/*.js', included: false },
// ...
// Finally, the test-main file.
'tests/test-main.js'
];
Finally, in the test-main.js file, I mangle the names of typescript files and declare them as require modules with the correct paths (to the corresponding .js file) in test-main.js:
var dynPaths = {
'jquery' : 'lib/jquery.min',
'text' : 'lib/text'
};
var baseUrl = 'base/app/',
compilePathUrl = '../tmp/';
Object.keys(window.__karma__.files)
.forEach(function (file) {
if ((/\.ts$/).test(file)) {
// For a typescript file, include compiled file's path
var fileName = file.match(/(.*)\.ts$/)[1].substr(1),
moduleName = fileName.substr(baseUrl.length);
dynPaths[moduleName] = compilePathUrl +
fileName.substr(baseUrl.length);
}
});
require({
// Karma serves files from '/base'
baseUrl: '/' + baseUrl,
paths: dynPaths,
shim: { /* ... */ },
deps: [ /* tests */ ],
// start test run, once requirejs is done
callback: function () {
window.__karma__.start();
}
});
Then as I edit the typescript files, they are compiled and put in the tmp folder as javascript files. These trigger karma's auto watch and it reruns the tests. In the tests, the require calls resolve correctly since we have explicitly overwritten the paths to the typescript files.
I realise that this is a bit hacky, but I had to jump through similar hoops while trying to include all my tests with REQUIRE_ADAPTER. So I assumed that there is no cleaner way of doing it.
Hopefully, if typescript becomes more prevalent, we will see better support for testing.
So here's ultimately what I've done: it turns out that Karma can handle/watch/serve files that are not within the base directory, and it makes them look to the browser in the form of "/absolute/C:/dir/folder/blah/file.js". This happens whenever files -> pattern starts with "../".
This feature can be used to make RequireJS see the whole directory structure exactly as it exists on the file system, thus allowing the tests to import app modules in the form of "../../Web/App/Module.ts".
files = [
// App files:
{ pattern: '../../Web/App/**/*', watched: true, served: true, included: false },
// Test files:
{ pattern: '../js/test/**/*.js', watched: true, served: true, included: false }
];
Reference (version 0.8): http://karma-runner.github.io/0.8/config/files.html
Since the typescript code is compiled to Javascript you can use all Javascript test frameworks.
I am using Jasmine: https://github.com/pivotal/jasmine/wiki
You can write your tests in Typescript with the .d.ts file here: https://github.com/borisyankov/DefinitelyTyped/blob/master/jasmine/jasmine.d.ts
But my client code is rather small and compiled to one output file, so I don't have the module issues that you describe.
Might be that I misunderstood your question - can't comment yet...
The runtime of the browser does not need any typescript information. So your test script should import the compiled ts files the same way as any other javascript files they need. Might be that you have to copy them to a subfolder of your test-project before you run your script.
I assume the bigger problem is that you have no interface information. Why do you want to import these informations instead of referencing them? Especially since importing them will also occur in the browser.
The Reference will only take place in the IDE , so it does not matter in which folders the interface-files are located.
/// <reference path="../../Web/Scripts/SubComponent/Module/References.ts" />

Categories

Resources