diff --git a/docs/modules/plugins/pages/plugin-web-app-playwright.adoc b/docs/modules/plugins/pages/plugin-web-app-playwright.adoc index 313d84adcb..623898ce8f 100644 --- a/docs/modules/plugins/pages/plugin-web-app-playwright.adoc +++ b/docs/modules/plugins/pages/plugin-web-app-playwright.adoc @@ -635,3 +635,5 @@ When I execute sequence of actions: |KEY_UP |c, ControlOrMeta | ---- ==== + +include::partial$common-web-app-browser-steps.adoc[] diff --git a/docs/modules/plugins/partials/common-web-app-browser-steps.adoc b/docs/modules/plugins/partials/common-web-app-browser-steps.adoc new file mode 100644 index 0000000000..823062c06f --- /dev/null +++ b/docs/modules/plugins/partials/common-web-app-browser-steps.adoc @@ -0,0 +1,20 @@ +=== Close browser + +Closes the browser. + +[source,gherkin] +---- +When I close browser +---- + +.Browser restart +[source,gherkin] +---- +Given I am on page with URL `https://vividus-test-site-a92k.onrender.com` +Then number of elements found by `xpath(//img)` is = `1` +When I execute javascript `document.querySelector('[name="vividus-logo"]').remove()` +Then number of elements found by `xpath(//img)` is = `0` +When I close browser +Given I am on page with URL `https://vividus-test-site-a92k.onrender.com` +Then number of elements found by `xpath(//img)` is = `1` +---- diff --git a/vividus-plugin-web-app-playwright/src/main/java/org/vividus/ui/web/playwright/BrowserContextProvider.java b/vividus-plugin-web-app-playwright/src/main/java/org/vividus/ui/web/playwright/BrowserContextProvider.java index 417da76801..2b5a5934a4 100644 --- a/vividus-plugin-web-app-playwright/src/main/java/org/vividus/ui/web/playwright/BrowserContextProvider.java +++ b/vividus-plugin-web-app-playwright/src/main/java/org/vividus/ui/web/playwright/BrowserContextProvider.java @@ -56,7 +56,13 @@ public BrowserContextProvider(BrowserType browserType, LaunchOptions launchOptio public BrowserContext get() { return testContext.get(BROWSER_CONTEXT_KEY, () -> { - BrowserContext browserContext = getPlaywrightContext().browser.newContext(); + PlaywrightContext context = getPlaywrightContext(); + Browser browser = getPlaywrightContext().browser; + if (!browser.isConnected()) + { + browser = launchBrowserWithCurrentOptions(context.playwright); + } + BrowserContext browserContext = browser.newContext(); networkContext.listenNetwork(browserContext); if (browserContextConfiguration.isTracingEnabled()) { @@ -72,7 +78,7 @@ public PlaywrightContext getPlaywrightContext() { return testContext.get(PLAYWRIGHT_CONTEXT_KEY, () -> { Playwright playwright = Playwright.create(); - Browser browser = browserType.launchBrowser(playwright, launchOptions); + Browser browser = launchBrowserWithCurrentOptions(playwright); return new PlaywrightContext(playwright, browser); }); } @@ -106,6 +112,17 @@ public void closePlaywrightContext() }); } + public void closeBrowserInstance() + { + Optional.ofNullable(testContext.get(PLAYWRIGHT_CONTEXT_KEY, PlaywrightContext.class)) + .ifPresent(playwrightContext -> playwrightContext.browser.close()); + } + + private Browser launchBrowserWithCurrentOptions(Playwright playwright) + { + return browserType.launchBrowser(playwright, launchOptions); + } + private record PlaywrightContext(Playwright playwright, Browser browser) { } diff --git a/vividus-plugin-web-app-playwright/src/main/java/org/vividus/ui/web/playwright/UiContext.java b/vividus-plugin-web-app-playwright/src/main/java/org/vividus/ui/web/playwright/UiContext.java index ebbbae339f..317db9bf06 100644 --- a/vividus-plugin-web-app-playwright/src/main/java/org/vividus/ui/web/playwright/UiContext.java +++ b/vividus-plugin-web-app-playwright/src/main/java/org/vividus/ui/web/playwright/UiContext.java @@ -31,6 +31,8 @@ public class UiContext { + private static final Class PLAYWRIGHT_CONTEXT_KEY = PlaywrightContext.class; + private final TestContext testContext; public UiContext(TestContext testContext) @@ -102,6 +104,11 @@ public Locator getCurrentContexOrPageRoot() return getInCurrentContext(context -> context, page -> page.locator("//html/body"), FrameLocator::owner); } + public void removePlaywrightContext() + { + testContext.remove(PLAYWRIGHT_CONTEXT_KEY); + } + private R getInCurrentContext(Function elementContextAction, Function pageContextAction, Function frameContextAction) { @@ -115,7 +122,7 @@ private R getInCurrentContext(Function elementContextAction, Fun private PlaywrightContext getPlaywrightContext() { - return testContext.get(PlaywrightContext.class, PlaywrightContext::new); + return testContext.get(PLAYWRIGHT_CONTEXT_KEY, PlaywrightContext::new); } private static final class PlaywrightContext diff --git a/vividus-plugin-web-app-playwright/src/main/java/org/vividus/ui/web/playwright/steps/BrowserSteps.java b/vividus-plugin-web-app-playwright/src/main/java/org/vividus/ui/web/playwright/steps/BrowserSteps.java new file mode 100644 index 0000000000..18b65f009e --- /dev/null +++ b/vividus-plugin-web-app-playwright/src/main/java/org/vividus/ui/web/playwright/steps/BrowserSteps.java @@ -0,0 +1,44 @@ +/* + * 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. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.vividus.ui.web.playwright.steps; + +import org.jbehave.core.annotations.When; +import org.vividus.ui.web.playwright.BrowserContextProvider; +import org.vividus.ui.web.playwright.UiContext; + +public class BrowserSteps +{ + private final BrowserContextProvider browserContextProvider; + private final UiContext uiContext; + + public BrowserSteps(BrowserContextProvider browserContextProvider, UiContext uiContext) + { + this.browserContextProvider = browserContextProvider; + this.uiContext = uiContext; + } + + /** + * Closes the browser + */ + @When("I close browser") + public void closeBrowser() + { + browserContextProvider.closeBrowserContext(); + browserContextProvider.closeBrowserInstance(); + uiContext.removePlaywrightContext(); + } +} diff --git a/vividus-plugin-web-app-playwright/src/main/resources/vividus-plugin/spring.xml b/vividus-plugin-web-app-playwright/src/main/resources/vividus-plugin/spring.xml index 62757543b9..14dc742c0f 100644 --- a/vividus-plugin-web-app-playwright/src/main/resources/vividus-plugin/spring.xml +++ b/vividus-plugin-web-app-playwright/src/main/resources/vividus-plugin/spring.xml @@ -77,6 +77,7 @@ + @@ -94,6 +95,7 @@ + diff --git a/vividus-plugin-web-app-playwright/src/test/java/org/vividus/ui/web/playwright/BrowserContextProviderTests.java b/vividus-plugin-web-app-playwright/src/test/java/org/vividus/ui/web/playwright/BrowserContextProviderTests.java index 65c55b3e2a..376c7260cb 100644 --- a/vividus-plugin-web-app-playwright/src/test/java/org/vividus/ui/web/playwright/BrowserContextProviderTests.java +++ b/vividus-plugin-web-app-playwright/src/test/java/org/vividus/ui/web/playwright/BrowserContextProviderTests.java @@ -22,10 +22,12 @@ import static org.junit.jupiter.api.Assertions.assertNotSame; import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.params.provider.Arguments.arguments; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mockStatic; import static org.mockito.Mockito.reset; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.verifyNoMoreInteractions; @@ -90,6 +92,7 @@ void shouldCreateBrowserContextAtFirstRetrievalOnly() Playwright playwright = mock(); playwrightStaticMock.when(Playwright::create).thenReturn(playwright); Browser browser = mock(); + when(browser.isConnected()).thenReturn(true); when(browserType.launchBrowser(playwright, launchOptions)).thenReturn(browser); BrowserContext browserContext = mock(); when(browser.newContext()).thenReturn(browserContext); @@ -122,6 +125,23 @@ void shouldCreateBrowserContextAtFirstRetrievalOnly() } } + @Test + void shouldReCreateClosedBrowser() + { + Browser browserToClose = mock(); + Browser newBrowserInstance = mock(); + when(browserType.launchBrowser(any(), any())).thenReturn(browserToClose).thenReturn(newBrowserInstance); + when(browserToClose.isConnected()).thenReturn(false); + when(newBrowserInstance.newContext()).thenReturn(mock(BrowserContext.class)); + + browserContextProvider.get(); + browserContextProvider.closeBrowserInstance(); + browserContextProvider.get(); + + verify(browserToClose).close(); + verify(browserType, times(2)).launchBrowser(any(), any()); + } + static Stream tracingConfigurations() { return Stream.of( diff --git a/vividus-plugin-web-app-playwright/src/test/java/org/vividus/ui/web/playwright/UiContextTests.java b/vividus-plugin-web-app-playwright/src/test/java/org/vividus/ui/web/playwright/UiContextTests.java index 253d3b1692..88bf943c7b 100644 --- a/vividus-plugin-web-app-playwright/src/test/java/org/vividus/ui/web/playwright/UiContextTests.java +++ b/vividus-plugin-web-app-playwright/src/test/java/org/vividus/ui/web/playwright/UiContextTests.java @@ -39,7 +39,8 @@ class UiContextTests { private static final PlaywrightLocator PLAYWRIGHT_LOCATOR = new PlaywrightLocator("xpath", "//div"); - private final UiContext uiContext = new UiContext(new SimpleTestContext()); + private final SimpleTestContext testContext = new SimpleTestContext(); + private final UiContext uiContext = new UiContext(testContext); static { @@ -200,6 +201,15 @@ void shouldNotThrowExceptionWhenResetFrameWithNoFrames() assertNull(uiContext.getCurrentFrame()); } + @Test + void shouldRemovePlaywrightContext() + { + uiContext.reset(); + assertEquals(1, testContext.size()); + uiContext.removePlaywrightContext(); + assertEquals(0, testContext.size()); + } + private FrameLocator setupFrameMock(boolean visibility) { FrameLocator frame = mock(); diff --git a/vividus-plugin-web-app-playwright/src/test/java/org/vividus/ui/web/playwright/steps/BrowserStepsTests.java b/vividus-plugin-web-app-playwright/src/test/java/org/vividus/ui/web/playwright/steps/BrowserStepsTests.java new file mode 100644 index 0000000000..efbfa65f24 --- /dev/null +++ b/vividus-plugin-web-app-playwright/src/test/java/org/vividus/ui/web/playwright/steps/BrowserStepsTests.java @@ -0,0 +1,43 @@ +/* + * 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. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.vividus.ui.web.playwright.steps; + +import static org.mockito.Mockito.verify; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.vividus.ui.web.playwright.BrowserContextProvider; +import org.vividus.ui.web.playwright.UiContext; + +@ExtendWith(MockitoExtension.class) +class BrowserStepsTests +{ + @Mock private BrowserContextProvider browserContextProvider; + @Mock private UiContext uiContext; + + @Test + void shouldCloseBrowser() + { + BrowserSteps steps = new BrowserSteps(browserContextProvider, uiContext); + steps.closeBrowser(); + verify(browserContextProvider).closeBrowserContext(); + verify(browserContextProvider).closeBrowserInstance(); + verify(uiContext).removePlaywrightContext(); + } +}