1

So I have this problem where I run a protractor/selenium test and sometimes a radio-button is already checked during the test and sometimes its not.

etc:

<div id="TRUCK" class="radio-item checked" data-gtm="truck">

or

<div id="TRUCK" class="radio-item" data-gtm="deliveryOpt-truck">

where you can see the class sometimes have the "checked" init and sometimes not.

What I am trying to do solve is that I want to make a function that clicks IF the radio-button is not checked and if its already checked then we just continue.

What I managed to do is:

it('Clicking Truck button', function (done) {

    browser.driver
        .then(() => browser.wait(EC.presenceOf(element(by.id("TRUCK")))), 30000, "Timed out button")
        .then(() => browser.executeScript("arguments[0].click();",element(by.id("TRUCK")).getWebElement()))
        .then(() => done());

however the problem is that it will uncheck it if the radio-button is already checked which is not good. So again.

I am trying to make a function that clicks. If the radio-button is not checked then we click. If its already checked then we continue.

How am I able to do that?

Guy
  • 46,488
  • 10
  • 44
  • 88
Thrillofit86
  • 599
  • 2
  • 7
  • 20

2 Answers2

1

Seems you were close. To identify an element when the class attribute doesn't contain the value checked you can use either of the following Locator Strategies:

  • xpath:

    //div[@id='TRUCK' and not(contains(@class,'checked'))]
    
  • css:

    div#TRUCK:not(.checked)
    

Effectively, if your use case is to invoke click() when the class attribute is not having the value checked, instead of presenceOf() you need to use the ExpectedConditions elementToBeClickable() and you can use either of the following Locator Strategies:

  • xpath:

    it('Clicking Truck button', function (done) {
    
        browser.driver
        .then(() => browser.wait(EC.elementToBeClickable(element(by.xpath("//div[@id='TRUCK' and not(contains(@class,'checked'))]")))), 30000, "Timed out button")
    
  • css:

    it('Clicking Truck button', function (done) {
    
        browser.driver
        .then(() => browser.wait(EC.elementToBeClickable(element(by.css("div#TRUCK:not(.checked)")))), 30000, "Timed out button")
    
undetected Selenium
  • 183,867
  • 41
  • 278
  • 352
  • 1
    Oh right! That is true. However now the problem is that I would get a "failed" in the test due to it is already clickable right? Is there a way to mark it as a "GOOD" if its already checked and vice versa if we need to click? – Thrillofit86 Feb 12 '20 at 09:31
  • 1
    1) Clicking Truck button <--- Failed | √ Clicking Truck button <--- Success – Thrillofit86 Feb 12 '20 at 09:32
  • This line of code will **fail**, incase the element html _class_ attribute contains `checked`, else this line will **pass**. – undetected Selenium Feb 12 '20 at 09:34
  • Yeah exactly. If its already checked then it will fail. I mean it seems to work as I wish but I was thinking maybe it would look more beautiful if it pass if the element is checked or to be checked. Fail only if etc. element is not found or button disabled? – Thrillofit86 Feb 12 '20 at 09:36
  • @Thrillofit86 Great News !!! Glad to be able to help you out !!! That logic is specific to protractor and I don't practice protractor that often :) I'm with pure webdriver through Java/Python. – undetected Selenium Feb 12 '20 at 09:38
  • Ahh! Alright seems right! However I did get a issue though. Im not sure if its actually now working or not. The error I do get when its checked is: `TypeError: Cannot read property 'isPresent' of undefined` seems like it shouldn't return that? – Thrillofit86 Feb 12 '20 at 09:42
  • @Thrillofit86 You are getting it from the next line of code pertaining to `getWebElement()` as `click()` doesn't returns anything and is considered as **undefined** / **NULL** – undetected Selenium Feb 12 '20 at 09:46
  • Ahhhhhh... Make sense now. So maybe if I could somehow a if statement or a assert from Chai https://www.chaijs.com/api/assert/ that checks basically if its true then we skip the click or something like that? I think... but either way since your knowledge is not on protractor and yet helped me I still consider this as the answer but would appreciate maybe if you have any ideas what to do if you check the Chai documentation :D Because I am still abit lost of ideas – Thrillofit86 Feb 12 '20 at 09:48
  • 1
    Done! Thank you! I will continue to see if there is a way to make a sort of if-else statement for this. :) – Thrillofit86 Feb 12 '20 at 10:00
  • 1
    By the way. I tried to change to `.then(() => browser.wait(EC.elementToBeClickable(element(by.xpath("//div[@id='TRUCK']")))), 30000, "Timed out button")` and it still says the error about `TypeError: Cannot read property 'isPresent' of undefined` It shouldn't do that? I removed the click function aswell so its only the same as your answer. – Thrillofit86 Feb 12 '20 at 10:02
  • @Thrillofit86 Did you declare `var EC = protractor.ExpectedConditions;`? See: [“Failed: Cannot read property 'isPresent' of undefined”](https://stackoverflow.com/questions/40909682/failed-cannot-read-property-ispresent-of-undefined) – undetected Selenium Feb 12 '20 at 10:06
  • 1
    Oh yeah. I do have it at the beginning of the code so it does triggers it. I believe thats the reason I do get a TypeError I believe otherwise I dont think I would get any message. – Thrillofit86 Feb 12 '20 at 10:07
  • 1
    Ahhh stupid me! I realized I did a mistake in another class... No wonder why I do get that problem. My fault!! – Thrillofit86 Feb 12 '20 at 10:10
0

This will check if checkbox is selected and if not will select it:

static async selectCheckbox(element: ElementFinder, markChecked: boolean) {
        const isSelected = await elementt.isSelected();
        if (isSelected !== markChecked) {
            await elementt.click();
        }
        return;
    }
Sanja Paskova
  • 1,110
  • 8
  • 15