diff --git a/docs/modules/plugins/pages/plugin-web-app.adoc b/docs/modules/plugins/pages/plugin-web-app.adoc index 866afd5373..099c6a5ab5 100644 --- a/docs/modules/plugins/pages/plugin-web-app.adoc +++ b/docs/modules/plugins/pages/plugin-web-app.adoc @@ -1170,6 +1170,27 @@ Then `${response}` matcher `.+` === Element wait steps +==== Wait for element appearance with timeout + +Waits for element appearance with desired timeout. + +WARNING: It's forbidden to use <<_visibility_types>> in the locator. + +[source,gherkin] +---- +Then element located by `$locator` appears in `$timeout` +---- + +* `$locator` - The <<_locator,locator>> used to find element. +* `$timeout` - The maximum time to wait for the element appearance in {durations-format-link} format. + +.Click on the button and waiting for element appearance for 2 minutes +[source,gherkin] +---- +When I click on element located by `buttonName(Show element)` +Then element located by 'id(element-to-show)' appears in 'PT2M' +---- + ==== Wait for element disappearance with timeout Waits for element disappearance with desired timeout. diff --git a/vividus-plugin-web-app/src/main/java/org/vividus/steps/ui/web/WaitSteps.java b/vividus-plugin-web-app/src/main/java/org/vividus/steps/ui/web/WaitSteps.java index cfee717346..1abc9eaa90 100644 --- a/vividus-plugin-web-app/src/main/java/org/vividus/steps/ui/web/WaitSteps.java +++ b/vividus-plugin-web-app/src/main/java/org/vividus/steps/ui/web/WaitSteps.java @@ -1,5 +1,5 @@ /* - * Copyright 2019-2023 the original author or authors. + * Copyright 2019-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,6 +23,7 @@ import java.time.Duration; +import org.apache.commons.lang3.Validate; import org.hamcrest.Matcher; import org.jbehave.core.annotations.Then; import org.jbehave.core.annotations.When; @@ -44,6 +45,7 @@ import org.vividus.ui.action.IExpectedConditions; import org.vividus.ui.action.IWaitActions; import org.vividus.ui.action.WaitResult; +import org.vividus.ui.action.search.Visibility; import org.vividus.ui.context.IUiContext; import org.vividus.ui.monitor.TakeScreenshotOnFailure; import org.vividus.ui.web.action.WebJavascriptActions; @@ -266,6 +268,20 @@ public boolean waitAlertDoesNotAppear(Duration timeout) return softAssert.assertFalse("Alert does not appear", wait.isWaitPassed()); } + /** + * Waits for element appearance with desired timeout + * @param locator The locating mechanism to use + * @param timeout Desired timeout + */ + @Then("element located by `$locator` appears in `$timeout`") + public void waitForElementAppearance(Locator locator, Duration timeout) + { + Validate.isTrue(Visibility.VISIBLE == locator.getSearchParameters().getVisibility(), + "The step supports locators with VISIBLE visibility settings only, but the locator is `%s`", + locator.toHumanReadableString()); + waitActions.wait(getSearchContext(), timeout, expectedSearchActionsConditions.visibilityOfElement(locator)); + } + /** * Waits for element disappearance with desired timeout * @param locator The locating mechanism to use diff --git a/vividus-plugin-web-app/src/test/java/org/vividus/steps/ui/web/WaitStepsTests.java b/vividus-plugin-web-app/src/test/java/org/vividus/steps/ui/web/WaitStepsTests.java index 59f3349eaf..6fc7d6bfec 100644 --- a/vividus-plugin-web-app/src/test/java/org/vividus/steps/ui/web/WaitStepsTests.java +++ b/vividus-plugin-web-app/src/test/java/org/vividus/steps/ui/web/WaitStepsTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2019-2023 the original author or authors. + * Copyright 2019-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,11 +18,13 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.when; import java.time.Duration; @@ -52,6 +54,8 @@ import org.vividus.ui.action.IExpectedConditions; import org.vividus.ui.action.IExpectedSearchContextCondition; import org.vividus.ui.action.WaitResult; +import org.vividus.ui.action.search.SearchParameters; +import org.vividus.ui.action.search.Visibility; import org.vividus.ui.context.IUiContext; import org.vividus.ui.web.action.IWebWaitActions; import org.vividus.ui.web.action.WebJavascriptActions; @@ -79,6 +83,28 @@ class WaitStepsTests @Mock private TimeoutConfigurer timeoutConfigurer; @InjectMocks private WaitSteps waitSteps; + @Test + void shouldElementByNameAppearsWithTimeout() + { + when(uiContext.getSearchContext()).thenReturn(webElement); + Locator locator = new Locator(WebLocatorType.ELEMENT_NAME, NAME); + IExpectedSearchContextCondition condition = mock(); + when(expectedSearchActionsConditions.visibilityOfElement(locator)).thenReturn(condition); + waitSteps.waitForElementAppearance(locator, TIMEOUT); + verify(waitActions).wait(webElement, TIMEOUT, condition); + } + + @Test + void shouldThrowAnExceptionInCaseOfIncorrectVisibilityUsedForAppearanceWait() + { + Locator locator = new Locator(WebLocatorType.ELEMENT_NAME, new SearchParameters(NAME, Visibility.ALL)); + var iae = assertThrows(IllegalArgumentException.class, + () -> waitSteps.waitForElementAppearance(locator, TIMEOUT)); + assertEquals("The step supports locators with VISIBLE visibility settings only, but the locator is " + + "`element name 'name' (visible or invisible)`", iae.getMessage()); + verifyNoInteractions(expectedSearchActionsConditions, waitActions); + } + @Test void testElementByNameDisappearsWithTimeout() { diff --git a/vividus-tests/src/main/resources/known-issues.json b/vividus-tests/src/main/resources/known-issues.json index 6e682d343a..d35065be63 100644 --- a/vividus-tests/src/main/resources/known-issues.json +++ b/vividus-tests/src/main/resources/known-issues.json @@ -97,5 +97,12 @@ "scenarioPattern": "Steps verification.*", "storyPattern": "ResourceCheckSteps", "stepPattern": "Then all resources found by.*" + }, + "VVD-15": { + "type": "Internal", + "assertionPattern": ".+waiting for visibility of element located by .+ \\(visible\\) \\(tried for 4 second\\(s\\) with .+ milliseconds interval\\).*", + "scenarioPattern": "Verify step: 'Then element located by `.+` appears in `.+`'", + "storyPattern": "WaitStepsTests", + "stepPattern": "Then element located by `.+` appears in `.+`" } } diff --git a/vividus-tests/src/main/resources/story/integration/WaitStepsTests.story b/vividus-tests/src/main/resources/story/integration/WaitStepsTests.story index d3df35424c..ff6c9ce48c 100644 --- a/vividus-tests/src/main/resources/story/integration/WaitStepsTests.story +++ b/vividus-tests/src/main/resources/story/integration/WaitStepsTests.story @@ -79,3 +79,6 @@ Scenario: Verify step: 'When I wait until frame with name `$frameName` appears a Given I am on page with URL `${vividus-test-site-url}/frames.html` When I wait until frame with name `exampleCom` appears and I switch to it Then text `Example Domain` exists + +Scenario: Verify step: 'Then element located by `$locator` appears in `$timeout`' +Then element located by `id(non-existent-element)` appears in `PT4S`