Home | History | Annotate | Download | only in layout
      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      3  *
      4  * Licensed under the Eclipse Public License, Version 1.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.eclipse.org/org/documents/epl-v10.php
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 
     18 package com.android.ide.common.layout;
     19 import static com.android.ide.common.layout.LayoutConstants.ANDROID_URI;
     20 import static com.android.ide.common.layout.LayoutConstants.ATTR_ID;
     21 
     22 import com.android.ide.common.api.DropFeedback;
     23 import com.android.ide.common.api.IClientRulesEngine;
     24 import com.android.ide.common.api.IDragElement;
     25 import com.android.ide.common.api.INode;
     26 import com.android.ide.common.api.IValidator;
     27 import com.android.ide.common.api.IViewMetadata;
     28 import com.android.ide.common.api.IViewRule;
     29 import com.android.ide.common.api.Margins;
     30 import com.android.ide.common.api.Point;
     31 import com.android.ide.common.api.Rect;
     32 import com.android.ide.eclipse.adt.internal.editors.layout.gre.ViewMetadataRepository;
     33 
     34 import java.util.ArrayList;
     35 import java.util.Collection;
     36 import java.util.Collections;
     37 import java.util.List;
     38 import java.util.Map;
     39 
     40 import junit.framework.TestCase;
     41 
     42 /**
     43  * Common layout helpers from LayoutRule tests
     44  */
     45 public class LayoutTestBase extends TestCase {
     46     /**
     47      * Helper function used by tests to drag a button into a canvas containing
     48      * the given children.
     49      *
     50      * @param rule The rule to test on
     51      * @param targetNode The target layout node to drag into
     52      * @param dragBounds The (original) bounds of the dragged item
     53      * @param dropPoint The drag point we should drag to and drop
     54      * @param secondDropPoint An optional second drag point to drag to before
     55      *            drawing graphics and dropping (or null if not applicable)
     56      * @param insertIndex The expected insert position we end up with after
     57      *            dropping at the dropPoint
     58      * @param currentIndex If the dragged widget is already in the canvas this
     59      *            should be its child index; if not, pass in -1
     60      * @param graphicsFragments This is a varargs array of String fragments
     61      *            we expect to see in the graphics output on the drag over
     62      *            event.
     63      * @return The inserted node
     64      */
     65     protected INode dragInto(IViewRule rule, INode targetNode, Rect dragBounds, Point dropPoint,
     66             Point secondDropPoint, int insertIndex, int currentIndex,
     67             String... graphicsFragments) {
     68 
     69         String draggedButtonId = (currentIndex == -1) ? "@+id/DraggedButton" : targetNode
     70                 .getChildren()[currentIndex].getStringAttr(ANDROID_URI, ATTR_ID);
     71 
     72         IDragElement[] elements = TestDragElement.create(TestDragElement.create(
     73                 "android.widget.Button", dragBounds).id(draggedButtonId));
     74 
     75         // Enter target
     76         DropFeedback feedback = rule.onDropEnter(targetNode, null/*targetView*/, elements);
     77         assertNotNull(feedback);
     78         assertFalse(feedback.invalidTarget);
     79         assertNotNull(feedback.painter);
     80 
     81         if (currentIndex != -1) {
     82             feedback.sameCanvas = true;
     83         }
     84 
     85         // Move near top left corner of the target
     86         feedback = rule.onDropMove(targetNode, elements, feedback, dropPoint);
     87         assertNotNull(feedback);
     88 
     89         if (secondDropPoint != null) {
     90             feedback = rule.onDropMove(targetNode, elements, feedback, secondDropPoint);
     91             assertNotNull(feedback);
     92         }
     93 
     94         if (insertIndex == -1) {
     95             assertTrue(feedback.invalidTarget);
     96         } else {
     97             assertFalse(feedback.invalidTarget);
     98         }
     99 
    100         // Paint feedback and make sure it's what we expect
    101         TestGraphics graphics = new TestGraphics();
    102         assertNotNull(feedback.painter);
    103         feedback.painter.paint(graphics, targetNode, feedback);
    104         String drawn = graphics.getDrawn().toString();
    105 
    106         // Check that each graphics fragment is drawn
    107         for (String fragment : graphicsFragments) {
    108             if (!drawn.contains(fragment)) {
    109                 // Get drawn-output since unit test truncates message in below
    110                 // contains-assertion
    111                 System.out.println("Could not find: " + fragment);
    112                 System.out.println("Full graphics output: " + drawn);
    113             }
    114             assertTrue(fragment + " not found; full=" + drawn, drawn.contains(fragment));
    115         }
    116 
    117         // Attempt a drop?
    118         if (insertIndex == -1) {
    119             // No, not expected to succeed (for example, when drop point is over an
    120             // invalid region in RelativeLayout) - just return.
    121             return null;
    122         }
    123         int childrenCountBefore = targetNode.getChildren().length;
    124         rule.onDropped(targetNode, elements, feedback, dropPoint);
    125 
    126         if (currentIndex == -1) {
    127             // Inserting new from outside
    128             assertEquals(childrenCountBefore+1, targetNode.getChildren().length);
    129         } else {
    130             // Moving from existing; must remove in old position first
    131             ((TestNode) targetNode).removeChild(currentIndex);
    132 
    133             assertEquals(childrenCountBefore, targetNode.getChildren().length);
    134         }
    135         // Ensure that it's inserted in the right place
    136         String actualId = targetNode.getChildren()[insertIndex].getStringAttr(
    137                 ANDROID_URI, ATTR_ID);
    138         if (!draggedButtonId.equals(actualId)) {
    139             // Using assertEquals instead of fail to get nice diff view on test
    140             // failure
    141             List<String> childrenIds = new ArrayList<String>();
    142             for (INode child : targetNode.getChildren()) {
    143                 childrenIds.add(child.getStringAttr(ANDROID_URI, ATTR_ID));
    144             }
    145             int index = childrenIds.indexOf(draggedButtonId);
    146             String message = "Button found at index " + index + " instead of " + insertIndex
    147                     + " among " + childrenIds;
    148             System.out.println(message);
    149             assertEquals(message, draggedButtonId, actualId);
    150         }
    151 
    152 
    153         return targetNode.getChildren()[insertIndex];
    154     }
    155 
    156     /**
    157      * Utility method for asserting that two collections contain exactly the
    158      * same elements (regardless of order)
    159      * @param expected expected collection
    160      * @param actual  actual collection
    161      */
    162     public static void assertContainsSame(Collection<String> expected, Collection<String> actual) {
    163         if (expected.size() != actual.size()) {
    164             fail("Collection sizes differ; expected " + expected.size() + " but was "
    165                     + actual.size());
    166         }
    167 
    168         // Sort prior to comparison to ensure we have the same elements
    169         // regardless of order
    170         List<String> expectedList = new ArrayList<String>(expected);
    171         Collections.sort(expectedList);
    172         List<String> actualList = new ArrayList<String>(actual);
    173         Collections.sort(actualList);
    174         // Instead of just assertEquals(expectedList, actualList);
    175         // we iterate one element at a time so we can show the first
    176         // -difference-.
    177         for (int i = 0; i < expectedList.size(); i++) {
    178             String expectedElement = expectedList.get(i);
    179             String actualElement = actualList.get(i);
    180             if (!expectedElement.equals(actualElement)) {
    181                 System.out.println("Expected items: " + expectedList);
    182                 System.out.println("Actual items  : " + actualList);
    183             }
    184             assertEquals("Collections differ; first difference:", expectedElement, actualElement);
    185         }
    186     }
    187 
    188     protected void initialize(IViewRule rule, String fqn) {
    189         rule.onInitialize(fqn, new TestRulesEngine(fqn));
    190     }
    191 
    192     private static class TestRulesEngine implements IClientRulesEngine {
    193         private final String mFqn;
    194 
    195         protected TestRulesEngine(String fqn) {
    196             mFqn = fqn;
    197         }
    198 
    199         public void debugPrintf(String msg, Object... params) {
    200             fail("Not supported in tests yet");
    201         }
    202 
    203         public void displayAlert(String message) {
    204             fail("Not supported in tests yet");
    205         }
    206 
    207         public String displayInput(String message, String value, IValidator filter) {
    208             fail("Not supported in tests yet");
    209             return null;
    210         }
    211 
    212         public String getFqcn() {
    213             return mFqn;
    214         }
    215 
    216         public IViewMetadata getMetadata(final String fqcn) {
    217             return new IViewMetadata() {
    218                 public String getDisplayName() {
    219                     // This also works when there is no "."
    220                     return fqcn.substring(fqcn.lastIndexOf('.') + 1);
    221                 }
    222 
    223                 public FillPreference getFillPreference() {
    224                     return ViewMetadataRepository.get().getFillPreference(fqcn);
    225                 }
    226 
    227                 public Margins getInsets() {
    228                     return null;
    229                 }
    230 
    231                 public List<String> getTopAttributes() {
    232                     return ViewMetadataRepository.get().getTopAttributes(fqcn);
    233                 }
    234             };
    235         }
    236 
    237         public int getMinApiLevel() {
    238             return 8;
    239         }
    240 
    241         public IViewRule loadRule(String fqcn) {
    242             fail("Not supported in tests yet");
    243             return null;
    244         }
    245 
    246         public String displayReferenceInput(String currentValue) {
    247             fail("Not supported in tests yet");
    248             return null;
    249         }
    250 
    251         public IValidator getResourceValidator() {
    252             fail("Not supported in tests yet");
    253             return null;
    254         }
    255 
    256         public String displayResourceInput(String resourceTypeName, String currentValue) {
    257             fail("Not supported in tests yet");
    258             return null;
    259         }
    260 
    261         public String[] displayMarginInput(String all, String left, String right, String top,
    262                 String bottom) {
    263             fail("Not supported in tests yet");
    264             return null;
    265         }
    266 
    267         public String displayIncludeSourceInput() {
    268             fail("Not supported in tests yet");
    269             return null;
    270         }
    271 
    272         public void select(Collection<INode> nodes) {
    273             fail("Not supported in tests yet");
    274         }
    275 
    276         public String displayFragmentSourceInput() {
    277             fail("Not supported in tests yet");
    278             return null;
    279         }
    280 
    281         public void layout() {
    282             fail("Not supported in tests yet");
    283         }
    284 
    285         public void redraw() {
    286             fail("Not supported in tests yet");
    287         }
    288 
    289         public Map<INode, Rect> measureChildren(INode parent, AttributeFilter filter) {
    290             return null;
    291         }
    292 
    293         public int pxToDp(int px) {
    294             fail("Not supported in tests yet");
    295             return px;
    296         }
    297 
    298         public String getUniqueId(String prefix) {
    299             fail("Not supported in tests yet");
    300             return null;
    301         }
    302 
    303         public int screenToLayout(int pixels) {
    304             fail("Not supported in tests yet");
    305             return 0;
    306         }
    307 
    308         public int dpToPx(int dp) {
    309             fail("Not supported in tests yet");
    310             return 0;
    311         }
    312     }
    313 
    314     public void testDummy() {
    315         // To avoid JUnit warning that this class contains no tests, even though
    316         // this is an abstract class and JUnit shouldn't try
    317     }
    318 }
    319