How to check state of a switch toggle in Selenium using c# - javascript

I am trying to validate if a switch is 'on or 'off' using selenium but I cant seem to get it right. The toggle is set to the on position on loading the webpage but filter results in a table when it is off etc. It works fine i just check get my selenium tests to get its current state.
element.Selected; always returns false (regards of toggle position)
element.Enabled; always returns true (regards of toggle position)
string test = myToggle.GetAttribute("class"); returns the text "slider round" which doesn't help
string test1 = myToggle.GetAttribute("checked"); is null
string test2 = myToggle.GetAttribute("value"); is null
Here is the code:
<label class="switch">
<input type="checkbox" id="myToggle" checked />
<span class="slider round"></span>
</label>
The code that checks the toggle position and loads the table data:
if (Amt == currentAmt ) {
if ($("#myToggle").prop("checked") == true) {
loadMyProducts('NAN', $("#total").val());
}
My test at the moment looks like this
[FindsBy(How = How.XPath, Using = "//*[#id='divTestAcc']/div[1]/p[9]/label/span")]
public IWebElement myToggle { get; set; }
public Boolean CheckMyToogleIsOnorOFF()
{
string test = myToggle.GetAttribute("class");
Console.Write("checking "+ test);
// string test1 = myToggle.GetAttribute("checked");
//string test2 = myToggle.GetProperty("checked");
// .Selected always returns false
// .Enables always returns true
Boolean result;
result = myToggle.Enabled;
bool result1 = myToggle.Selected;
if (result == true)
{
Console.WriteLine("My toggle is enabled");
}
else
{
Console.WriteLine("My toggle is not enabled");
}
return result;
}

// is it checked?
var isChecked = driver.FindElement(By.XPath("//input[#type='checkbox']").Selected;
Using the .Selected attribute should achieve what you are trying to do. The reason I add the driver.FindElement statement is to ensure you are locating the correct element -- based on your problem description, I'm not sure if the element you located & tested against was the correct one.
As another user pointed out, if GetAttribute("class") returns slider round, then you are looking at the wrong element here. Ensure the input element has been located first.
Your XPath at your file header //*[#id='divTestAcc']/div[1]/p[9]/label/span will locate the span element, not the input -- input is the one with checked, so that's what we need to test against.

Related

restrict the user from typing a new name and allow only to select from existing list

I'm working on autocomplete textbox feature of angularjs. I want the user only to select name from the existing autocomplete list instead of typing a new name. Eg.,When user types 'Al' autocomplete list shows the matching list and user can select one name from the existing list instead of typing a new name.How to restrict user from submitting a new name which is not present in the existing list.
Demo : http://plnkr.co/edit/AdmtP1b6K9kQorMHmt7t?p=preview
Code Sample:
$scope.countryList = ["Afghanistan","Albania","Algeria","Andorra","Angola","Anguilla","Antigua & Barbuda","Argentina","Armenia","Aruba","Australia","Austria","Azerbaijan","Bahamas","Bahrain","Bangladesh","Barbados","Belarus","Belgium","Belize","Benin","Bermuda","Bhutan","Bolivia","Bosnia & Herzegovina","Botswana","Brazil","British Virgin Islands","Brunei"];
$scope.validateField = function(){
alert("Clicked on submit , validte field");
}
$scope.complete=function(string){
var output=[];
angular.forEach($scope.countryList,function(country){
if(country.toLowerCase().indexOf(string.toLowerCase())>=0){
output.push(country);
}
});
$scope.filterCountry=output;
}
$scope.fillTextbox=function(string){
$scope.country=string;
$scope.filterCountry=null;
}
Any inputs would be helpful.
You can disable submit button and also highlight the border of the input field red, telling user to select name from drop down list.
First you need to update your complete() function. Use an else if statement that will check if the value is from the list or not, if not then you can implement your desired logic in that else if statement.
This method is flexible and easy to customize your error generation messages. You can show and hide the div that has the error message or you can apply css style on input-field using ng-style or ng-class. Right now I'll show you how to disable or enable button. Here is the updated code snippet:
$scope.complete = function(string) {
var output = [];
angular.forEach($scope.countryList, function(country) {
if (country.toLowerCase().indexOf(string.toLowerCase()) >= 0) {
output.push(country);
$scope.enableDisable = false;
} else if (country.toLowerCase().indexOf(string.toLowerCase()) < 0) {
$scope.enableDisable = true;
}
});
$scope.filterCountry = output;
}
And the In the html section you just need to add ng-disabled attribute and set its value.
<input type="submit" value="submit" ng-disabled="enableDisable" ng-click="validateField()">
So, you can do whatever you want in that else if statement to get the desire error message.
Take a look at this plunkr.
you can check for the validity of input using something like below and monitoring the value using ng-change
$scope.checkInput = function(){
$scope.validInput = $scope.countryList.indexOf($scope.country) > -1;
}

Doing mutual exclusive checkbox of two buttons with siblings()

I am trying to get two buttons groups with checkboxes mutually exclusive.
Here's my current result on this JS Fiddle
As you can see, there are four divs (with id="UserVsComputer", id="User1VsUser2", id="PlayableHits" and id="button-new-game").
I want the two first <div> ( UserVsComputer and User1VsUser2 ) to be mutually exclusive when we click on the checkbox of concerning <input> (i.e corresponding to the right <div>).
In JavaScript part, I did:
// Select the clicked checkbox for game type
$('input.game').on('click',function(){
setGameType();
});
function setGameType() {
// Get state of the first clicked element
var element = $('#UserVsComputer input.game');
var checkBoxState = element.prop('checked');
// Set !checkBoxState for the sibling checkbox, i.e the other
element.siblings().find('input.game').prop('checked',!checkBoxState);
updateGameType();
}
function updateGameType() {
// Set type of game
if ($('#UserVsComputer input').prop('checked'))
gameType = 'UserVsComputer';
else
gameType = 'User1VsUser2';
}
I don't want the <div id="PlayableHits" class="checkbox"> to be concerned by this mutual exclusion on two first checkboxes.
For example, below a capture showing that I can set the two first checkbox to true without making them exclusive:
What might be wrong here?
Try the following - it uses the target of the click event to ascertain which checkbox was checked:
// Select the clicked checkbox for game type
$('input.game').on('click',function(e){
setGameType(e.target);
});
function setGameType(cb) {
var container = $(cb).parent().parent();
var checkBox = $(cb);
var checkBoxState = checkBox.prop('checked');
// Set !checkBoxState for the sibling checkbox, i.e the other
container.siblings().find('input.game').prop('checked', !checkBoxState);
updateGameType();
}
function updateGameType() {
// Set type of game
if ($('#UserVsComputer input').prop('checked')) {
gameType = 'UserVsComputer';
} else {
gameType = 'User1VsUser2';
}
}
There are other bits which could use some attention (the hardcoded .parent().parent() isn't pretty but works in this case..

Enabling a disabled element

I tried to enable a disabled element on click of a P element.The code below will store the value from the textbox into another textbox which I have appended with the div.later this textbox will be disabled.On mouse over the div an edit and delete will appear.On click of the edit, the textbox within the div must be enabled again.
<div id="ta"></div>
<input type="text" id="tb"><br>
<button onclick="add()">Submit</button><br>
<script type="text/javascript">
var ta="";
function add() {
var newDiv="",newTa="",newP="",newImg="";
ta=document.getElementById('ta');
newDiv = document.createElement("div");
ta.appendChild(newDiv);
newTa = document.createElement("input");
newTa.type="text"
newTa.disabled="true";
newTa.value=document.getElementById("tb").value;
newDiv.onmousedown=function(){
newP.style.visibility="visible";
newImg.style.visibility="visible";
};
newP=document.createElement("p");
newP.innerHTML="Edit";
newP.style.visibility="hidden";
newP.style.display="inline";
newP.style.padding="5px";
newP.onclick=function()
{
newTa.disabled="false";//this is not working
}
Why is it not working?Is there any other way to do this?
The reason is probably because you are providing "false" as a string. From another answer here:
[...] a non empty string is truthy. So assigning "false" to the disabled property has the same effect of setting it to true.
Try using the proper boolean value instead.
newTa.disabled = false;
newTa.disabled="true"
newTa.disabled="false"
these two should be without ""
newTa.disabled=true
newTa.disabled=false
otherwise you could do it like this:
var x = document.getElementById("mySelect").disabled;
https://www.w3schools.com/jsref/prop_select_disabled.asp

Multiple conditions on single checkbox

I wanted to have a single checkbox in a form but i need to implement multiple scenarios but not sure if this is possible using a single checkbox or if i need radio buttons . Please advise
box shown and checked: Accepted / yes
(hidden)Box shown and not checked: Declined / no
Box not shown: Not Shown / blank
not sure if this is possible using a single checkbox
box shown and checked: Accepted / yes
(hidden)Box shown and not checked: Declined / no
Box not shown: Not Shown / blank
if the requirements 1/2/3 can be met using a single checkbox .The reason i ask is a single checkbox can hold only one value and if there is a way i can alter the value in Jquery dynamically still satisfying all the requirements.
Yes, it is possible. You can create an object having properties set to selectors :checked, :not(:checked, :hidden), :hidden; with corresponding values set to yes, no, blank. Set variable at change event handler using for..in loop, .is()
var obj = {
":checked": "yes",
":not(:checked, :hidden)": "no",
":hidden": "blank"
};
var curr;
$(":checkbox").change(function() {
for (var prop in obj) {
if ($(this).is(prop)) {
curr = obj[prop]; break;
}
}
// do stuff with `curr`
console.log(curr);
});
// check `:hidden`
$(":checkbox").prop("hidden", true)
.change() // `curr` should log `blank`
.prop("hidden", false);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js">
</script>
<input type="checkbox" />
I have created one sample onchange function where you can handle mutiple events
codepen URL for reference:
http://codepen.io/nagasai/pen/xOGNYW
<input type="checkbox" id="checkTest" onchange="myFunction()">
<input type="text" id="myText" value="checked">
#myText
{
display:none;
}
function myFunction() {
if (document.getElementById("checkTest").checked) {
document.getElementById("myText").style.display = "block";
} else {
document.getElementById("myText").style.display = "none";
}
}

IE javascript error - possibly related to setAttribute?

I am using Safalra's javascript to create a collapsible list. The script works across several browsers with no problem. However, when I apply the javascript to my own list, it fails to act as expected when I use IE (I'm using 7 at the moment). It simply writes the list, without the expand and contract images.
I copied the Safalra's javascript precisely, so I assume the error must be in my own list. This is how I generated my list:
<body onLoad="makeCollapsible(document.getElementById('libguides'));">
<ul id="libguides">
<script type="text/javascript" src="http://api.libguides.com/api_subjects.php?iid=54&more=false&format=js&guides=true&break=li"></script>
</ul>
(Yes, I do close the body tag eventually.) When I run this in IE, it tells me that line 48 is causing the problem, which appears to be:
node.onclick=createToggleFunction(node,list);
Here's the entire function:
function makeCollapsible(listElement){
// removed list item bullets and the sapce they occupy
listElement.style.listStyle='none';
listElement.style.marginLeft='0';
listElement.style.paddingLeft='0';
// loop over all child elements of the list
var child=listElement.firstChild;
while (child!=null){
// only process li elements (and not text elements)
if (child.nodeType==1){
// build a list of child ol and ul elements and hide them
var list=new Array();
var grandchild=child.firstChild;
while (grandchild!=null){
if (grandchild.tagName=='OL' || grandchild.tagName=='UL'){
grandchild.style.display='none';
list.push(grandchild);
}
grandchild=grandchild.nextSibling;
}
// add toggle buttons
var node=document.createElement('img');
node.setAttribute('src',CLOSED_IMAGE);
node.setAttribute('class','collapsibleClosed');
node.onclick=createToggleFunction(node,list);
child.insertBefore(node,child.firstChild);
}
I confess I'm too much of a javascript novice to understand why that particular line of code is causing the error. I looked at some of the other questions here, and was wondering if it might be a problem with setAttribute?
Thanks in advance.
Edited to add:
Here's the code for the createToggleFunction function. The whole of the script is just these two functions (plus declaring variables for the images).
function createToggleFunction(toggleElement,sublistElements){
return function(){
// toggle status of toggle gadget
if (toggleElement.getAttribute('class')=='collapsibleClosed'){
toggleElement.setAttribute('class','collapsibleOpen');
toggleElement.setAttribute('src',OPEN_IMAGE);
}else{
toggleElement.setAttribute('class','collapsibleClosed');
toggleElement.setAttribute('src',CLOSED_IMAGE);
}
// toggle display of sublists
for (var i=0;i<sublistElements.length;i++){
sublistElements[i].style.display=
(sublistElements[i].style.display=='block')?'none':'block';
}
}
}
Edited to add (again):
Per David's suggestion, I changed all instances of setAttribute & getAttribute...but clearly I did something wrong. IE is breaking at the 1st line (which is simply the doctype declaration) and at line 49, which is the same line of code where it was breaking before:
node.onclick=createToggleFunction(node,list);
Here's the first function as written now:
function makeCollapsible(listElement){
// removed list item bullets and the sapce they occupy
listElement.style.listStyle='none';
listElement.style.marginLeft='0';
listElement.style.paddingLeft='0';
// loop over all child elements of the list
var child=listElement.firstChild;
while (child!=null){
// only process li elements (and not text elements)
if (child.nodeType==1){
// build a list of child ol and ul elements and hide them
var list=new Array();
var grandchild=child.firstChild;
while (grandchild!=null){
if (grandchild.tagName=='OL' || grandchild.tagName=='UL'){
grandchild.style.display='none';
list.push(grandchild);
}
grandchild=grandchild.nextSibling;
}
// add toggle buttons
var node=document.createElement('img');
node.src = CLOSED_IMAGE;
node.className = 'collapsibleClosed';
node.onclick=createToggleFunction(node,list);
child.insertBefore(node,child.firstChild);
}
child=child.nextSibling;
}
}
And here's the second function:
function createToggleFunction(toggleElement,sublistElements){
return function(){
// toggle status of toggle gadget
// Use foo.className = 'bar'; instead of foo.setAttribute('class', 'bar');
if (toggleElement.className == 'collapsibleClosed') {
toggleElement.className = 'collapsibleOpen';
toggleElement.src = OPEN_IMAGE;
} else {
toggleElement.className = 'collapsibleClosed';
toggleElement.src = CLOSED_IMAGE;
}
// toggle display of sublists
for (var i=0;i<sublistElements.length;i++){
sublistElements[i].style.display=
(sublistElements[i].style.display=='block')?'none':'block';
}
}
}
Internet Explorer (until version 8, and then only in best standards mode) has a very broken implementation of setAttribute and getAttribute.
It effectively looks something like this:
function setAttribute(attribute, value) {
this[attribute] = value;
function getAttribute(attribute, value) {
return this[attribute];
}
This works fine iif the attribute name matches the property name, and the property takes a string value.
This isn't the case for the class attribute, where the matching property is className.
Use foo.className = 'bar'; instead of foo.setAttribute('class', 'bar');
node.onclick=createToggleFunction(node,list);
That is probably not what you want. Does createToggleFunction return a function? If it doesn't, then I bet you meant this:
node.onClick = function() { createToggleFunction(node, list); };
If my guess is right then the way you have it will set the onClick event handler to be the result of createToggleFunction, not a function like it needs to be.

Categories

Resources