Rayrun
← Back to Discord Forum

Why can I not get the input value using .inputValue()?

I have tried all sorts of combinations to get this to work but for some reason I just can't get the value of the input elements. 90% of them are input[type=text] and there are a couple selects but the inputValue() supports inputs, selects, and textareas.

The annoying thing is I am getting the id attribute just fine but using the same locator I can't get the value. If I use .getAttribute('value') then I can get the text values but not the selects.

CODE

await page.waitForSelector('.input-field')
        const inputs = page.locator('.input-field')
        const inputs_count = await inputs.count()
        for (let input_pos=0; input_pos<inputs_count; input_pos++)
        { 
            
            const input = inputs.nth(input_pos)
            const id = await input.getAttribute('id')
            const value = await input.inputValue()
            console.log(`[${input_pos}] ${id} => ${value}`)
        }

This thread is trying to answer question "Why can I not get the input value using .inputValue()?"

13 replies
refactoreric

Hi, the code looks fine to me. Except maybe the waitForSelector because it returns element handles, and anything returning element handles should be avoided nowadays.

Do you know the number of input fields to expect? Maybe using an await expect(page.locator('.input-field')).toHaveCount(5) will help to make it more reliable. It ensures that you don't start the loop before the expected number of input fields is present. (But I don't know if that even was an issue for you. Perhaps those fields are all appearing immediately and at the same time.)

Do you get any errors on calling the .inputValue function? Or is it 'just' returning empty values all the time?

Maybe these are some fancy elements where the actual value is held somewhere else?

Wondering if it all looks fine as refactoreric mentions... still need to consider a closed shadow dom or possibly you are missing an iframe? Might suggest going midevil and use an eval and get the value that way. Might try debugging and use .highlight() to verify the controls you're hitting.

@refactoreric, @dand33 Thanks for replying and taking a look at the issue. I don't get any errors, when I use .inputValue() it returns nothing. When I use .getAttribute('value') I get null for the inputs that actually have a value.

For more context here is the DOM structure and what it looks like visually.

I've tried debugging but I will try again. I have tried using the option to record your session but the issue there is it is grabbing the full static path to the element. We have a form like this for every country and unfortunately the devs did not create a single template file so every country the element IDs may change :S.

Any further advice would be much appreciated.

image.png
image.png
refactoreric

Hmm could Playwright be so fast that it retrieves values from the fields before they are initialized? What if you add a (temporary) large waitForTimeout before looping through the fields)?

Might rework your code? Might suspect you are hitting the case why page.waitForSelector discourages doing what you are, and not using a locator waitFor() as you are...

https://playwright.dev/docs/api/class-page#page-wait-for-selector Discouraged! Use web assertions that assert visibility or a locator-based locator.waitFor() instead. Read more about locators.

@dand33 I appreciate the links and recommendation. Sadly this has also not solved the issue. This is really getting on my nerves TBH. I have tried using evaluate, tried fetching the value of the input directly with no loops, tried using the .waitFor and even adding long .waitForTimeout . No matter how I set up the test I just can't get the value of inputs which only have a class identifier. Whether it is a locator or elementHandle or if I use any of the .value, .getAttribute('value'), .inputValue() properties and methods.

Does anyone have a working example of fetching the value from an input that is working? Ideally within some sort of loop on the page. Something dead simple (which this SHOULD be) just getting input by class name, simple loop, print their values. I feel like something wonky is going on here.

To be clear, there are no iframes and this is not a react or any other type of SPA. I think our developers use C# with .NET but the output is just HTML/JS/CSS.

tphillips8117
test('test', async ({ page }) => {
  await page.goto('https://www.rnz.co.nz/search/results?q=rteastd&commit=Search');
  await expect(page.getByPlaceholder('Search')).not.toBeEmpty();
  const searchTerm = await page.getByPlaceholder('Search').inputValue();
  console.log(searchTerm)
});```
tphillips8117

This works fine

tphillips8117

It's using a specific locator for a single control on the page

tphillips8117

but it does force some synchronisation by calling await expect(...).not.toBeEmpty() to make sure the box is not empty

tphillips8117

I do understand sometimes the value might be empty

tphillips8117

is one of the fields on the page expected to be always populated?

@socks6618 From what I can see in the DOM, I suspect that there may be verification handlers attached to the input field. One of the project I worked on had a text field component where there were two <input> for the same text field, one hidden and one visible, visible one was used to display/edit text and the hidden one was used to store values. I suspect that this might be true in your case as well. Try getting values from hidden <input>s and see that if it solve your problem.

TwitterGitHubLinkedIn
AboutQuestionsDiscord ForumBrowser ExtensionTagsQA Jobs

Rayrun is a community for QA engineers. I am constantly looking for new ways to add value to people learning Playwright and other browser automation frameworks. If you have feedback, email [email protected].