Karma + PhantomJS + Jasmine + Kendo UI component not rendering during test - kendo-ui
Relatively lengthy question here, so bear with me please.
I have been trying to add unit testing to our client-side code for awhile now, and finally got the go ahead to take the time to do it. We use AMD (requirejs) as of now, but that is also something I am exploring switching out of. So the past few days I have been working on getting some of the testing infrastructure in place for our current setup, and am using phantomJS, Karma, and Jasmine to test from the terminal. I have run into a problem with the rendering of Kendo components, so before I dive any deeper, I wanted to ask here to see if anybody know if:
What is the problem caused by.
How to fix it in our setup files.
Some background on:
All our library scripts are loaded locally with requirejs. jQuery and kendoui are loaded statically via script tags (something to do with globalization not working correctly when doing it via requirejs).
When I try to test a Marionette View that wraps a Kendo component, I get "$el.kendoGrid" is not a function. The "kendo" global is however attached to window.
karma.conf.js:
// Karma configuration
// Generated on Wed Dec 28 2016 13:38:24 GMT-0600 (Central Standard Time)
module.exports = function (config) {
"use strict";
config.set({
// base path that will be used to resolve all patterns (eg. files, exclude)
basePath: '',
// frameworks to use
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
frameworks: ['jasmine'],
// list of files / patterns to load in the browser
files: [
// Loads jQuery and kendoui statically via a script tag so the globals are available as expected by our
// source JavaScript files.
'web-libs-common/src/main/resources/META-INF/resources/static/js/lib/jquery/jquery.js',
'web-libs-common/src/main/resources/META-INF/resources/static/js/lib/kendoui/kendo.all.js',
// Load requirejs and its karma adapter after making the above scripts available.
'node_modules/requirejs/require.js',
'node_modules/karma-requirejs/lib/adapter.js',
//The following patterns make the files available to be loaded by requireJS.
{pattern: 'healthems-web/test/js/**/*.js', included: false}, //Make the test files available, but do not load.
//Make the source files available, but do not load
{pattern: 'healthems-web/src/main/resources/META-INF/resources/static/js/**/*.js', included: false},
//Make the library files available but do not load.
{
pattern: 'web-libs-common/src/main/resources/META-INF/resources/static/js/lib/**/*.js',
included: false
},
//Make the html templates available but do not load.
{pattern: 'healthems-web/src/main/resources/META-INF/resources/static/html/**/*.html', included: false},
//Make the test_utils directory available, but do not load.
{pattern: 'test_utils/*.js', included: false},
{pattern: 'node_modules/squirejs/src/Squire.js', included: false},
'test-main.js'
],
// list of files to exclude
exclude: [
],
// preprocess matching files before serving them to the browser
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
preprocessors: {},
// test results reporter to use
// possible values: 'dots', 'progress'
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
reporters: ['spec'],
// web server port
port: 9876,
// enable / disable colors in the output (reporters and logs)
colors: true,
// level of logging
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO ||
// config.LOG_DEBUG
logLevel: config.LOG_ERROR,
// enable / disable watching file and executing tests whenever any file changes
autoWatch: true,
// start these browsers
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
browsers: ['PhantomJS'],
// Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits
singleRun: false,
// Concurrency level
// how many browser should be started simultaneous
concurrency: Infinity
});
};
test-main.js:
"use strict";
var allTestFiles = [];
var TEST_REGEXP = /(spec|test)\.js$/i;
// Get a list of all the test files to include
Object.keys(window.__karma__.files).forEach(function (file) {
if (TEST_REGEXP.test(file)) {
// Normalize paths to RequireJS module names.
// If you require sub-dependencies of test files to be loaded as-is (requiring file extension)
// then do not normalize the paths
var normalizedTestModule = file.replace(/^\/base\/|\.js$/g, '');
allTestFiles.push(normalizedTestModule);
}
});
var baseLibPath = "web-libs-common/src/main/resources/META-INF/resources/static/js/";
var baseAppPath = "healthems-web/src/main/resources/META-INF/resources/static/js/";
var baseTemplatePath = "healthems-web/src/main/resources/META-INF/resources/static/";
require.config({
// Karma serves files under /base, which is the basePath from your config file
baseUrl: '/base',
map: {
'*': {
underscore: 'lodash'
}
},
paths: {
'app': baseAppPath + 'app',
'backbone': baseLibPath + 'lib/backbonejs/backbone',
'backbone.marionette': baseLibPath + 'lib/backbonejs/backbone.marionette',
'backbone.paginator': baseLibPath + 'lib/backbonejs/backbone.paginator',
'backbone.validation': baseLibPath + 'lib/backbonejs/backbone.validation',
'format': baseAppPath + 'format',
'jquery.ui': baseLibPath + 'lib/jquery/jquery.ui',
'jquery.waypoints': baseLibPath + 'lib/jquery/jquery.waypoints',
'jquery.waypoints.sticky': baseLibPath + 'lib/jquery/jquery.waypoints.sticky',
'kendoui': baseLibPath + 'lib/kendoui/kendo.all',
'json3': baseLibPath + 'lib/json3',
'jstz': baseLibPath + 'lib/jstz',
'jszip': baseLibPath + 'lib/kendoui/jszip.min',
'jquery': baseLibPath + 'lib/jquery/jquery',
'lodash': baseLibPath + 'lib/lodash',
'mocks': 'test_utils/defaultMocks',
'moment': baseLibPath + 'lib/momentjs/moment-with-locales',
'moment.timezone': baseLibPath + 'lib/momentjs/moment-timezone-with-data',
'rsvp': baseLibPath + 'lib/rsvp',
'sockjs': baseLibPath + 'lib/sockjs',
'spin': baseLibPath + 'lib/spin',
'stomp': baseLibPath + 'lib/stomp',
'Squire': 'node_modules/squirejs/src/Squire',
'template': baseTemplatePath + 'html/template',
'text': baseLibPath + 'lib/requirejs-text/text',
'util': baseAppPath + 'util',
'sprintf': baseLibPath + 'lib/sprintf'
},
shim: {
'jstz': {
exports: 'jstz'
},
'jquery.waypoints': {
deps: ['jquery'],
exports: 'Waypoint'
},
'jquery.waypoints.sticky': {
deps: ['jquery.waypoints'],
exports: 'Waypoint.Sticky'
},
'spin': {
exports: 'Spinner'
},
'stomp': {
exports: 'Stomp'
},
'sprintf': {
exports: 'sprintf'
}
}
// dynamically load all test files
//deps: allTestFiles,
// we have to kickoff jasmine, as it is asynchronous
//callback: window.__karma__.start
});
require(allTestFiles, function () {
window.__karma__.start();
});
Our main app requirejs config:
global.requirejs.config({
map: {
'*': {
underscore: 'lodash'
}
},
paths: {
'backbone': 'lib/backbonejs/backbone',
'backbone.marionette': 'lib/backbonejs/backbone.marionette',
'backbone.paginator': 'lib/backbonejs/backbone.paginator',
'backbone.validation': 'lib/backbonejs/backbone.validation',
'jquery.ui': 'lib/jquery/jquery.ui',
'jquery.waypoints': 'lib/jquery/jquery.waypoints',
'jquery.waypoints.sticky': 'lib/jquery/jquery.waypoints.sticky',
'json3': 'lib/json3',
'jstz': 'lib/jstz',
'jszip': 'lib/kendoui/jszip.min',
'lodash': 'lib/lodash',
'moment': 'lib/momentjs/moment-with-locales',
'moment.timezone': 'lib/momentjs/moment-timezone-with-data',
'rsvp': 'lib/rsvp',
'sockjs': 'lib/sockjs',
'spin': 'lib/spin',
'stomp': 'lib/stomp',
'template': '../html/template',
'text': 'lib/requirejs-text/text',
'sprintf': 'lib/sprintf'
},
shim: {
'jstz': {
exports: 'jstz'
},
'jquery.waypoints': {
deps: ['jquery'],
exports: 'Waypoint'
},
'jquery.waypoints.sticky': {
deps: ['jquery.waypoints'],
exports: 'Waypoint.Sticky'
},
'spin': {
exports: 'Spinner'
},
'stomp': {
exports: 'Stomp'
},
'sprintf': {
exports: 'sprintf'
}
}
});
define('jquery', [], function() {
return window.jQuery;
});
define('kendoui', [], function() {
window.kendo.culture("en-US");
window.kendo.culture().numberFormat.currency.pattern[0] = "-$n";
return window.kendo;
});
I am very new to node, and have limited experience with karma, jasmine, and phantomJS, so I've been rolling around on my back for awhile now trying to figure this out, so any help would be excellent. Thanks!
Related
Nuxt.js app deployed to Heroku only has TailwindCSS's styles for < SM breakpoint
I deployed my 1st Nuxt.js app to Heroku...Everything went smooth but when I opened the app I realised that every .vue file/component has TailwindCSS styles up untill SM breakpoint. Mobile view is fine, but anything bigger than SM breakpoint is not apllied. I also used Purgecss to remove unused styles but not sure if that can cause the problems... Any ideas on how to fix this?
I fixed my problem just by finding this https://github.com/nuxt/nuxt.js/issues/2262 I created modules folder and added import-tailwind-config.js with the code: module.exports = function () { const tailwindConfig = require('#nuxtjs/tailwindcss') this.options.env.tailwind = tailwindConfig } And inside nuxt.config.js, outside of module.exports I added const PurgecssPlugin = require('purgecss-webpack-plugin') const glob = require('glob-all') const path = require('path') class TailwindExtractor { static extract (content) { return content.match(/[A-z0-9-:/]+/g) || [] } } As well as this code inside of module.exports build: { extend (config, ctx) { config.plugins.push( new PurgecssPlugin({ whitelist: ['html', 'body'], paths: glob.sync([ path.join(__dirname, 'components/**/*.vue'), path.join(__dirname, 'layouts/**/*.vue'), path.join(__dirname, 'pages/**/*.vue'), path.join(__dirname, 'plugins/**/*.vue') ]), extractors: [{ extractor: TailwindExtractor, extensions: ['html', 'js', 'vue'] }] }) ) } } modules: [ '~modules/import-tailwind-config' ]
How to view <swagger-ui-url>/app.yaml content in the browser and not download the yaml file instead?
I am using swagger api documentation tool for my backend, and I need to view the contents of the .yaml file in the browser when the url is called. But instead, I always end up having the file downloaded. This is the content of my SwaggerUI tag: <script> window.onload = function() { // Build a system const ui = SwaggerUIBundle({ url: "./app.yaml", dom_id: '#swagger-ui', deepLinking: true, presets: [ SwaggerUIBundle.presets.apis, SwaggerUIStandalonePreset ], plugins: [ SwaggerUIBundle.plugins.DownloadUrl ], layout: "StandaloneLayout" }) window.ui = ui } </script>
Require a jQuery-Plugin with Webpack
I want to use Webpack in order to create one single scripts.js file out of all needed Javascript files. Within my main.js I require three modules: require('jquery'); require('readmore'); require('foundation'); My webpack.config.js is this: var path = require('path'); module.exports = { entry: ["./js/main.js"], output: { path: path.resolve(__dirname, 'build'), filename: "scripts.js" }, resolve: { modulesDirectories: ["bower_components", "node_modules"], alias: { jquery: '../bower_components/jquery/dist/jquery.js', readmore: '../node_modules/readmore-js/readmore.js', foundation: '../bower_components/foundation-sites/dist/js/foundation.js' } } } My problem: as readmore-js is a jQuery-Plugin it requires jQuery by itself. I got this error after running Webpack: ERROR in ./~/readmore-js/readmore.js Module not found: Error: Can't resolve 'jquery' in '/Users/myName/www/myProject/node_modules/readmore-js' # ./~/readmore-js/readmore.js 17:4-31 # ./js/main.js # multi main From my understanding the problem is that readmore also wants to load the module jQuery within the directory "nodes_modules". My first approach was to resolve this problem by adding moduleDirectories to the config-file, but it does still not work. And even in this case, the plugin shouldn't load jQuery again. Do you have any idea how I can load jQuery globally and then "tell" all modules which require jQuery by themself "look, it's there!" As it may helps, the following is copied out of the plugin's readmore.js: (function(factory) { if (typeof define === 'function' && define.amd) { // AMD define(['jquery'], factory); } else if (typeof exports === 'object') { // CommonJS module.exports = factory(require('jquery')); } else { // Browser globals factory(jQuery); } }
You can use webpack.ProvidePlugin for this: Remove require jquery from main.js: require('readmore'); require('foundation'); Configure webpack.ProvidePlugin inside webpack.config.js: var path = require('path'); module.exports = { entry: ["./js/main.js"], output: { path: path.resolve(__dirname, 'build'), filename: "scripts.js" }, resolve: { modulesDirectories: ["bower_components", "node_modules"], alias: { readmore: '../node_modules/readmore-js/readmore.js', foundation: '../bower_components/foundation-sites/dist/js/foundation.js' } }, plugins: [ new webpack.ProvidePlugin({ $: 'jquery', jQuery: 'jquery' }), ] }
Module name “lib/chai” has not been loaded yet for context: use require([])
it is working well with karma-jasmine.....but not working with karma-mocha...y?? module.exports = function(config){ config.set({ basePath : '../app', preprocessors: { '**/*.html':'ng-html2js' }, ngHtml2JsPreprocessor: { prependPrefix: '/' }, files : [ 'node_modules/jquery/**/*.js', 'lib/angular/angular.js', 'lib/angular/angular-*.js', '../test/lib/angular-mocks.js', '../test/lib/sinon-1.15.0.js', '../test/lib/chai.js', 'js/**/*.js', '../test/unit/**/*.js', '**/*.html' ], autoWatch : true, frameworks: ['mocha','requirejs','chai'], browsers : ['Chrome'], plugins : [ 'karma-chrome-launcher', 'karma-mocha', 'karma-ng-html2js-preprocessor', 'karma-requirejs', 'karma-chai' ], junitReporter : { outputFile: 'test_out/unit.xml', suite: 'unit' } }); }; MY SAMPLE CODE::: 'use strict'; describe('calendarHelper', function() { beforeEach(module('eventsApp')); it('should return January when given a zero', inject(function(calendarHelper) { expect(calendarHelper.getMonthName(0)).toBe('January'); })) });
I came across a similar situation just with Jasmine. I'd like to introduce my solution. Try it what is written in the error message. There is a link to a website: http://requirejs.org/docs/errors.html#notloaded Use this in your spec file: //If this code is not in a define call, //DO NOT use require('foo'), but use the async //callback version: require(['foo'], function (foo) { //foo is now loaded. }); My case written for Jasmine and Sinon in Coffeescript looks like this: sinon = require(['sinon', 'jasmine-sinon']) (foo)-> Now I can use sinon as an object in my unit test and can also follow the documentation of sinon, as well as jasmin-sinon.
how does phantomjs work with protractor?
I am getting my head around protractor and phantomjs. The test looks like this, it works fine with just chrome: describe('angularjs homepage', function () { beforeEach(function () { browser.driver.manage().window().setSize(1124, 850); }); it('should greet the named user', function () { browser.driver.get('https://angularjs.org/'); element(by.model('yourName')).sendKeys('Julie'); var greeting = element(by.binding('yourName')); expect(greeting.getText()).toEqual('Hello Julie!'); }); }); the protractor.config looks like this : // An example configuration file. exports.config = { // Capabilities to be passed to the webdriver instance. capabilities: { 'browserName': 'phantomjs', 'phantomjs.binary.path': 'C:/ptor_testing/node_modules/phantomjs/lib/phantom/phantomjs.exe' }, // For speed, let's just use the Chrome browser. //chromeOnly: true, // Spec patterns are relative to the current working directly when // protractor is called. specs: ['example.spec.js'], // Options to be passed to Jasmine-node. jasmineNodeOpts: { // onComplete will be called just before the driver quits. onComplete: null, // If true, display spec names. isVerbose: true, // If true, print colors to the terminal. showColors: true, // If true, include stack traces in failures. includeStackTrace: true, // Default time to wait in ms before a test fails. defaultTimeoutInterval: 30000 }, seleniumAddress: 'http://localhost:4444/wd/hub' }; When I run this i get: Error: Error while waiting for Protractor to sync with the page: {"message":"Can't find variable: angular","name":"ReferenceError","line":4,"stack":"ReferenceError: Can't find variable: angular\n at :4\n at anonymous (:13)\n at Na (phantomjs://webpage.evaluate():14)\n at phantomjs://webpage.evaluate():15\n at phantomjs://webpage.evaluate():15\n at phantomjs://webpage.evaluate():16\n at phantomjs://webpage.evaluate():16\n at phantomjs://webpage.evaluate():16","stackArray":[{"sourceURL":"","line":4},{"sourceURL":"","line":13,"function":"anonymous"},{"sourceURL":"phantomjs://webpage.evaluate()","line":14,"function":"Na"},{"sourceURL":"phantomjs://webpage.evaluate()","line":15},{"sourceURL":"phantomjs://webpage.evaluate()","line":15},{"sourceURL":"phantomjs://webpage.evaluate()","line":16},{"sourceURL":"phantomjs://webpage.evaluate()","line":16},{"sourceURL":"phantomjs://webpage.evaluate()","line":16}],"sourceId":81819056} How can I fix this?