Skip to content

Commit

Permalink
[plugin-web-app] Add mobile emulation steps
Browse files Browse the repository at this point in the history
  • Loading branch information
uarlouski authored and valfirst committed Dec 12, 2023
1 parent 4b450cf commit bf52d02
Show file tree
Hide file tree
Showing 5 changed files with 242 additions and 0 deletions.
45 changes: 45 additions & 0 deletions docs/modules/plugins/pages/plugin-web-app.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -1395,6 +1395,51 @@ Then value `$value` is selected in slider located by `$locator`
Then value `50` is selected in slider located by `id(test_slider)`
----

=== Mobile Emulation

==== Emulate mobile device

Emulates mobile device using the provided configuration.

IMPORTANT: The step is only supported by Chrome browser.

[source,gherkin]
----
When I emulate mobile device with configuration:`$jsonConfiguration`
----

* `$jsonConfiguration` - The JSON containing https://chromedevtools.github.io/devtools-protocol/tot/Emulation/#method-setDeviceMetricsOverride[device metrics] to override.

.Emulate iPhone 14 Pro Max
[source,gherkin]
----
When I emulate mobile device with configuration:`{
"width": 430,
"height": 932,
"deviceScaleFactor": 3,
"mobile": true
}`
----

==== Reset mobile device emulation

Resets the mobile device emulation returning the browser to its initial state.

IMPORTANT: The step is only supported by Chrome browser.

IMPORTANT: The step ignores the `web/desktop/chrome/mobile_emulation/phone` profile settings when returning the browser to its initial state.

[source,gherkin]
----
When I reset mobile device emulation
----

.Resets device metrics to defaults
[source,gherkin]
----
When I reset mobile device emulation
----

== Tips & Tricks

=== Validate URL host of the opened page
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*
* Copyright 2019-2023 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.steps.ui.web.devtools;

import static org.apache.commons.lang3.Validate.isTrue;

import java.util.Map;

import org.jbehave.core.annotations.When;
import org.openqa.selenium.chromium.HasCdp;
import org.openqa.selenium.remote.Browser;
import org.vividus.selenium.IWebDriverProvider;
import org.vividus.selenium.manager.IWebDriverManager;
import org.vividus.util.json.JsonUtils;

public class MobileEmulationSteps
{
private final IWebDriverProvider webDriverProvider;
private final IWebDriverManager webDriverManager;
private final JsonUtils jsonUtils;

public MobileEmulationSteps(IWebDriverProvider webDriverProvider, IWebDriverManager webDriverManager,
JsonUtils jsonUtils)
{
this.webDriverProvider = webDriverProvider;
this.webDriverManager = webDriverManager;
this.jsonUtils = jsonUtils;
}

/**
* Emulates mobile device using the provided configuration.
*
* <p>
* <strong>The step is only supported by Chrome browser.</strong>
* </p>
*
* @param jsonConfiguration The JSON containing device metrics to override.
*/
@SuppressWarnings("unchecked")
@When("I emulate mobile device with configuration:`$jsonConfiguration`")
public void overrideDeviceMetrics(String jsonConfiguration)
{
executeCdpCommand("Emulation.setDeviceMetricsOverride", jsonUtils.toObject(jsonConfiguration, Map.class));
}

/**
* Resets the mobile device emulation returning the browser to its initial state.
*
* <p>
* <strong>The step is only supported by Chrome browser.</strong>
* </p>
*/
@When("I reset mobile device emulation")
public void clearDeviceMetrics()
{
executeCdpCommand("Emulation.clearDeviceMetricsOverride", Map.of());
}

private void executeCdpCommand(String command, Map<String, Object> metrics)
{
isTrue(webDriverManager.isBrowserAnyOf(Browser.CHROME), "The step is only supported by Chrome browser.");
HasCdp hasCdp = webDriverProvider.getUnwrapped(HasCdp.class);
hasCdp.executeCdpCommand(command, metrics);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,8 @@
<property name="windowsStrategy" value="${selenium.windows-strategy}" />
</bean>

<bean id="mobileEmulationSteps" class="org.vividus.steps.ui.web.devtools.MobileEmulationSteps" />

<bean class="org.vividus.ui.web.monitor.PublishingWebScreenshotOnFailureMonitor"
parent="abstractPublishingScreenshotOnFailureMonitor"/>

Expand Down Expand Up @@ -302,6 +304,7 @@
<idref bean="performanceSteps" />
<idref bean="windowSteps" />
<idref bean="browserSteps" />
<idref bean="mobileEmulationSteps" />
</util:list>

<util:map id="propertyEditors-WebUi" key-type="java.lang.Class">
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/*
* Copyright 2019-2023 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.steps.ui.web.devtools;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import java.util.Map;

import org.junit.jupiter.api.BeforeEach;
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.openqa.selenium.chromium.HasCdp;
import org.openqa.selenium.remote.Browser;
import org.vividus.selenium.IWebDriverProvider;
import org.vividus.selenium.manager.IWebDriverManager;
import org.vividus.util.json.JsonUtils;

@ExtendWith(MockitoExtension.class)
class MobileEmulationStepsTests
{
@Mock private IWebDriverProvider webDriverProvider;
@Mock private IWebDriverManager webDriverManager;
@Mock private HasCdp hasCdp;
private MobileEmulationSteps steps;

@BeforeEach
void init()
{
this.steps = new MobileEmulationSteps(webDriverProvider, webDriverManager, new JsonUtils());
}

@Test
void shouldOverrideDeviceMetrics()
{
when(webDriverManager.isBrowserAnyOf(Browser.CHROME)).thenReturn(true);
when(webDriverProvider.getUnwrapped(HasCdp.class)).thenReturn(hasCdp);

String metrics = """
{
"width": 430,
"height": 932,
"deviceScaleFactor": 3,
"mobile": true
}
""";

steps.overrideDeviceMetrics(metrics);

verify(hasCdp).executeCdpCommand("Emulation.setDeviceMetricsOverride", Map.of(
"width", 430,
"height", 932,
"deviceScaleFactor", 3,
"mobile", true
));
}

@Test
void shouldClearDeviceMetrics()
{
when(webDriverManager.isBrowserAnyOf(Browser.CHROME)).thenReturn(true);
when(webDriverProvider.getUnwrapped(HasCdp.class)).thenReturn(hasCdp);

steps.clearDeviceMetrics();

verify(hasCdp).executeCdpCommand("Emulation.clearDeviceMetricsOverride", Map.of());
}

@Test
void shouldFailIfBrowserIsNotChrome()
{
when(webDriverManager.isBrowserAnyOf(Browser.CHROME)).thenReturn(false);

IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, steps::clearDeviceMetrics);

assertEquals("The step is only supported by Chrome browser.", thrown.getMessage());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
Scenario: Validate steps: 'When I emulate mobile device with configuration:`$deviceMetrics`', 'When I reset mobile device emulation'
Given I am on page with URL `${vividus-test-site-url}`
When I execute javascript `return window.screen;` and save result to scenario variable `initialScreen`
When I emulate mobile device with configuration:`{
"width": 430,
"height": 932,
"deviceScaleFactor": 3,
"mobile": true
}`

When I execute javascript `return window.screen;` and save result to scenario variable `overridenScreen`
Then `${overridenScreen.height}` is = `932`
Then `${overridenScreen.width}` is = `430`

When I reset mobile device emulation

When I execute javascript `return window.screen;` and save result to scenario variable `clearedScreen`
Then `${initialScreen.height}` is = `${clearedScreen.height}`
Then `${initialScreen.width}` is = `${clearedScreen.width}`

0 comments on commit bf52d02

Please sign in to comment.