testing for click event with jasmine? - javascript

I am required to write a Jasmine.js test to test a menu icon for what will happen when it is clicked, (the menu bar slides in when it is clicked for the first time, and out when it is clicked for the second time which it does, but my test fails to demonstrate it)
I came up with this idea but the spec-runner shows (expected false to be true). any help on what could be the problem?
describe('The menu', function () {
/* TODO: Write a test that ensures the menu changes
* visibility when the menu icon is clicked. This test
* should have two expectations: does the menu display when
* clicked and does it hide when clicked again.
*/
it('the menu changes visibility when the menu icon is clicked', function () {
var menuIconClicked, menuChangesWhenClicked = false,
menuChangesWhenClickedAgain = false;
$(".menu-icon-link").click(function(){
var $this = $(this);
$(this).data('clicked', true);
if($(this).data('clicked')) {
menuIconClicked=true // if menu icon is clicked, set the menuIconClicked value to true
if (menuIconClicked && $('body').hasClass(null)) {
menuChangesWhenClicked=true;
}
}
if($this.data('clicked') && menuIconClicked===true) {
menuIconClicked=false // if menu icon is clicked when it already has been clicked aka menuIconClicked===true
if (!menuIconClicked && $('body').hasClass('menu-hidden')) {
menuChangesWhenClickedAgain=true;
}
}
});
expect(menuChangesWhenClicked).toBe(true);
expect(menuChangesWhenClickedAgain).toBe(true);
});
});

It looks like you are already using Jasmine and JQuery, so I would suggest using also the jasmine-jquery.js library to help you with tracking states?
This was a good reference: Testing That A DOM Event Was Fired
To get the code below to work, just include jasmine-jquery.js in your project folder, link the <\script> via your index.html's <\head> and your set. Hope this helps.
describe('The menu', function() {
// Add a spyOnEvent
let spyEvent, menu;
beforeEach(function() {
// I assumed your menu icon has a unique ID of 'menuIconID'
// so I passed onto a spy listener.
spyEvent = spyOnEvent('#menuIconID', 'click');
});
it('the menu changes visibility when the menu icon is clicked', function() {
// Click once
$("#menuIconID").trigger("click");
expect('click').toHaveBeenTriggeredOn('#menuIconID');
expect(spyEvent).toHaveBeenTriggered();
menu = $('body').attr('class'); // assign the new class
expect(menu).toBe('');
// Click again
$("#menuIconID").trigger("click");
expect('click').toHaveBeenTriggeredOn('#menuIconID');
expect(spyEvent).toHaveBeenTriggered();
menu = $('body').attr('class'); // update the new class
expect(menu).toBe('menu-hidden');
});
});

Related

element not clickable for chrome driver protractor angular 2

I am trying to click the second level menu options which will expand to third level. some of the menu options not getting clicked. I added browser.driver.manage().window().setSize(1280, 1024 ) in before all section.
below is my code:
it('Should expect clicking the second level menu option will expand the third level', () => {
element.all((by.css('div.panel.panel-default'))).click().then(() => {
var groupList = element.all((by.css('.list-group-header.sub-menu-header.active-element')));
// expect(groupList.get(1).getAttribute('class')).toMatch('active-element');
expect(groupList.count()).toEqual(1);
});
});
When we are dealing with multi-level menus, it's good to use protractor.ExpectedConditions for checking element's visibility and clickable status.
And in your case, use 'each()' method of protractor for clicking each element.Hope below code will help you.
Code Snippet:
var EC = protractor.ExpectedConditions;
var timeout=5000;
it('Should expect clicking the second level menu option will expand the
third level', () => {
element.all((by.css('div.panel.panel-default'))).each(function(ele,index)
{
//check whether each element becomes visibile or not
browser.wait(EC.visibilityOf(ele), timeout).thenCatch(function () {
assert.fail('element is not visibile');
});
//check whether each element is clickable or not
browser.wait(EC.elementToBeClickable(ele), timeout).thenCatch(function
() {
assert.fail('element is not click able');
});
//then click each element
ele.click().then(function(){
var groupList = element.all((by.css('.list-group-header.sub-menu-
header.active-element')));
// expect(groupList.get(1).getAttribute('class')).toMatch('active-
element');
expect(groupList.count()).toEqual(1);
});
});
});

Jquery tab. Check if any of them is open

I have some tabs. All are collapsed by default. If the user click on a button first tab opens. I figured out that part:
jQuery(document).ready(function() {
jQuery('#showFirstTab').on('click', function() {
var tabObj = jQuery('#podcast-tabs li:first a');
tabObj.tab('show');
var programId = tabObj.data('programid');
jQuery('#calendar-' + programId).fullCalendar('render');
});
});
Now I need to check if any tab is open, and click again on the same button, all tabs should collapse. I was thinking in use a variable to save the state, but not sure if library provides already a solution for this.
You can first check if any tab is open, by using the tabsactivate event:
var isActive = false;
$(".podcast-tabs").on("tabsactivate", function( event, ui ) {
isActive = true;
});
Now, inside your click code check for that variable and if true close all tabs using option like:
if (isActive)
$("#podcast-tabs").tabs("option", "active", false);

Javascript function interacts with other function

I am completely new to javascript (and jquery) and have been experimenting with drop down menus the past couple of days. I found this one fancy notification menu, and I tried to see what happens when I have two of them on the page. Anyways, I made a quick example of my problem here:
http://jsfiddle.net/rgt03mu4/24/
The problem is that I can have both notification containers open up if I click on both.
If I am already clicked on one of the bells, then I click on the other, it should close the other one. Instead it keeps it open, and even when you click on the other container one, it still doesn't close it. You have to click off the page or click the notification bells. I am trying to make it to where you can only have one open at a time. So in order to do this, I tried changing the names of the functions:
As you can see:
$(function() {
var nContainer = $(".notification-popup-container");
//notification popup
$("#notification-link").click(function() {
nContainer.fadeToggle(300);
return false;
});
//page click to hide the popup
$(document).click(function() {
nContainer.hide();
});
//popup notification bubble on click
nContainer.click(function() {
return false;
});
});
I added the next function to be called test(), which you would think, since it's an entirely new function it would work differently. Instead, the error still persists.
What am I doing wrong? I even gave the the new bell it's own divs and link name. I also renamed container to container2.
Set the global variable for your container:
var nContainer = $(".notification-popup-container");
var nContainer2 = $(".notification2-popup-container");
$(function() {
var nContainer = $(".notification-popup-container");
//notification popup
$("#notification-link").click(function() {
nContainer.fadeToggle(300);
nContainer2.hide(); //hide the second container
return false;
});
//page click to hide the popup
$(document).click(function() {
nContainer.hide();
});
//popup notification bubble on click
nContainer.click(function() {
return false;
});
});
And you can do same with other function.
DEMO
There is no need to give the popup containers different classnames.
I would give the a-tags a common classname instead of an id. The href can be used to identify the target popup, so the binding between the link and the target popup is set in the origin of action. The JS part would be abstracted and could be reused.
<a class='notification-link' href='#firstpopup'>X</a>
<a class='notification-link' href='#secondpopup'>X</a>
<div class='notification-popup-container' id="firstpopup">
... firstpopup
</div>
<div class='notification-popup-container' id="secondpopup">
... secondpopup
</div>
The click handler first hides all the popups before opening a new one.
$(".notification-link").click(function () {
$(".notification-popup-container").hide();
var targetId = $(this).attr('href');
$(targetId).fadeIn(300);
return false;
})
working example: http://jsfiddle.net/qyLekdwk/
The problem here is how the event propgation is handled
$(function () {
var nContainer = $(".notification-popup-container");
//notification popup
$("#notification-link").click(function () {
nContainer.fadeToggle(300);
});
//page click to hide the popup
$(document).click(function (e) {
if (!$(e.target).closest('#notification-link, .notification-popup-container').length) {
nContainer.hide();
}
});
});
$(function test() {
var nContainer2 = $(".notification2-popup-container");
//notification popup
$("#notification2-link").click(function test() {
nContainer2.fadeToggle(300);
});
$(document).click(function (e) {
if (!$(e.target).closest('#notification2-link, .notification-popup-container').length) {
nContainer2.hide();
}
});
});
Demo: Fiddle

mootools Fx.Slide toggle on hidden element dont't work

I'am loading some html with a request and use it as a template for all other items.
My code is:
itemDummy.destroy()
this.content.each(function(task) {
//
//more code
//
item = itemDummy.clone();
detailBox = item.getElement('.descriptionBox');
detailBox.id = "description" + task.id;
//detailBox.toggle ()
//open it on click
item.addEvent("click", function() {
new Fx.Slide("description" + task.id).toggle();
});
//
//more code
//
detailBox.inject(itemWrapper);
item.inject(wrapper);
});
If the line detailBox.toggle () is activated, my box doesn't show, but the Fx animation dont' work (the box never appears visible).
But when I set s this line commented the detailBox is shown and the toggle animation is working, but I want a hidden box at the beginning.
But when I set this line as a comment, the detailBox is displayed and the toggle animation is working, but I want the Box invisible to start with
Following Johan comment it works after the inject:
detailBoxIds.each(function (id) {
new Fx.Slide(id).hide();
//instead of $$(id).hide () or $$(id).toggle ()
//a direct toogle/hide hides the element, but the Fx.Slide can't open it again
})
$$('.taksItemWraper').addEvent ("click", function () {
var id = this.getElement('.descriptionBox').id;
new Fx.Slide(id, {
duration:300
}).toggle();
})

Detect click outside element?

Similar to this question, but taking it a step further. I would like to detect clicks outside of a set of items, which I am handling in the following way:
$('#menu div').live('click', function() {
// Close other open menu items, if any.
// Toggle the clicked menu item.
$('body').one('click', function(event) {
// Hide the menu item.
event.stopPropagation();
});
});
This works like a charm, unfortunately, when another menu item is open and a
second is clicked, it requires two clicks to open the second item. The first
click hides the first menu item that was open, the second shows the second menu
item.
The "correct" behavior works in the following way:
Clicking a menu item opens it.
Clicking the same menu item (or it's children) closes it.
Clicking another menu item closes the first, opens the second.
Clicking away from (open) menu items closes them.
I have tried the following in place of the above $('body').one() order to ignore clicks on menu items with little success:
// Captures click on menu items in spite of the not.
$('*').not('#menu *').one('click', function() { // Hide menu }
$('*:not(#menu)').one('click', function() { // Hide menu }
As always, thanks for any help!
Just move the body click handler outside and do something like this:
$('body').bind('click', function(e) {
if($(e.target).closest('#menu').length == 0) {
// click happened outside of menu, hide any visible menu items
}
});
It was incorrectly pointed out in the comments that e.target does not work in IE; this is not true as jQuery's Event object fixes these inconsistencies where necessary (IE, Safari).
I wrote this a long time ago, before the glory days of jQuery...
function clickedOutsideElement(elemId) {
var theElem = getEventTarget(window.event);
while(theElem != null) {
if(theElem.id == elemId)
return false;
theElem = theElem.offsetParent;
}
return true;
}
function getEventTarget(evt) {
var targ = (evt.target) ? evt.target : evt.srcElement;
if(targ != null) {
if(targ.nodeType == 3)
targ = targ.parentNode;
}
return targ;
}
document.onclick = function() {
if(clickedOutsideElement('divTest'))
alert('Outside the element!');
else
alert('Inside the element!');
}

Categories

Resources