Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / cocoa / constrained_window / constrained_window_sheet_controller_unittest.mm
1 // Copyright (c) 2012 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 "chrome/browser/ui/cocoa/constrained_window/constrained_window_sheet_controller.h"
6
7 #import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
8 #import "chrome/browser/ui/cocoa/constrained_window/constrained_window_custom_sheet.h"
9 #import "testing/gtest_mac.h"
10
11 namespace {
12
13 const int kSystemSheetReturnCode = 77;
14
15 }  // namespace
16
17 @interface ConstrainedWindowSystemSheetTest
18     : NSObject <ConstrainedWindowSheet> {
19   int returnCode_;
20   NSAlert* alert_;  // weak
21 }
22
23 @property(nonatomic, readonly) int returnCode;
24 @property(nonatomic, assign) NSAlert* alert;
25
26 @end
27
28 @implementation ConstrainedWindowSystemSheetTest
29
30 @synthesize returnCode = returnCode_;
31 @synthesize alert = alert_;
32
33 - (void)showSheetForWindow:(NSWindow*)window {
34   [alert_ beginSheetModalForWindow:window
35                      modalDelegate:self
36                     didEndSelector:@selector(alertDidEnd:returnCode:ctxInfo:)
37                        contextInfo:NULL];
38 }
39
40 - (void)closeSheetWithAnimation:(BOOL)withAnimation {
41   [NSApp endSheet:[alert_ window] returnCode:kSystemSheetReturnCode];
42 }
43
44 - (void)hideSheet {
45 }
46
47 - (void)unhideSheet {
48 }
49
50 - (void)pulseSheet {
51 }
52
53 - (void)makeSheetKeyAndOrderFront {
54 }
55
56 - (void)updateSheetPosition {
57 }
58
59 - (void)alertDidEnd:(NSAlert *)alert
60          returnCode:(NSInteger)returnCode
61             ctxInfo:(void *)contextInfo {
62   returnCode_ = returnCode;
63 }
64
65 @end
66
67 class ConstrainedWindowSheetControllerTest : public CocoaTest {
68  protected:
69   virtual ~ConstrainedWindowSheetControllerTest() {
70   }
71
72   virtual void SetUp() override {
73     CocoaTest::SetUp();
74
75     // Center the window so that the sheet doesn't go offscreen.
76     [test_window() center];
77
78     // The real view setup is quite a few levels deep; recreate something
79     // similar.
80     NSRect dummy_rect = NSMakeRect(0, 0, 50, 50);
81     tab_view_parent_ = [test_window() contentView];
82     for (int i = 0; i < 3; ++i) {
83       base::scoped_nsobject<NSView> new_view(
84           [[NSView alloc] initWithFrame:dummy_rect]);
85       [tab_view_parent_ addSubview:new_view.get()];
86       tab_view_parent_ = new_view.get();
87     }
88
89     // Create two dummy tabs and make the first one active.
90     tab_views_.reset([[NSMutableArray alloc] init]);
91     for (int i = 0; i < 2; ++i) {
92       base::scoped_nsobject<NSView> view(
93           [[NSView alloc] initWithFrame:dummy_rect]);
94       [tab_views_ addObject:view];
95     }
96     tab0_ = [tab_views_ objectAtIndex:0];
97     tab1_ = [tab_views_ objectAtIndex:1];
98     ActivateTabView(tab0_);
99
100     // Create a test sheet.
101     sheet_window_.reset([[NSWindow alloc]
102         initWithContentRect:dummy_rect
103                   styleMask:NSTitledWindowMask
104                     backing:NSBackingStoreBuffered
105                       defer:NO]);
106     [sheet_window_ setReleasedWhenClosed:NO];
107     sheet_.reset([[CustomConstrainedWindowSheet alloc]
108         initWithCustomWindow:sheet_window_]);
109
110     controller_.reset([[ConstrainedWindowSheetController
111             controllerForParentWindow:test_window()] retain]);
112     EXPECT_TRUE(controller_);
113     EXPECT_FALSE([ConstrainedWindowSheetController controllerForSheet:sheet_]);
114   }
115
116   virtual void TearDown() override {
117     sheet_.reset();
118     sheet_window_.reset();
119     CocoaTest::TearDown();
120   }
121
122   void ActivateTabView(NSView* tab_view) {
123     for (NSView* view in tab_views_.get())
124       [view removeFromSuperview];
125     [tab_view_parent_ addSubview:tab_view];
126     active_tab_view_ = tab_view;
127
128     ConstrainedWindowSheetController* controller =
129         [ConstrainedWindowSheetController
130             controllerForParentWindow:test_window()];
131     EXPECT_TRUE(controller);
132     [controller parentViewDidBecomeActive:active_tab_view_];
133   }
134
135   NSRect GetViewFrameInScreenCoordinates(NSView* view) {
136     NSRect rect = [view convertRect:[view bounds] toView:nil];
137     rect.origin = [[view window] convertBaseToScreen:rect.origin];
138     return rect;
139   }
140
141   void VerifySheetXPosition(NSRect sheet_frame, NSView* parent_view) {
142     NSRect parent_frame = GetViewFrameInScreenCoordinates(parent_view);
143     CGFloat expected_x = NSMinX(parent_frame) +
144         (NSWidth(parent_frame) - NSWidth(sheet_frame)) / 2.0;
145     EXPECT_EQ(expected_x, NSMinX(sheet_frame));
146   }
147
148   CGFloat GetSheetYOffset(NSRect sheet_frame, NSView* parent_view) {
149     return NSMaxY(sheet_frame) -
150            NSMaxY(GetViewFrameInScreenCoordinates(parent_view));
151   }
152
153   base::scoped_nsobject<NSWindow> sheet_window_;
154   base::scoped_nsobject<CustomConstrainedWindowSheet> sheet_;
155   base::scoped_nsobject<ConstrainedWindowSheetController> controller_;
156   base::scoped_nsobject<NSMutableArray> tab_views_;
157   NSView* tab_view_parent_;
158   NSView* active_tab_view_;
159   NSView* tab0_;
160   NSView* tab1_;
161 };
162
163 // Test showing then hiding the sheet.
164 TEST_F(ConstrainedWindowSheetControllerTest, ShowHide) {
165   EXPECT_FALSE([sheet_window_ isVisible]);
166   [controller_ showSheet:sheet_ forParentView:active_tab_view_];
167   EXPECT_TRUE([ConstrainedWindowSheetController controllerForSheet:sheet_]);
168   EXPECT_TRUE([sheet_window_ isVisible]);
169
170   [controller_ closeSheet:sheet_];
171   EXPECT_FALSE([ConstrainedWindowSheetController controllerForSheet:sheet_]);
172   EXPECT_FALSE([sheet_window_ isVisible]);
173 }
174
175 // Test that switching tabs correctly hides the inactive tab's sheet.
176 TEST_F(ConstrainedWindowSheetControllerTest, SwitchTabs) {
177   [controller_ showSheet:sheet_ forParentView:active_tab_view_];
178
179   EXPECT_TRUE([sheet_window_ isVisible]);
180   EXPECT_EQ(1.0, [sheet_window_ alphaValue]);
181   ActivateTabView([tab_views_ objectAtIndex:1]);
182   EXPECT_TRUE([sheet_window_ isVisible]);
183   EXPECT_EQ(0.0, [sheet_window_ alphaValue]);
184   ActivateTabView([tab_views_ objectAtIndex:0]);
185   EXPECT_TRUE([sheet_window_ isVisible]);
186   EXPECT_EQ(1.0, [sheet_window_ alphaValue]);
187 }
188
189 // Test that adding a sheet to an inactive view doesn't show it.
190 TEST_F(ConstrainedWindowSheetControllerTest, AddToInactiveTab) {
191   ActivateTabView(tab0_);
192   [controller_ showSheet:sheet_ forParentView:tab1_];
193   EXPECT_EQ(0.0, [sheet_window_ alphaValue]);
194
195   ActivateTabView(tab1_);
196   EXPECT_EQ(1.0, [sheet_window_ alphaValue]);
197   VerifySheetXPosition([sheet_window_ frame], tab1_);
198 }
199
200 // Test that two parent windows with two sheet controllers don't conflict.
201 TEST_F(ConstrainedWindowSheetControllerTest, TwoParentWindows) {
202   base::scoped_nsobject<NSWindow> parent_window2(
203       [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 30, 30)
204                                   styleMask:NSTitledWindowMask
205                                     backing:NSBackingStoreBuffered
206                                       defer:NO]);
207   [parent_window2 setReleasedWhenClosed:NO];
208
209   ConstrainedWindowSheetController* controller2 =
210       [ConstrainedWindowSheetController
211           controllerForParentWindow:parent_window2];
212   EXPECT_TRUE(controller2);
213   EXPECT_NSNE(controller_, controller2);
214
215   [controller2 showSheet:sheet_ forParentView:[parent_window2 contentView]];
216   EXPECT_NSEQ(controller2,
217               [ConstrainedWindowSheetController controllerForSheet:sheet_]);
218
219   [parent_window2 close];
220 }
221
222 // Test that resizing sheet works.
223 TEST_F(ConstrainedWindowSheetControllerTest, Resize) {
224   [controller_ showSheet:sheet_ forParentView:active_tab_view_];
225
226   NSRect old_frame = [sheet_window_ frame];
227
228   NSRect sheet_frame;
229   sheet_frame.size = NSMakeSize(NSWidth(old_frame) + 100,
230                                 NSHeight(old_frame) + 50);
231   sheet_frame.origin = [controller_ originForSheet:sheet_
232                                     withWindowSize:sheet_frame.size];
233
234   // Y pos should not have changed.
235   EXPECT_EQ(NSMaxY(sheet_frame), NSMaxY(old_frame));
236
237   // X pos should be centered on parent view.
238   VerifySheetXPosition(sheet_frame, active_tab_view_);
239 }
240
241 // Test that resizing a hidden sheet works.
242 TEST_F(ConstrainedWindowSheetControllerTest, ResizeHiddenSheet) {
243   [controller_ showSheet:sheet_ forParentView:tab0_];
244   EXPECT_EQ(1.0, [sheet_window_ alphaValue]);
245   ActivateTabView(tab1_);
246   EXPECT_EQ(0.0, [sheet_window_ alphaValue]);
247
248   NSRect old_frame = [sheet_window_ frame];
249   NSRect new_inactive_frame = NSInsetRect(old_frame, -30, -40);
250   [sheet_window_ setFrame:new_inactive_frame display:YES];
251
252   ActivateTabView(tab0_);
253   EXPECT_EQ(1.0, [sheet_window_ alphaValue]);
254
255   NSRect new_active_frame = [sheet_window_ frame];
256   EXPECT_EQ(NSWidth(new_inactive_frame), NSWidth(new_active_frame));
257   EXPECT_EQ(NSHeight(new_inactive_frame), NSHeight(new_active_frame));
258 }
259
260 // Test resizing parent window keeps the sheet anchored.
261 TEST_F(ConstrainedWindowSheetControllerTest, ResizeParentWindow) {
262   [controller_ showSheet:sheet_ forParentView:active_tab_view_];
263   CGFloat sheet_offset =
264       GetSheetYOffset([sheet_window_ frame], active_tab_view_);
265
266   // Test 3x3 different parent window sizes.
267   CGFloat insets[] = {-10, 0, 10};
268   NSRect old_frame = [test_window() frame];
269
270   for (size_t x = 0; x < arraysize(insets); x++) {
271     for (size_t y = 0; y < arraysize(insets); y++) {
272       NSRect resized_frame = NSInsetRect(old_frame, insets[x], insets[y]);
273       [test_window() setFrame:resized_frame display:YES];
274       NSRect sheet_frame = [sheet_window_ frame];
275
276       // Y pos should track parent view's position.
277       EXPECT_EQ(sheet_offset, GetSheetYOffset(sheet_frame, active_tab_view_));
278
279       // X pos should be centered on parent view.
280       VerifySheetXPosition(sheet_frame, active_tab_view_);
281     }
282   }
283 }
284
285 // Test system sheets.
286 TEST_F(ConstrainedWindowSheetControllerTest, SystemSheet) {
287   base::scoped_nsobject<ConstrainedWindowSystemSheetTest> system_sheet(
288       [[ConstrainedWindowSystemSheetTest alloc] init]);
289   base::scoped_nsobject<NSAlert> alert([[NSAlert alloc] init]);
290   [system_sheet setAlert:alert];
291
292   EXPECT_FALSE([[alert window] isVisible]);
293   [controller_ showSheet:system_sheet forParentView:active_tab_view_];
294   EXPECT_TRUE([[alert window] isVisible]);
295
296   [controller_ closeSheet:system_sheet];
297   EXPECT_FALSE([[alert window] isVisible]);
298   EXPECT_EQ(kSystemSheetReturnCode, [system_sheet returnCode]);
299 }
300
301 // Test showing a system sheet on an inactive tab.
302 TEST_F(ConstrainedWindowSheetControllerTest, SystemSheetAddToInactiveTab) {
303   base::scoped_nsobject<ConstrainedWindowSystemSheetTest> system_sheet(
304       [[ConstrainedWindowSystemSheetTest alloc] init]);
305   base::scoped_nsobject<NSAlert> alert([[NSAlert alloc] init]);
306   [system_sheet setAlert:alert];
307
308   EXPECT_FALSE([[alert window] isVisible]);
309   [controller_ showSheet:system_sheet forParentView:tab1_];
310   EXPECT_FALSE([[alert window] isVisible]);
311
312   ActivateTabView(tab1_);
313   EXPECT_TRUE([[alert window] isVisible]);
314   EXPECT_EQ(1.0, [[alert window] alphaValue]);
315
316   [controller_ closeSheet:system_sheet];
317 }