symfony / panther

A browser testing and web crawling library for PHP and Symfony
MIT License
2.93k stars 220 forks source link

Using waitForAttributeToNotContain with empty value not working #508

Open jmendes92 opened 2 years ago

jmendes92 commented 2 years ago

In a project, I'm trying to test a form submit. During the form filling, there are fields which are automatically filled by a JS code using other fields values. In some cases, I need to overwrite the autogenerated value with another for the test purpose but I must wait for the JS to set the value field before the override. I tried achieving it with the code below but I get an issue: strpos(): Empty needle

self::$pantherClient->waitForAttributeToNotContain('input#field-serial', 'value', '');

The issue appears to be in file PantherWebDriverExpectedCondition.php where if $text = '' the strpos call fails.

public static function elementAttributeNotContains(WebDriverBy $by, string $attribute, string $text): callable
    {
        return static function (WebDriver $driver) use ($by, $attribute, $text) {
            try {
                $attributeValue = $driver->findElement($by)->getAttribute($attribute);

                return null !== $attributeValue && false === strpos($attributeValue, $text);
            } catch (StaleElementReferenceException $e) {
                return null;
            }
        }
        ;
    }

For now, I simply created my own method :

 public static function elementAttributeNotContains(WebDriverBy $by, string $attribute, string $text): callable
  {
    return static function (WebDriver $driver) use ($by, $attribute, $text) {
      try {
        $attributeValue = $driver->findElement($by)->getAttribute($attribute);

        if (empty($text)) {
          return !empty($attributeValue);
        }

        return null !== $attributeValue && false === strpos($attributeValue, $text);
      } catch (StaleElementReferenceException $e) {
        return null;
      }
    }
      ;
  }
   self::$pantherClient->wait()->until(
      AbstractFunctionalTest::elementAttributeNotContains(WebDriverBy::cssSelector('input#field-seriald'), 'value', '')
    );

If there is another way to achieve what I need to do I'm all ears. When I get a little more time I may open a PR with a fix but in the meantime, if anyone is able to do it or has a better solution, go for it.