1 /*
   2  * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package test.javafx.scene.bounds;
  27 
  28 import static test.com.sun.javafx.test.TestHelper.assertBoundsEqual;
  29 import static test.com.sun.javafx.test.TestHelper.assertGroupBounds;
  30 import static test.com.sun.javafx.test.TestHelper.box;
  31 import static test.com.sun.javafx.test.TestHelper.formatBounds;
  32 import static junit.framework.Assert.assertEquals;
  33 
  34 import java.util.LinkedList;
  35 
  36 import javafx.geometry.Bounds;
  37 import javafx.scene.Group;
  38 import javafx.scene.shape.Rectangle;
  39 
  40 import org.junit.Test;
  41 
  42 public class GroupBoundsTest {
  43 
  44     /***************************************************************************
  45      * * Group Tests * * These are tests related to transforming the basic node
  46      * types including * * /
  47      **************************************************************************/
  48 
  49     // test that an empty group has empty bounds
  50     public @Test
  51     void testGroupBounds_Empty() {
  52         assertGroupBounds(new Group());
  53     }
  54 
  55     // test that adding a node to a group updates the Groups bounds
  56     public @Test
  57     void testGroupBounds_AddRect() {
  58         Group g = new Group();
  59         assertGroupBounds(g);
  60 
  61         g.getChildren().add(new Rectangle(20, 20, 50, 50));
  62         assertGroupBounds(g);
  63 
  64         g.getChildren().add(new Rectangle(90, 20, 50, 50));
  65         assertGroupBounds(g);
  66     }
  67 
  68     // test that changing a node in a group updates the groups bounds
  69     public @Test
  70     void testGroupBounds_ChangeRect() {
  71         Rectangle r1 = new Rectangle(20, 20, 50, 50);
  72         Rectangle r2 = new Rectangle(90, 20, 50, 50);
  73         Group g = new Group(r1, r2);
  74 
  75         assertGroupBounds(g);
  76 
  77         r1.setWidth(200);
  78         assertGroupBounds(g);
  79         r2.setWidth(20);
  80         assertGroupBounds(g);
  81     }
  82 
  83     // test that removing a node from the group updates the Groups bounds
  84     public @Test
  85     void testGroupBounds_RemoveRect() {
  86         Rectangle r1 = new Rectangle(20, 20, 50, 50);
  87         Rectangle r2 = new Rectangle(90, 20, 50, 50);
  88         Group g = new Group(r1, r2);
  89 
  90         assertGroupBounds(g);
  91 
  92         g.getChildren().remove(r2);
  93         assertGroupBounds(g);
  94         g.getChildren().remove(r1);
  95         assertGroupBounds(g);
  96     }
  97 
  98     public @Test
  99     void testGroupBounds_RemoveAllChildNodesAndAddOneBack() {
 100         Rectangle r1 = new Rectangle(20, 20, 50, 50);
 101         Rectangle r2 = new Rectangle(90, 20, 50, 50);
 102         Group g = new Group(r1, r2);
 103 
 104         assertGroupBounds(g);
 105         g.getChildren().clear();
 106         assertGroupBounds(g);
 107         g.getChildren().add(r1);
 108         assertGroupBounds(g);
 109     }
 110 
 111     // test that adding the first node to a Group, which node is an invisible
 112     // node, gets the right answer for the Group's bounds.
 113     public @Test
 114     void testGroupBounds_InitialNodeInvisible() {
 115         Rectangle r1 = new Rectangle(20, 20, 50, 50);
 116         r1.setVisible(false);
 117         Group g = new Group(r1);
 118 
 119         assertGroupBounds(g);
 120     }
 121 
 122     // test that adding invisible nodes to a group doesn't update the bounds
 123     public @Test
 124     void testGroupBounds_InvisibleNodes() {
 125         Rectangle r1 = new Rectangle(20, 20, 50, 50);
 126         Rectangle r2 = new Rectangle(90, 20, 50, 50);
 127         Group g = new Group(r1, r2);
 128         assertGroupBounds(g);
 129 
 130         Rectangle invisible = new Rectangle(-100, -100, 1, 1);
 131         invisible.setVisible(true);
 132         g.getChildren().add(invisible);
 133         assertGroupBounds(g);
 134     }
 135 
 136     // test that adding zero sized nodes does update a Groups bounds
 137     public @Test
 138     void testGroupBounds_ZeroSizedNodes() {
 139         Rectangle r1 = new Rectangle(20, 20, 50, 50);
 140         Rectangle r2 = new Rectangle(90, 20, 50, 50);
 141         Group g = new Group(r1, r2);
 142         assertGroupBounds(g);
 143 
 144         Rectangle small = new Rectangle(-100, -100, 0, 0);
 145         g.getChildren().add(small);
 146         assertGroupBounds(g);
 147     }
 148 
 149     // test that making a node invisible updates the groups bounds
 150     public @Test
 151     void testGroupBounds_NodeMadeInvisible() {
 152         Rectangle r1 = new Rectangle(20, 20, 50, 50);
 153         Rectangle r2 = new Rectangle(90, 20, 50, 50);
 154         Group g = new Group(r1, r2);
 155         assertGroupBounds(g);
 156 
 157         r1.setVisible(false);
 158         assertGroupBounds(g);
 159     }
 160 
 161     public @Test
 162     void testGroupBounds_NodeWithNoWidthMadeInvisible() {
 163         Rectangle r1 = new Rectangle(20, 20, 50, 50);
 164         Rectangle r2 = new Rectangle(90, 20, 0, 50);
 165         Group g = new Group(r1, r2);
 166         assertGroupBounds(g);
 167 
 168         r2.setVisible(false);
 169         assertGroupBounds(g);
 170     }
 171 
 172     public @Test
 173     void testGroupBounds_FirstNodeHasNoWidthSecondNodeDoes() {
 174         Rectangle r1 = new Rectangle(20, 20, 0, 50);
 175         Rectangle r2 = new Rectangle(90, 20, 50, 50);
 176         Group g = new Group(r1, r2);
 177         assertGroupBounds(g);
 178     }
 179 
 180     public @Test
 181     void testGroupBounds_FirstNodeHasNoWidthSecondNodeDoes_Added() {
 182         Rectangle r1 = new Rectangle(20, 20, 0, 50);
 183         Rectangle r2 = new Rectangle(90, 20, 50, 50);
 184         Group g = new Group();
 185         assertGroupBounds(g);
 186         g.getChildren().add(r1);
 187         assertGroupBounds(g);
 188         g.getChildren().add(r2);
 189         assertGroupBounds(g);
 190     }
 191 
 192     public @Test
 193     void testGroupBounds_FirstNodeHasNoWidthSecondNodeDoes_ClearedThenAdded() {
 194         Rectangle r1 = new Rectangle(20, 20, 0, 50);
 195         Rectangle r2 = new Rectangle(90, 20, 50, 50);
 196         Rectangle r3 = new Rectangle(10, 15, 75, 20);
 197         Group g = new Group(r1, r2);
 198         assertGroupBounds(g);
 199         g.getChildren().remove(r2);
 200         assertGroupBounds(g);
 201         g.getChildren().add(r3);
 202         assertGroupBounds(g);
 203     }
 204 
 205     // this test uncovered a bug when using the GroupBoundsHelper. It needs
 206     // two invisible nodes to tickle it You also have to ask assert the bounds
 207     // after each change or it may not fail
 208     public @Test
 209     void testGroupBounds_TwoNodesMadeInvisible_ThenNodeAdded() {
 210         Rectangle r1 = new Rectangle(20, 20, 50, 50);
 211         Rectangle r2 = new Rectangle(90, 20, 50, 50);
 212         Rectangle r3 = new Rectangle(10, 15, 75, 20);
 213         Group g = new Group();
 214 
 215         assertGroupBounds(g);
 216         g.getChildren().add(r1);
 217         assertGroupBounds(g);
 218         r1.setVisible(false);
 219         assertGroupBounds(g);
 220         g.getChildren().add(r2);
 221         assertGroupBounds(g);
 222         r2.setVisible(false);
 223         assertGroupBounds(g);
 224         g.getChildren().add(r3);
 225         assertGroupBounds(g);
 226     }
 227 
 228     public @Test
 229     void testGroupBounds_TogglingVisiblityToFalseAndTrueWhileExpandingBounds() {
 230         Rectangle r1 = new Rectangle(20, 20, 50, 50);
 231         Rectangle r2 = new Rectangle(90, 20, 50, 50);
 232         Rectangle r3 = new Rectangle(10, 15, 75, 20);
 233         Group g = new Group();
 234         assertGroupBounds(g);
 235         g.getChildren().add(r1);
 236         assertGroupBounds(g);
 237         g.getChildren().add(r2);
 238         assertGroupBounds(g);
 239         r2.setVisible(false);
 240         assertGroupBounds(g);
 241         g.getChildren().add(r3);
 242         assertGroupBounds(g);
 243         r2.setVisible(true);
 244         assertGroupBounds(g);
 245     }
 246 
 247     private Group createGroupWithRects() {
 248         Group group = new Group();
 249         group.setId("group");
 250         for (int i = 1; i <= 3; i++) {
 251             for (int j = 1; j <= 3; j++) {
 252                 Rectangle r = new Rectangle(j * 100, i * 100, 50, 50);
 253                 r.setId("rect[" + i + "," + j + "]");
 254                 group.getChildren().add(r);
 255             }
 256         }
 257 
 258         // sanity test check that the size of the group is correct
 259         assertEquals(box(100, 100, 250, 250), group.getBoundsInLocal());
 260 
 261         return group;
 262     }
 263 
 264     // Started out as a simple test and now pretty well covers all the use
 265     // cases. Oops. Bad Richard.
 266     public @Test
 267     void testMovingNodesTowardCenterOfGroupAndOther() {
 268         Group group = createGroupWithRects();
 269 
 270         // move the 1, 3, 5, 7 nodes in towards the center. Doing so should not
 271         // change the group's bounds
 272         ((Rectangle) group.getChildren().get(1)).setX(200);
 273         ((Rectangle) group.getChildren().get(1)).setY(200);
 274         ((Rectangle) group.getChildren().get(3)).setX(200);
 275         ((Rectangle) group.getChildren().get(3)).setY(200);
 276         ((Rectangle) group.getChildren().get(5)).setX(200);
 277         ((Rectangle) group.getChildren().get(5)).setY(200);
 278         ((Rectangle) group.getChildren().get(7)).setX(200);
 279         ((Rectangle) group.getChildren().get(7)).setY(200);
 280         assertEquals(box(100, 100, 250, 250), group.getBoundsInLocal());
 281 
 282         // move the 2 and 6 nodes in towards the center. Doing so should not
 283         // change the group's bounds
 284         ((Rectangle) group.getChildren().get(2)).setX(200);
 285         ((Rectangle) group.getChildren().get(2)).setY(200);
 286         ((Rectangle) group.getChildren().get(6)).setX(200);
 287         ((Rectangle) group.getChildren().get(6)).setY(200);
 288         assertEquals(box(100, 100, 250, 250), group.getBoundsInLocal());
 289 
 290         // move the 0 node into the center. Doing so SHOULD change the bounds
 291         // such that all nodes are in the center (200, 200) except for the
 292         // number 8 node which is at (300, 300)
 293         ((Rectangle) group.getChildren().get(0)).setX(200);
 294         ((Rectangle) group.getChildren().get(0)).setY(200);
 295         assertEquals(box(200, 200, 150, 150), group.getBoundsInLocal());
 296 
 297         // move the 8 node a little towards the center (but not all the way)
 298         // just to test that moving the bottom-right will adjust things
 299         ((Rectangle) group.getChildren().get(8)).setX(250);
 300         ((Rectangle) group.getChildren().get(8)).setY(250);
 301         assertEquals(box(200, 200, 100, 100), group.getBoundsInLocal());
 302 
 303         // move the rest of the nodes down past #8
 304         for (int i = 0; i <= 7; i++) {
 305             ((Rectangle) group.getChildren().get(i)).setX(300);
 306             ((Rectangle) group.getChildren().get(i)).setY(300);
 307         }
 308         assertEquals(box(250, 250, 100, 100), group.getBoundsInLocal());
 309 
 310         // now move #8 onto the rest
 311         ((Rectangle) group.getChildren().get(8)).setX(300);
 312         ((Rectangle) group.getChildren().get(8)).setY(300);
 313         assertEquals(box(300, 300, 50, 50), group.getBoundsInLocal());
 314     }
 315 
 316     public @Test
 317     void testMovingNodesAwayFromCenterOfGroup() {
 318         Group group = createGroupWithRects();
 319 
 320         ((Rectangle) group.getChildren().get(4)).setX(600);
 321         ((Rectangle) group.getChildren().get(4)).setY(600);
 322         assertEquals(box(100, 100, 550, 550), group.getBoundsInLocal());
 323     }
 324 
 325     public @Test
 326     void testMovingNodesWithinInteriorOfGroup() {
 327         Group group = createGroupWithRects();
 328 
 329         ((Rectangle) group.getChildren().get(4)).setX(250);
 330         ((Rectangle) group.getChildren().get(4)).setY(250);
 331         assertEquals(box(100, 100, 250, 250), group.getBoundsInLocal());
 332     }
 333 
 334     public @Test
 335     void testMovingExteriorNodesOnExterior() {
 336         Group group = createGroupWithRects();
 337 
 338         ((Rectangle) group.getChildren().get(0)).setY(150);
 339         ((Rectangle) group.getChildren().get(1)).setX(100);
 340         ((Rectangle) group.getChildren().get(2)).setX(150);
 341         ((Rectangle) group.getChildren().get(3)).setY(120);
 342         ((Rectangle) group.getChildren().get(5)).setY(100);
 343         ((Rectangle) group.getChildren().get(6)).setX(250);
 344         ((Rectangle) group.getChildren().get(7)).setX(120);
 345         ((Rectangle) group.getChildren().get(8)).setY(200);
 346 
 347         assertEquals(box(100, 100, 250, 250), group.getBoundsInLocal());
 348     }
 349 
 350     public @Test
 351     void testRemovingInteriorNodes() {
 352         Group group = createGroupWithRects();
 353 
 354         group.getChildren().remove(4);
 355         assertEquals(box(100, 100, 250, 250), group.getBoundsInLocal());
 356     }
 357 
 358     public @Test
 359     void testRemovingExteriorNodes() {
 360         Group group = createGroupWithRects();
 361 
 362         group.getChildren().remove(7);
 363         assertEquals(box(100, 100, 250, 250), group.getBoundsInLocal());
 364         group.getChildren().remove(6);
 365         assertEquals(box(100, 100, 250, 250), group.getBoundsInLocal());
 366         group.getChildren().remove(5);
 367         assertEquals(box(100, 100, 250, 250), group.getBoundsInLocal());
 368         group.getChildren().remove(3);
 369         assertEquals(box(100, 100, 250, 250), group.getBoundsInLocal());
 370         group.getChildren().remove(2);
 371         assertEquals(box(100, 100, 250, 250), group.getBoundsInLocal());
 372         group.getChildren().remove(1);
 373         assertEquals(box(100, 100, 250, 250), group.getBoundsInLocal());
 374 
 375         // and now the bounds should be changing
 376         group.getChildren().remove(0);
 377         assertEquals(box(200, 200, 150, 150), group.getBoundsInLocal());
 378         group.getChildren().remove(1);
 379         assertEquals(box(200, 200, 50, 50), group.getBoundsInLocal());
 380     }
 381 
 382     // run a set of tests that add 1000's of random sized and random positioned
 383     // rectangles to the Group, and check the groups bounds at each stage.
 384     // Also randomly make some invisible, some visible, remove some, toggle
 385     // visibility, and so forth.
 386     public @Test
 387     void testGroupBounds_Stress() {
 388         boolean fullTest = Boolean.getBoolean("test.everything");
 389         if (fullTest) {
 390             Group g = new Group();
 391             assertGroupBounds(g);
 392             for (int j = 0; j < 500; j++) {
 393                 LinkedList<String> whatHappenedStack = new java.util.LinkedList<String>();
 394                 for (int i = 0; i <= 50; i++) {
 395                     Bounds layoutBounds = g.getLayoutBounds();
 396                     int numChildren = g.getChildren().size();
 397                     String whatHappened = "";
 398                     double rnd = Math.random();
 399                     int index = (int) (Math.random() * numChildren);
 400                     if (rnd > .3 && rnd < .5 && numChildren > 0) {
 401                         // translate some rect
 402                         int direction = (Math.random() > .5) ? -1 : 1;
 403                         Bounds oldBoundsInParent = g.getChildren().get(index)
 404                                 .getBoundsInParent();
 405                         g.getChildren()
 406                                 .get(index)
 407                                 .setTranslateX(
 408                                         (int) (Math.random() * 500 * direction));
 409                         g.getChildren()
 410                                 .get(index)
 411                                 .setTranslateY(
 412                                         (int) (Math.random() * 500 * direction));
 413                         whatHappened = "On iteration " + j + "-"+ i + "I translated a "
 414                                 + g.getChildren().get(index) + " with boundsInParent "
 415                                 + formatBounds(oldBoundsInParent) + " which was the "
 416                                 + index+1 + "th item. Its new bounds are "
 417                                 + formatBounds(g.getChildren().get(index).getBoundsInParent()) + ". "
 418                                 + "The layoutBounds of the Group was "
 419                                 + formatBounds(layoutBounds) + " and is now " + formatBounds(g.getLayoutBounds()) + " and had "
 420                                 + numChildren + " number of child nodes";
 421                         whatHappenedStack.add(whatHappened);
 422                     } else if (rnd > .5 && rnd < .6 && numChildren > 0) {
 423                         // deletesome rect
 424                         whatHappened = "On iteration " + j + "-" + i+ " I deleted a "
 425                                 + "" + g.getChildren().get(index) + " with boundsInParent "
 426                                 + "" + formatBounds(g.getChildren().get(index).getBoundsInParent())+ " which was the "
 427                                 + "" + index+1+ "th item. The layoutBounds of the Group was "
 428                                 + "" + formatBounds(layoutBounds)+ " and is now " + formatBounds(g.getLayoutBounds())+ " and had "
 429                                 + "" + numChildren+ " number of child nodes";
 430                         g.getChildren().remove(index);
 431                         whatHappenedStack.add(whatHappened);
 432                     } else if (rnd > .6 && rnd < .65 && numChildren > 0) {
 433                         // toggle visibility on some rect
 434                         g.getChildren().get(index)
 435                                 .setVisible(!g.getChildren().get(index).isVisible());
 436                         whatHappened = "On iteration " + j+ "-" + i+ " I toggled the "
 437                                 + "visibility of " + g.getChildren().get(index) + " with boundsInParent "
 438                                 + "" + formatBounds(g.getChildren().get(index).getBoundsInParent())+ " to "
 439                                 + "" + g.getChildren().get(index).isVisible() + ". The layoutBounds of the "
 440                                 + "Group was " + formatBounds(layoutBounds)+ " and is now " + formatBounds(g.getLayoutBounds())+ " and "
 441                                 + "had " + numChildren+ " number of child nodes";
 442                         whatHappenedStack.add(whatHappened);
 443                     } else {
 444                         Rectangle rect = new Rectangle(
 445                                 ((int) (Math.random() * 1000)),
 446                                 ((int) (Math.random() * 1000)),
 447                                 ((int) (Math.random() * 100)),
 448                                 ((int) (Math.random() * 100)));
 449                         g.getChildren().add(rect);
 450                         whatHappened = "On iteration " + j+ "-" + i+ " I added a " + rect+ " with "
 451                                 + "boundsInParent " + formatBounds(rect.getBoundsInParent())+ " to the group. The "
 452                                 + "layoutBounds of the Group was " + formatBounds(layoutBounds)+ " and is now "
 453                                 + "" + formatBounds(g.getLayoutBounds())+ " and had " + numChildren+ " number of "
 454                                 + "child nodes";
 455                         whatHappenedStack.add(whatHappened);
 456                     }
 457                     try {
 458                         assertGroupBounds(g);
 459                     } catch (Exception any) {
 460                         System.out.println("Something went wrong. Here's what happened:");
 461                         for (String item : whatHappenedStack) {
 462                             System.out.println("{item}");
 463                         }
 464                         throw new RuntimeException(any);
 465                     }
 466                 }
 467             }
 468         }
 469     }
 470 
 471     // here is a special test for impl_getPivotX and impl_getPivotY
 472     @Test
 473     public void testPivotXAndPivotY() {
 474         Rectangle rect = new Rectangle(100, 100);
 475         assertEquals(50.0f, (float) rect.impl_getPivotX());
 476         assertEquals(50.0f, (float) rect.impl_getPivotY());
 477         rect.setWidth(70.0f);
 478         assertEquals(35.0f, (float) rect.impl_getPivotX());
 479         assertEquals(50.0f, (float) rect.impl_getPivotY());
 480     }
 481 
 482     /***************************************************************************
 483      * Group Bounds Sanity Tests * * These tests are for Group
 484      * to make sure that their * bounds are reported correctly
 485      * before effects or clips or transforms * are taken into account. * * The
 486      * group tests here are just basic tests, a full set of Group bounds * tests
 487      * are included in their own section later in this file. There are * many
 488      * edge cases to group bounds. The primary purpose of these next * few tests
 489      * are just to make sure that group's bounds are correct in the * simple
 490      * case. * *
 491      **************************************************************************/
 492 
 493     public @Test
 494     void testBoundsForGroup() {
 495         Rectangle r1 = new Rectangle(20, 20, 50, 50);
 496         Rectangle r2 = new Rectangle(90, 20, 50, 50);
 497         Group group = new Group(r1, r2);
 498 
 499         assertEquals(box(20, 20, 120, 50), group.getBoundsInLocal());
 500         assertEquals(group.getBoundsInLocal(), group.getBoundsInParent());
 501         assertEquals(group.getBoundsInLocal(), group.getLayoutBounds());
 502     }
 503 
 504     /**
 505      * Just a basic test to make sure basic group node bounds calculation works
 506      */
 507     public @Test
 508     void testBoundsForGroup_childGeomChanging() {
 509         Rectangle rect = new Rectangle();
 510         rect.setId("rect");
 511         Rectangle square = new Rectangle();
 512         square.setId("square");
 513         Group group = new Group(rect, square);
 514         group.setId("group");
 515 
 516         assertBoundsEqual(box(0, 0, 0, 0), rect.getBoundsInLocal());
 517         assertBoundsEqual(box(0, 0, 0, 0), square.getBoundsInLocal());
 518         assertBoundsEqual(box(0, 0, 0, 0), group.getBoundsInLocal());
 519 
 520         rect.setX(50);
 521         rect.setY(50);
 522         rect.setWidth(100);
 523         rect.setHeight(30);
 524 
 525         assertBoundsEqual(box(50, 50, 100, 30), rect.getBoundsInLocal());
 526         assertBoundsEqual(box(0, 0, 0, 0), square.getBoundsInLocal());
 527         assertBoundsEqual(box(0, 0, 150, 80), group.getBoundsInLocal());
 528 
 529         square.setX(25);
 530         square.setY(25);
 531         square.setWidth(50);
 532         square.setHeight(50);
 533 
 534         assertBoundsEqual(box(50, 50, 100, 30), rect.getBoundsInLocal());
 535         assertBoundsEqual(box(25, 25, 50, 50), square.getBoundsInLocal());
 536         assertBoundsEqual(box(25, 25, 125, 55), group.getBoundsInLocal());
 537     }
 538 
 539     public @Test
 540     void testBoundsInParentOfGroup() {
 541         Rectangle rect = new Rectangle(50, 50, 100, 30);
 542         rect.setId("rect");
 543         Group group = new Group(rect);
 544         group.setId("group");
 545         group.setTranslateX(100);
 546         group.setTranslateY(100);
 547 
 548         assertBoundsEqual(box(150, 150, 100, 30), group.getBoundsInParent());
 549     }
 550 
 551     /**
 552      * Tests that if I have a group with nobody listening to the bounds, and the
 553      * bounds change, and then I ask for the new bounds, that the bounds are
 554      * valid.
 555      */
 556     public @Test
 557     void testRequestingBoundsOnGroupWithNoListenersWorks() {
 558         Group group = new Group(new Rectangle(50, 50, 100, 30));
 559 
 560         assertBoundsEqual(box(50, 50, 100, 30), group.getBoundsInLocal());
 561     }
 562 
 563 }