Skip to content

Commit 2aa1a2b

Browse files
authored
feat(junit): add Browser.NewContextOptions fixture (#2005)
1 parent d0a3b81 commit 2aa1a2b

5 files changed

Lines changed: 236 additions & 35 deletions

File tree

‎playwright/src/main/java/com/microsoft/playwright/impl/junit/BrowserContextExtension.java‎

Lines changed: 1 addition & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
package com.microsoft.playwright.impl.junit;
1818

1919
import com.microsoft.playwright.*;
20-
import com.microsoft.playwright.impl.Utils;
2120
import com.microsoft.playwright.junit.Options;
2221
import org.junit.jupiter.api.extension.*;
2322

@@ -62,7 +61,7 @@ public static BrowserContext getOrCreateBrowserContext(ExtensionContext extensio
6261
Playwright playwright = PlaywrightExtension.getOrCreatePlaywright(extensionContext);
6362
setTestIdAttribute(playwright, options);
6463
Browser browser = BrowserExtension.getOrCreateBrowser(extensionContext);
65-
Browser.NewContextOptions contextOptions = getContextOptions(playwright, options);
64+
Browser.NewContextOptions contextOptions = BrowserContextOptionsExtension.getContextOptions(playwright, options);
6665
browserContext = browser.newContext(contextOptions);
6766
if (options.defaultTimeout != null) {
6867
browserContext.setDefaultTimeout(options.defaultTimeout);
@@ -192,35 +191,4 @@ private void closeBrowserContext() {
192191
private static boolean shouldRecordTrace(Options options) {
193192
return options.trace.equals(Options.Trace.ON) || options.trace.equals(Options.Trace.RETAIN_ON_FAILURE);
194193
}
195-
196-
private static Browser.NewContextOptions getContextOptions(Playwright playwright, Options options) {
197-
Browser.NewContextOptions contextOptions = Utils.clone(options.contextOptions);
198-
if (contextOptions == null) {
199-
contextOptions = new Browser.NewContextOptions();
200-
}
201-
202-
if (options.baseUrl != null) {
203-
contextOptions.setBaseURL(options.baseUrl);
204-
}
205-
206-
if (options.deviceName != null) {
207-
DeviceDescriptor deviceDescriptor = DeviceDescriptor.findByName(playwright, options.deviceName);
208-
if (deviceDescriptor == null) {
209-
throw new PlaywrightException("Unknown device name: " + options.deviceName);
210-
}
211-
contextOptions.userAgent = deviceDescriptor.userAgent;
212-
if (deviceDescriptor.viewport != null) {
213-
contextOptions.setViewportSize(deviceDescriptor.viewport.width, deviceDescriptor.viewport.height);
214-
}
215-
contextOptions.deviceScaleFactor = deviceDescriptor.deviceScaleFactor;
216-
contextOptions.isMobile = deviceDescriptor.isMobile;
217-
contextOptions.hasTouch = deviceDescriptor.hasTouch;
218-
}
219-
220-
if (options.ignoreHTTPSErrors != null) {
221-
contextOptions.setIgnoreHTTPSErrors(options.ignoreHTTPSErrors);
222-
}
223-
224-
return contextOptions;
225-
}
226194
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/*
2+
* Copyright (c) Microsoft Corporation.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.microsoft.playwright.impl.junit;
18+
19+
import com.microsoft.playwright.Browser;
20+
import com.microsoft.playwright.Playwright;
21+
import com.microsoft.playwright.PlaywrightException;
22+
import com.microsoft.playwright.impl.Utils;
23+
import com.microsoft.playwright.junit.Options;
24+
import org.junit.jupiter.api.extension.*;
25+
26+
import static com.microsoft.playwright.impl.junit.ExtensionUtils.isParameterSupported;
27+
28+
public class BrowserContextOptionsExtension implements ParameterResolver {
29+
@Override
30+
public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException {
31+
return isParameterSupported(parameterContext, extensionContext, Browser.NewContextOptions.class);
32+
}
33+
34+
@Override
35+
public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException {
36+
Options options = OptionsExtension.getOptions(extensionContext);
37+
Playwright playwright = PlaywrightExtension.getOrCreatePlaywright(extensionContext);
38+
return getContextOptions(playwright, options);
39+
}
40+
41+
// Returns a new instance every time, so that callers can modify it without affecting other tests.
42+
static Browser.NewContextOptions getContextOptions(Playwright playwright, Options options) {
43+
Browser.NewContextOptions contextOptions = Utils.clone(options.contextOptions);
44+
if (contextOptions == null) {
45+
contextOptions = new Browser.NewContextOptions();
46+
}
47+
48+
if (options.baseUrl != null) {
49+
contextOptions.setBaseURL(options.baseUrl);
50+
}
51+
52+
if (options.deviceName != null) {
53+
DeviceDescriptor deviceDescriptor = DeviceDescriptor.findByName(playwright, options.deviceName);
54+
if (deviceDescriptor == null) {
55+
throw new PlaywrightException("Unknown device name: " + options.deviceName);
56+
}
57+
if (options.browserName != null && deviceDescriptor.defaultBrowserType != null &&
58+
!options.browserName.equals(deviceDescriptor.defaultBrowserType)) {
59+
throw new PlaywrightException("Device \"" + options.deviceName + "\" requires \"" + deviceDescriptor.defaultBrowserType +
60+
"\" browser, but browserName is \"" + options.browserName + "\"");
61+
}
62+
contextOptions.userAgent = deviceDescriptor.userAgent;
63+
if (deviceDescriptor.viewport != null) {
64+
contextOptions.setViewportSize(deviceDescriptor.viewport.width, deviceDescriptor.viewport.height);
65+
}
66+
contextOptions.deviceScaleFactor = deviceDescriptor.deviceScaleFactor;
67+
contextOptions.isMobile = deviceDescriptor.isMobile;
68+
contextOptions.hasTouch = deviceDescriptor.hasTouch;
69+
}
70+
71+
if (options.ignoreHTTPSErrors != null) {
72+
contextOptions.setIgnoreHTTPSErrors(options.ignoreHTTPSErrors);
73+
}
74+
75+
return contextOptions;
76+
}
77+
}

‎playwright/src/main/java/com/microsoft/playwright/junit/UsePlaywright.java‎

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,22 @@
3636
* <li> {@link com.microsoft.playwright.Browser Browser browser}</li>
3737
* <li> {@link com.microsoft.playwright.APIRequestContext APIRequestContext request}</li>
3838
* <li> {@link com.microsoft.playwright.Playwright Playwright playwright}</li>
39+
* <li> {@link com.microsoft.playwright.Browser.NewContextOptions Browser.NewContextOptions contextOptions}</li>
3940
* </ul>
4041
* {@code Page} and {@code BrowserContext} are created before each test and closed
4142
* after the test has finished. {@code Browser} and {@code Playwright} are reused
42-
* between tests for better efficiency.
43+
* between tests for better efficiency. {@code Browser.NewContextOptions} is a new instance
44+
* every time it is requested, configured from the {@link OptionsFactory} the same way as for
45+
* the {@code BrowserContext} fixture. Unlike {@code Page} and {@code BrowserContext}, it can also
46+
* be used in {@code @BeforeAll} and {@code @AfterAll} methods to create a context manually:
47+
* <pre>{@code
48+
* @BeforeAll
49+
* static void beforeAll(Browser browser, Browser.NewContextOptions contextOptions) {
50+
* BrowserContext context = browser.newContext(contextOptions);
51+
* // ...
52+
* context.close();
53+
* }
54+
* }</pre>
4355
*
4456
* <p> An example of using {@code @UsePlaywright} annotation:
4557
* <pre>{@code
@@ -73,7 +85,7 @@
7385
* <a href="https://playwright.dev/java/docs/junit">JUnit guide</a>.
7486
*/
7587
@ExtendWith({OptionsExtension.class, PlaywrightExtension.class, BrowserExtension.class, BrowserContextExtension.class,
76-
PageExtension.class, APIRequestContextExtension.class})
88+
PageExtension.class, APIRequestContextExtension.class, BrowserContextOptionsExtension.class})
7789
@Retention(RetentionPolicy.RUNTIME)
7890
@Target(ElementType.TYPE)
7991
@Inherited
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/*
2+
* Copyright (c) Microsoft Corporation.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.microsoft.playwright.impl.junit;
18+
19+
import com.microsoft.playwright.Browser;
20+
import com.microsoft.playwright.Playwright;
21+
import com.microsoft.playwright.PlaywrightException;
22+
import com.microsoft.playwright.junit.Options;
23+
import org.junit.jupiter.api.Test;
24+
25+
import static org.junit.jupiter.api.Assertions.*;
26+
27+
public class TestBrowserContextOptionsExtension {
28+
@Test
29+
void shouldThrowWhenBrowserNameDoesNotMatchDevice() {
30+
try (Playwright playwright = Playwright.create()) {
31+
Options options = new Options().setDeviceName("iPhone 14").setBrowserName("chromium");
32+
PlaywrightException e = assertThrows(PlaywrightException.class,
33+
() -> BrowserContextOptionsExtension.getContextOptions(playwright, options));
34+
assertEquals("Device \"iPhone 14\" requires \"webkit\" browser, but browserName is \"chromium\"", e.getMessage());
35+
}
36+
}
37+
38+
@Test
39+
void shouldAllowBrowserNameMatchingDevice() {
40+
try (Playwright playwright = Playwright.create()) {
41+
Options options = new Options().setDeviceName("iPhone 14").setBrowserName("webkit");
42+
Browser.NewContextOptions contextOptions = BrowserContextOptionsExtension.getContextOptions(playwright, options);
43+
assertTrue(contextOptions.isMobile);
44+
}
45+
}
46+
}
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
/*
2+
* Copyright (c) Microsoft Corporation.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.microsoft.playwright.junit;
18+
19+
import com.microsoft.playwright.Browser;
20+
import com.microsoft.playwright.BrowserContext;
21+
import com.microsoft.playwright.Page;
22+
import org.junit.jupiter.api.AfterAll;
23+
import org.junit.jupiter.api.BeforeAll;
24+
import org.junit.jupiter.api.Test;
25+
26+
import static org.junit.jupiter.api.Assertions.*;
27+
28+
@FixtureTest
29+
@UsePlaywright(TestFixtureNewContextOptions.CustomOptions.class)
30+
public class TestFixtureNewContextOptions {
31+
// Only checked as an option value, never navigated to.
32+
private static final String BASE_URL = "http://localhost:1234/base/";
33+
private static Browser.NewContextOptions contextOptionsFromBeforeAll;
34+
35+
public static class CustomOptions implements OptionsFactory {
36+
@Override
37+
public Options getOptions() {
38+
return new Options()
39+
.setBaseUrl(BASE_URL)
40+
.setDeviceName("iPhone 14")
41+
.setIgnoreHTTPSErrors(true)
42+
.setContextOptions(new Browser.NewContextOptions().setLocale("de-DE"));
43+
}
44+
}
45+
46+
private static void assertConfiguredFromOptionsFactory(Browser.NewContextOptions contextOptions) {
47+
assertNotNull(contextOptions);
48+
assertEquals(BASE_URL, contextOptions.baseURL);
49+
assertEquals(true, contextOptions.ignoreHTTPSErrors);
50+
assertEquals("de-DE", contextOptions.locale);
51+
assertEquals(390, contextOptions.viewportSize.get().width);
52+
assertEquals(664, contextOptions.viewportSize.get().height);
53+
assertEquals(true, contextOptions.isMobile);
54+
assertEquals(true, contextOptions.hasTouch);
55+
assertTrue(contextOptions.userAgent.contains("iPhone"), contextOptions.userAgent);
56+
}
57+
58+
@BeforeAll
59+
static void beforeAll(Browser browser, Browser.NewContextOptions contextOptions) {
60+
assertConfiguredFromOptionsFactory(contextOptions);
61+
contextOptionsFromBeforeAll = contextOptions;
62+
63+
BrowserContext context = browser.newContext(contextOptions);
64+
Page page = context.newPage();
65+
assertEquals(390, page.viewportSize().width);
66+
assertEquals(664, page.viewportSize().height);
67+
assertEquals("de-DE", page.evaluate("() => navigator.language"));
68+
assertTrue(((String) page.evaluate("() => navigator.userAgent")).contains("iPhone"));
69+
context.close();
70+
71+
// Modifying the options must not affect other tests.
72+
contextOptions.setBaseURL("http://localhost:1234/modified/").setLocale("fr-FR");
73+
}
74+
75+
@AfterAll
76+
static void afterAll(Browser.NewContextOptions contextOptions) {
77+
assertConfiguredFromOptionsFactory(contextOptions);
78+
}
79+
80+
@Test
81+
void shouldBeConfiguredFromOptionsFactory(Browser.NewContextOptions contextOptions) {
82+
assertConfiguredFromOptionsFactory(contextOptions);
83+
}
84+
85+
@Test
86+
void shouldReturnNewInstanceEveryTime(Browser.NewContextOptions contextOptions1, Browser.NewContextOptions contextOptions2) {
87+
assertNotSame(contextOptionsFromBeforeAll, contextOptions1);
88+
assertNotSame(contextOptions1, contextOptions2);
89+
contextOptions1.setBaseURL("http://localhost:1234/modified/").setLocale("fr-FR");
90+
assertConfiguredFromOptionsFactory(contextOptions2);
91+
}
92+
93+
@Test
94+
void shouldNotAffectBrowserContextFixture(Page page) {
95+
assertEquals(390, page.viewportSize().width);
96+
assertEquals("de-DE", page.evaluate("() => navigator.language"));
97+
}
98+
}

0 commit comments

Comments
 (0)