I'm writing integrations tests for an Ember app using QUnit. Is there anyway to test if an element is visible?
My experience with integration testing comes from Capybara which detects only visible elements by default.
If you have HTML fixture as described in the guide you should be able to check the elements using jQuery:
test( "search, close", function() {
//SNIP
// Note the use of a real element here:
element = $( "#autocomplete" ).autocomplete({
source: data,
minLength: 0
}),
menu = element.autocomplete( "widget" );
//SNIP
ok( menu.is( ":visible" ), "menu is visible after search" );
//SNIP
});
Code source:
Test for visible in QUnit test of JQueryUI widget
Related
I'm using Jasmine for unit testing to test an application with Backbone.js (and it's the first time that I'm working with them both so I'm a little bit stuck :/ )
Here is my Backbone view
define(['jquery','backbone','underscore','handelbars','models/story','text!templates/story.html',
'controllers/storyController'],
function($, Backbone, _,handelbars, story,storyTemplate,ctrl){
var View = Backbone.View.extend({
el: '#main',
events:{
'click .close-story' : 'closeStory',
}
// Some functions
});
return View;
});
and the spec of Jasmine
define(['views/storyView'],function (storyView) {
describe("Testing the Story View ",function () {
var stView;
beforeEach(function(){
stView=new storyView({id:1});
stView.render();
})
it("Test if el is defined and trigger the click ",function () {
expect(stView.el).toBeDefined();
})
})
})
Thank you :)
You have hardcode el: '#main' in the view constructor.
This will evaluate when the AMD module is loaded.
And when you run jasmine unit tests, I don't think this element of your application is available in Jasmine test page, unless you have mocked it somehow. You can test this via putting a break point on the constructor and inspecting the DOM.
For the existing code to work, you should attach a dummy element on whatever DOM jasmine is using to run your tests before loading the module containing view definition.
On the other hand, It's better to remove the hardcoded el: '#main' (You can tell the developer that it's a very bad coding practice) and pass the element reference while creating view instance, so you can do
new storyView({id:1, el : $('<div/>'}); // dummy element for test
I'm trying to unit test React Bootstrap modal dialog using Jasmine. But it is not working as expected.
Here is jsfiddle link using latest versions of React, React Bootstrap, Jasmine.: http://jsfiddle.net/30qmcLyf/3/
Test which fails:
line# 27-28
// This test fails. Find DOM Node.
var instanceDomNode = ReactDOM.findDOMNode(instance);
expect(instanceDomNode).not.toBe(null);
line# 39-40
//This test fails. Find modal header.
var headerComponents = TestUtils.scryRenderedComponentsWithType(component, ReactBootstrap.Modal.Header);
expect(headerComponents.length).not.toBe(0);
Also what is wrong with line#35-36. If I uncomment lines I get error shown in comments.
// Error: Did not find exactly one match for componentType:function ModalHeader()...
//var headerComponent = TestUtils.findRenderedComponentWithType(component, ReactBootstrap.Modal.Header);
//expect(headerComponent).not.toBe(null);
As per latest official documentation for test utilities (link), you are supposed to pass ReactComponent as first argument.
Can somebody tell me what is wrong?
Check out how the react-bootstrap team writes tests for this. The modal is rendered into a different subtree which is how it gets rendered to the document body and not directly as a child of its parent. In other words your srcying fails because the component is not in that Component tree.
You can use refs on the modal or look for the DOM nodes directly in the document.
React-Bootstrap modal can be unit tested using mount of enzyme
it(componentToTest.title + 'renders Modal component', () => {
expect(wrapper.find(UVModal).length).toEqual(1);
});
it(componentToTest.title + 'renders major html elements', () => {
// Test whether modal-content element has 3 html children elements.
expect(wrapper.find('.modal-content').length).toEqual(1);
expect(wrapper.find('.modal-content').children()).toHaveLength(3);
// Test whether modal-header element has 2 html children elements.
expect(wrapper.find('.modal-header').length).toEqual(1);
expect(wrapper.find('.modal-header').children()).toHaveLength(2);
// Test whether modal-body element has 1 html child element.
expect(wrapper.find('.modal-body').length).toEqual(1);
expect(wrapper.find('.modal-body').children()).toHaveLength(1);
// Test whether modal-footer element has 1 html child element.
expect(wrapper.find('.modal-footer').length).toEqual(1);
expect(wrapper.find('.modal-footer').children()).toHaveLength(1);
elementToSearch = <p>Lannisters always pay their debt</p>;
expect(wrapper.contains(elementToSearch)).toEqual(false);
});
Check following blog for details:
https://medium.com/#yuvi1422/unit-test-react-bootstrap-modal-a37bf59732ab
In case you are using an older version of Enzyme, you can pass the container element to mount where you want your Modal to be rendered, like this:
Actual Code:
------------
import React from 'react'
import { Modal } from 'reactstrap'
export default MyModal = () => {
return (
<Modal isOpen={props.isOpen}>
<ModalHeader>Header</ModalHeader>
<ModalBody>Body</ModalBody>
</Modal>
);
}
Unit Test:
----------
import React from 'react'
import MyModal from './MyModal'
import { mount } from 'enzyme'
describe(() => {
let wrapper;
beforeEach(() => {
const container = document.createElement("div");
document.body.appendChild(container);
wrapper = mount( <MyModal isOpen={true}/> , {attachTo: container});
});
it('renders correctly', () => {
expect(wrapper).toMatchSnapshot();
expect(wrapper.find('ModalHeader')).toHaveLength(1);
expect(wrapper.find('ModalBody')).toHaveLength(1);
});
})
Scenario
I am in the process of writing a number of jasmine tests for a Durandal based app that I am in the process of writing. The Durandal documentation suggests that the way to write tests is like
ViewModel
define([
'knockout',
'plugins/router',
'services/unitofwork',
'services/logger',
'services/errorhandler',
'services/config'
],
function (ko, router, unitofwork, logger, errorhandler, config) {
var uow = unitofwork.create();
var searchTerm = ko.observable();
var results = ko.observableArray([]);
var search = function () {
uow.myySearch(searchTerm).then(function (data) {
results(data);
logger.log(data.length + ' records found', '', 'myViewModel', true);
});
};
var vm = {
search : search,
searchTerm : searchTerm,
results : results
};
});
Test
define(['viewmodels/myViewModel'], function (myViewModel) {
describe('Stuff im testing', function(){
it('returns true', function () {
expect(true).toBe(true);
});
});
});
and for most of my tests this works great.
Problem
How do I mock/stub/fake a module that has been passed into ViewModel. For instance the UnitOfWork module so that it always returns a standard set of data.
For unit testing check out https://github.com/iammerrick/Squire.js/ a dependency mocker for requirejs. Another technique using require context is described in How can I mock dependencies for unit testing in RequireJS?.
For integration testing you might look into something like http://saucelabs.com (selenium based).
For some grunt tasks that helps setting up unit tests in phantomjs|browser see https://github.com/RainerAtSpirit/HTMLStarterKitPro (Disclaimer: I'm the maintainer of the repo). I'd love to see some mockup integration, so send a pull request if you feel inclined.
Check this out
https://github.com/danyg/jasmine-durandal
this is a library that I'm working on, in a few days will have the ability to test widgets too.
In my JS view-code I am using a jQuery UI Dialog component to render a popup.
I instantiate it like this:
var popupDialog = $("#myPopupDiv").dialog({
title: "My dialog",
dialogClass: "myDialogClass",
create: createHandler,
draggable: false,
width: width,
height: height,
autoOpen: false
});
Notice it's got autoOpen set to "false". I open it in the "create"-handler:
var createHandler = function(event, ui) {
//Vi venter litt for å sikre at popupen er "klar"
setTimeout(function () {
popupDialog.dialog("open");
}, 5);
};
The open-logic is wrapped in a setTimeout to ensure the popup is ready.
The code works fine in app the browser, but when I run this code using Jasmine test-framework I get an error:
Error: cannot call methods on dialog prior to initialization; attempted to call method 'open'
The test actually passes, so clearly the item is rendered. But I don't like the error showing up when I run the tests!
I suspect that since the Jasmine tests run so fast, the component has not had time to initialize itself. So how can I assure that the component is initialized? I thought putting this logic in the "create"-handler would take care of that since that event is "Triggered when the dialog is created.", but clearly that is not the case.
Here is how I test it:
it("should show my popup", function () {
var myPopupLink = $('.popupLink');
myPopupLink.click();
//Wait until popup is shown
waitsFor(function () {
return !$('.myDialogClass').is(":hidden");
}, "Popupen didn't show", 1000);
//Check that the DOM is as expected
expect($('.myDialogClass .popupContentDiv')).toExist();
expect(...
//Close popup
myPopupLink.click();
expect($('.myDialogClass .popupContentDiv')).not.toExist();
});
Anybody have a clue how I can verify the initialization-status of the popup-dialog?
Or any other workarounds?
Thanks!
The problem with your test is, that it is more an acceptance test then a unit test. Most of stuff that you try to test is functionality of jQueryUi. What you really wanna test is that the createHandler opened the dialog with a delay. So your popupDialog.dialog should be a spy where you can check that it was called after the delay.
At the moment your code is really hard to test cause it is based directly on jquery. You should think about to have functions where you can inject your depenedencies instead of relying on global variables like popupDialog.
Here is an example on how to mock out all dependencies:
//mock out setTimeout so you dont have to wait in your test
jasmine.Clock.useMock();
//create a mock that will return from $().dialog()
var mockDialog = jasmine.createSpy('dialog');
// mock $ to return {dialog: mock that return {dialog: mockDialog}}
var mock$ = spyOn(window, '$').andReturn({
dialog:jasmine.createSpy('$').andReturn({
dialog: mockDialog
})
})
expect(mock$).toHaveBeenCalled();
// call the create function
window[mock$.mostRecentCall.args[0].create]();
jasmine.Clock.tick(4999);
expect(mockDialog$).not.toHaveBeenCalled();
jasmine.Clock.tick(5001);
expect(mockDialog$).toHaveBeenCalledWith('open');
As you can see its very complicated to mock out all the jQuery dependencies. So ether you rewrite your code for better testability or test this stuff as acceptance test with selenium capybara etc.
with angularJs 1.0.2 I created simple directive that binds to click event on element.
I tried to unittest it with testacular
var linked;
beforeEach(inject(function($rootScope, $compile) {
scope = $rootScope.$new();
var widget_definition = 'click here';
linked = $compile(widget_definition);
}));
it('chceck logic on click', function() {
var button = linked(scope);
// this doesnt work so I give up :/
button.triggerHandler('click');
});
but it tells me that there is no such function defined on button element. but this is already jQ(lite) object and in other tests I can use methods defined for jQlite.
is this a bug in angular??
triggerHandler was added in 1.0.3
Here's a JSFiddle that doesn't throw an exeception http://jsfiddle.net/jaimem/c5Tfw/1/
btw, if you are dealing with UI changes you might want to do e2e tests.