Hello I am testing my code in jquery with Karma jasmine and the following code works correctly:
it("Test click", function(){
var $element = $('a#buttonID');
var spy = spyOnEvent($element, 'click');
$element.click();
expect(spy).toHaveBeenTriggered();
});
But when I run the following code with a function inside click it doesn't work.
it("Test click", function(){
var $element = $('a#buttonID');
var spy = spyOnEvent($element, 'click');
$element.click(function(){
console.log("Execute some code here")
});
expect(spy).toHaveBeenTriggered();
});
Test click FAILED
Expected event click to have been triggered on [object Object]
The code inside the click function is not executed. I don't know if it is a timeout or is it asynchronous issue?
Related
The following is in foo.js
var analytics = {};
analytics.myLinks = function(){
return 2;
};
analytics.myView = function() {
analytics.myLinks();
};
$('#marquee').on('click', analytics.myView);
The following is my spec file foo.spec.js Fixture is appended using jasmine-fixture utility's affix helper. (https://github.com/searls/jasmine-fixture)
(function() {
describe('click event handlers', function() {
it('calls function when #marquee is clicked on', function() {
affix('#marquee');
spyOn(analytics, 'myView').and.callThrough();
$('#marquee').trigger('click');
expect(analytics.myView).toHaveBeenCalled();
});
it('calls inner function when #marquee is clicked on', function() {
affix('#marquee');
spyOn(analytics, 'myLinks').and.callThrough();
$('#marquee').trigger('click');
expect(analytics.myLinks).toHaveBeenCalled();
});
});
}).call(this);
I am using Karma as my test runner and it throws an error on the above unit test saying
"Expected spy myView to have been called."
and
"Expected spy myLinks to have been called."
I have tried different variations of the same but not sure where I am going wrong. Please help!
I've been writing tests for all my events (and everything else of course) but I'm at a loss on how to test that this.props.onClick(this) was called on a child component.
My child component has the following code:
closeModal: function() {
this.props.onClick(this);
},
render: function() {
return (
<i className="close-icon" onClick={this.closeModal}></i>
)
}
and the parent is listening to it like so:
onCloseModal: function() {
this.replaceState({
modalStatus: 'hidden'
});
},
render: function() {
return (
<QuestionModal modalStatus={this.state.modalStatus} onClick={this.onCloseModal} />
)
}
I know how to test the parent's click event and I know how to call the child's button click event in the tests as well but I'm not sure what I should be exactly testing.
If I used Sinon and Jasmine, I would stub the closeModal method and check that it was called. Can I do that with Jest and if so how exactly?
UPDATE
I've tried writing a test based on #PhilVarg's answer but I'm not getting very far as I'm not able to mock closeModal.
Here's my test:
var closeIcon,
myMock = jest.genMockFunction();
form = TestUtils.renderIntoDocument(
<QuestionForm />
);
form.closeModal = myMock;
closeIcon = TestUtils.findRenderedDOMComponentWithClass(form, 'close-icon');
TestUtils.Simulate.click(closeIcon);
expect(form.closeModal).toBeCalled();
The test errors with Expected Function to be called. and closeModal is not mocked but still runs (I have a console log in it at the moment). I've been on it all afternoon but haven't been able to figure it out. Any help would be very appreciated.
Thanks to some of the suggestions from Phil, I finally figured it out. What I want to test is that closeModal is called when I click the icon. I have already tested that the parent component behaves as expected but I couldn't work out how to mock closeModal because I'm testing this specific component and by default, this is the only one Jest doesn't mock for me. I could stub it manually but that somehow didn't want to work.
What I've done now is mock this.props.onClick within closeModal and I check that it fires.
Here's how that looks in code:
describe('QuestionForm', function() {
var onClickFunc,
form;
beforeEach(function() {
onClickFunc = jest.genMockFunction();
form = TestUtils.renderIntoDocument(
<QuestionForm onClick={onClickFunc} />
);
});
it('should call closeModal when the icon is clicked', function() {
var closeIcon = TestUtils.findRenderedDOMComponentWithClass(form, 'close-icon');
TestUtils.Simulate.click(closeIcon);
expect(onClickFunc).toBeCalled();
});
});
I think that sufficiently tests that closeModal behaves as expected.
If you want to check that the function is called you'd want to use jest's toBeCalled function (or toBeCalledWith). Assuming you've done some set up to instantiate the components, renderIntoDocument, and simulate the click (checkout the tutorial if not)
describe('#closeModal', function(){
beforeEach(function(){
// setup in here to instantiate / render component
// and simulate the click if the i tag
})
it('is called on click', function(){
expect(questionModal.closeModal).toBeCalled()
})
})
EDIT:
Ok, so after tinkering with it, I was able to get a passing test doing something similar to your original structure. I created a mock function, but instead of doing form.closeModal = mock, I passed the mock into the Question as the onClick prop, and checked if it got called.
describe('#closeModal', function(){
var mock, form, closeIcon;
beforeEach(function(){
mock = jest.genMockFunction();
form = TestUtils.renderIntoDocument(
<QuestionForm onClick={ mock } />
);
closeIcon = TestUtils.findRenderedDOMComponentWithClass(form, 'close-icon');
TestUtils.Simulate.click(closeIcon);
})
it('is called on click', function(){
expect(mock).toBeCalled()
})
})
You could use an asynchronous test. You have to call done() in your onClick handler. If everything is fine the handler will call done() and the test passes. If the handler won't be called the test fails after some time because Jasmine cannot end it.
No need for stubbing or mocking.
it('should click', function(done) {
function onClick() {
done();
}
var instance = TestUtils.renderIntoDocument(
<Component onClick={onClick} />
);
var button = TestUtils.findRenderedDOMComponentWithTag(instance, 'button');
var buttonDOM = React.findDOMNode(button);
React.addons.TestUtils.Simulate.click(buttonDOM);
});
I am trying to bind an liszt:ready event of my list, to be invoked once that the list has been initialized by chosen.
I follow the steps that here are describing without any success.
This is my code:
var initPreferredCollaboratorChosen = function () {
$("#preferredCollaboratorChosenId").chosen({width: "95%"}).trigger("chosen:ready");
};
var initListener = function () {
$("preferredCollaboratorChosenId").on("chosen:ready", function(){
alert("Hey, I am ready!");
});
initPreferredCollaboratorChosen()
};
I try with "liszt:ready" instead "chosen:ready" as well.
Can anyone that has work with this plugin tell me how make it?.
Regards.
I have a function below that is bound to a button click. Code below part of TeaserView class.
addCard: function() {
if(!this.model.get("loggedIn")){
Backbone.pubSub.trigger("Signup");
return;
}
this.showAddCardDialog();
}
This is my test method
it("Should trigger signup event when clicked and not logged in", function(){
Backbone.pubSub = _.extend({}, Backbone.Events);
signupCallback = jasmine.createSpy("Signup");
//Backbone.pubSub.on("Signup", signupCallback);
teaserView = new TeaserView({
el: "#teaser",
model: this.model //was created in setup call
});
$("#addCard").trigger("click");
expect(signupCallback).toHaveBeenCalled();
});
But my test to check if the Backbone.pubSub custom event was called fails. How do I test the listening for this event correctly?
Your given test code isn't actually listening to the signup event.
signupCallback = jasmine.createSpy("Signup");
Isn't what you want.
signupCallback = jasmine.createSpy();
Backbone.pubSub.on('Signup', signupCallback);
Should get you what you want.
In this new code, the signupCallback is being assigned as an event callback, so triggering the event should call the spy callback.
I have the following jQuery:
// change the number of finished and missing assets
$('.add-requirements .overall-status .status-dropdown li').live('click', function() {
var remaining_titles = $('.item-section.finished').length;
$('.add-requirements .remaining-titles').text(remaining_titles);
});
It fires whenever a status dropdown is changed. How would I also make it fire when the page loads?
From what I can understand you want to update the remaining count on page load and I assume that the finished status is pre setted on the desired elements.
I'll go about this in another way
$('.add-requirements .overall-status .status-dropdown li').live('click', updateRemaining);
updateRemaining()
function updateRemaining(){
var remaining_titles = $('.item-section.finished').length;
$('.add-requirements .remaining-titles').text(remaining_titles);
}
Just chain on a trigger('click') to trigger a click on first pageload :
$('.add-requirements .overall-status .status-dropdown li').live('click', function() {
var remaining_titles = $('.item-section.finished').length;
$('.add-requirements .remaining-titles').text(remaining_titles);
}).trigger('click');
But you should really be using on()
$('closest_non_dynamic_parent').on('click', 'your_freakishly_long_selector', function() {
A bit more verbose, but here is what worked for me:
var remaining_titles_section = $('.add-requirements .remaining-titles');
remaining_titles_section.text($('.item-section.finished').length);
$('.add-requirements .overall-status .status-dropdown li').live('click', function() {
var remaining_titles = $('.item-section.finished').length;
remaining_titles_section.text(remaining_titles);
});