Skip to content

Commit

Permalink
[plugin-web-app-playwright] Add step waiting for element matching text
Browse files Browse the repository at this point in the history
  • Loading branch information
uarlouski committed Dec 13, 2024
1 parent 70b4275 commit afe05d9
Show file tree
Hide file tree
Showing 8 changed files with 115 additions and 20 deletions.
11 changes: 11 additions & 0 deletions .github/workflows/gradle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,17 @@ jobs:
echo Exit code is $exitCode
exit -1
fi
- name: Integration tests - Playwright
shell: bash
run: |
./gradlew :vividus-tests:debugStories -Pvividus.configuration.environments= \
-Pvividus.configuration.suites= \
-Pvividus.configuration.profiles=web_pw/headless/chromium \
-Pvividus.batch-1.meta-filters="groovy: playwrightSupported" \
-Pvividus.batch-1.resource-location=story/integration \
-Pvividus.batch-1.resource-include-patterns=*Steps*.story \
-Pvividus.web-application.main-page-url='${variables.vividus-test-site-url}'
- name: System tests
if: matrix.platform == 'ubuntu-latest'
Expand Down
18 changes: 0 additions & 18 deletions docs/modules/plugins/partials/generic-ui-steps.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -165,24 +165,6 @@ Then element located by `$locator` exists for `$duration` duration
Then element located by `id(banner)` exists for `PT5S` duration
----

=== Wait until element has text matching regular expression

Waits until an element with the specified locator has text that matches the provided https://www.regular-expressions.info/[regular expression].

[source,gherkin]
----
When I wait until element located by `$locator` has text matching `$regex`
----

* `$locator` - The <<_locator>> of the element which text to check.
* `$regex` - The https://www.regular-expressions.info/[regular expression] used to validate the text of the element.

.The element should have text consisting of numbers only
[source,gherkin]
----
When I wait until element located by `id(indicator)` has text matching `\d+`
----

=== Verify elements order

Gets a collection of elements by locator and checks that they are sorted by
Expand Down
18 changes: 18 additions & 0 deletions docs/modules/plugins/partials/ui-wait-element-state-steps.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,21 @@ When I wait `$duration` with `$pollingDuration` polling until element located by
----
When I wait `PT10S` with `PT1S` polling until element located by `id(element-to-hide)` becomes not visible
----

=== Wait until element has text matching regular expression

Waits until an element with the specified locator has text that matches the provided https://www.regular-expressions.info/[regular expression].

[source,gherkin]
----
When I wait until element located by `$locator` has text matching `$regex`
----

* `$locator` - The <<_locator>> of the element which text to check.
* `$regex` - The https://www.regular-expressions.info/[regular expression] used to validate the text of the element.

.The element should have text consisting of numbers only
[source,gherkin]
----
When I wait until element located by `id(indicator)` has text matching `\d+`
----
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@

import static org.vividus.ui.web.playwright.PlaywrightAssertionConfiguration.ASSERTION_NO_WAIT_TIMEOUT;

import java.util.regex.Pattern;

import com.microsoft.playwright.Locator;
import com.microsoft.playwright.assertions.LocatorAssertions;
import com.microsoft.playwright.assertions.PlaywrightAssertions;
Expand All @@ -28,6 +30,13 @@ private PlaywrightLocatorAssertions()
{
}

public static void assertElementHasTextMatchingRegex(Locator locator, Pattern pattern, boolean waitForState)
{
LocatorAssertions.ContainsTextOptions options = waitForState ? null
: new LocatorAssertions.ContainsTextOptions().setTimeout(ASSERTION_NO_WAIT_TIMEOUT);
getLocatorAssertions(locator).containsText(pattern, options);
}

public static void assertElementVisible(Locator locator, boolean waitForState)
{
LocatorAssertions.IsVisibleOptions options = waitForState ? null : new LocatorAssertions.IsVisibleOptions()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import java.time.Duration;
import java.util.function.BooleanSupplier;
import java.util.function.Supplier;
import java.util.regex.Pattern;

import com.microsoft.playwright.Locator;
import com.microsoft.playwright.Page;
Expand All @@ -32,6 +33,7 @@
import org.vividus.ui.web.playwright.BrowserContextProvider;
import org.vividus.ui.web.playwright.UiContext;
import org.vividus.ui.web.playwright.action.WaitActions;
import org.vividus.ui.web.playwright.assertions.PlaywrightLocatorAssertions;
import org.vividus.ui.web.playwright.locator.PlaywrightLocator;
import org.vividus.ui.web.playwright.locator.Visibility;
import org.vividus.util.wait.DurationBasedWaiter;
Expand Down Expand Up @@ -160,6 +162,24 @@ public void waitDurationWithPollingTillElementState(Duration duration, Duration
isElementInState);
}

/**
* Waits until an element with the specified locator has text that matches the provided regular expression.
*
* @param locator The locator of the element which text to check
* @param regex The regular expression used to validate the text of the element
*/
@When("I wait until element located by `$locator` has text matching `$regex`")
public void waitUntilElementHasTextMatchingRegex(PlaywrightLocator locator, Pattern regex)
{
Supplier<String> conditionDescription = () -> "The element located by `%s` has text matching regex '%s'"
.formatted(locator, regex);
waitActions.runWithTimeoutAssertion(conditionDescription, () ->
{
Locator element = uiContext.locateElement(locator);
PlaywrightLocatorAssertions.assertElementHasTextMatchingRegex(element, regex, true);
});
}

private void waitForElementStateValidatingVisibility(PlaywrightLocator locator,
ElementState state)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,13 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.RETURNS_SELF;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;

import java.util.function.Consumer;
import java.util.regex.Pattern;

import com.microsoft.playwright.Locator;
import com.microsoft.playwright.assertions.LocatorAssertions;
Expand All @@ -40,9 +42,33 @@
class PlaywrightLocatorAssertionsTests
{
private static final double ASSERTION_NO_WAIT_TIMEOUT = 0.1;
private static final Pattern PATTERN = Pattern.compile("\\d+");

@Mock private Locator locator;

@Test
void shouldAssertElementHasTextMatchingRegex()
{
shouldAssertElement(locatorAssertions ->
{
PlaywrightLocatorAssertions.assertElementHasTextMatchingRegex(locator, PATTERN, false);
ArgumentCaptor<LocatorAssertions.ContainsTextOptions> captor = ArgumentCaptor
.forClass(LocatorAssertions.ContainsTextOptions.class);
verify(locatorAssertions).containsText(eq(PATTERN), captor.capture());
assertEquals(ASSERTION_NO_WAIT_TIMEOUT, captor.getValue().timeout);
});
}

@Test
void shouldAssertElementHasTextMatchingRegexWaitForState()
{
shouldAssertElement(locatorAssertions ->
{
PlaywrightLocatorAssertions.assertElementHasTextMatchingRegex(locator, PATTERN, true);
verify(locatorAssertions).containsText(PATTERN, null);
});
}

@Test
void shouldAssertElementVisibleWithWaitForState()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import java.util.function.BooleanSupplier;
import java.util.function.Consumer;
import java.util.function.Supplier;
import java.util.regex.Pattern;
import java.util.stream.Stream;

import com.microsoft.playwright.BrowserContext;
Expand Down Expand Up @@ -183,6 +184,33 @@ void shouldWaitDurationWithPollingTillElementState(boolean initialStateResult, b
eq(finalStateResult));
}

@SuppressWarnings("unchecked")
@Test
void shouldWaitUntilElementHasTextMatchingRegex()
{
Pattern pattern = Pattern.compile("\\d+");
doNothing().when(waitActions).runWithTimeoutAssertion((Supplier<String>) argThat(s ->
{
String value = ((Supplier<String>) s).get();
return "The element located by `css(div) with visibility: visible` has text matching regex '\\d+'"
.equals(value);
}), argThat(runnable ->
{
runnable.run();
return true;
}));
Locator locator = mock();
when(uiContext.locateElement(playwrightLocator)).thenReturn(locator);

try (var playwrightLocatorAssertions = mockStatic(PlaywrightLocatorAssertions.class))
{
waitSteps.waitUntilElementHasTextMatchingRegex(playwrightLocator, pattern);

playwrightLocatorAssertions.verify(
() -> PlaywrightLocatorAssertions.assertElementHasTextMatchingRegex(locator, pattern, true));
}
}

private void shouldWaitForElementState(ElementState state, Consumer<WaitSteps> test,
MockedStatic.Verification verification)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,11 @@ When I scroll context to TOP edge
When I reset context
When I wait until element located by `id(current-vertical):a` contains text `0`

Scenario: Verify steps: "When I scroll element located by `$locator` into view", "Then element located by `$locator` $presence visible in viewport"
Scenario: Verify steps: "When I scroll element located by `$locator` into view", "Then element located by `$locator` $presence visible in viewport", "When I wait until element located by `$locator` has text matching `$regex`"
Meta:
@requirementId 436
When I refresh page
@playwrightSupported
Given I am on page with URL `${vividus-test-site-url}/scrollableElements.html`
Then element located by `xpath(//a[text()="Contact"])` is not visible in viewport
When I scroll element located by `xpath(//a[text()="Contact"])` into view
Then element located by `xpath(//a[text()="Contact"])` is visible in viewport
Expand Down

0 comments on commit afe05d9

Please sign in to comment.