chromium/content/public/android/javatests/src/org/chromium/content/browser/ViewportTest.java

// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package org.chromium.content.browser;

import android.content.Context;
import android.util.DisplayMetrics;
import android.view.WindowManager;

import androidx.test.InstrumentationRegistry;
import androidx.test.filters.MediumTest;

import org.junit.Assert;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;

import org.chromium.base.test.BaseJUnit4ClassRunner;
import org.chromium.base.test.util.CommandLineFlags;
import org.chromium.base.test.util.Feature;
import org.chromium.content_public.browser.test.util.JavaScriptUtils;
import org.chromium.content_shell_apk.ContentShellActivityTestRule;
import org.chromium.ui.base.DeviceFormFactor;

/** Test suite for viewport-related properties. */
@RunWith(BaseJUnit4ClassRunner.class)
public class ViewportTest {
    @Rule
    public ContentShellActivityTestRule mActivityTestRule = new ContentShellActivityTestRule();

    protected String evaluateStringValue(String expression) throws Throwable {
        return JavaScriptUtils.executeJavaScriptAndWaitForResult(
                mActivityTestRule.getWebContents(), expression);
    }

    protected float evaluateFloatValue(String expression) throws Throwable {
        return Float.valueOf(evaluateStringValue(expression));
    }

    protected int evaluateIntegerValue(String expression) throws Throwable {
        return Integer.parseInt(evaluateStringValue(expression));
    }

    @Test
    @MediumTest
    @Feature({"Viewport", "InitialViewportSize"})
    @CommandLineFlags.Add({"enable-features=DefaultViewportIsDeviceWidth"})
    public void testDefaultViewportSize_DefaultViewportIsDeviceWidth() throws Throwable {
        testDefaultViewportSize(/* isDefaultViewportDeviceWidth= */ true);
    }

    @Test
    @MediumTest
    @Feature({"Viewport", "InitialViewportSize"})
    @CommandLineFlags.Add({"disable-features=DefaultViewportIsDeviceWidth"})
    public void testDefaultViewportSize_DefaultViewportIs980() throws Throwable {
        testDefaultViewportSize(/* isDefaultViewportDeviceWidth= */ false);
    }

    private void testDefaultViewportSize(boolean isDefaultViewportDeviceWidth) throws Throwable {
        mActivityTestRule.launchContentShellWithUrl("about:blank");
        mActivityTestRule.waitForActiveShellToBeDoneLoading();

        Context context = InstrumentationRegistry.getTargetContext();
        WindowManager winManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        DisplayMetrics metrics = new DisplayMetrics();
        winManager.getDefaultDisplay().getMetrics(metrics);

        // window.devicePixelRatio should match the default display. Only check to 1 decimal place
        // to allow for rounding.
        Assert.assertEquals(metrics.density, evaluateFloatValue("window.devicePixelRatio"), 0.1);

        // Check that the viewport width is vaguely sensible.
        int viewportWidth = evaluateIntegerValue("document.documentElement.clientWidth");
        Assert.assertTrue(Math.abs(evaluateIntegerValue("window.innerWidth") - viewportWidth) <= 1);
        if (isDefaultViewportDeviceWidth && isTablet()) {
            // On tablets, when the DefaultViewportIsDeviceWidth flag is enabled, viewport width
            // will default to device width without viewport tag.
            Assert.assertTrue(viewportWidth >= metrics.widthPixels / metrics.density - 1);
            Assert.assertTrue(viewportWidth <= metrics.widthPixels / metrics.density + 1);
        } else {
            Assert.assertTrue(viewportWidth >= 979);
            Assert.assertTrue(
                    viewportWidth <= Math.max(981, metrics.widthPixels / metrics.density + 1));
        }
    }

    private boolean isTablet() {
        return DeviceFormFactor.isNonMultiDisplayContextOnTablet(mActivityTestRule.getActivity());
    }
}