Jasmine .toHaveBeenCalledTimes throws 'undefined is not a constructor' error - jasmine

I have the following unit test:
describe('shouldDeleteLogos', () => {
beforeEach(() => {
productService.product.project.parts['Logo'] = {
name: 'Logo'
};
productService.product.project.parts['Accent'] = {
name: 'Accent'
};
});
it(`should only call deleteLogos once if the part was provided to the method`, () => {
let part: Part = new Part();
part.name = 'Logo';
spyOn(creationSpacePSTLInstance, 'deleteLogos');
creationSpacePSTLInstance.shouldDeleteLogos(part);
expect(creationSpacePSTLInstance.deleteLogos).toHaveBeenCalledTimes(1);
});
});
However when I run the tests I get the following error: TypeError: undefined is not a constructor (evaluating 'expect(creationSpacePSTLInstance.deleteLogos).toHaveBeenCalledTimes(1)')
What is wrong here? I've spied on the method and I want to test that it was only called one time. Based on the documentation this should be working. It does work with just .toHaveBeenCalled();, just not with the times argument.
Here is the versions of Jasmine and Karma that I'm using.
"jasmine-core": "2.3.4"
"karma": "0.13.22",

toHaveBeenCalledTimes() was introduced in Jasmine 2.4. If you upgrade, that should fix it.

Related

Function implementation showing type error in Cypress while running tests

I am working on cypress for web application automation and having an issue with accessing a function from an object.
The code below is from a javascript file in 'e2e' folder.
class productsDemo {
pageObjects = {
productName: () => cy.get('.product-name-input'),
productDescription: () => {
cy.get('.product-description-input');
},
productCode: () => cy.get('.product-code-input')
}
inputProdName(prodname) {
this.pageObjects.productName().type(prodName);
}
inputProdDesc(proddesc) {
this.pageObjects.productDescription().type(proddesc);
}
}
module.exports = new productsDemo();
The code below is from a cypress test file to import and use the class.
import productsDemo from '../pageClasses/products.js'
describe('Product Creation', () => {
it('Create new Product', () => {
cy.visit('http://localhost:3000/products');
productsDemo.inputProdName('Laptop');
productsDemo.inputProdDesc('Electronics');
productsDemo.pageObjects.productCode().should('have.text', 'XXX124');
}
})
While running this file, getting this error in test runner.
Cannot read properties of undefined (reading 'type')
And, this type error is showing in the javascript file for 'inputProdDesc' function.
If the function declaration in 'pageObjects' object from the javascript file is modified as follows, then it works without problems:
productDescription: () => cy.get('.product-description-input'),
Could anyone help me to understand what is the issue with this code in setting value for 'product description' and how and to resolve this?
productDescription: () => {
cy.get('.product-description-input');
},
You have simply missed out the return statement from your page object class method call.
This is how it should look
productDescription: () => {
return cy.get('.product-description-input');
},
Without that return statements the code thinks you are returning undefined and that is the error message it is giving you:
Cannot read properties of undefined

How will write jasmine to cover my function? I am getting error "config method in not exist"

Getting error to my function which I am trying to cover in Jasmine
"Error is config method does not exist" And config the method which I am trying to cover.
I am expecting to cover the right test case scenario to my config method.
const config = () => {
return ({
name: 'modal.name',
class: 'modal.class',
choice: 'modal.choice'
});
}
describe('Config', () => {
it('config is defined', () => {
let data = {
name: 'modal.name',
class: 'modal.class',
choice: 'modal.choice'
};
Object.assign(config, data);
spyOn(data, 'config').and.returnValue(Promise.resolve(data));
});
});
You are getting that error because you are trying to spy the config method in your data object with the statement:
spyOn(data, 'config').and.returnValue(Promise.resolve(data));
The data object has no config method so, when you call spyOn it throws that error.
Your it says that you are trying to test that config is defined, but you are doing really strange things in your test. If you want to check that config is defined you could do:
it('config is defined', () => {
expect(config).toBeDefined();
});
A more elaborated test would be to test that the method, besides existing, returns the data you want:
it('config returns the configuration', () => {
expect(config()).toEqual({
name: 'modal.name',
class: 'modal.class',
choice: 'modal.choice'
});
});

Jasmine mock window.location.reload(true);

I have a constructor of a js object that looks like this:
function SomeThing(window, document) {
var self = this;
self.window = window;
self.document = document;
if (!self.window.sessionStorage.getItem('page-reloaded')) {
self.window.sessionStorage.setItem('page-reloaded', true);
self.window.location.reload(true); // PROBLEM ON THIS LINE
return;
}
}
my mock test looks like this:
beforeEach(function() {
mockWindowObj = {
'location': {
'href': '',
'search': '?hello=world',
'pathname': '/some/path',
'replace': function () {},
'reload': jasmine.createSpy()
}
};
spyOn(mockWindowObj.location, 'reload').and.callFake(function(){}); ;
some = new SomeThing(mockWindowObj, mockDocumentObj);
});
When I run a test I get this error:
PhantomJS 2.1.1 (Mac OS X 0.0.0) ERROR
{
"message": "Some of your tests did a full page reload!",
"str": "Some of your tests did a full page reload!"
}
If I comment out the line window.location.reload(true) all of my test run fine and pass. I'm sort of new to unit tests and I'm not sure how to get around this. Any help would be very much appreciated. Thanks in advance.
Your posted code cannot be what you actually ran. The line containing self.window.sessionStorage.getItem would have to fail since you did not define sessionStorage on your mock.
I guess the SomeThing function is being called with window pointing to the real window object. That explains what you observe.

Expected and Actual Values in Failed Protractor Test Cases

I have recently installed the jasmine-spec-reporter package in order to produce more verbose and helpful logging during execution of test suites.
I want to be able to log expected and actual values for failed test cases and was wondering if I needed to explicitly have a statement in the form of expect(someCondition).toEqual(true); in order for me to see these values.
For example, I have a function like the following:
it('should log in', function(done) {
var customerNameElement;
customerNameElement = element.all(by.xpath('some_xpath')).first();
core.infoMessage(browser, JSON.stringify(params, undefined, 4));
login.login(browser, undefined, undefined, getWaitTime())
.then(function() {
return browser.wait(protractor.ExpectedConditions.and(
function() { return core.isUnobscured(browser, customerNameElement);
}, protractor.ExpectedConditions.elementToBeClickable(customerNameElement)), getWaitTime());
})
.catch(fail)
.then(done);
});
I can still log the failure to the console but not in the form that I'd like. Does jasmine-spec-reporter handle this or do I have to add the statement from above in each test case?
Also, does the fail keyword in the .catch() have any properties I can use to my advantage? It comes from:
// Type definitions for Jasmine 2.5.2 // Project: http://jasmine.github.io/
Thanks
you can try adding the below in protractor_config file:
let SpecReporter = require('jasmine-spec-reporter').SpecReporter;
exports.config = {
// your config here ...
onPrepare: function () {
jasmine.getEnv().addReporter(new SpecReporter({
spec: {
displayStacktrace: true
}
}));
}
}
Also, add the print function in the jasmineNodeOptssection
jasmineNodeOpts: {
...
print: function() {}
}

Jasmine2: get current spec name

In Jasmine 1.3, we had this option to the get current spec and suite names:
describe("name for describe", function () {
it("name for it", function () {
console.log(this.suite.getFullName()); // would print "name for describe"
console.log(this.description); // would print "name for it"
});
});
This does not longer work in Jasmine 2.x.
Anyone knows how to fetch those?
Thanks.
I add a new jasmine reporter, then get the spec name without define N variable on each spec. Hope can help, thanks.
var reporterCurrentSpec = {
specStarted: function(result) {
this.name = result.fullName;
}
};
jasmine.getEnv().addReporter(reporterCurrentSpec);
The reason this no longer works is because this is not the test. You can introduce a subtle change to your declarations however that fix it. Instead of just doing:
it("name for it", function() {});
Define the it as a variable:
var spec = it("name for it", function() {
console.log(spec.description); // prints "name for it"
});
This requires no plug-ins and works with standard Jasmine.
As far as Jasmine 2 is concerned currentSpec is discontinued on purpose. However there is a custom plugin/library developed that is based on jasmine reporter plugin which you can use. Here's the Link. Hope it helps with your requirement.
Its very simple to use, install the package with npm command -
npm install -g jasmine-test-container-support
Get the test container support by writing below lines before your describe or test suite -
var JasmineTestContainerSupport = window.JasmineTestContainerSupport || require('jasmine-test-container-support');
JasmineTestContainerSupport.extend(jasmine);
Later use the test container in your spec's to get its description -
var specDesc = jasmine.getEnv().getTestContainer();
Hope this helps.
var currentSpecName = describe('Test1', function() {
var currentStepName = it("Step1", function(){
console.log(currentStepName.description); // Prints It Name
console.log(currentSpecName.getFullName()); //Prints Describe Name
});
});
This worked for me in jasmine 3.5+
I know this is a relatively old question but found something which worked for me
describe('Desc1',() => {
afterEach(() => {
const myReporter = {
specDone: (result) => {
console.log('Spec FullName: ' + result.fullName);
console.log('Spec Result: ' + result.status);
}
};
jasmine.getEnv().addReporter(myReporter);
});
})
Credit for the solution : https://groups.google.com/g/jasmine-js/c/qqOk6Nh7m4c/m/Nyovy2EjAgAJ
This is probably a bit late but you can get the suite name outside the spec.
Please try the following code:
describe("name for describe", function () {
console.log(this.getFullName()); // would print "name for describe"
it("name for it", function () {
//Your test spec
});
});

Resources