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.
4
5#import "ui/views/controls/menu/menu_runner_impl_cocoa.h"
6
7#include "base/strings/utf_string_conversions.h"
8#include "ui/base/models/simple_menu_model.h"
9#include "ui/events/event_utils.h"
10#include "ui/views/test/views_test_base.h"
11
12namespace views {
13namespace test {
14
15class MenuRunnerCocoaTest : public ViewsTestBase {
16 public:
17  MenuRunnerCocoaTest() : runner_(NULL) {}
18  virtual ~MenuRunnerCocoaTest() {}
19
20  virtual void SetUp() OVERRIDE {
21    ViewsTestBase::SetUp();
22
23    menu_.reset(new ui::SimpleMenuModel(NULL));
24    menu_->AddItem(0, base::ASCIIToUTF16("Menu Item"));
25
26    runner_ = new internal::MenuRunnerImplCocoa(menu_.get());
27    EXPECT_FALSE(runner_->IsRunning());
28  }
29
30  virtual void TearDown() OVERRIDE {
31    if (runner_) {
32      runner_->Release();
33      runner_ = NULL;
34    }
35
36    ViewsTestBase::TearDown();
37  }
38
39  // Runs the menu after scheduling |block| on the run loop.
40  MenuRunner::RunResult RunMenu(dispatch_block_t block) {
41    CFRunLoopPerformBlock(CFRunLoopGetCurrent(), kCFRunLoopCommonModes, ^{
42        EXPECT_TRUE(runner_->IsRunning());
43        block();
44    });
45    return runner_->RunMenuAt(
46        NULL, NULL, gfx::Rect(), MENU_ANCHOR_TOPLEFT, MenuRunner::CONTEXT_MENU);
47  }
48
49 protected:
50  scoped_ptr<ui::SimpleMenuModel> menu_;
51  internal::MenuRunnerImplCocoa* runner_;
52
53 private:
54  DISALLOW_COPY_AND_ASSIGN(MenuRunnerCocoaTest);
55};
56
57TEST_F(MenuRunnerCocoaTest, RunMenuAndCancel) {
58  base::TimeDelta min_time = ui::EventTimeForNow();
59
60  MenuRunner::RunResult result = RunMenu(^{
61      runner_->Cancel();
62      EXPECT_FALSE(runner_->IsRunning());
63  });
64
65  EXPECT_EQ(MenuRunner::NORMAL_EXIT, result);
66  EXPECT_FALSE(runner_->IsRunning());
67
68  EXPECT_GE(runner_->GetClosingEventTime(), min_time);
69  EXPECT_LE(runner_->GetClosingEventTime(), ui::EventTimeForNow());
70
71  // Cancel again.
72  runner_->Cancel();
73  EXPECT_FALSE(runner_->IsRunning());
74}
75
76TEST_F(MenuRunnerCocoaTest, RunMenuAndDelete) {
77  MenuRunner::RunResult result = RunMenu(^{
78      runner_->Release();
79      runner_ = NULL;
80  });
81
82  EXPECT_EQ(MenuRunner::MENU_DELETED, result);
83}
84
85TEST_F(MenuRunnerCocoaTest, RunMenuTwice) {
86  for (int i = 0; i < 2; ++i) {
87    MenuRunner::RunResult result = RunMenu(^{
88        runner_->Cancel();
89    });
90    EXPECT_EQ(MenuRunner::NORMAL_EXIT, result);
91    EXPECT_FALSE(runner_->IsRunning());
92  }
93}
94
95TEST_F(MenuRunnerCocoaTest, CancelWithoutRunning) {
96  runner_->Cancel();
97  EXPECT_FALSE(runner_->IsRunning());
98  EXPECT_EQ(base::TimeDelta(), runner_->GetClosingEventTime());
99}
100
101TEST_F(MenuRunnerCocoaTest, DeleteWithoutRunning) {
102  runner_->Release();
103  runner_ = NULL;
104}
105
106}  // namespace test
107}  // namespace views
108