1// Copyright (c) 2013 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.
4
5#import "ui/base/cocoa/nsview_additions.h"
6
7#include "base/mac/scoped_nsobject.h"
8#include "testing/gtest/include/gtest/gtest.h"
9#import "testing/gtest_mac.h"
10#import "ui/gfx/test/ui_cocoa_test_helper.h"
11
12typedef ui::CocoaTest NSViewChromeAdditionsTest;
13
14@interface ParentView : NSView {
15 @private
16  int removeCount_;
17  int addCount_;
18}
19
20@property(readonly, nonatomic) int removeCount;
21@property(readonly, nonatomic) int addCount;
22
23@end
24
25@implementation ParentView
26
27@synthesize removeCount = removeCount_;
28@synthesize addCount = addCount_;
29
30- (void)willRemoveSubview:(NSView*)view {
31  ++removeCount_;
32}
33
34- (void)didAddSubview:(NSView*)view {
35  ++addCount_;
36}
37
38@end
39
40TEST_F(NSViewChromeAdditionsTest, BelowAboveView) {
41  base::scoped_nsobject<NSView> parent(
42      [[NSView alloc] initWithFrame:NSZeroRect]);
43  base::scoped_nsobject<NSView> child1(
44      [[NSView alloc] initWithFrame:NSZeroRect]);
45  base::scoped_nsobject<NSView> child2(
46      [[NSView alloc] initWithFrame:NSZeroRect]);
47
48  [parent addSubview:child1];
49  [parent addSubview:child2];
50  EXPECT_TRUE([child1 cr_isBelowView:child2]);
51  EXPECT_FALSE([child1 cr_isAboveView:child2]);
52  EXPECT_FALSE([child2 cr_isBelowView:child1]);
53  EXPECT_TRUE([child2 cr_isAboveView:child1]);
54
55  [child1 removeFromSuperview];
56  [child2 removeFromSuperview];
57  [parent addSubview:child2];
58  [parent addSubview:child1];
59  EXPECT_FALSE([child1 cr_isBelowView:child2]);
60  EXPECT_TRUE([child1 cr_isAboveView:child2]);
61  EXPECT_TRUE([child2 cr_isBelowView:child1]);
62  EXPECT_FALSE([child2 cr_isAboveView:child1]);
63}
64
65TEST_F(NSViewChromeAdditionsTest, EnsurePosition) {
66  base::scoped_nsobject<NSView> parent(
67      [[NSView alloc] initWithFrame:NSZeroRect]);
68  base::scoped_nsobject<NSView> child1(
69      [[NSView alloc] initWithFrame:NSZeroRect]);
70  base::scoped_nsobject<NSView> child2(
71      [[NSView alloc] initWithFrame:NSZeroRect]);
72
73  [parent addSubview:child1];
74  [parent cr_ensureSubview:child2
75              isPositioned:NSWindowAbove
76                relativeTo:child1];
77  EXPECT_NSEQ([[parent subviews] objectAtIndex:0], child1);
78  EXPECT_NSEQ([[parent subviews] objectAtIndex:1], child2);
79
80  [child2 removeFromSuperview];
81  [parent cr_ensureSubview:child2
82              isPositioned:NSWindowBelow
83                relativeTo:child1];
84  EXPECT_NSEQ([[parent subviews] objectAtIndex:0], child2);
85  EXPECT_NSEQ([[parent subviews] objectAtIndex:1], child1);
86}
87
88// Verify that no view is removed or added when no change is needed.
89TEST_F(NSViewChromeAdditionsTest, EnsurePositionNoChange) {
90  base::scoped_nsobject<ParentView> parent(
91      [[ParentView alloc] initWithFrame:NSZeroRect]);
92  base::scoped_nsobject<NSView> child1(
93      [[NSView alloc] initWithFrame:NSZeroRect]);
94  base::scoped_nsobject<NSView> child2(
95      [[NSView alloc] initWithFrame:NSZeroRect]);
96  [parent addSubview:child1];
97  [parent addSubview:child2];
98
99  EXPECT_EQ(0, [parent removeCount]);
100  EXPECT_EQ(2, [parent addCount]);
101  [parent cr_ensureSubview:child2
102              isPositioned:NSWindowAbove
103                relativeTo:child1];
104  EXPECT_EQ(0, [parent removeCount]);
105  EXPECT_EQ(2, [parent addCount]);
106}
107