Checking states of Slide toggle not working in Cypress Tests - javascript

I am trying to test the states of slide-toggles within my app using Cypress.
These time out and fails the test:
cy.get('label.mat-slide-toggle-label').eq(2).should('be.checked')
or
cy.get('div.mat-slide-toggle-bar').eq(2).should('be.checked')
Where as these pass
cy.get('label.mat-slide-toggle-label').eq(2).should('not.checked')
or
cy.get('div.mat-slide-toggle-bar').eq(2).should('not.checked')
The only difference is that the state of the toggle has changed.
Can someone help explain why the "not.checked" tests pass, but the others don't?

The documentation states:
The <mat-slide-toggle> uses an internal <input type="checkbox">
to provide an accessible experience. This internal checkbox
receives focus and is automatically labelled by the text content of
the <mat-slide-toggle> element.
When Angular Material adds the switch, it adds a whole little hierarchy of elements under the outer <mat-slide-toggle> element; divs with classes like mat-slide-toggle-label, mat-slide-toggle-bar, etc. But it also adds a real (but hidden) <input> element.
The 'checked' test only applies to input elements (this is probably why your should('not.be.checked') tests are working--because non-input elements can never be checked. So, to use Cypress's should('be.checked') test, you need to tell Cypress to get a reference to the actual <input> contained within the <mat-slide-toggle>, and not one of the other mat-xxx elements.
Example:
cy.get('mat-slide-toggle#whateverId input').should('be.checked');
// get reference to the single <input> inside the <mat-slide-toggle>
or:
cy.get('mat-slide-toggle#whateverId .mat-slide-toggle-input').should('be.checked');
// get reference to the element with class "mat-slide-toggle-input" inside the <mat-slide-toggle> (which is the <input> itself)

I was going to invite you to use the GUI snapshots panel to better understand what could be wrong, and maybe increase the timeout(s).
But in fact, I'm tempted to conclude that neither <label> nor <div> can be checked. <input type="checkbox"> can.
Is there another property you can assert on your label ?

I have managed to find a element for each toggle that allows me to check the state (checked or not checked).
input#mat-slide-toggle-29-input.mat-slide-toggle-input.cdk-visually-hidden
All I need to do is change the number to related to the toggle under test. I can check that the toggle is checked, press the master switch and then check that it is unchecked. I will also created a test where I test each toggle individually to ensure that the toggle works in a ground and singularly.

Related

Svelte: Change classes of checked checkbox (without creating variable for checkbox)

I am kind of new to Svelte and trying to solve this (seemingly trivial) problem with my UI:
I would like to change the classes of a checkbox and/or its parent element when the checkbox is checked. The Svelte docs tell me to create a boolean var for every checkbox and bind activation the classes to it: https://svelte.dev/tutorial/class-shorthand
but I have a random amount of checkboxes and many different types of checkboxes with different behaviour in styling and I don't want to create (or generate) a variable for every single checkbox.
Is there any elegant way in Svelte for changing the classes of checkboxes when they are indivually checked? (vanilla javascript instead if jquery if possible :) )
Cheers
Some Svelte noob
Based on what you have said, I would create a subcomponent to wrap the checkbox.
Lets Call it ToggleCheck. And if you want a div around each checkbox, then the div would live inside of of the ToggleCheck component
Then each instance of ToggleCheck would have its own var.
Your parent component could then have one or many instances of , even within a loop.
For something like this I would use... use, or actions. You can add/remove the class/classes using vanilla JS.
Since the class doesn't actually exist in the component you'll get an error if you define the class in your component unless you use :global()and even when doing that if you've set a property of CSS you'll need to make sure the specificity of the global selector is higher than the class generated by Svelte (i.e. :global(div.class))
Here's a REPL showing it in action with a few checkboxes and no need for variables or id's.

Identifying Which Toggle Was Toggled - Office UI Fabric - React

I am trying to use multiple toggles in my add-in but having trouble identifying which one was toggled.
I am able to get the id of the toggle in most cases, but if a user clicks on the smaller knob within the toggle, I am unable to get the toggle's id.
From the example above, if I click on the toggle thumb, where the red arrow points, I get the following output as the target.id
I have no way to identify which toggle this came from and do not believe I can set the id of the toggle thumb.
When the user clicks anywhere in the green sections, I get the following log where I can grab the ID and do conditional logic.
Before reporting this as a bug on github, I wanted to make sure I wasn't doing something wrong. I came across this which was similar but not what I am looking for: https://github.com/OfficeDev/office-ui-fabric-react/issues/6753
This code pen will show the issue:
https://codepen.io/rocketlobster5/pen/eYOvGjz
I don't think it should considered as a bug, to get the element that the event listener is attached to currentTarget property should be used instead of target.
The following example demonstrates how to retrieve id of toggle element:
private handleChange(ev: React.MouseEvent<HTMLElement>, checked: boolean) {
console.log(ev.currentTarget["id"]);
}
Modified codepen

How can I manipulate HTML elements which are added during the runtime?

The code im working on first makes a call to the database. Through this call, it is determined wether there are available workstations in the office or not.
If there are available workstations, "option" elements are added to a "select" element. This is achieved via jquery:
$('#idofselectelement').html(data)
Where "data" represents the markup to be inserted into the "select" element.
Now, my problem is that I'm trying to implement some code which checks wether your "favorite workstation" is available in the selected timeframe and then automatically preselects the respective workstation from the dropdownmenu in the "select" element. Everything is working so far, except for the selection of the workstation from the dropdown menu :/
The part of
I'm rather new to programming with javascript and the HTML DOM, so I'm not sure whether the fact that the options im trying to chose from are added during the runtime?
The code I've tried to manipulate the dropdown menu with is like this:
$('#idofselectelement').val(favoriteworkstation);
However, as I said, this doesn't work.
I've also already tried to output (console.log) the select element's length property right after the code which adds the markup with the available options has run.
But according to the output Im getting, the length is zero Oo
However, the dropdownmenu is definitely being created AND I can indeed manipulate it, but unfortunately not in the way I want to.
If I add an onclick event which sets the value of the respective select element, then the value in the select field indeed changes to the value specified in the event handler.
So I wonder why I can't have the favorite workstation preselected after the timeframe was chosen...
EDIT:
For further insight into the problem, I'm adding a bit more code here.
This is what the HTML Select element looks like BEFORE anything is added during the runtime:
<label for="#sitz">Sitz Nr.</label>
<select type="text" class="form-control" id="sitz" name="sitz" value="">
the markup which is added during the runtime
<option>workstationvalue</option>
<option>workstationvalue</option>
//and so on, depending on the situation...
This is a timing issue.
The js trying to find the element is faster than the actual add of the element to DOM.
Can you describe what you want to do? You might be able to do that before adding the element to DOM.
Editing before adding to DOM is possible if you convert your String to an jQuery object
var $jqueryObject = $(data);
$jqueryObject.find('.classYouSearch').val(value);
$('.whereToAd').html($jqueryObject);

React render, change radio button programmatically

I was creating a Dropdown component for React. Inside the dropdown, I have a form of radio group buttons.
<DropdownButton />
<DropdownForm />
In the DropdownButton, I have an state to know if it is open or not. Depends on that, DropdownForm it's hidden or not (using display: none).
The use case is: User selects a radio button, click apply and something happen. However, if user selects some radio button, and mouse out the dropdown (without clicking the apply button), the one that is selected should be the one that I get from the store.
Something like:
render: function () {
...
if(store.getSomeParam() != this.state.someParam && !this.props.isOpen){
someParam = store.getSomeParam()
}
Then the radio buttons are like:
<input checked={someParam == "something"} ... />
It doesn't really work. It re-renders but it doesn't change the button that is checked. I also tried with refs:
this.refs.myInput.getDOMNode().checked = true
But still nothing. Is this a correct behaviour?
The only solution I found so far is not using a css hiding class (display: none). So what I do is that the DropdownButton renders the DropdownForm depending on if it's open or not (so if you close it, you are forcing DropdownForm to unmount). Then when opening again, it is taking the values from the store (getInitialState) and it shows the correct radio button selected. But, I am not sure if this is the best solution and if there is any drawback in unmounting the component instead of just css hiding it.
This probably has nothing to do with React at all.
Most browsers don't validate the value of the checked attribute, but merely if it is there or not: http://jsfiddle.net/7jzm7gvw/
Just set the checked attribute to either true or null:
<input checked={someParam == "something" ? true: null} ... />
TL;DR: You must use the componentDidMount lifecycle method, not render, to work with the rendered dom nodes directly.
I was struggling with this as well, and after doing some online research I figured I might as well look into it for myself. Here's what I came up with:
Use the componentDidMount lifecycle method and update whatever you need to in there. Here's a Pen I used to prototype this, and I think it looks okay: http://codepen.io/gholts/pen/GpWzdb
You could drop this in pretty easily to what your'e working on by just putting a componentDidMount method on your object and doing it there. I used document.getElementById but you could definitely use jQuery or whatever else you wanted in there, as once the component has mounted it's available to DOM selectors.
I'm using this now to update 20 radio button groups (so it has to check a prop for three different states and update accordingly) and it loads instantly.
Hope it helps! I used the ES6 class syntax in my Pen, you should check it out if you have some time to refactor :) It's fun.
EDIT: So I figured it out, I'm a dummy. You don't need to do the whole document.getElementById business that I was doing. Just use your this.refs.whichever.getDOMNode().checked = true and it'll work, so long as you do it in componentDidMount. It works there because there is an actual DOM element on the page at that point.

KnockoutJS: based on length of array enable button

In a project we're doing, we have created an inbox where the users (amongst other things) can select the items. If a user selects an item, the button should be enabled -- if none are selected, the button should be disabled.
Simple enough, but for the life of me, I can't get it working :-(
You can find a fiddle here: http://jsfiddle.net/rzrfp/
I presume I'm missing something very, very, VERY simple and stupid, but I've been tried virtually everything, and can't get it working ...
Use ko.computed instead of ko.computable.
Or even better: use data-bind="enable: selectedItems().length > 0" in your button element.
So you can omit the computed showButton.
EDIT: To use the right context use var modelImpl = new myModel("myParam");. Otherwise this inside the model refers to the window object.

Categories

Resources