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 @SuppressWarnings("javadoc")
     46 public class LayoutTestBase extends TestCase {
     47     /**
     48      * Helper function used by tests to drag a button into a canvas containing
     49      * the given children.
     50      *
     51      * @param rule The rule to test on
     52      * @param targetNode The target layout node to drag into
     53      * @param dragBounds The (original) bounds of the dragged item
     54      * @param dropPoint The drag point we should drag to and drop
     55      * @param secondDropPoint An optional second drag point to drag to before
     56      *            drawing graphics and dropping (or null if not applicable)
     57      * @param insertIndex The expected insert position we end up with after
     58      *            dropping at the dropPoint
     59      * @param currentIndex If the dragged widget is already in the canvas this
     60      *            should be its child index; if not, pass in -1
     61      * @param graphicsFragments This is a varargs array of String fragments
     62      *            we expect to see in the graphics output on the drag over
     63      *            event.
     64      * @return The inserted node
     65      */
     66     protected INode dragInto(IViewRule rule, INode targetNode, Rect dragBounds, Point dropPoint,
     67             Point secondDropPoint, int insertIndex, int currentIndex,
     68             String... graphicsFragments) {
     69 
     70         String draggedButtonId = (currentIndex == -1) ? "@+id/DraggedButton" : targetNode
     71                 .getChildren()[currentIndex].getStringAttr(ANDROID_URI, ATTR_ID);
     72 
     73         IDragElement[] elements = TestDragElement.create(TestDragElement.create(
     74                 "android.widget.Button", dragBounds).id(draggedButtonId));
     75 
     76         // Enter target
     77         DropFeedback feedback = rule.onDropEnter(targetNode, null/*targetView*/, elements);
     78         assertNotNull(feedback);
     79         assertFalse(feedback.invalidTarget);
     80         assertNotNull(feedback.painter);
     81 
     82         if (currentIndex != -1) {
     83             feedback.sameCanvas = true;
     84         }
     85 
     86         // Move near top left corner of the target
     87         feedback = rule.onDropMove(targetNode, elements, feedback, dropPoint);
     88         assertNotNull(feedback);
     89 
     90         if (secondDropPoint != null) {
     91             feedback = rule.onDropMove(targetNode, elements, feedback, secondDropPoint);
     92             assertNotNull(feedback);
     93         }
     94 
     95         if (insertIndex == -1) {
     96             assertTrue(feedback.invalidTarget);
     97         } else {
     98             assertFalse(feedback.invalidTarget);
     99         }
    100 
    101         // Paint feedback and make sure it's what we expect
    102         TestGraphics graphics = new TestGraphics();
    103         assertNotNull(feedback.painter);
    104         feedback.painter.paint(graphics, targetNode, feedback);
    105         String drawn = graphics.getDrawn().toString();
    106 
    107         // Check that each graphics fragment is drawn
    108         for (String fragment : graphicsFragments) {
    109             if (!drawn.contains(fragment)) {
    110                 // Get drawn-output since unit test truncates message in below
    111                 // contains-assertion
    112                 System.out.println("Could not find: " + fragment);
    113                 System.out.println("Full graphics output: " + drawn);
    114             }
    115             assertTrue(fragment + " not found; full=" + drawn, drawn.contains(fragment));
    116         }
    117 
    118         // Attempt a drop?
    119         if (insertIndex == -1) {
    120             // No, not expected to succeed (for example, when drop point is over an
    121             // invalid region in RelativeLayout) - just return.
    122             return null;
    123         }
    124         int childrenCountBefore = targetNode.getChildren().length;
    125         rule.onDropped(targetNode, elements, feedback, dropPoint);
    126 
    127         if (currentIndex == -1) {
    128             // Inserting new from outside
    129             assertEquals(childrenCountBefore+1, targetNode.getChildren().length);
    130         } else {
    131             // Moving from existing; must remove in old position first
    132             ((TestNode) targetNode).removeChild(currentIndex);
    133 
    134             assertEquals(childrenCountBefore, targetNode.getChildren().length);
    135         }
    136         // Ensure that it's inserted in the right place
    137         String actualId = targetNode.getChildren()[insertIndex].getStringAttr(
    138                 ANDROID_URI, ATTR_ID);
    139         if (!draggedButtonId.equals(actualId)) {
    140             // Using assertEquals instead of fail to get nice diff view on test
    141             // failure
    142             List<String> childrenIds = new ArrayList<String>();
    143             for (INode child : targetNode.getChildren()) {
    144                 childrenIds.add(child.getStringAttr(ANDROID_URI, ATTR_ID));
    145             }
    146             int index = childrenIds.indexOf(draggedButtonId);
    147             String message = "Button found at index " + index + " instead of " + insertIndex
    148                     + " among " + childrenIds;
    149             System.out.println(message);
    150             assertEquals(message, draggedButtonId, actualId);
    151         }
    152 
    153 
    154         return targetNode.getChildren()[insertIndex];
    155     }
    156 
    157     /**
    158      * Utility method for asserting that two collections contain exactly the
    159      * same elements (regardless of order)
    160      * @param expected expected collection
    161      * @param actual  actual collection
    162      */
    163     public static void assertContainsSame(Collection<String> expected, Collection<String> actual) {
    164         if (expected.size() != actual.size()) {
    165             fail("Collection sizes differ; expected " + expected.size() + " but was "
    166                     + actual.size());
    167         }
    168 
    169         // Sort prior to comparison to ensure we have the same elements
    170         // regardless of order
    171         List<String> expectedList = new ArrayList<String>(expected);
    172         Collections.sort(expectedList);
    173         List<String> actualList = new ArrayList<String>(actual);
    174         Collections.sort(actualList);
    175         // Instead of just assertEquals(expectedList, actualList);
    176         // we iterate one element at a time so we can show the first
    177         // -difference-.
    178         for (int i = 0; i < expectedList.size(); i++) {
    179             String expectedElement = expectedList.get(i);
    180             String actualElement = actualList.get(i);
    181             if (!expectedElement.equals(actualElement)) {
    182                 System.out.println("Expected items: " + expectedList);
    183                 System.out.println("Actual items  : " + actualList);
    184             }
    185             assertEquals("Collections differ; first difference:", expectedElement, actualElement);
    186         }
    187     }
    188 
    189     protected void initialize(IViewRule rule, String fqn) {
    190         rule.onInitialize(fqn, new TestRulesEngine(fqn));
    191     }
    192 
    193     private static class TestRulesEngine implements IClientRulesEngine {
    194         private final String mFqn;
    195 
    196         protected TestRulesEngine(String fqn) {
    197             mFqn = fqn;
    198         }
    199 
    200         @Override
    201         public void debugPrintf(String msg, Object... params) {
    202             fail("Not supported in tests yet");
    203         }
    204 
    205         @Override
    206         public void displayAlert(String message) {
    207             fail("Not supported in tests yet");
    208         }
    209 
    210         @Override
    211         public String displayInput(String message, String value, IValidator filter) {
    212             fail("Not supported in tests yet");
    213             return null;
    214         }
    215 
    216         @Override
    217         public String getFqcn() {
    218             return mFqn;
    219         }
    220 
    221         @Override
    222         public IViewMetadata getMetadata(final String fqcn) {
    223             return new IViewMetadata() {
    224                 @Override
    225                 public String getDisplayName() {
    226                     // This also works when there is no "."
    227                     return fqcn.substring(fqcn.lastIndexOf('.') + 1);
    228                 }
    229 
    230                 @Override
    231                 public FillPreference getFillPreference() {
    232                     return ViewMetadataRepository.get().getFillPreference(fqcn);
    233                 }
    234 
    235                 @Override
    236                 public Margins getInsets() {
    237                     return null;
    238                 }
    239 
    240                 @Override
    241                 public List<String> getTopAttributes() {
    242                     return ViewMetadataRepository.get().getTopAttributes(fqcn);
    243                 }
    244             };
    245         }
    246 
    247         @Override
    248         public int getMinApiLevel() {
    249             return 8;
    250         }
    251 
    252         @Override
    253         public IViewRule loadRule(String fqcn) {
    254             fail("Not supported in tests yet");
    255             return null;
    256         }
    257 
    258         @Override
    259         public String displayReferenceInput(String currentValue) {
    260             fail("Not supported in tests yet");
    261             return null;
    262         }
    263 
    264         @Override
    265         public IValidator getResourceValidator() {
    266             fail("Not supported in tests yet");
    267             return null;
    268         }
    269 
    270         @Override
    271         public String displayResourceInput(String resourceTypeName, String currentValue) {
    272             fail("Not supported in tests yet");
    273             return null;
    274         }
    275 
    276         @Override
    277         public String[] displayMarginInput(String all, String left, String right, String top,
    278                 String bottom) {
    279             fail("Not supported in tests yet");
    280             return null;
    281         }
    282 
    283         @Override
    284         public String displayIncludeSourceInput() {
    285             fail("Not supported in tests yet");
    286             return null;
    287         }
    288 
    289         @Override
    290         public void select(Collection<INode> nodes) {
    291             fail("Not supported in tests yet");
    292         }
    293 
    294         @Override
    295         public String displayFragmentSourceInput() {
    296             fail("Not supported in tests yet");
    297             return null;
    298         }
    299 
    300         @Override
    301         public void layout() {
    302             fail("Not supported in tests yet");
    303         }
    304 
    305         @Override
    306         public void redraw() {
    307             fail("Not supported in tests yet");
    308         }
    309 
    310         @Override
    311         public Map<INode, Rect> measureChildren(INode parent, AttributeFilter filter) {
    312             return null;
    313         }
    314 
    315         @Override
    316         public int pxToDp(int px) {
    317             fail("Not supported in tests yet");
    318             return px;
    319         }
    320 
    321         @Override
    322         public String getUniqueId(String prefix) {
    323             fail("Not supported in tests yet");
    324             return null;
    325         }
    326 
    327         @Override
    328         public int screenToLayout(int pixels) {
    329             fail("Not supported in tests yet");
    330             return 0;
    331         }
    332 
    333         @Override
    334         public int dpToPx(int dp) {
    335             fail("Not supported in tests yet");
    336             return 0;
    337         }
    338 
    339         @Override
    340         public String getAppNameSpace() {
    341             fail("Not supported in tests yet");
    342             return null;
    343         }
    344     }
    345 
    346     public void testDummy() {
    347         // To avoid JUnit warning that this class contains no tests, even though
    348         // this is an abstract class and JUnit shouldn't try
    349     }
    350 }
    351