I have a problem I want to test this javascript
$("#ShootBtn").on('click', () => foo.testFunc());
var foo = {
testFunc: function() {
hub.server.shoot(true, username, gameCode);
}
}
I'm using Jasmine as my test framework, and I have tried Karma and Chutzpah as my test runner.
In my test project where I try to refer to the file above I try have tried a lot of different things, but I can't seem to get my head around it. The test looks like this atm.
/// <reference path="../../TankWebApplication/Scripts/jquery-3.3.1.js"/>
/// <reference path="../../TankWebApplication/Scripts/virtualjoystick.js"/>
/// <reference path="../../TankWebApplication/Scripts/gameController.js"/>
describe("DefaultTest",
function () {
beforeEach(function() {
})
it("Test",
function() {
spyOn(foo, 'testFunc');
document.getElementById('ShootBtn').click();
expect(foo.testFunc).toHaveBeenCalled();
});
});
The testFunc haven't been called says:
TypeError: Cannot read property 'click' of null
Which I think means that it cannot click on my shootBtn
Is it impossible to test this, or what do I do wrong?
What you can do is to spy on document.getElementById and make it return an object that has click function :
spyOn(document, "getElementById").andCallFake(() => ({
click: () => foo.testFunc()
}));
jsFiddle
Otherwise, create an element with id = ShootBtn, attach a click handler to it then add it to the body (all this should be done inside your test)
jsFiddle
Related
I have a strange situation (you can read about the context here. I'm not sure that the answer to this question will answer the question in the link, hence two questions.), where I'd like to modify an AngularJS service after the framework has already been loaded. Here's some code we'd like to do:
<script>
document.onload = function () {
angular.module('common')
.config(function ($provide) {
$provide.factory("$exceptionHandler", function () {
return function (exception) {
throw exception;
};
});
});
}
</script>
This works fine when it's not wrapped in a document.onload. But when it's put in an onload, it doesn't seem to have any effect. How can I modify a service in a document.onload?
For what it's worth, I'm on angular 1.2.
This worked when we tried it:
<script>
window.onload = function () {
angular.element(document.body).injector().invoke(function($log) {
$log.error = function(message) {
throw new Error(message)
};
});
}
</script>
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 am working on jasmine tests for a button on rails which changes html dir attribute. My click functionality is working fine but when I run my tests, I do see reference error. Any help or suggestions would be highly appreciated.
view.html.erb
<p><%= button_tag 'Convert', remote: 'true' %></p>
convert.js
$(document).ready(function(){
$('button').on('click', function (){
$('html').attr('dir', getElement);
});
function getElement() {
return this.getAttribute('dir') === 'rtl' ? 'ltr' : 'rtl';
}
});
Here is my jasmine test file.
conversion_spec.js
//= require jquery
describe('#rtl', function (){
describe("Testing spies", function () {
it("Should replace the return value of function being spied on", function () {
// Arrange
var myApp = new getElement();
spyOn(myApp, "getAttribute").and.returnValue('rtl');
// Act
var result = myApp.useFlagForSomething();
// Assert
expect(result).toBe("rtl");
});
});
});
Here is my error message:
Failures:
#rtl Testing spies Should replace the return value of function being spied on
ReferenceError: Can't find variable: getElement in http://localhost:45463/__spec__/conversion_spec.js (line 28)
ReferenceError: Can't find variable: getElement
at http://localhost:45463/__spec__/conversion_spec.js:28
at attemptSync (http://localhost:45463/__jasmine__/jasmine.js:1789)
at http://localhost:45463/__jasmine__/jasmine.js:1777
at http://localhost:45463/__jasmine__/jasmine.js:1762
at http://localhost:45463/__jasmine__/jasmine.js:627
at http://localhost:45463/__jasmine__/jasmine.js:357
1 spec, 1 failure
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 have two files - main, and events. I'm trying to call some function from one file to another.
So, this is how it looks:
events
require(['app/main'], function(call) {
// click event respond test
document.body.addEventListener("click", function(e) {
var target = e.target;
if (target.hasClass === "call"){
functionCall()();
}
});
});
main
define(["jquery"], function() {
// Call
var box = $('.box');
return function functionCall(){
box.addClass('visible');
}
});
What is wrong, can anyboyd help?
main:
define(["jquery"], function($) {
var main = {
functionCall: function(){
$('.box').addClass('visible');
}
}
return main;
});
events:
require(['jquery','app/main'], function($, main) {
$('body').on('click', function () {
if($(this).hasClass('call')){
main.functionCall();
}
});
});
One way is to add this code where you need to make call to function:
require('pathToModuleOrModuleName').functionYouWantToCall()
But if you have module defined or required in the beggining (as 'main' in the events), then in place where call to function needed just add:
call.functionName();
Unless my eyes deceive me the simplest change to make to your code would be to replace this:
functionCall()();
with this:
call();
since the function that the main module returns is imported as call in your events module, because that's how you name it in the callback passed to define.
Firstly your code has some basic problems
In the following code
define(["jquery"], function() {
Where are you referring the query inside the function definition.
I think you should first map the jquery defined into the function declaration like below
define(["jquery"], function($) {
Secondly, what is the () doing after the calling function?
if (target.hasClass === "call"){
functionCall()();
}
Remove the trailing () from that call. It should just be functionCall();