Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature]: Ability to check wait for value on a input #1444

Closed
Georgegriff opened this issue Mar 20, 2020 · 14 comments
Closed

[Feature]: Ability to check wait for value on a input #1444

Georgegriff opened this issue Mar 20, 2020 · 14 comments

Comments

@Georgegriff
Copy link
Contributor

It would be great if Playwright had something similar to CodeceptJS methods:
image
or

image

I guess this could be in a form similar to waitForProperty? which waits for an element to exist and waits for a property of key and value

e.g. waitForProperty(selector, "innerText", "Foo",{timeout}) waitForProperty(selector, "value", "bar",{timeout})

@arjunattam
Copy link
Contributor

Thanks for the suggestion! I wonder if you were able to use waitForSelector with a text selector? For example, the following would wait for an element with text Foo.

page.waitForSelector('text=Foo')

It is possible to have a narrower criteria, like wait for a div with the same text.

page.waitForSelector('css=div >> text=Foo')

I'm trying to learn if there are reasons this wouldn't work for your needs?

@Georgegriff
Copy link
Contributor Author

Georgegriff commented Mar 20, 2020

Thanks for the response this >> text=Foo is this some playwright specific thing for the css engine? Can't see to get it work for my custom locator. I should have clarified i'm using a custom locator engine e.g.

The problem area i'm working in is shadow dom, im using the awesome custom selectors feature to register a selector, like so: https:/Georgegriff/query-selector-shadow-dom#playwright

await page.goto('chrome://downloads');
  // shadow= allows a css query selector that automatically pierces shadow roots.
  await page.waitForSelector('shadow=#no-downloads span', {timeout: 3000})

@arjunattam
Copy link
Contributor

Yes, the >> combinator is part of the selector syntax and can be used to combine multiple selectors (in the above case, css=div and text=Foo). Can you share more details on what is not working?

Also we fixed an issue in #1169, and it might be worth trying against playwright@next

@Georgegriff
Copy link
Contributor Author

Thanks for the info, i'll experiment and get back to you

@Georgegriff
Copy link
Contributor Author

So i took a look, this is mostly fantastic for text. Where it runs into problems is value on input fields.
Typically the property value of inputs are set using a js property but not reflected to an attribute so css/xpath selectors wont work. I'm wondering if it might be possible to expose some more helpers similar to the text=* for value properties

@arjunattam
Copy link
Contributor

Typically the property value of inputs are set using a js property but not reflected to an attribute so css/xpath selectors wont work.

Can you elaborate on this please? If the value is an attribute on the element, one can use input[value="placeholder"], but it seems that not the case? What could be a helper that would fix this?

@Georgegriff
Copy link
Contributor Author

Georgegriff commented Mar 23, 2020

Value on input is not always an attribute in the HTML. Forgive me i'm stating something you're already aware of but.
In the DOM you have attributes (the stuff you can see in the dom e.g. href, src etc)

But dom elements also have properties these are not available in the html, but sometimes properties are reflected to attributes such that they have the same value.

For input elements the value property is not automatically reflected. For example

values_input

Hopefully the gif shows how attributes in the dom aren't always reflected to their properties and vice versa. If i do a setAttribute on value it does nothing, if i do a .value updates in the UI but does not update the getAttribute call

And because the attribute value is not updated when the property is set a css/xpath selector on that attribute doesnt do anything

@Georgegriff
Copy link
Contributor Author

Georgegriff commented Mar 23, 2020

I can do this in user land with a custom engine by copying what your code does for these, but might be trickier

function createAttributeEngine(attribute: string): SelectorEngine {
bu for properties in instead

@Georgegriff Georgegriff changed the title [Feature]: Ability to check wait for text/value on a page [Feature]: Ability to check wait for value on a input Mar 23, 2020
@Georgegriff
Copy link
Contributor Author

Related issue someone else asking for this: #1427

@Georgegriff
Copy link
Contributor Author

Georgegriff commented Mar 23, 2020

For reference he's a naive implementation, doesn't work as well as text built in engine because it relies on a previous compound selector to have found an element for it to succeed.

const createValueEngine = () => {
  return {
    // Creates a selector that matches given target when queried at the root.
    // Can return undefined if unable to create one.
    create(root, target) {
      return null;
    },

    // Returns the first element matching given selector in the root's subtree.
    query(root, selector) {
      if (!root) {
        return null;
      }
      return "" + root["value"] === selector;
    },

    // Returns all elements matching given selector in the root's subtree.
    queryAll(root, selector) {
      if (!root) {
        return null;
      }
      return "" + root["value"] === selector;
    }
  };
};
await playwright.selectors.register("value", createValueEngine);

// example usage input.my-cvlass >> value="User input value"

@arjunattam
Copy link
Contributor

Thanks @Georgegriff! I think #1427 captures this issue, and I'm going to close this as a duplicate for now. Feel free to reopen if I've missed something.

@hpohlmeyer
Copy link

Hey @arjunattam the PR you mentioned does only deal with values on submit buttons. Having some kind of waitForInputValue method would be really nice.

My use case

We are populating input fields asynchronously and I would like to check if they are fully loaded by checking for them in playwright.

<label for="title">Title</label>
<input id="title" name="title" />
// Pseudo version of our update function
const response = await fetch("/title-data");
const title = await response.text();
const titleInput = document.querySelector("#title");
titleInput.value = title;
// Current solution in playwright
page.waitForFunction(({expectedTitle}) => {
	const titleInput = document.querySelector("#title");
    return titleInput.value === expectedTitle;
}, { expectedTitle: "my-input-value" })

That works, but I do not have access to the full power of playwright. For example it would be hard to select the input by its label text. Also being able to use the playwright selector engine instead of document.querySelector would be nice.

Possible solutions

So I was hoping for a selector like waitForInputValue that works similar to waitForSelector:

// Matches input that has label text of `Title` and an input value of `my-input-value`
await page.waitForInputValue(`"Title"`, "my-input-value");

A different approach would be an extension to the text selector. E.g.

// Matches input that has label text of `Title` and an input value of `my-input-value`
await page.waitForSelector(`"Title" >> value="my-input-value"`)

Other

@chmoder
Copy link

chmoder commented Aug 9, 2023

This worked okay for me but I would make it a function and add a time out:

while(await page.$eval('span.class', (el) => !el.textContent?.includes('some inner text')));

@changan1111
Copy link

changan1111 commented Mar 26, 2024

How to use same for Playwright with java?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants