mobile/android/base/tests/testVkbOverlap.java

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/mobile/android/base/tests/testVkbOverlap.java	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,105 @@
     1.4 +package org.mozilla.gecko.tests;
     1.5 +
     1.6 +import org.mozilla.gecko.Actions;
     1.7 +import org.mozilla.gecko.PaintedSurface;
     1.8 +
     1.9 +import android.net.Uri;
    1.10 +
    1.11 +/**
    1.12 + * A test to ensure that when an input field is focused, it is not obscured by the VKB.
    1.13 + * - Loads a page with an input field past the bottom of the visible area.
    1.14 + * - scrolls down to make the input field visible at the bottom of the screen.
    1.15 + * - taps on the input field to bring up the VKB
    1.16 + * - verifies that the input field is still visible.
    1.17 + */
    1.18 +public class testVkbOverlap extends PixelTest {
    1.19 +    private static final int CURSOR_BLINK_PERIOD = 500;
    1.20 +    private static final int LESS_THAN_CURSOR_BLINK_PERIOD = CURSOR_BLINK_PERIOD - 50;
    1.21 +    private static final int PAGE_SETTLE_TIME = 5000;
    1.22 +
    1.23 +    public void testVkbOverlap() {
    1.24 +        blockForGeckoReady();
    1.25 +        testSetup("initial-scale=1.0, user-scalable=no", false);
    1.26 +        testSetup("initial-scale=1.0", false);
    1.27 +        testSetup("", "phone".equals(mDevice.type));
    1.28 +    }
    1.29 +
    1.30 +    private void testSetup(String viewport, boolean shouldZoom) {
    1.31 +        loadAndPaint(getAbsoluteUrl("/robocop/test_viewport.sjs?metadata=" + Uri.encode(viewport)));
    1.32 +
    1.33 +        // scroll to the bottom of the page and let it settle
    1.34 +        Actions.RepeatedEventExpecter paintExpecter = mActions.expectPaint();
    1.35 +        MotionEventHelper meh = new MotionEventHelper(getInstrumentation(), mDriver.getGeckoLeft(), mDriver.getGeckoTop());
    1.36 +        meh.dragSync(10, 150, 10, 50);
    1.37 +
    1.38 +        // the input field has a green background, so let's count the number of green pixels
    1.39 +        int greenPixelCount = 0;
    1.40 +
    1.41 +        PaintedSurface painted = waitForPaint(paintExpecter);
    1.42 +        paintExpecter.unregisterListener();
    1.43 +        try {
    1.44 +            greenPixelCount = countGreenPixels(painted);
    1.45 +        } finally {
    1.46 +            painted.close();
    1.47 +        }
    1.48 +
    1.49 +        mAsserter.ok(greenPixelCount > 0, "testInputVisible", "Found " + greenPixelCount + " green pixels after scrolling");
    1.50 +
    1.51 +        paintExpecter = mActions.expectPaint();
    1.52 +        // the input field should be in the bottom-left corner, so tap thereabouts
    1.53 +        meh.tap(5, mDriver.getGeckoHeight() - 5);
    1.54 +
    1.55 +        // After tapping in the input field, the page needs some time to do stuff, like draw and undraw the focus highlight
    1.56 +        // on the input field, trigger the VKB, process any resulting events generated by the system, and scroll the page. So
    1.57 +        // we give it a few seconds to do all that. We are sufficiently generous with our definition of "few seconds" to
    1.58 +        // prevent intermittent test failures.
    1.59 +        try {
    1.60 +            Thread.sleep(PAGE_SETTLE_TIME);
    1.61 +        } catch (InterruptedException ie) {
    1.62 +            ie.printStackTrace();
    1.63 +        }
    1.64 +
    1.65 +        // now that the focus is in the text field we will repaint every 500ms as the cursor blinks, so we need to use a smaller
    1.66 +        // "no paints" threshold to consider the page painted
    1.67 +        paintExpecter.blockUntilClear(LESS_THAN_CURSOR_BLINK_PERIOD);
    1.68 +        paintExpecter.unregisterListener();
    1.69 +        painted = mDriver.getPaintedSurface();
    1.70 +        try {
    1.71 +            // if the vkb scrolled into view as expected, then the number of green pixels now visible should be about the
    1.72 +            // same as it was before, since the green pixels indicate the text input is in view. use a fudge factor of 0.9 to
    1.73 +            // account for borders and such of the text input which might still be out of view.
    1.74 +            int newCount = countGreenPixels(painted);
    1.75 +
    1.76 +            // if zooming is allowed, the number of green pixels visible should have increased substatially
    1.77 +            if (shouldZoom) {
    1.78 +                mAsserter.ok(newCount > greenPixelCount * 1.5, "testVkbOverlap", "Found " + newCount + " green pixels after tapping; expected " + greenPixelCount);
    1.79 +            } else {
    1.80 +                mAsserter.ok((Math.abs(greenPixelCount - newCount) / greenPixelCount < 0.1), "testVkbOverlap", "Found " + newCount + " green pixels after tapping; expected " + greenPixelCount);
    1.81 +            }
    1.82 +        } finally {
    1.83 +            painted.close();
    1.84 +        }
    1.85 +    }
    1.86 +
    1.87 +    private int countGreenPixels(PaintedSurface painted) {
    1.88 +        int count = 0;
    1.89 +        for (int y = painted.getHeight() - 1; y >= 0; y--) {
    1.90 +            for (int x = painted.getWidth() - 1; x >= 0; x--) {
    1.91 +                int pixel = painted.getPixelAt(x, y);
    1.92 +                int r = (pixel >> 16) & 0xFF;
    1.93 +                int g = (pixel >> 8) & 0xFF;
    1.94 +                int b = (pixel & 0xFF);
    1.95 +                if (g > (r + 0x30) && g > (b + 0x30)) {
    1.96 +                    // there's more green in this pixel than red or blue, so count it.
    1.97 +                    // the reason this is so hacky-looking is because even though green is supposed to
    1.98 +                    // be (r,g,b) = (0x00, 0x80, 0x00), the GL readback ends up coming back quite
    1.99 +                    // different.
   1.100 +                    count++;
   1.101 +                }
   1.102 +                // uncomment for debugging:
   1.103 +                // if (pixel != -1) mAsserter.dumpLog("Pixel at " + x + ", " + y + ": " + Integer.toString(pixel, 16));
   1.104 +            }
   1.105 +        }
   1.106 +        return count;
   1.107 +    }
   1.108 +}

mercurial