I'm in the process of switching from Karma to Chutzpah and got all my tests executing fine, except when it comes to interpret jasmine's fixturepath, in Chutzpah, I'm getting "Fixture could not be loaded". It seems as if Chutzpah is unaware of what to do with the "base" portion of the url
it('Get all filtered', function () {
jasmine.getFixtures().fixturesPath = "base/site/js/apps/mock-json-data/";
var response = readFixtures("all.json");
makes = JSON.parse(response);
expect(makes).toBeDefined();
});
Is there a configuration in Chutzpah that could tell it to interpret "base"? We could replace it, but don't want to force all developers to move from Karma to Chutzpah, which will just be used for CI
Not the prettiest solution, but we ended up overriding the readFixtures function to replace the "base" in the url pattern expected by Karma as follows:
var rf = readFixtures;
var readFixtures = function (path) {
jasmine.getFixtures().fixturesPath =
jasmine.getFixtures().fixturesPath.replace(
'base/site/js/apps', '../'
); // makes the path relative for Chutzpah
return rf(path);
};
Related
I need to pass the Randomly generated string data in all my Test Cases but it is only working when i put this below code in all it() block
but i need to set this code somewhere i can access these values in all my it() block or in all my TestCases
FYI-beforeAll() and beforeEach() also not able to do this
so how can i make these thing global form where in can read in all my TestCases??
`const Rs = new RandomString();
var UserEmaill = Rs.getRandomUserEmail();
cy.log(UserEmaill);
var UserData = Rs.getRandomUser();
cy.log(UserData)`
You can do in multiple ways. If you want to generate random strings in your tests, you can use faker npm module and you can do it easily... So you can do this in as many as tests possible....
npm install faker
let faker = require('faker');
cy.log(faker.internet.email());
But as you are saying that you want to use globally across multiple tests, So I suggest you to do below stuff in before hooks of support/index.js. and call those variable wherever you want.
Do as below in index.js and it will be done at before your tests execution..
let faker = require('faker');
before(() => {
global.EMAIL1 = getRandomEmail();
global.EMAIL2 = getRandomEmail();
global.EMAIL3 = getRandomEmail();
global.EMAIL4 = getRandomEmail();
function getRandomEmail() {
return faker.internet.email();
}
})
In your test you can access as below
cy.log(global.EMAIL1);
It will work like charm, please use it and like the answer to reach to more people...
Then it is super easy, all you have to do is generate the random email per test case. So that it would not be impacted by any other test and it will not impact others too. I still suggest you to use test data per test so that other test do not get effected... I think below snippet is enough for you.
let faker = require('faker');
describe('test suite', () => {
it('test1', () => {
var email1 = faker.internet.email().split('#')[0]+'#mailinator.com';
cy.log(`test1 email is ${email1}`);
});
it('test2', () => {
var email2 = faker.internet.email().split('#')[0]+'#mailinator.com';
cy.log(`test2 email is ${email2}`);
})
})
I have a problem with Karate afterFeature configuration.
I want to call a clean up step from a separate feature file after every scenario. Hence, I configured a afterFeature js function, that should call that cleanup feature using karates call function.
The callonce works fine in prior step, but I have problem with the afterFeature.
This is the code how I configure afterFeature:
* def result = callonce read('../callOnceCreateCompanyForBrowse.feature')
* def id = result.response.data.createCompanyEvent.id
* configure afterFeature = function(){ karate.call('../../deleteCompanyEvent.feature', {id : id}); }
Suggestion, instead of relative paths (which is hard to get right) use the classpath: prefix.
* configure afterFeature = function(){ karate.call('classpath:com/myco/deleteCompanyEvent.feature', { id: id }) }
EDIT: looks like the solution was using a runner instead of running the feature directly.
I'am using chakram + mocha.
How can I use shared variables for all test?
For example, I would like to use variable API_PATH="http://example.com/v1/" in tests. And this variable could be changed during running test. So, my test looks like this.
var response = chakram.get(API_PATH + "products");
expect(response).to.have.status(200);
As example, protractor has conf.js with parameter baseUrl. Running test looks like protractor conf.js --baseUrl http://example.com/
what have you tried so far? Have you tried using beforeEach to reinitialize the object that you are using? You could just make the the shared variables declared outside of your tests.
EDIT: Adding details from what Jerry said:
If you want all variable to be reused within the same test, you must make them global variables. See example below
///include dependencies
var assert = require('assert'),
chai = require('chai'),
expect = chai.expect,
chakram = require('chakram');
//INIT GLOBAL VARAIBLES FOR within the same test
var testObj,
dummyData = {
user: 'John Kim',
lastSeenOnline: 'Wed August 11 12:05 2017'
};
describe ('#User', function () {
beforeEach(function () {
//init what the object contains
testObj = new DataStore(data, ContainerStore);
});
it ('#Should return the name of the user', function () {
assert.equal(testObj.get('user'), dummyData.user);
});
it("should offer simple HTTP request capabilities", function () {
return chakram.get("http://httpbin.org/get");
});
});
Note: I work with react but this is an example. We assume that the ContainerStore contains a method that has a method for get() which just gets the value of our JSON object. You can use testObj many time in different describe blocks since it is declared outside of your tests. But you should remember to always reinitialize your tesObj in a beforeEach(); otherwise, you risk populating your individual tests. There are cases were you do not have to initialize the beforeEach() and it is optional.
For Example in config.js
module.exports = {
"baseUrl": "http://example.com/",
"googleUrl": "http://www.google.com.tr/"
};
And use in javascript code:
let config = require('/config');
describle("test describle", () => {
it("test", () => {
chakram.get(config.baseUrl + "products"); //for example use
})
})
While writing tests I got bug TypeError: $.extend is not a function on toastr plugin that we are using. It seems that jQuery is not picked up properly, even tho is working normally in browser.
In our main mock file we imported jQuery and bind it to global windows object and it's accessible across whole application (but toastr plugin), even while testing in mocha:
import jsdom from 'jsdom';
import $ from 'jquery';
import chai from 'chai';
import chaiImmutable from 'chai-immutable';
import React from 'react';
const doc = jsdom.jsdom('<!doctype html><html><body></body></html>');
const win = doc.defaultView;
global.document = doc;
global.window = win;
global.expect = chai.expect;
global.$ = $(win);
global.jquery = $(win);
global.jQuery = $(win);
Object.keys(window).forEach((key) => {
if (!(key in global)) {
global[key] = window[key];
}
});
chai.use(chaiImmutable);
So while taking closer look at toastr I noticed this:
; (function (define) {
define(['jquery'], function ($) {
// this function is called on inizialization
function getOptions() {
return $.extend({}, getDefaults(), toastr.options);
}
It takes jquery from node_modules directly and then defines object $ in function scope, that means that it's ignoring window.$ (which is working normally even in here).
Therefore logging $ will return function, and logging $.anyMethodFromjQuery ($.extend) will return undefined.
In the end I tried logging $.prototype, in the browser it will return me jQuery object while in mocha it returns empty object {}
So in the end it define didn't created prototype in mocha environment and I cannot add one line of code $ = window.$; in plugin, since no one should edit a plugin + we are using npm.
Is there any solution for this?
You're running into trouble because you are loading code that should be loaded by JSDom outside of it. While it is possible in some cases to load code in Node and then pass it to the window that JSDom creates, that's a brittle approach, as you've discovered. Whenever I use JSDom for things other than write-and-toss cases, I load every script that would normally be loaded by a browser through JSDom. This avoids running into the issue you ran into. Here's a proof-of-concept based on the code you've shown in the question. You'll see that toastr.getContainer() runs fine, because Toastr has been loaded by JSDom. If you try to use the same code with an import toastr from "toastr" you'll get the same problem you ran into.
import jsdom from 'jsdom';
import $ from 'jquery';
import path from "path";
const doc = jsdom.jsdom('<!doctype html><html><body></body></html>', {
features: {
FetchExternalResources: ["script"],
ProcessExternalResources: ["script"]
}
});
const win = doc.defaultView;
global.document = doc;
global.window = win;
global.$ = $(win);
global.jquery = $(win);
global.jQuery = $(win);
window.addEventListener("error", function () {
console.log("ERROR");
});
const script = document.createElement("script");
script.src = path.join(__dirname, "./node_modules/toastr/toastr.js");
document.head.appendChild(script);
// The load will necessarily be asynchronous, so we have to wait for it.
script.addEventListener("load", function () {
console.log("LOADED");
console.log(window.toastr);
// We do this here so that `toastr` is also picked up.
Object.keys(window).forEach((key) => {
if (!(key in global)) {
global[key] = window[key];
}
});
toastr.getContainer();
});
Note that the code hung when I tried calling toastr.info(...). I took a look at the code of Toastr but it is not clear to me what causes the problem. There are features of browsers that JSDom is unable to emulate. It is possible that Toastr is dependent on such features. In the past, I've sometimes had to switch test suites away from JSDom due to its limitations.
I am attempting to test an AngularJS controller with a Jasmine unit test spec file. My approach is to use $httpBacked, in the following test:
describe('SubmissionsController', function() {
var minimal_mock_response = [ { id: 1 } ];
var scope, routeParams, $httpBackend;
beforeEach(module('submissionServices'));
beforeEach(inject(function($_httpBackend_, $rootScope) {
scope = $rootScope.$new();
$httpBackend = $_httpBackend_;
$httpBackend.expectGET('/submissions').respond(minimal_mock_response);
routeParams = {};
}));
it('passes a trivial test', function() {
expect(true).toBe(true);
});
});
I inserted the expect(true).toBe(true) just to get the test to execute and fail, even though it does not touch the angular controller. When I I attempt to run the test with jasmine-headless-webkit, I receive the following error:
jasmine-headless-webkit spec/javascripts/SubmissionsControllerSpec.js
Running Jasmine specs...
F
FAIL: 1 test, 1 failure, 0.011 secs.
Submissions controllers SubmissionsController passes a trivial test. (XXX/spec/javascripts/SubmissionsControllerSpec.js:18)
Error: Unknown provider: $_httpBackend_Provider <- $_httpBackend_
Test ordering seed: --seed 9254
Are there any hints on how I can correct this error and make the trivial test execute?
Enclosing service names with underscores has some benefit.
From your code, I can see that you probably wanted to save the reference to $httpBackend. This is how you wanted to do. The placement of underscore was one off.
beforeEach(inject(function(_$httpBackend_, $rootScope) {
scope = $rootScope.$new();
$httpBackend = _$httpBackend_;
...
Angular is smart enough to remove underscores and returns $httpBackend back to you, and you can save it to your own $httpBackend.
I believe this is because you're injecting the wrong service. It doesn't know what $_httpBackend_ is. You should be able to just do this:
beforeEach(inject(function($httpBackend, $rootScope) {
scope = $rootScope.$new();
$httpBackend.expectGET('/submissions').respond(minimal_mock_response);
routeParams = {};
}));
If you want to get a reference to the $httpBackend service once and store that as $httpBackend, ghiden's answer is the way to go.