How to identify if Angular toggle-switch toggle is clicked?
Question:
I am trying to define if Angular’s toggle-switch is clicked or not using Selenium and Python tools.
When open a new form my input id has class ng-untouched ng-pristine ng-valid
.
After clicked, it changes to ng-valid ng-dirty ng-touched
. But after a third click nothing changes.
After I click it and save the form, the class stays always ng-valid ng-dirty ng-touched
and remains the same after any change (even after disabling toggle and saving).
This is not a bug because changes are saved on server side.
Which CSS property should I look at to define what is changed?
Here is html code sample:
<div _ngcontent-c26="" class="form-group">
<label _ngcontent-c26="" for="checked">Checked</label>
<div _ngcontent-c26="" class="toggle-switch">
<input _ngcontent-c26="" id="opened" name="checked" type="checkbox" class="ng-valid ng-dirty ng-touched">
<label _ngcontent-c26="" for="checked"></label>
</div>
<span _ngcontent-c26="" class="form-control-helper"></span>
</div>
Answers:
Form State and Input State
AngularJS constantly updates the state of both the <form>
and the <input>
fields.
Input fields have the following states:
$untouched
: The field has not been touched yet
$touched
: The field has been touched
$pristine
: The field has not been modified yet
$dirty
: The field has been modified
$invalid
: The field content is not valid
$valid
: The field content is valid
These are the properties of the <input>
field, and are either true
or false
.
Forms also have the following states:
$pristine
: No fields have been modified yet
$dirty
: One or more have been modified
$invalid
: The form content is not valid
$valid
: The form content is valid
$submitted
: The form is submitted
This usecase
To validate the Angular toggle-switch state using Selenium and python you have to induce WebDriverWait for visibility_of_element_located
and you can use either of the following Locator Strategies:
-
Probing ng-touched
:
try:
WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.XPATH, "//input[@id='opened' and @name='checked'][contains(@class, 'ng-touched')]")))
print("Toggle Switch has been touched")
except TimeoutException:
print("Toggle Switch has not been touched")
-
Probing ng-dirty
:
try:
WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.XPATH, "//input[@id='opened' and @name='checked'][contains(@class, 'ng-dirty')]")))
print("Toggle Switch has been touched")
except TimeoutException:
print("Toggle Switch has not been touched")
-
Note : You have to add the following imports :
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
After trying a few options and more research I found two solutions to test is a toggle/checkbox is checked.
First, by using .is_selected() Selenium’s method:
driver.find_element_by_css_selector("input[type=checkbox]").is_selected()
It returns True if a toggle is ON and False if it is OFF.
Second, I looked closely and CSS settings and found out that when a toggle is ON, :checked is added to it. So, you can use a boolean expression for this locator.
In Chrome’s DevTools this attribute can be found in Properties tab, the name is checked
. More details are here:
The locator for checked toggle will look like:
input[type=checkbox]:checked
For unchecked:
input[type=checkbox]
Also, there is a third option which will work for many cases. For example, if a toggle changes its color, its property is also changed. So you can use:
driver.find_element_by_css_selector("input[type=checkbox]").value_of_css_property("background-color") == "some color"
For example, place "#fff"
(white) if you expect this CSS property to be white.
I am trying to define if Angular’s toggle-switch is clicked or not using Selenium and Python tools.
When open a new form my input id has class ng-untouched ng-pristine ng-valid
.
After clicked, it changes to ng-valid ng-dirty ng-touched
. But after a third click nothing changes.
After I click it and save the form, the class stays always ng-valid ng-dirty ng-touched
and remains the same after any change (even after disabling toggle and saving).
This is not a bug because changes are saved on server side.
Which CSS property should I look at to define what is changed?
Here is html code sample:
<div _ngcontent-c26="" class="form-group">
<label _ngcontent-c26="" for="checked">Checked</label>
<div _ngcontent-c26="" class="toggle-switch">
<input _ngcontent-c26="" id="opened" name="checked" type="checkbox" class="ng-valid ng-dirty ng-touched">
<label _ngcontent-c26="" for="checked"></label>
</div>
<span _ngcontent-c26="" class="form-control-helper"></span>
</div>
Form State and Input State
AngularJS constantly updates the state of both the <form>
and the <input>
fields.
Input fields have the following states:
$untouched
: The field has not been touched yet$touched
: The field has been touched$pristine
: The field has not been modified yet$dirty
: The field has been modified$invalid
: The field content is not valid$valid
: The field content is valid
These are the properties of the <input>
field, and are either true
or false
.
Forms also have the following states:
$pristine
: No fields have been modified yet$dirty
: One or more have been modified$invalid
: The form content is not valid$valid
: The form content is valid$submitted
: The form is submitted
This usecase
To validate the Angular toggle-switch state using Selenium and python you have to induce WebDriverWait for visibility_of_element_located
and you can use either of the following Locator Strategies:
-
Probing
ng-touched
:try: WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.XPATH, "//input[@id='opened' and @name='checked'][contains(@class, 'ng-touched')]"))) print("Toggle Switch has been touched") except TimeoutException: print("Toggle Switch has not been touched")
-
Probing
ng-dirty
:try: WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.XPATH, "//input[@id='opened' and @name='checked'][contains(@class, 'ng-dirty')]"))) print("Toggle Switch has been touched") except TimeoutException: print("Toggle Switch has not been touched")
-
Note : You have to add the following imports :
from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.common.by import By from selenium.webdriver.support import expected_conditions as EC
After trying a few options and more research I found two solutions to test is a toggle/checkbox is checked.
First, by using .is_selected() Selenium’s method:
driver.find_element_by_css_selector("input[type=checkbox]").is_selected()
It returns True if a toggle is ON and False if it is OFF.
Second, I looked closely and CSS settings and found out that when a toggle is ON, :checked is added to it. So, you can use a boolean expression for this locator.
In Chrome’s DevTools this attribute can be found in Properties tab, the name is checked
. More details are here:
The locator for checked toggle will look like:
input[type=checkbox]:checked
For unchecked:
input[type=checkbox]
Also, there is a third option which will work for many cases. For example, if a toggle changes its color, its property is also changed. So you can use:
driver.find_element_by_css_selector("input[type=checkbox]").value_of_css_property("background-color") == "some color"
For example, place "#fff"
(white) if you expect this CSS property to be white.