Skip to content

CDP Emulation Domain

aqualityAutomation edited this page Mar 28, 2023 · 11 revisions

CDP Emulation Domain

Common emulation commands

The test class EmulationTests demonstrates several common emulation commands that are not related by the common functionality.

Should_BePossibleTo_CheckThatBrowserCanEmulate

The Should_BePossibleTo_CheckThatBrowserCanEmulate test demonstrates the canEmulate() method, which checks whether the current browser supports device emulation.

        [Test]
        public void Should_BePossibleTo_CheckThatBrowserCanEmulate()
        {
            var canEmulate = false;
            Assert.DoesNotThrowAsync(async () => canEmulate = await DevTools.CanEmulate(), "Should be possible to check that browser can emulate");
            Assert.IsTrue(canEmulate, "Emulation should be supported in browser");
        }

Should_BePossibleTo_SetScriptExecutionDisabled_AndEnableAgain

The Should_BePossibleTo_SetScriptExecutionDisabled_AndEnableAgain demonstrates the ability to disable and enable browser-side javascript execution using the following methods:

void setScriptExecutionDisabled(boolean value) - enables (value = false) and disables (value = true) javascript execution in the browser; void setScriptExecutionDisabled() - disables javascript execution in the browser. This test uses a web page containing buttons that trigger various Alerts using javascscript. After calling the setScriptExecutionDisabled() method, Alert will not appear when the button is clicked (a NoAlertPresentException is thrown). Next, the JS execution is activated using setScriptExecutionDisabled(true) and now Alert will be called when the button is clicked.

        [Test]
        public void Should_BePossibleTo_SetScriptExecutionDisabled_AndEnableAgain()
        {
            var alertsForm = new JavaScriptAlertsForm();
            alertsForm.Open();
            alertsForm.JsAlertButton.Click();
            Assert.DoesNotThrow(() => AqualityServices.Browser.HandleAlert(AlertAction.Accept), "Alert should appear and be handled");

            Assert.DoesNotThrowAsync(() => DevTools.SetScriptExecutionDisabled(), "Should be possible to set script execution disabled");
            alertsForm.JsAlertButton.Click();
            Assert.Throws<NoAlertPresentException>(() => AqualityServices.Browser.HandleAlert(AlertAction.Accept), "Alert should not appear as JS scripts disabled");

            Assert.DoesNotThrowAsync(() => DevTools.SetScriptExecutionDisabled(false), "Should be possible to set script execution enabled");
            alertsForm.JsAlertButton.Click();
            Assert.DoesNotThrow(() => AqualityServices.Browser.HandleAlert(AlertAction.Accept), "Alert should appear and be handled as JS scripts are enabled again");
        }

Should_BePossibleTo_SetEmulatedMedia

Using DevTools, it is possible to override the mediaType property of the device that CSS media queries are oriented to when generating styles (one style for PCs, another for smartphones, third for TVs, etc.). Aquality Selenium works with this property using the following methods:

void setEmulatedMedia(Optional media, Optional<Map<String, String>> mediaFeatures) - sets the media type and properties to be emulated (such as screen sizes, aspect ratio, etc.). Empty media disables mediaType override; void setEmulatedMedia(String media, Map<String, String> mediaFeatures) - the method is similar to the previous one, only without the use of Optional; void setEmulatedMedia(Map<String, Object> params) - sets the mediaType emulation through parameters that are directly used in the DevTools command for the Emulation.setEmulatedMedia method; void disableEmulatedMediaOverride() - disables media type override. The setEmulatedMediaTest test demonstrates media type overriding.

        [Test]
        public void Should_BePossibleTo_SetEmulatedMedia()
        {
            const string emulatedMedia = "projection";

            static string getMediaType() => AqualityServices.Browser.ExecuteScriptFromFile<string>("Resources.GetMediaType.js");
            var initialValue = getMediaType();
            Assume.That(initialValue, Does.Not.Contain(emulatedMedia), "Initial media type should differ from value to be set");

            Assert.DoesNotThrowAsync(() => DevTools.SetEmulatedMedia(emulatedMedia, new Dictionary<string, string> { { "width", DeviceModeSettingWidth.ToString() } }), 
                "Should be possible to set emulated media");
            Assert.AreEqual(emulatedMedia, getMediaType(), "Media type should equal to emulated");
            Assert.DoesNotThrowAsync(() => DevTools.DisableEmulatedMediaOverride(), "Should be possible to disable emulated media override");
            Assert.AreEqual(initialValue, getMediaType(), "Media type should equal to initial after disabling the override");
        }

Geolocation emulation

In Aquality Selenium, arbitrary geolocation is emulated using the following methods:

void setGeolocationOverride(Optional latitude, Optional longitude, Optional accuracy) - sets the current latitude, longitude, and geolocation accuracy. Omitting any of the parameters emulates position unavailable; void setGeolocationOverride(double latitude, double longitude, double accuracy) - has almost the same functionality as the previous method, the only difference is the use of primitives as parameters; void setGeolocationOverride(double latitude, double longitude) - a wrapper over the previous method, setting accuracy = 1. That is 100% geolocation accuracy. void clearGeolocationOverride() - resets the overridden geolocation set by the setGeolocationOverride() method. Geolocation override is demonstrated in the OverrideGeolocationTest class.

        [Test]
        public void Should_BePossibleTo_SetAndClearGeoLocationOverride()
        {
            CheckGeolocationOverride(
                (latitude, longitude, accuracy) => 
                Assert.DoesNotThrowAsync(() => DevTools.SetGeoLocationOverride(latitude, longitude, accuracy), "Should be possible to override geoLocation"),
                () => Assert.DoesNotThrowAsync(() => DevTools.ClearGeolocationOverride(), "Should be possible to clear geoLocation"));
        }

        [Test]
        public void Should_BePossibleTo_SetAndClearGeoLocationOverride_ByExecutingCdpCommand()
        {
            CheckGeolocationOverride(
                   (latitude, longitude, accuracy) =>
                   DevTools.ExecuteCdpCommand(
                       new SetGeolocationOverrideCommandSettings().CommandName,
                       new Dictionary<string, object>
                       {
                        { "latitude", latitude},
                        { "longitude", longitude},
                        { "accuracy", accuracy},
                       }),
                   () => DevTools.ExecuteCdpCommand(new ClearGeolocationOverrideCommandSettings().CommandName, new Dictionary<string, object>()));
        }

In the overrideGeolocationTest test, using the setGeolocationOverride() method, a new geolocation is set (LAT_FOR_OVERRIDE, LNG_FOR_OVERRIDE coordinates) and checks that the coordinates have been changed. Next, the geolocation is reset using the clearGeolocationOverride() method to the default value and it is checked that the coordinate values have returned to their original values.

Device Emulation

Using the DevTools commands, it is possible to emulate various devices by overriding the screen size (width, height), device type (desktop or mobile) and orientation (portrait or landscape). In Aquality Selenium, work with this functionality is carried out using the following methods:

void setDeviceMetricsOverride(Integer width, Integer height, Number deviceScaleFactor, Boolean mobile, Optional screenOrientationType, Optional screenOrientationAngle) - sets the width, height, scale, device type, orientation type, and angle at which the device is located; void setDeviceMetricsOverride(Integer width, Integer height, Number deviceScaleFactor, Boolean mobile) - overloaded version of the previous method with default values for screenOrientationType and screenOrientationAngle; void setDeviceMetricsOverride(Map<String, Object> params) - in this method, the device is configured using the Map<String, Object> params object, where the key is the name of the parameter (for example, the screen width), the value is the value of this parameter. These parameters are directly used in DevTools method Emulation.setDeviceMetricsOverride; void clearDeviceMetricsOverride() - resets overridden device metrics. The DeviceEmulationTest test class demonstrates how these methods work.

In the Should_BePossibleTo_SetAndClearDeviceMetricsOverride_WithVersionSpecificParameters test, the setDeviceMetricsOverride() method is used to set the width, height, scale, and device type. Checks for all tests are carried out in the checkDeviceMetricsOverride(Runnable setAction) method.

        [Test]
        public void Should_BePossibleTo_SetAndClearDeviceMetricsOverride_WithVersionSpecificParameters()
        {
            void setAction(long width, long height, bool isMobile, double scaleFactor)
            {
                var parameters = new OpenQA.Selenium.DevTools.V108.Emulation.SetDeviceMetricsOverrideCommandSettings
                {
                    DisplayFeature = new OpenQA.Selenium.DevTools.V108.Emulation.DisplayFeature
                    {
                        Orientation = OpenQA.Selenium.DevTools.V108.Emulation.DisplayFeatureOrientationValues.Horizontal
                    },
                    Width = width,
                    Height = height,
                    Mobile = isMobile,
                    DeviceScaleFactor = scaleFactor
                };
                Assert.DoesNotThrowAsync(() => DevTools.SetDeviceMetricsOverride(parameters), 
                    "Should be possible to set device metrics override with version-specific parameters, even if the version doesn't match");
            }

            CheckDeviceMetricsOverride(setAction);
        }

This method assert that the current screen height is different from the set height, then runs the setAction action to override the device metrics and checks that the screen height has been overridden. Then the overridden values are reset to default values using clearDeviceMetricsOverride() method and success of this action is checked.

In the Should_BePossibleTo_SetAndClearDeviceMetricsOverride_WithVersionSpecificParameters, device size override is performed using the generic X sendCommand(Command command) method of the DevToolsHandling class, which sends an arbitrary DevTools Command (class from org.openqa.selenium.devtools package) to the browser. In this case, an Emulation.setDeviceMetricsOverride() command is sent, the result of which is similar to the actions performed in the previous test.