0

I'm doing automation using cucumber (My first time doing automation). The UI is in iFrame & using ember. (UI code is from another team, therefore, any change on UI is not applicable)

I'm trying to find the text field & fill in the field (the last piece). However, I keep getting element not found. Anyone can help to suggest any method to find it ?

HTML Code

  <div id="payeePassportNumber" class="form-row-line">
        <div id="ember866" class="rdc-component-base rdc-text-input rdc-text-input no-label label-top ember-view">  
            <div class="label-holder">
                <label>Passport Number</label><!---->
            </div>
            <div class="component-holder">
                <div class="component-wrapper textinput-wrapper">
                    <input type="text" placeholder="" maxlength="140" id="ember867" class="ember-text-field ember-view">
                </div>
            </div>
        </div>
    </div>

Ruby Code before question was anwsered

session.within_frame(session.find(:xpath, "//[@id='myframe']")) do
    session.driver.browser.find_element(:id, 'payeeDetails').click
    if payeeDetails == 'Passport Number'
    session.find(:xpath,"//[text()[normalize-space()='#{payeeDetails}']]").click
    session.driver.browser.find_element(:id, 'payeePassportCountry').click
    session.find(:xpath,"//[text()[normalize-space()='#{country}']]").click
    session.fill_in session.find(:xpath, "//[@id='payeePassportNumber']/div/div[2]/div[contains(@Class, 'component-wrapper textinput-wrapper')]"), :with => "123456"

Error

 invalid selector: Unable to locate an element with the xpath expression //[@id='payeePassportNumber']///div/[contains(@Class, 'component-wrapper textinput-wrapper')] because of the following error:
    SyntaxError: Failed to execute 'evaluate' on 'Document': The string '//[@id='payeePassportNumber']///div/[contains(@Class, 'component-wrapper textinput-wrapper')]' is not a valid XPath expression.
    (Selenium::WebDriver::Error::InvalidSelectorError)

Ruby Code after question was anwsered

session.within_frame('myframe') do
        #find proxy type dropdown list & select proxy type
        session.find('#payeeDetails').click
        session.find("li", text: "#{payeeDetails}").click       
            if payeeDetails == 'Passport Number'

                #find country dropdownlist & select country
                session.find('#payeePassportCountry').click
                session.find(:xpath,"//*[text()[normalize-space()='#
                {country}']]").click
                #fills in proxy ID
                session.find('#payeePassportNumber').fill_in with: proxyID
            end
end
yanayeay
  • 31
  • 5
  • @Sers Perhaps I still didn't understand the objective of your edit where you removed the [tag:CssSelector] _tag_ but your answer still continues to suggest a CssSelector. – undetected Selenium Mar 10 '19 at 10:08
  • @DebanjanB I replaced css selector with capybara because of the tag limitation and capybara was more relevant, but the problem resolved. – Sers Mar 10 '19 at 10:17
  • @Sers See how your edit vandalized the post. You removed the tag [tag:css-selectors] to add the tag [tag:capybara] but you didn't remove the [tag:webdriverwait]. Please take care during your edits else OP will never receive canonical and working answers. – undetected Selenium Mar 10 '19 at 10:32

3 Answers3

0

Your error tells you what is wrong:

"//[@id='payeePassportNumber']/div/div[2]/div[contains(@Class, 'component-wrapper textinput-wrapper')]"

is not a valid XPath expression.

I suspect that @Class is confused by the space in the class name. Try the following xpath:

"//div[@id='payeePassportNumber']/div/div[2]/div[contains(@class, 'component-wrapper') and  contains(@class, 'textinput-wrapper')]"

Does that help?

C. Peck
  • 3,641
  • 3
  • 19
  • 36
  • thanks for the suggestion, but im getting the same error as others.. it says unable to find the field.. :( – yanayeay Mar 10 '19 at 08:02
0

You can't use @Class with capital C, and overall your selector is wrong.
Try to use simple selectors like below:

  1. css selector: #payeePassportNumber input
  2. xpath: //div[@id='payeePassportNumber']//input
Sers
  • 12,047
  • 2
  • 12
  • 31
  • Nice. Much better than my attempt at patching the user's xpath. – C. Peck Mar 10 '19 at 05:45
  • ohmygod... i didn't realize the capital c.. thanks for highlighting this.. i have tried using this //div[@id='payeePassportNumber']//input before, but it's still below error ElementNotFound : Unable to find field # – yanayeay Mar 10 '19 at 07:35
  • @yanayeay try with wait and check if there’s any iframe – Sers Mar 10 '19 at 08:00
  • i have put in sleep 5, but still getting the unable to find field.. and i have check.. only have one iframe... T_T – yanayeay Mar 10 '19 at 08:22
  • @yanayeay please check how to correct switch to iframe with Capybara [here](https://makandracards.com/makandra/34015-use-capybara-commands-inside-an-iframe) – Sers Mar 10 '19 at 08:33
  • @Sers do i need to switch again ? as i already switch to iframe. i have few other steps, which need to select country. i'm already able to click & select the country, and next step is to fill in the text field (it's within the same iframe).. which im unable to.. – yanayeay Mar 10 '19 at 08:48
  • @yanayeay don’t need – Sers Mar 10 '19 at 08:49
  • @Sers if the html code, having the value of placeholder, would that be easier ? – yanayeay Mar 10 '19 at 08:51
0

There's a number of things wrong with your code:

  1. You're calling find where you don't need to.
  2. You're calling direct driver methods (anytime you're using .driver.browser you're probably doing something wrong).
  3. You're passing elements to methods that don't take elements (fill_in),
  4. Doing complex xpath queries with normalize-space is generally never the right approach.

Without seeing all the HTML your code is referring to (#payeeDetails, which elements you're trying to click with your normalize-space xpaths, etc) it's hard to give full fixes for your code but the simplest way to fill in the input field shown in your HTML (assuming it's in an iframe with id of 'myframe') would be something like

session.within_frame('myframe') do
  session.find('#payeePassportNumber').fill_in with: '123456'
end
Thomas Walpole
  • 48,548
  • 5
  • 64
  • 78
  • Your answer doesn't address OP's main error i.e. _invalid selector_ – undetected Selenium Mar 10 '19 at 10:35
  • @DebanjanB Correct, it answers the OPs question which is "I'm trying to find the text field & fill in the field (the last piece)...... Anyone can help to suggest any method to find it ?" - which is exactly what my answer does. – Thomas Walpole Mar 10 '19 at 10:39
  • 1
    @ThomasWalpole 1. session.within_frame('myframe') -> this won't do, I already used it and it cannot find the iframe. I'm myself not sure why. Therefore, i put in the find xpath 2. I'm really new to coding, those with driver.browser -> i use it due to whenever i tried to use find xpath or find css, i won't be able to find the element. 3. Ahh i see.. will take not on this. 4. I found the code while doing some research hehe, and able to find the element that way. – yanayeay Mar 10 '19 at 10:39
  • @yanayeay It will if you're using a newish version of Capybara - I'm guessing you're still on 2.x ?? – Thomas Walpole Mar 10 '19 at 10:39
  • 1
    @ThomasWalpole capybara (3.14.0) -> my capybara version – yanayeay Mar 10 '19 at 10:43
  • @yanayeay hmmm -- maybe there's a bug then.. It definitely should work like that if your iframe has an id of `myframe` - you weren't passing `#myframe` were you?? It defaults to the :frame selector type - not a CSS selector. If you did want to use css or xpath you could do `session.within_frame(:css, '#myframe') do` – Thomas Walpole Mar 10 '19 at 10:46
  • 1
    @ThomasWalpole nope, i used this exact same code `session.within_frame('myframe')` , not sure if using ember (the HTML code is using ember) if will behaving differently ? I still have so much to learn. From all the comments i'm learning something new. – yanayeay Mar 10 '19 at 10:50
  • @yanayeay 2. Without knowing what code you had before it's impossible to say why it wasn't finding what you wanted, but dropping to `.driver.browser` is never really a good idea, especially as a beginner. 4. Without knowing which elements exactly you were trying to find I can't give a replacement, but you probably want to be using the `text` option that find takes along with a selector that chooses an element type instead. – Thomas Walpole Mar 10 '19 at 10:51
  • @ThomasWalpole Anyway, i have use this to fill in `session.find('#payeePassportNumber').fill_in with: '123456'` & it's a success! oh my god. i've been working for 2 days for this thing. – yanayeay Mar 10 '19 at 10:51
  • @yanayeay Great to hear -- that works because there's only one fillable field inside the payeePassportNumber div so `fill_in` will assume that's the one you want it to fill in. – Thomas Walpole Mar 10 '19 at 10:53
  • @ThomasWalpole I see, will take note on that. Thanks a zillion ! – yanayeay Mar 10 '19 at 10:55
  • @yanayeay You're welcome. If you could provide the HTML for your iframe element (possibly file an issue on the Capybara github) I would like to figure out why the `within_frame` with id isn't working for you because I can't replicate that failure and it's something specifically tested for in Capybaras test suite. The only reason I can come up with is if you were already inside a `within` block that didn't contain the iframe element, but your code in the question doesn't show that. – Thomas Walpole Mar 10 '19 at 18:55
  • 1
    @ThomasWalpole silly me.. i didn't put any quote when i used `session.within_frame('myframe')` I have now replace the code.. and it's working fine. Thank you. – yanayeay Mar 11 '19 at 03:24