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

[plugin-web-app-playwright] Add step waiting for element matching text #5591

Merged
merged 1 commit into from
Dec 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading