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 +}