Home | History | Annotate | Download | only in tests
      1 /*
      2  * Copyright (C) 2012 Google Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  * 1.  Redistributions of source code must retain the above copyright
      8  *     notice, this list of conditions and the following disclaimer.
      9  * 2.  Redistributions in binary form must reproduce the above copyright
     10  *     notice, this list of conditions and the following disclaimer in the
     11  *     documentation and/or other materials provided with the distribution.
     12  *
     13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND
     14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     16  * ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE
     17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     19  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
     20  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     23  * SUCH DAMAGE.
     24  */
     25 
     26 #include "config.h"
     27 #include "web/PopupContainer.h"
     28 
     29 #include <gtest/gtest.h>
     30 
     31 using namespace WebCore;
     32 using namespace blink;
     33 
     34 class MockPopupContent : public PopupContent {
     35 public:
     36     virtual void setMaxHeight(int max) OVERRIDE { maxHeight = max; }
     37     virtual int popupContentHeight() const OVERRIDE { return height; }
     38     virtual ~MockPopupContent() { }
     39 
     40     virtual void layout() OVERRIDE
     41     {
     42         layoutCount++;
     43         width = std::min(maxWidth, width);
     44         height = std::min(maxHeight, height);
     45         height -= height % 16;
     46     }
     47 
     48     virtual void setMaxWidthAndLayout(int max) OVERRIDE
     49     {
     50         maxWidth = max;
     51         layout();
     52     }
     53 
     54     MockPopupContent(const IntSize& widgetSize)
     55         : width(widgetSize.width() - borderSize * 2)
     56         , height(widgetSize.height() - borderSize * 2)
     57         , maxWidth(width)
     58         , maxHeight(height)
     59         , layoutCount(0)
     60     {
     61     }
     62 
     63     int width;
     64     int height;
     65     int maxWidth;
     66     int maxHeight;
     67     unsigned layoutCount;
     68 
     69     static const int borderSize = 1; // Should match to kBorderSize in PopupContainer.cpp.
     70 };
     71 
     72 const int screenMaxX = 1024;
     73 const int screenMaxY = 768;
     74 const int targetControlWidth = 130;
     75 
     76 static IntRect calculatePositionWithTransformAndRTL(const IntRect& initialRect, const IntSize& transformOffset, int verticalOffset, PopupContent* content)
     77 {
     78     const bool isRTL = true;
     79     const int targetControlHeight = 20;
     80     const FloatRect screenRect(0, 0, screenMaxX, screenMaxY);
     81     const FloatRect windowRect(0, 0, 512, 512);
     82     int rtlOffset = targetControlWidth - initialRect.width();
     83     bool needToResizeView = false;
     84     return PopupContainer::layoutAndCalculateWidgetRectInternal(initialRect, targetControlHeight, windowRect, screenRect, !isRTL, rtlOffset, verticalOffset, transformOffset, content, needToResizeView);
     85 }
     86 
     87 static IntRect calculatePosition(const IntRect& initialRect, PopupContent* content, FloatRect windowRect = FloatRect(0, 0, 512, 512), bool isRTL = true)
     88 {
     89     const int targetControlHeight = 20;
     90     const FloatRect screenRect(0, 0, screenMaxX, screenMaxY);
     91     int rtlOffset = (targetControlWidth - initialRect.width()) * (isRTL ? 1 : -1);
     92     bool needToResizeView = false;
     93     return PopupContainer::layoutAndCalculateWidgetRectInternal(initialRect, targetControlHeight, windowRect, screenRect, !isRTL, rtlOffset, 0, IntSize(), content, needToResizeView);
     94 }
     95 
     96 TEST(PopupContainerTest, PopupPosition)
     97 {
     98     // Suppose that initialRect.location is the bottom-left corner of the target
     99     // control such as <select>.
    100 
    101     {
    102         // If initialRect is in the screen, nothing should happen.
    103         IntRect initialRect(100, 100, 256, 258);
    104         MockPopupContent content(initialRect.size());
    105         IntRect resultRect = calculatePosition(initialRect, &content);
    106         EXPECT_EQ(initialRect, resultRect);
    107         EXPECT_EQ(0u, content.layoutCount);
    108     }
    109 
    110     {
    111         // If the left edge of the control is projecting from the screen, making
    112         // the widget aligned to the right edge of the control.
    113         IntRect initialRect(-10, 100, 100, 258);
    114         MockPopupContent content(initialRect.size());
    115         IntRect resultRect = calculatePosition(initialRect, &content);
    116         EXPECT_EQ(IntRect(20, 100, 100, 258), resultRect);
    117     }
    118 
    119     {
    120         // Made the widget aligned to the right edge. But it's still projecting
    121         // from the screen.
    122         IntRect initialRect(-10, 100, targetControlWidth, 258);
    123         MockPopupContent content(initialRect.size());
    124         IntRect resultRect = calculatePosition(initialRect, &content);
    125         EXPECT_EQ(IntRect(0, 100, 120, 258), resultRect);
    126         EXPECT_EQ(118, content.width);
    127         EXPECT_TRUE(content.layoutCount);
    128     }
    129 
    130     {
    131         // If the right edge of the control is projecting from the screen,
    132         // shrink the width of the widget.
    133         IntRect initialRect(screenMaxX - 100, 100, targetControlWidth, 258);
    134         MockPopupContent content(initialRect.size());
    135         IntRect resultRect = calculatePosition(initialRect, &content);
    136         EXPECT_EQ(IntRect(screenMaxX - 100, 100, 100, 258), resultRect);
    137         EXPECT_EQ(98, content.width);
    138         EXPECT_TRUE(content.layoutCount);
    139     }
    140 
    141     {
    142         // If there is no enough room below, move the widget upwards.
    143         IntRect initialRect(100, 700, targetControlWidth, 258);
    144         MockPopupContent content(initialRect.size());
    145         IntRect resultRect = calculatePosition(initialRect, &content);
    146         EXPECT_EQ(IntRect(100, 422, targetControlWidth, 258), resultRect);
    147         EXPECT_EQ(0u, content.layoutCount);
    148     }
    149 
    150     {
    151         // There is no enough room below and above, and the below space is larger.
    152         IntRect initialRect(100, 300, targetControlWidth, 514);
    153         MockPopupContent content(initialRect.size());
    154         IntRect resultRect = calculatePosition(initialRect, &content);
    155         EXPECT_EQ(IntRect(100, 300, targetControlWidth, 466), resultRect);
    156         EXPECT_TRUE(content.layoutCount);
    157         EXPECT_EQ(464, content.height);
    158     }
    159 
    160     {
    161         // There is no enough room below and above, and the above space is larger.
    162         IntRect initialRect(100, 400, targetControlWidth, 514);
    163         MockPopupContent content(initialRect.size());
    164         IntRect resultRect = calculatePosition(initialRect, &content);
    165         EXPECT_EQ(IntRect(100, 10, targetControlWidth, 370), resultRect);
    166         EXPECT_TRUE(content.layoutCount);
    167         EXPECT_EQ(368, content.height);
    168     }
    169 
    170     {
    171         // There is not enough room to the right, so open the popup menu to the left.
    172         IntRect initialRect(screenMaxX - targetControlWidth - 6, 100, targetControlWidth * 2, 100);
    173         MockPopupContent content(initialRect.size());
    174         IntRect resultRect = calculatePosition(initialRect, &content, FloatRect(0, 0, screenMaxX, screenMaxY), false);
    175         EXPECT_EQ(IntRect(758, 100, 260, 100), resultRect);
    176     }
    177 
    178     {
    179         // Test for --webkit-transform:rotate(53deg).
    180         IntRect initialRect(100, 700, targetControlWidth, 258);
    181         MockPopupContent content(initialRect.size());
    182         IntSize transformOffset(-4, -8);
    183         IntRect resultRect = calculatePositionWithTransformAndRTL(initialRect, transformOffset, -104, &content);
    184         EXPECT_EQ(IntRect(104, 430, targetControlWidth, 258), resultRect);
    185         EXPECT_EQ(0u, content.layoutCount);
    186     }
    187 
    188     {
    189         // Test for --webkit-transform:rotate(-53deg).
    190         IntRect initialRect(100, 700, targetControlWidth, 258);
    191         MockPopupContent content(initialRect.size());
    192         IntSize transformOffset(4, -8);
    193         IntRect resultRect = calculatePositionWithTransformAndRTL(initialRect, transformOffset, 104, &content);
    194         EXPECT_EQ(IntRect(96, 430, targetControlWidth, 258), resultRect);
    195         EXPECT_EQ(0u, content.layoutCount);
    196     }
    197 }
    198