I am trying to test a piece of my code using Jasmine, but I am stuck on which method to use and how to go about testing this particular function. Here is my code:
const foodInfoToggle1 = () => {
const foodInfo = document.querySelector('#first');
foodInfo.style.display === "none" ? foodInfo.style.display = "block" : foodInfo.style.display = "none";
}
This function encompasses toggle functionality and is assigned to a button. Once the button is clicked, the function runs to see if the paragraph is set to 'none'. If it is, then it switches to 'block' and vice versa. As you can see, my function is not accepting any parameters so I am finding it difficult to use test cases. How exactly would I go about testing this type of code using Jasmine.
describe('foodInfoToggle1', () => {
let element;
beforeEach(() => {
element = document.createElement('span');
spyOn(document, 'querySelector').and.callFake(selector => {
if (selector === '#first') return element;
});
});
it('Should change the display from none to block', () => {
element.style.display = 'none';
foodInfoToggle1();
expect(element.style.display).toEqual('block');
});
it('Should change the display from block to none', () => {
element.style.display = 'block';
foodInfoToggle1();
expect(element.style.display).toEqual('none');
});
});
I didn't find a quick way to include jasmine in the post, so hopefully all my syntax is correct.
The idea here being for each test, we create a dummy element and mockout the querySelector method. If it is called with the expected selector, return the dummy element.
Then for each of our tests, we put the style display in our expected initial value. We then call the method, and verify that the style display changed.
Related
i'm trying to do something with an element when i click on it. I putted this eventListener so it changes the value of a variable when i click on that element.
But it doesn't work, and when i check with debugger the function is not even getting inside of the eventListener, it just completely ignores it and i don't get errors in the console, why does this happen??
my code:
markAsRead(articleid) {
debugger
//there is three different "X", and i needed to get the three of them
let mainNode = document.querySelectorAll('.markasread')[0];
let firstNode = document.querySelectorAll('.markasread')[1];
let secondNode = document.querySelectorAll('.markasread')[2];
firstNode.addEventListener('click', ()=>{
this.$parent.markingAsRead = false;
this.isLoading = false;
console.log('test 1')
});
secondNode.addEventListener('click', ()=>{
this.$parent.markingAsRead = false;
this.isLoading = false;
console.log('test 2')
});
this.isLoading = true;
this.$parent.markingAsRead = true;
this.$eventBus.$emit('articleRemove', (articleid));
this.titleAcross = '';
}, ```
I'm using Vue.js, btw
querySelector and querySelectorAll are usually not the way to go in VueJS, if you want to select something. Either bind with state or use a template reference.
I need to rewrite some Jquery into native JavaScript code but I am facing a problem that I am not so sure how to solve.
This is Jquery code I need to rewrite in native JS:
$('.class1').click(function () {
setTimeout(() => {
$('.class2').css('top', '252px');
$('.class3').css('bottom', '0px');
}, 200);
$('.class2').css('z-index', '-1');
$('.class1').css('z-index', '-1');
});
And this is what I have written in native JavaScrip:
if (document.querySelector('.class1')){
document.querySelector('.class1').addEventListener('click', function () {
setTimeout(() => {
if (document.querySelector('.class2')) {
document.querySelector('.class2').style.top = '252px';
}
if ( document.querySelector('.class3')) {
document.querySelector('.class3').style.bottom = '0px';
}
}, 200);
if (document.querySelector('.class2')) {
document.querySelector('.class2').style.zIndex = '-1';
}
if ( document.querySelector('.class1')) {
document.querySelector('.class1').style.zIndex = '-1';
}
})
}
I was hoping that people could explain to me how to solve two things:
Is there a more elegant way to check for an element on the current page if the code runs on the whole site?
Is there something else that I can replace those if statements inside the function?
In Jquery those statements are executed one by one but in my case I need to check for an element first and if it is there do something with it.
You can make the code more succinct by storing the result of querySelector within a variable. Also note that a class selector in jQuery can return multiple elements, so the native equivalent of it is querySelectorAll().
As such you will need to loop through all the elements in that collection and add the event handlers, or update their style, as necessary. Due to this loop you don't need to explicitly check for the existence of the elements, as the forEach() will simply not execute if the collection is empty.
With that said, try this:
let class1 = document.querySelectorAll('.class1');
let class2 = document.querySelectorAll('.class2');
let class3 = document.querySelectorAll('.class3');
class1.forEach(el => {
el.addEventListener('click', e => {
setTimeout(() => {
class2.forEach(el => el.style.top = '252px');
class3.forEach(el => el.style.top = '0px');
}, 200);
class1.forEach(el => el.style.zIndex = -1);
class2.forEach(el => el.style.zIndex = -1);
});
});
Learning JS and was following a complex tutorial and keep getting errors for these specific functions. Stating that my "hide and show element" functions are undefined? Which i thought was odd since they are definitions kinda? Mostly confused because worked fine for the person in the video tutorial.
Any help understanding why is much appreciated!
'use strict';
hideElement = (element) => element.style.display = 'none';
showElement = (element) => element.style.display = 'block';
hideElement('connectWalletBtn');
showElement('userProfileBtn');
// define user button elements
const connectWalletBtn = document.getElementById('connectWalletBtn');
const userProfileBtn = document.getElementById('userProfileBtn');
<button id="connectWalletBtn">Connect Wallet</button>
<button id="userProfileBtn">Profile</button>
Firstly, you have never defined your variables for your functions. Do that:
const hideElement = (element) => element.style.display = 'none';
const showElement = (element) => element.style.display = 'block';
Second, your functions expect to get passed an element, but you are calling them with a string. Go with
hideElement(connectWalletBtn);
showElement(userProfileBtn);
instead.
The third problem is that you're using constant variables which you only declare after using them.
As an improvement, to toggle the display property of an element between none and initial, the DOM API has the hidden property/attribute (which sync). Use it.
Here's the corrected snippet:
'use strict';
const hideElement = element => element.hidden = true;
const showElement = element => element.hidden = false;
// make sure the DOM is fully parsed so elements
// are available for Javascript access
document.addEventListener('DOMContentLoaded', function() {
// find user button elements and store references in variables
const connectWalletBtn = document.getElementById('connectWalletBtn');
const userProfileBtn = document.getElementById('userProfileBtn');
hideElement(connectWalletBtn);
showElement(userProfileBtn);
})
<button id="connectWalletBtn">Connect Wallet</button>
<button id="userProfileBtn">Profile</button>
I think you forgot to grab the element from the dom.
hideElement = (element) => document.getElementById(element).style.display = 'none';
showElement = (element) => document.getElementById(element).style.display = 'block';
I am new to the jasmine test case I tried to do jasmine test case for selection module after doing this style property is getting undefined
function Selection() {
}
Selection.prototype.expandFlightDetails = function() {
document.getElementsByClassName("flight-details-container").style.display = 'none';
document.getElementById("expandedFlightDetails").style.display = 'block';
};
Selection.prototype.hideFlightDetails = function() {
document.getElementById("expandedFlightDetails").style.display = 'none';
document.getElementsByClassName("flight-details-container").style.display = 'block';
};
My testcase is
describe("selection module", function() {
var selection;
beforeEach(function () {
selection= new Selection();
});
afterEach(function () {
});
it('expand the flight details part ' , function(){
selection.expandFlightDetails();
expect(document.body.getElementsByClassName('flight-details-container')[0].style.display).toEqual('none');
});
xit('hide the flight details part ', function(){
selection.hideFlightDetails();
expect(document.getElementById('expandedFlightDetails').style.display).toEqual('none');
});
});
After doing this I'm geting and removed code to beforEach
TypeError: Cannot read property 'style' of undefined
please correct me if I have done wrong
You have a few errors on this code.
First in Selection.prototype.expandFlightDetails make sure to get the first result of the array (you forgot the [0]):
document.getElementsByClassName("flight-details-container")[0]
Same comment for Selection.prototype.hideFlightDetails
Then in your test suite you create a Selection instance named selection but then in both tests you are using a variable called flightselection which is declared nowhere. Shouldn't it be selection instead?
Finally your problem seems to be that you try to manipulate 'flight-details-container' in your test, although this element is created on the afterEach callback. afterEach means that this will be executed after each test, so it doesn't exist during the test.
I have an element that does not allow it to be clickable using CSS property pointer-events: none; How can I check whether that element is clickable or not as doing a .click() on the element throws an exception that I cannot catch UnknownError: unknown error: Element is not clickable at point The element is a link so I just want to check if the redirect happened but because of this error it ends the test right away and try catch cannot catch the exception.
I don't know about protractor, but using plain JS you can do:
window.getComputedStyle(element).getPropertyValue('pointer-events') == 'none';
however support for getComputedStyle may not be available in all browsers you wish to support, see MDN compatibility matrix, which indicates no support in IE 8, however it may not support the pointer-events CSS property anyway.
if you really want to use protractor you can use the following:
expect( protractor.ExpectedConditions.elementToBeClickable(element)).not.toBe(true);
There are actually two methods to check it.
1) Using ExpectedConditions
var EC = protractor.ExpectedConditions;
// Waits for the element with id 'abc' to be clickable.
browser.wait(EC.elementToBeClickable($('#abc')), 5000);
If not found or not clickable, will return error.
2) Using protractor's isEnabled, isDisplayed and isPresent
So as far as my understanding goes, you can create isClickable, which will return true if element is present, displayed and enabled and false otherwise:
function isClickable(element) {
return element.isPresent().then((isPresent) => {
if (isPresent) {
return element.isDisplayed().then((isDisplayed) => {
if (isDisplayed) {
return element.isEnabled();
}
return false;
});
}
return false;
});
}
I have wrote small check utility method, keep in mind it will click on element immediately when it become clickable:
import { ElementFinder, promise } from 'protractor';
export let testHelpers = {
isClickable(el: ElementFinder): promise.Promise<boolean> {
return new promise.Promise(resolve => {
let interval = setInterval(() => {
el.click().then(() => {
clearInterval(interval);
setTimeout(() => {
resolve(true);
}, 500);
}, () => { });
}, 100);
});
}
}
In your test code:
mport { testHelpers } from '../src/core/e2e/helpers';
describe('App', () => {
it('should do something', () {
let btn = $('.cls');
browser.wait(testHelpers.isClickable(btn), 3000);
});
});