Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / components / mus / public / cpp / tests / view_unittest.cc
blobc991ca3b9855695bc7ced6cf80f9d67b29f5d2fc
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "components/mus/public/cpp/view.h"
7 #include "base/logging.h"
8 #include "base/strings/stringprintf.h"
9 #include "components/mus/public/cpp/lib/view_private.h"
10 #include "components/mus/public/cpp/util.h"
11 #include "components/mus/public/cpp/view_observer.h"
12 #include "components/mus/public/cpp/view_property.h"
13 #include "testing/gtest/include/gtest/gtest.h"
15 namespace mus {
17 // View ------------------------------------------------------------------------
19 typedef testing::Test ViewTest;
21 // Subclass with public ctor/dtor.
22 class TestView : public View {
23 public:
24 TestView() { ViewPrivate(this).set_id(1); }
25 ~TestView() {}
27 private:
28 MOJO_DISALLOW_COPY_AND_ASSIGN(TestView);
31 TEST_F(ViewTest, AddChild) {
32 TestView v1;
33 TestView v11;
34 v1.AddChild(&v11);
35 EXPECT_EQ(1U, v1.children().size());
38 TEST_F(ViewTest, RemoveChild) {
39 TestView v1;
40 TestView v11;
41 v1.AddChild(&v11);
42 EXPECT_EQ(1U, v1.children().size());
43 v1.RemoveChild(&v11);
44 EXPECT_EQ(0U, v1.children().size());
47 TEST_F(ViewTest, Reparent) {
48 TestView v1;
49 TestView v2;
50 TestView v11;
51 v1.AddChild(&v11);
52 EXPECT_EQ(1U, v1.children().size());
53 v2.AddChild(&v11);
54 EXPECT_EQ(1U, v2.children().size());
55 EXPECT_EQ(0U, v1.children().size());
58 TEST_F(ViewTest, Contains) {
59 TestView v1;
61 // Direct descendant.
62 TestView v11;
63 v1.AddChild(&v11);
64 EXPECT_TRUE(v1.Contains(&v11));
66 // Indirect descendant.
67 TestView v111;
68 v11.AddChild(&v111);
69 EXPECT_TRUE(v1.Contains(&v111));
72 TEST_F(ViewTest, GetChildById) {
73 TestView v1;
74 ViewPrivate(&v1).set_id(1);
75 TestView v11;
76 ViewPrivate(&v11).set_id(11);
77 v1.AddChild(&v11);
78 TestView v111;
79 ViewPrivate(&v111).set_id(111);
80 v11.AddChild(&v111);
82 // Find direct & indirect descendents.
83 EXPECT_EQ(&v11, v1.GetChildById(v11.id()));
84 EXPECT_EQ(&v111, v1.GetChildById(v111.id()));
87 TEST_F(ViewTest, DrawnAndVisible) {
88 TestView v1;
89 EXPECT_TRUE(v1.visible());
90 EXPECT_FALSE(v1.IsDrawn());
92 ViewPrivate(&v1).set_drawn(true);
94 TestView v11;
95 v1.AddChild(&v11);
96 EXPECT_TRUE(v11.visible());
97 EXPECT_TRUE(v11.IsDrawn());
99 v1.RemoveChild(&v11);
100 EXPECT_TRUE(v11.visible());
101 EXPECT_FALSE(v11.IsDrawn());
104 namespace {
105 DEFINE_VIEW_PROPERTY_KEY(int, kIntKey, -2);
106 DEFINE_VIEW_PROPERTY_KEY(const char*, kStringKey, "squeamish");
109 TEST_F(ViewTest, Property) {
110 TestView v;
112 // Non-existent properties should return the default values.
113 EXPECT_EQ(-2, v.GetLocalProperty(kIntKey));
114 EXPECT_EQ(std::string("squeamish"), v.GetLocalProperty(kStringKey));
116 // A set property value should be returned again (even if it's the default
117 // value).
118 v.SetLocalProperty(kIntKey, INT_MAX);
119 EXPECT_EQ(INT_MAX, v.GetLocalProperty(kIntKey));
120 v.SetLocalProperty(kIntKey, -2);
121 EXPECT_EQ(-2, v.GetLocalProperty(kIntKey));
122 v.SetLocalProperty(kIntKey, INT_MIN);
123 EXPECT_EQ(INT_MIN, v.GetLocalProperty(kIntKey));
125 v.SetLocalProperty(kStringKey, static_cast<const char*>(NULL));
126 EXPECT_EQ(NULL, v.GetLocalProperty(kStringKey));
127 v.SetLocalProperty(kStringKey, "squeamish");
128 EXPECT_EQ(std::string("squeamish"), v.GetLocalProperty(kStringKey));
129 v.SetLocalProperty(kStringKey, "ossifrage");
130 EXPECT_EQ(std::string("ossifrage"), v.GetLocalProperty(kStringKey));
132 // ClearProperty should restore the default value.
133 v.ClearLocalProperty(kIntKey);
134 EXPECT_EQ(-2, v.GetLocalProperty(kIntKey));
135 v.ClearLocalProperty(kStringKey);
136 EXPECT_EQ(std::string("squeamish"), v.GetLocalProperty(kStringKey));
139 namespace {
141 class TestProperty {
142 public:
143 TestProperty() {}
144 virtual ~TestProperty() { last_deleted_ = this; }
145 static TestProperty* last_deleted() { return last_deleted_; }
147 private:
148 static TestProperty* last_deleted_;
149 MOJO_DISALLOW_COPY_AND_ASSIGN(TestProperty);
152 TestProperty* TestProperty::last_deleted_ = NULL;
154 DEFINE_OWNED_VIEW_PROPERTY_KEY(TestProperty, kOwnedKey, NULL);
156 } // namespace
158 TEST_F(ViewTest, OwnedProperty) {
159 TestProperty* p3 = NULL;
161 TestView v;
162 EXPECT_EQ(NULL, v.GetLocalProperty(kOwnedKey));
163 TestProperty* p1 = new TestProperty();
164 v.SetLocalProperty(kOwnedKey, p1);
165 EXPECT_EQ(p1, v.GetLocalProperty(kOwnedKey));
166 EXPECT_EQ(NULL, TestProperty::last_deleted());
168 TestProperty* p2 = new TestProperty();
169 v.SetLocalProperty(kOwnedKey, p2);
170 EXPECT_EQ(p2, v.GetLocalProperty(kOwnedKey));
171 EXPECT_EQ(p1, TestProperty::last_deleted());
173 v.ClearLocalProperty(kOwnedKey);
174 EXPECT_EQ(NULL, v.GetLocalProperty(kOwnedKey));
175 EXPECT_EQ(p2, TestProperty::last_deleted());
177 p3 = new TestProperty();
178 v.SetLocalProperty(kOwnedKey, p3);
179 EXPECT_EQ(p3, v.GetLocalProperty(kOwnedKey));
180 EXPECT_EQ(p2, TestProperty::last_deleted());
183 EXPECT_EQ(p3, TestProperty::last_deleted());
186 // ViewObserver --------------------------------------------------------
188 typedef testing::Test ViewObserverTest;
190 bool TreeChangeParamsMatch(const ViewObserver::TreeChangeParams& lhs,
191 const ViewObserver::TreeChangeParams& rhs) {
192 return lhs.target == rhs.target && lhs.old_parent == rhs.old_parent &&
193 lhs.new_parent == rhs.new_parent && lhs.receiver == rhs.receiver;
196 class TreeChangeObserver : public ViewObserver {
197 public:
198 explicit TreeChangeObserver(View* observee) : observee_(observee) {
199 observee_->AddObserver(this);
201 ~TreeChangeObserver() override { observee_->RemoveObserver(this); }
203 void Reset() { received_params_.clear(); }
205 const std::vector<TreeChangeParams>& received_params() {
206 return received_params_;
209 private:
210 // Overridden from ViewObserver:
211 void OnTreeChanging(const TreeChangeParams& params) override {
212 received_params_.push_back(params);
214 void OnTreeChanged(const TreeChangeParams& params) override {
215 received_params_.push_back(params);
218 View* observee_;
219 std::vector<TreeChangeParams> received_params_;
221 MOJO_DISALLOW_COPY_AND_ASSIGN(TreeChangeObserver);
224 // Adds/Removes v11 to v1.
225 TEST_F(ViewObserverTest, TreeChange_SimpleAddRemove) {
226 TestView v1;
227 TreeChangeObserver o1(&v1);
228 EXPECT_TRUE(o1.received_params().empty());
230 TestView v11;
231 TreeChangeObserver o11(&v11);
232 EXPECT_TRUE(o11.received_params().empty());
234 // Add.
236 v1.AddChild(&v11);
238 EXPECT_EQ(2U, o1.received_params().size());
239 ViewObserver::TreeChangeParams p1;
240 p1.target = &v11;
241 p1.receiver = &v1;
242 p1.old_parent = NULL;
243 p1.new_parent = &v1;
244 EXPECT_TRUE(TreeChangeParamsMatch(p1, o1.received_params().back()));
246 EXPECT_EQ(2U, o11.received_params().size());
247 ViewObserver::TreeChangeParams p11 = p1;
248 p11.receiver = &v11;
249 EXPECT_TRUE(TreeChangeParamsMatch(p11, o11.received_params().front()));
250 EXPECT_TRUE(TreeChangeParamsMatch(p11, o11.received_params().back()));
252 o1.Reset();
253 o11.Reset();
254 EXPECT_TRUE(o1.received_params().empty());
255 EXPECT_TRUE(o11.received_params().empty());
257 // Remove.
259 v1.RemoveChild(&v11);
261 EXPECT_EQ(2U, o1.received_params().size());
262 p1.target = &v11;
263 p1.receiver = &v1;
264 p1.old_parent = &v1;
265 p1.new_parent = NULL;
266 EXPECT_TRUE(TreeChangeParamsMatch(p1, o1.received_params().front()));
268 EXPECT_EQ(2U, o11.received_params().size());
269 p11 = p1;
270 p11.receiver = &v11;
271 EXPECT_TRUE(TreeChangeParamsMatch(p11, o11.received_params().front()));
272 EXPECT_TRUE(TreeChangeParamsMatch(p11, o11.received_params().back()));
275 // Creates these two trees:
276 // v1
277 // +- v11
278 // v111
279 // +- v1111
280 // +- v1112
281 // Then adds/removes v111 from v11.
282 TEST_F(ViewObserverTest, TreeChange_NestedAddRemove) {
283 TestView v1, v11, v111, v1111, v1112;
285 // Root tree.
286 v1.AddChild(&v11);
288 // Tree to be attached.
289 v111.AddChild(&v1111);
290 v111.AddChild(&v1112);
292 TreeChangeObserver o1(&v1), o11(&v11), o111(&v111), o1111(&v1111),
293 o1112(&v1112);
294 ViewObserver::TreeChangeParams p1, p11, p111, p1111, p1112;
296 // Add.
298 v11.AddChild(&v111);
300 EXPECT_EQ(2U, o1.received_params().size());
301 p1.target = &v111;
302 p1.receiver = &v1;
303 p1.old_parent = NULL;
304 p1.new_parent = &v11;
305 EXPECT_TRUE(TreeChangeParamsMatch(p1, o1.received_params().back()));
307 EXPECT_EQ(2U, o11.received_params().size());
308 p11 = p1;
309 p11.receiver = &v11;
310 EXPECT_TRUE(TreeChangeParamsMatch(p11, o11.received_params().back()));
312 EXPECT_EQ(2U, o111.received_params().size());
313 p111 = p11;
314 p111.receiver = &v111;
315 EXPECT_TRUE(TreeChangeParamsMatch(p111, o111.received_params().front()));
316 EXPECT_TRUE(TreeChangeParamsMatch(p111, o111.received_params().back()));
318 EXPECT_EQ(2U, o1111.received_params().size());
319 p1111 = p111;
320 p1111.receiver = &v1111;
321 EXPECT_TRUE(TreeChangeParamsMatch(p1111, o1111.received_params().front()));
322 EXPECT_TRUE(TreeChangeParamsMatch(p1111, o1111.received_params().back()));
324 EXPECT_EQ(2U, o1112.received_params().size());
325 p1112 = p111;
326 p1112.receiver = &v1112;
327 EXPECT_TRUE(TreeChangeParamsMatch(p1112, o1112.received_params().front()));
328 EXPECT_TRUE(TreeChangeParamsMatch(p1112, o1112.received_params().back()));
330 // Remove.
331 o1.Reset();
332 o11.Reset();
333 o111.Reset();
334 o1111.Reset();
335 o1112.Reset();
336 EXPECT_TRUE(o1.received_params().empty());
337 EXPECT_TRUE(o11.received_params().empty());
338 EXPECT_TRUE(o111.received_params().empty());
339 EXPECT_TRUE(o1111.received_params().empty());
340 EXPECT_TRUE(o1112.received_params().empty());
342 v11.RemoveChild(&v111);
344 EXPECT_EQ(2U, o1.received_params().size());
345 p1.target = &v111;
346 p1.receiver = &v1;
347 p1.old_parent = &v11;
348 p1.new_parent = NULL;
349 EXPECT_TRUE(TreeChangeParamsMatch(p1, o1.received_params().front()));
351 EXPECT_EQ(2U, o11.received_params().size());
352 p11 = p1;
353 p11.receiver = &v11;
354 EXPECT_TRUE(TreeChangeParamsMatch(p11, o11.received_params().front()));
356 EXPECT_EQ(2U, o111.received_params().size());
357 p111 = p11;
358 p111.receiver = &v111;
359 EXPECT_TRUE(TreeChangeParamsMatch(p111, o111.received_params().front()));
360 EXPECT_TRUE(TreeChangeParamsMatch(p111, o111.received_params().back()));
362 EXPECT_EQ(2U, o1111.received_params().size());
363 p1111 = p111;
364 p1111.receiver = &v1111;
365 EXPECT_TRUE(TreeChangeParamsMatch(p1111, o1111.received_params().front()));
366 EXPECT_TRUE(TreeChangeParamsMatch(p1111, o1111.received_params().back()));
368 EXPECT_EQ(2U, o1112.received_params().size());
369 p1112 = p111;
370 p1112.receiver = &v1112;
371 EXPECT_TRUE(TreeChangeParamsMatch(p1112, o1112.received_params().front()));
372 EXPECT_TRUE(TreeChangeParamsMatch(p1112, o1112.received_params().back()));
375 TEST_F(ViewObserverTest, TreeChange_Reparent) {
376 TestView v1, v11, v12, v111;
377 v1.AddChild(&v11);
378 v1.AddChild(&v12);
379 v11.AddChild(&v111);
381 TreeChangeObserver o1(&v1), o11(&v11), o12(&v12), o111(&v111);
383 // Reparent.
384 v12.AddChild(&v111);
386 // v1 (root) should see both changing and changed notifications.
387 EXPECT_EQ(4U, o1.received_params().size());
388 ViewObserver::TreeChangeParams p1;
389 p1.target = &v111;
390 p1.receiver = &v1;
391 p1.old_parent = &v11;
392 p1.new_parent = &v12;
393 EXPECT_TRUE(TreeChangeParamsMatch(p1, o1.received_params().front()));
394 EXPECT_TRUE(TreeChangeParamsMatch(p1, o1.received_params().back()));
396 // v11 should see changing notifications.
397 EXPECT_EQ(2U, o11.received_params().size());
398 ViewObserver::TreeChangeParams p11;
399 p11 = p1;
400 p11.receiver = &v11;
401 EXPECT_TRUE(TreeChangeParamsMatch(p11, o11.received_params().front()));
403 // v12 should see changed notifications.
404 EXPECT_EQ(2U, o12.received_params().size());
405 ViewObserver::TreeChangeParams p12;
406 p12 = p1;
407 p12.receiver = &v12;
408 EXPECT_TRUE(TreeChangeParamsMatch(p12, o12.received_params().back()));
410 // v111 should see both changing and changed notifications.
411 EXPECT_EQ(2U, o111.received_params().size());
412 ViewObserver::TreeChangeParams p111;
413 p111 = p1;
414 p111.receiver = &v111;
415 EXPECT_TRUE(TreeChangeParamsMatch(p111, o111.received_params().front()));
416 EXPECT_TRUE(TreeChangeParamsMatch(p111, o111.received_params().back()));
419 namespace {
421 class OrderChangeObserver : public ViewObserver {
422 public:
423 struct Change {
424 View* view;
425 View* relative_view;
426 mojo::OrderDirection direction;
428 typedef std::vector<Change> Changes;
430 explicit OrderChangeObserver(View* observee) : observee_(observee) {
431 observee_->AddObserver(this);
433 ~OrderChangeObserver() override { observee_->RemoveObserver(this); }
435 Changes GetAndClearChanges() {
436 Changes changes;
437 changes_.swap(changes);
438 return changes;
441 private:
442 // Overridden from ViewObserver:
443 void OnViewReordering(View* view,
444 View* relative_view,
445 mojo::OrderDirection direction) override {
446 OnViewReordered(view, relative_view, direction);
449 void OnViewReordered(View* view,
450 View* relative_view,
451 mojo::OrderDirection direction) override {
452 Change change;
453 change.view = view;
454 change.relative_view = relative_view;
455 change.direction = direction;
456 changes_.push_back(change);
459 View* observee_;
460 Changes changes_;
462 MOJO_DISALLOW_COPY_AND_ASSIGN(OrderChangeObserver);
465 } // namespace
467 TEST_F(ViewObserverTest, Order) {
468 TestView v1, v11, v12, v13;
469 v1.AddChild(&v11);
470 v1.AddChild(&v12);
471 v1.AddChild(&v13);
473 // Order: v11, v12, v13
474 EXPECT_EQ(3U, v1.children().size());
475 EXPECT_EQ(&v11, v1.children().front());
476 EXPECT_EQ(&v13, v1.children().back());
479 OrderChangeObserver observer(&v11);
481 // Move v11 to front.
482 // Resulting order: v12, v13, v11
483 v11.MoveToFront();
484 EXPECT_EQ(&v12, v1.children().front());
485 EXPECT_EQ(&v11, v1.children().back());
487 OrderChangeObserver::Changes changes = observer.GetAndClearChanges();
488 ASSERT_EQ(2U, changes.size());
489 EXPECT_EQ(&v11, changes[0].view);
490 EXPECT_EQ(&v13, changes[0].relative_view);
491 EXPECT_EQ(mojo::ORDER_DIRECTION_ABOVE, changes[0].direction);
493 EXPECT_EQ(&v11, changes[1].view);
494 EXPECT_EQ(&v13, changes[1].relative_view);
495 EXPECT_EQ(mojo::ORDER_DIRECTION_ABOVE, changes[1].direction);
499 OrderChangeObserver observer(&v11);
501 // Move v11 to back.
502 // Resulting order: v11, v12, v13
503 v11.MoveToBack();
504 EXPECT_EQ(&v11, v1.children().front());
505 EXPECT_EQ(&v13, v1.children().back());
507 OrderChangeObserver::Changes changes = observer.GetAndClearChanges();
508 ASSERT_EQ(2U, changes.size());
509 EXPECT_EQ(&v11, changes[0].view);
510 EXPECT_EQ(&v12, changes[0].relative_view);
511 EXPECT_EQ(mojo::ORDER_DIRECTION_BELOW, changes[0].direction);
513 EXPECT_EQ(&v11, changes[1].view);
514 EXPECT_EQ(&v12, changes[1].relative_view);
515 EXPECT_EQ(mojo::ORDER_DIRECTION_BELOW, changes[1].direction);
519 OrderChangeObserver observer(&v11);
521 // Move v11 above v12.
522 // Resulting order: v12. v11, v13
523 v11.Reorder(&v12, mojo::ORDER_DIRECTION_ABOVE);
524 EXPECT_EQ(&v12, v1.children().front());
525 EXPECT_EQ(&v13, v1.children().back());
527 OrderChangeObserver::Changes changes = observer.GetAndClearChanges();
528 ASSERT_EQ(2U, changes.size());
529 EXPECT_EQ(&v11, changes[0].view);
530 EXPECT_EQ(&v12, changes[0].relative_view);
531 EXPECT_EQ(mojo::ORDER_DIRECTION_ABOVE, changes[0].direction);
533 EXPECT_EQ(&v11, changes[1].view);
534 EXPECT_EQ(&v12, changes[1].relative_view);
535 EXPECT_EQ(mojo::ORDER_DIRECTION_ABOVE, changes[1].direction);
539 OrderChangeObserver observer(&v11);
541 // Move v11 below v12.
542 // Resulting order: v11, v12, v13
543 v11.Reorder(&v12, mojo::ORDER_DIRECTION_BELOW);
544 EXPECT_EQ(&v11, v1.children().front());
545 EXPECT_EQ(&v13, v1.children().back());
547 OrderChangeObserver::Changes changes = observer.GetAndClearChanges();
548 ASSERT_EQ(2U, changes.size());
549 EXPECT_EQ(&v11, changes[0].view);
550 EXPECT_EQ(&v12, changes[0].relative_view);
551 EXPECT_EQ(mojo::ORDER_DIRECTION_BELOW, changes[0].direction);
553 EXPECT_EQ(&v11, changes[1].view);
554 EXPECT_EQ(&v12, changes[1].relative_view);
555 EXPECT_EQ(mojo::ORDER_DIRECTION_BELOW, changes[1].direction);
559 namespace {
561 typedef std::vector<std::string> Changes;
563 std::string ViewIdToString(Id id) {
564 return (id == 0) ? "null"
565 : base::StringPrintf("%d,%d", HiWord(id), LoWord(id));
568 std::string RectToString(const mojo::Rect& rect) {
569 return base::StringPrintf("%d,%d %dx%d", rect.x, rect.y, rect.width,
570 rect.height);
573 class BoundsChangeObserver : public ViewObserver {
574 public:
575 explicit BoundsChangeObserver(View* view) : view_(view) {
576 view_->AddObserver(this);
578 ~BoundsChangeObserver() override { view_->RemoveObserver(this); }
580 Changes GetAndClearChanges() {
581 Changes changes;
582 changes.swap(changes_);
583 return changes;
586 private:
587 // Overridden from ViewObserver:
588 void OnViewBoundsChanging(View* view,
589 const mojo::Rect& old_bounds,
590 const mojo::Rect& new_bounds) override {
591 changes_.push_back(base::StringPrintf(
592 "view=%s old_bounds=%s new_bounds=%s phase=changing",
593 ViewIdToString(view->id()).c_str(), RectToString(old_bounds).c_str(),
594 RectToString(new_bounds).c_str()));
596 void OnViewBoundsChanged(View* view,
597 const mojo::Rect& old_bounds,
598 const mojo::Rect& new_bounds) override {
599 changes_.push_back(base::StringPrintf(
600 "view=%s old_bounds=%s new_bounds=%s phase=changed",
601 ViewIdToString(view->id()).c_str(), RectToString(old_bounds).c_str(),
602 RectToString(new_bounds).c_str()));
605 View* view_;
606 Changes changes_;
608 MOJO_DISALLOW_COPY_AND_ASSIGN(BoundsChangeObserver);
611 } // namespace
613 TEST_F(ViewObserverTest, SetBounds) {
614 TestView v1;
616 BoundsChangeObserver observer(&v1);
617 mojo::Rect rect;
618 rect.width = rect.height = 100;
619 v1.SetBounds(rect);
621 Changes changes = observer.GetAndClearChanges();
622 ASSERT_EQ(2U, changes.size());
623 EXPECT_EQ(
624 "view=0,1 old_bounds=0,0 0x0 new_bounds=0,0 100x100 phase=changing",
625 changes[0]);
626 EXPECT_EQ(
627 "view=0,1 old_bounds=0,0 0x0 new_bounds=0,0 100x100 phase=changed",
628 changes[1]);
632 namespace {
634 class VisibilityChangeObserver : public ViewObserver {
635 public:
636 explicit VisibilityChangeObserver(View* view) : view_(view) {
637 view_->AddObserver(this);
639 ~VisibilityChangeObserver() override { view_->RemoveObserver(this); }
641 Changes GetAndClearChanges() {
642 Changes changes;
643 changes.swap(changes_);
644 return changes;
647 private:
648 // Overridden from ViewObserver:
649 void OnViewVisibilityChanging(View* view) override {
650 changes_.push_back(
651 base::StringPrintf("view=%s phase=changing visibility=%s",
652 ViewIdToString(view->id()).c_str(),
653 view->visible() ? "true" : "false"));
655 void OnViewVisibilityChanged(View* view) override {
656 changes_.push_back(base::StringPrintf("view=%s phase=changed visibility=%s",
657 ViewIdToString(view->id()).c_str(),
658 view->visible() ? "true" : "false"));
661 View* view_;
662 Changes changes_;
664 MOJO_DISALLOW_COPY_AND_ASSIGN(VisibilityChangeObserver);
667 } // namespace
669 TEST_F(ViewObserverTest, SetVisible) {
670 TestView v1;
671 EXPECT_TRUE(v1.visible());
673 // Change visibility from true to false and make sure we get notifications.
674 VisibilityChangeObserver observer(&v1);
675 v1.SetVisible(false);
677 Changes changes = observer.GetAndClearChanges();
678 ASSERT_EQ(2U, changes.size());
679 EXPECT_EQ("view=0,1 phase=changing visibility=true", changes[0]);
680 EXPECT_EQ("view=0,1 phase=changed visibility=false", changes[1]);
683 // Set visible to existing value and verify no notifications.
684 VisibilityChangeObserver observer(&v1);
685 v1.SetVisible(false);
686 EXPECT_TRUE(observer.GetAndClearChanges().empty());
690 TEST_F(ViewObserverTest, SetVisibleParent) {
691 TestView parent;
692 ViewPrivate(&parent).set_id(1);
693 TestView child;
694 ViewPrivate(&child).set_id(2);
695 parent.AddChild(&child);
696 EXPECT_TRUE(parent.visible());
697 EXPECT_TRUE(child.visible());
699 // Change visibility from true to false and make sure we get notifications
700 // on the parent.
701 VisibilityChangeObserver observer(&parent);
702 child.SetVisible(false);
704 Changes changes = observer.GetAndClearChanges();
705 ASSERT_EQ(1U, changes.size());
706 EXPECT_EQ("view=0,2 phase=changed visibility=false", changes[0]);
710 TEST_F(ViewObserverTest, SetVisibleChild) {
711 TestView parent;
712 ViewPrivate(&parent).set_id(1);
713 TestView child;
714 ViewPrivate(&child).set_id(2);
715 parent.AddChild(&child);
716 EXPECT_TRUE(parent.visible());
717 EXPECT_TRUE(child.visible());
719 // Change visibility from true to false and make sure we get notifications
720 // on the child.
721 VisibilityChangeObserver observer(&child);
722 parent.SetVisible(false);
724 Changes changes = observer.GetAndClearChanges();
725 ASSERT_EQ(1U, changes.size());
726 EXPECT_EQ("view=0,1 phase=changed visibility=false", changes[0]);
730 namespace {
732 class SharedPropertyChangeObserver : public ViewObserver {
733 public:
734 explicit SharedPropertyChangeObserver(View* view) : view_(view) {
735 view_->AddObserver(this);
737 ~SharedPropertyChangeObserver() override { view_->RemoveObserver(this); }
739 Changes GetAndClearChanges() {
740 Changes changes;
741 changes.swap(changes_);
742 return changes;
745 private:
746 // Overridden from ViewObserver:
747 void OnViewSharedPropertyChanged(
748 View* view,
749 const std::string& name,
750 const std::vector<uint8_t>* old_data,
751 const std::vector<uint8_t>* new_data) override {
752 changes_.push_back(base::StringPrintf(
753 "view=%s shared property changed key=%s old_value=%s new_value=%s",
754 ViewIdToString(view->id()).c_str(), name.c_str(),
755 VectorToString(old_data).c_str(), VectorToString(new_data).c_str()));
758 std::string VectorToString(const std::vector<uint8_t>* data) {
759 if (!data)
760 return "NULL";
761 std::string s;
762 for (char c : *data)
763 s += c;
764 return s;
767 View* view_;
768 Changes changes_;
770 MOJO_DISALLOW_COPY_AND_ASSIGN(SharedPropertyChangeObserver);
773 } // namespace
775 TEST_F(ViewObserverTest, SetLocalProperty) {
776 TestView v1;
777 std::vector<uint8_t> one(1, '1');
780 // Change visibility from true to false and make sure we get notifications.
781 SharedPropertyChangeObserver observer(&v1);
782 v1.SetSharedProperty("one", &one);
783 Changes changes = observer.GetAndClearChanges();
784 ASSERT_EQ(1U, changes.size());
785 EXPECT_EQ(
786 "view=0,1 shared property changed key=one old_value=NULL new_value=1",
787 changes[0]);
788 EXPECT_EQ(1U, v1.shared_properties().size());
791 // Set visible to existing value and verify no notifications.
792 SharedPropertyChangeObserver observer(&v1);
793 v1.SetSharedProperty("one", &one);
794 EXPECT_TRUE(observer.GetAndClearChanges().empty());
795 EXPECT_EQ(1U, v1.shared_properties().size());
798 // Set the value to NULL to delete it.
799 // Change visibility from true to false and make sure we get notifications.
800 SharedPropertyChangeObserver observer(&v1);
801 v1.SetSharedProperty("one", NULL);
802 Changes changes = observer.GetAndClearChanges();
803 ASSERT_EQ(1U, changes.size());
804 EXPECT_EQ(
805 "view=0,1 shared property changed key=one old_value=1 new_value=NULL",
806 changes[0]);
807 EXPECT_EQ(0U, v1.shared_properties().size());
810 // Setting a null property to null shouldn't update us.
811 SharedPropertyChangeObserver observer(&v1);
812 v1.SetSharedProperty("one", NULL);
813 EXPECT_TRUE(observer.GetAndClearChanges().empty());
814 EXPECT_EQ(0U, v1.shared_properties().size());
818 namespace {
820 typedef std::pair<const void*, intptr_t> PropertyChangeInfo;
822 class LocalPropertyChangeObserver : public ViewObserver {
823 public:
824 explicit LocalPropertyChangeObserver(View* view)
825 : view_(view), property_key_(nullptr), old_property_value_(-1) {
826 view_->AddObserver(this);
828 ~LocalPropertyChangeObserver() override { view_->RemoveObserver(this); }
830 PropertyChangeInfo PropertyChangeInfoAndClear() {
831 PropertyChangeInfo result(property_key_, old_property_value_);
832 property_key_ = NULL;
833 old_property_value_ = -3;
834 return result;
837 private:
838 void OnViewLocalPropertyChanged(View* window,
839 const void* key,
840 intptr_t old) override {
841 property_key_ = key;
842 old_property_value_ = old;
845 View* view_;
846 const void* property_key_;
847 intptr_t old_property_value_;
849 MOJO_DISALLOW_COPY_AND_ASSIGN(LocalPropertyChangeObserver);
852 } // namespace
854 TEST_F(ViewObserverTest, LocalPropertyChanged) {
855 TestView v1;
856 LocalPropertyChangeObserver o(&v1);
858 static const ViewProperty<int> prop = {-2};
860 v1.SetLocalProperty(&prop, 1);
861 EXPECT_EQ(PropertyChangeInfo(&prop, -2), o.PropertyChangeInfoAndClear());
862 v1.SetLocalProperty(&prop, -2);
863 EXPECT_EQ(PropertyChangeInfo(&prop, 1), o.PropertyChangeInfoAndClear());
864 v1.SetLocalProperty(&prop, 3);
865 EXPECT_EQ(PropertyChangeInfo(&prop, -2), o.PropertyChangeInfoAndClear());
866 v1.ClearLocalProperty(&prop);
867 EXPECT_EQ(PropertyChangeInfo(&prop, 3), o.PropertyChangeInfoAndClear());
869 // Sanity check to see if |PropertyChangeInfoAndClear| really clears.
870 EXPECT_EQ(PropertyChangeInfo(reinterpret_cast<const void*>(NULL), -3),
871 o.PropertyChangeInfoAndClear());
874 } // namespace mus