Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(333)

Side by Side Diff: chrome/browser/ui/cocoa/history_menu_bridge_unittest.mm

Issue 2192253002: Refactor history menu tests for clearer setup (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/ui/cocoa/history_menu_bridge.h" 5 #include "chrome/browser/ui/cocoa/history_menu_bridge.h"
6 6
7 #import <Cocoa/Cocoa.h> 7 #import <Cocoa/Cocoa.h>
8 8
9 #include <memory> 9 #include <memory>
10 #include <vector> 10 #include <vector>
Robert Sesek 2016/07/29 21:37:25 #include <initializer_list>
11 11
12 #include "base/memory/ptr_util.h" 12 #include "base/memory/ptr_util.h"
13 #include "base/memory/ref_counted_memory.h" 13 #include "base/memory/ref_counted_memory.h"
14 #include "base/strings/string_util.h" 14 #include "base/strings/string_util.h"
15 #include "base/strings/sys_string_conversions.h" 15 #include "base/strings/sys_string_conversions.h"
16 #include "base/strings/utf_string_conversions.h" 16 #include "base/strings/utf_string_conversions.h"
17 #include "chrome/app/chrome_command_ids.h" 17 #include "chrome/app/chrome_command_ids.h"
18 #include "chrome/browser/sessions/chrome_tab_restore_service_client.h" 18 #include "chrome/browser/sessions/chrome_tab_restore_service_client.h"
19 #include "chrome/browser/ui/cocoa/cocoa_profile_test.h" 19 #include "chrome/browser/ui/cocoa/cocoa_profile_test.h"
20 #include "chrome/test/base/testing_profile.h" 20 #include "chrome/test/base/testing_profile.h"
(...skipping 22 matching lines...) Expand all
43 MockBridge(Profile* profile) 43 MockBridge(Profile* profile)
44 : HistoryMenuBridge(profile), 44 : HistoryMenuBridge(profile),
45 menu_([[NSMenu alloc] initWithTitle:@"History"]) {} 45 menu_([[NSMenu alloc] initWithTitle:@"History"]) {}
46 46
47 NSMenu* HistoryMenu() override { return menu_.get(); } 47 NSMenu* HistoryMenu() override { return menu_.get(); }
48 48
49 private: 49 private:
50 base::scoped_nsobject<NSMenu> menu_; 50 base::scoped_nsobject<NSMenu> menu_;
51 }; 51 };
52 52
53 class TestEntries {
Sidney San Martín 2016/07/29 20:21:33 This class is longer/nastier than I wanted — if an
54 public:
55 struct Entry {
56 SessionID::id_type id;
57 virtual std::unique_ptr<MockTRS::Entry> toTRS() const = 0;
Robert Sesek 2016/07/29 21:37:25 naming: always use CamelCase for method names, unl
58 virtual void test(const MockBridge::HistoryItem&, NSMenuItem*) const = 0;
59
60 void test(const MockBridge::HistoryItem& historyItem) const {
61 EXPECT_EQ(id, historyItem.session_id);
62 }
63
64 Entry(SessionID::id_type id_) : id{id_} {}
65 };
66
67 struct Tab : public Entry {
68 std::string url, title;
Robert Sesek 2016/07/29 21:37:25 Don't declare member variables using comma notatio
69
70 Tab(SessionID::id_type id_, std::string url_, std::string title_)
Robert Sesek 2016/07/29 21:37:25 Take std::string arguments as const&, and the argu
Sidney San Martín 2016/07/29 22:02:33 WRT underscores, it's to avoid shadowing the membe
Robert Sesek 2016/08/02 14:39:25 I use a_var or an_var, indirect through the this p
71 : Entry{id_}, url{url_}, title{title_} {}
72
73 std::unique_ptr<MockTRS::Tab> toTRSTab() const {
74 auto tab = base::MakeUnique<MockTRS::Tab>();
75 tab->id = id;
76 tab->current_navigation_index = 0;
77 tab->navigations.push_back(
78 sessions::SerializedNavigationEntryTestHelper::CreateNavigation(
79 url, title));
80 return tab;
81 }
82
83 std::unique_ptr<MockTRS::Entry> toTRS() const override {
84 return std::unique_ptr<MockTRS::Entry>(toTRSTab());
85 }
86
87 void test(const MockBridge::HistoryItem& historyItem,
Robert Sesek 2016/07/29 21:37:25 naming: unless this is an ObjC method, variables a
88 NSMenuItem* menuItem) const override {
89 Entry::test(historyItem);
90 EXPECT_NSEQ(base::SysUTF8ToNSString(title), menuItem.title);
91 }
92 };
93
94 struct Window : public Entry {
95 std::vector<Tab> tabs;
96
97 Window(SessionID::id_type id_, std::vector<Tab> tabs_)
98 : Entry{id_}, tabs{tabs_} {}
99
100 std::unique_ptr<MockTRS::Entry> toTRS() const override {
101 auto window = new MockTRS::Window;
102 window->id = id;
103 window->tabs.reserve(tabs.size());
104 for (const auto& tab : tabs) {
105 window->tabs.push_back(*tab.toTRSTab());
106 }
107 return std::unique_ptr<MockTRS::Entry>(window);
108 }
109
110 void test(const MockBridge::HistoryItem& historyItem,
111 NSMenuItem* menuItem) const override {
112 Entry::test(historyItem);
113 NSMenu* submenu = menuItem.submenu;
114 EXPECT_EQ(tabs.size() + 2, (size_t)submenu.numberOfItems);
Robert Sesek 2016/07/29 21:37:25 numberOfItems should be NSUInteger and so should b
115 EXPECT_TRUE([submenu itemAtIndex:1].isSeparatorItem);
116 for (size_t i = 0; i < tabs.size(); i++) {
117 tabs[i].test(*historyItem.tabs[i], [submenu itemAtIndex:i + 2]);
118 }
119 }
120 };
121
122 private:
Robert Sesek 2016/07/29 21:37:25 Style does not mix public and private. private alw
Sidney San Martín 2016/07/29 22:02:33 I like that. When I was writing this I thought ent
123 std::vector<std::unique_ptr<Entry>> entries_;
124
125 public:
126 TestEntries(std::initializer_list<Entry*> l) {
127 entries_.reserve(l.size());
128 for (const auto& entry : l) {
129 entries_.emplace_back(entry);
130 }
131 }
132
133 void test(MockBridge* bridge) const {
134 NSMenu* menu = bridge->HistoryMenu();
135 ASSERT_EQ(entries_.size(), (size_t)[[menu itemArray] count]);
136 for (size_t i = 0; i < entries_.size(); i++) {
137 NSMenuItem* menuItem = [menu itemAtIndex:i];
138 MockBridge::HistoryItem* historyItem =
139 bridge->HistoryItemForMenuItem(menuItem);
140 EXPECT_TRUE(historyItem);
141 entries_[i]->test(*historyItem, [menu itemAtIndex:i]);
142 }
143 }
144
145 MockTRS::Entries toTRS() const {
146 MockTRS::Entries ret;
147 for (const auto& entry : entries_) {
148 ret.push_back(entry->toTRS().release());
149 }
150 return ret;
151 }
152 };
153
53 class HistoryMenuBridgeTest : public CocoaProfileTest { 154 class HistoryMenuBridgeTest : public CocoaProfileTest {
54 public: 155 public:
55 void SetUp() override { 156 void SetUp() override {
56 CocoaProfileTest::SetUp(); 157 CocoaProfileTest::SetUp();
57 profile()->CreateFaviconService(); 158 profile()->CreateFaviconService();
58 bridge_.reset(new MockBridge(profile())); 159 bridge_.reset(new MockBridge(profile()));
59 } 160 }
60 161
61 // We are a friend of HistoryMenuBridge (and have access to 162 // We are a friend of HistoryMenuBridge (and have access to
62 // protected methods), but none of the classes generated by TEST_F() 163 // protected methods), but none of the classes generated by TEST_F()
(...skipping 26 matching lines...) Expand all
89 } 190 }
90 191
91 HistoryMenuBridge::HistoryItem* CreateItem(const base::string16& title) { 192 HistoryMenuBridge::HistoryItem* CreateItem(const base::string16& title) {
92 HistoryMenuBridge::HistoryItem* item = 193 HistoryMenuBridge::HistoryItem* item =
93 new HistoryMenuBridge::HistoryItem(); 194 new HistoryMenuBridge::HistoryItem();
94 item->title = title; 195 item->title = title;
95 item->url = GURL(title); 196 item->url = GURL(title);
96 return item; 197 return item;
97 } 198 }
98 199
99 MockTRS::Tab CreateSessionTab(const std::string& url,
100 const std::string& title) {
101 MockTRS::Tab tab;
102 tab.current_navigation_index = 0;
103 tab.navigations.push_back(
104 sessions::SerializedNavigationEntryTestHelper::CreateNavigation(
105 url, title));
106 return tab;
107 }
108
109 void GetFaviconForHistoryItem(HistoryMenuBridge::HistoryItem* item) { 200 void GetFaviconForHistoryItem(HistoryMenuBridge::HistoryItem* item) {
110 bridge_->GetFaviconForHistoryItem(item); 201 bridge_->GetFaviconForHistoryItem(item);
111 } 202 }
112 203
113 void GotFaviconData(HistoryMenuBridge::HistoryItem* item, 204 void GotFaviconData(HistoryMenuBridge::HistoryItem* item,
114 const favicon_base::FaviconImageResult& image_result) { 205 const favicon_base::FaviconImageResult& image_result) {
115 bridge_->GotFaviconData(item, image_result); 206 bridge_->GotFaviconData(item, image_result);
116 } 207 }
117 208
118 std::unique_ptr<MockBridge> bridge_; 209 std::unique_ptr<MockBridge> bridge_;
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
206 // Confirm tooltips and confirm they are not trimmed (like the item 297 // Confirm tooltips and confirm they are not trimmed (like the item
207 // name might be). Add tolerance for URL fixer-upping; 298 // name might be). Add tolerance for URL fixer-upping;
208 // e.g. http://foo becomes http://foo/) 299 // e.g. http://foo becomes http://foo/)
209 EXPECT_GE([[[menu itemAtIndex:0] toolTip] length], (2*short_url.length()-5)); 300 EXPECT_GE([[[menu itemAtIndex:0] toolTip] length], (2*short_url.length()-5));
210 EXPECT_GE([[[menu itemAtIndex:1] toolTip] length], (2*long_url.length()-5)); 301 EXPECT_GE([[[menu itemAtIndex:1] toolTip] length], (2*long_url.length()-5));
211 } 302 }
212 303
213 // Test that the menu is created for a set of simple tabs. 304 // Test that the menu is created for a set of simple tabs.
214 TEST_F(HistoryMenuBridgeTest, RecentlyClosedTabs) { 305 TEST_F(HistoryMenuBridgeTest, RecentlyClosedTabs) {
215 std::unique_ptr<MockTRS> trs(new MockTRS(profile())); 306 std::unique_ptr<MockTRS> trs(new MockTRS(profile()));
216 MockTRS::Entries entries;
217 307
218 MockTRS::Tab tab1 = CreateSessionTab("http://google.com", "Google"); 308 const TestEntries testEntries{
219 tab1.id = 24; 309 new TestEntries::Tab{24, "http://google.com", "Google"},
220 entries.push_back(&tab1); 310 new TestEntries::Tab{42, "http://apple.com", "Apple"},
311 };
221 312
222 MockTRS::Tab tab2 = CreateSessionTab("http://apple.com", "Apple"); 313 auto entries = testEntries.toTRS();
223 tab2.id = 42;
224 entries.push_back(&tab2);
225
226 using ::testing::ReturnRef; 314 using ::testing::ReturnRef;
227 EXPECT_CALL(*trs.get(), entries()).WillOnce(ReturnRef(entries)); 315 EXPECT_CALL(*trs.get(), entries()).WillOnce(ReturnRef(entries));
228 316
229 bridge_->TabRestoreServiceChanged(trs.get()); 317 bridge_->TabRestoreServiceChanged(trs.get());
230 318 testEntries.test(bridge_.get());
231 NSMenu* menu = bridge_->HistoryMenu();
232 ASSERT_EQ(2U, [[menu itemArray] count]);
233
234 NSMenuItem* item1 = [menu itemAtIndex:0];
235 MockBridge::HistoryItem* hist1 = bridge_->HistoryItemForMenuItem(item1);
236 EXPECT_TRUE(hist1);
237 EXPECT_EQ(24, hist1->session_id);
238 EXPECT_NSEQ(@"Google", [item1 title]);
239
240 NSMenuItem* item2 = [menu itemAtIndex:1];
241 MockBridge::HistoryItem* hist2 = bridge_->HistoryItemForMenuItem(item2);
242 EXPECT_TRUE(hist2);
243 EXPECT_EQ(42, hist2->session_id);
244 EXPECT_NSEQ(@"Apple", [item2 title]);
245 } 319 }
246 320
247 // Test that the menu is created for a mix of windows and tabs. 321 // Test that the menu is created for a mix of windows and tabs.
248 TEST_F(HistoryMenuBridgeTest, RecentlyClosedTabsAndWindows) { 322 TEST_F(HistoryMenuBridgeTest, RecentlyClosedTabsAndWindows) {
249 std::unique_ptr<MockTRS> trs(new MockTRS(profile())); 323 std::unique_ptr<MockTRS> trs(new MockTRS(profile()));
250 MockTRS::Entries entries;
251 324
252 MockTRS::Tab tab1 = CreateSessionTab("http://google.com", "Google"); 325 const TestEntries testEntries{
253 tab1.id = 24; 326 new TestEntries::Window{30, {
254 entries.push_back(&tab1); 327 {31, "http://foo.com", "foo"},
328 {32, "http://bar.com", "bar"},
329 }},
330 new TestEntries::Tab{42, "http://apple.com", "Apple"},
331 new TestEntries::Window{50, {
332 {51, "http://magic.com", "magic"},
333 {52, "http://goats.com", "goats"},
334 {53, "http://teleporter.com", "teleporter"},
335 }},
336 };
255 337
256 // TODO(sdy): The tab ids below *must* be set after all of them have been 338 auto entries = testEntries.toTRS();
257 // pushed onto window.tabs. Otherwise, the ids will change when push_back
258 // reallocates the vector's storage and calls each tabs' copy ctor. Ugh.
259
260 MockTRS::Window win1;
261 win1.id = 30;
262 win1.tabs.push_back(CreateSessionTab("http://foo.com", "foo"));
263 win1.tabs.push_back(CreateSessionTab("http://bar.com", "bar"));
264 win1.tabs[0].id = 31;
265 win1.tabs[1].id = 32;
266 entries.push_back(&win1);
267
268 MockTRS::Tab tab2 = CreateSessionTab("http://apple.com", "Apple");
269 tab2.id = 42;
270 entries.push_back(&tab2);
271
272 MockTRS::Window win2;
273 win2.id = 50;
274 win2.tabs.push_back(CreateSessionTab("http://magic.com", "magic"));
275 win2.tabs.push_back(CreateSessionTab("http://goats.com", "goats"));
276 win2.tabs.push_back(CreateSessionTab("http://teleporter.com", "teleporter"));
277 win2.tabs[0].id = 51;
278 win2.tabs[1].id = 52;
279 win2.tabs[2].id = 53;
280 entries.push_back(&win2);
281
282 using ::testing::ReturnRef; 339 using ::testing::ReturnRef;
283 EXPECT_CALL(*trs.get(), entries()).WillOnce(ReturnRef(entries)); 340 EXPECT_CALL(*trs.get(), entries()).WillOnce(ReturnRef(entries));
284 341
285 bridge_->TabRestoreServiceChanged(trs.get()); 342 bridge_->TabRestoreServiceChanged(trs.get());
286 343 testEntries.test(bridge_.get());
287 NSMenu* menu = bridge_->HistoryMenu();
288 ASSERT_EQ(4U, [[menu itemArray] count]);
289
290 NSMenuItem* item1 = [menu itemAtIndex:0];
291 MockBridge::HistoryItem* hist1 = bridge_->HistoryItemForMenuItem(item1);
292 EXPECT_TRUE(hist1);
293 EXPECT_EQ(24, hist1->session_id);
294 EXPECT_NSEQ(@"Google", [item1 title]);
295
296 NSMenuItem* item2 = [menu itemAtIndex:1];
297 MockBridge::HistoryItem* hist2 = bridge_->HistoryItemForMenuItem(item2);
298 EXPECT_TRUE(hist2);
299 EXPECT_EQ(30, hist2->session_id);
300 EXPECT_EQ(2U, hist2->tabs.size());
301 // Do not test menu item title because it is localized.
302 NSMenu* submenu1 = [item2 submenu];
303 EXPECT_EQ(4U, [[submenu1 itemArray] count]);
304 // Do not test Restore All Tabs because it is localiced.
305 EXPECT_TRUE([[submenu1 itemAtIndex:1] isSeparatorItem]);
306 EXPECT_NSEQ(@"foo", [[submenu1 itemAtIndex:2] title]);
307 EXPECT_NSEQ(@"bar", [[submenu1 itemAtIndex:3] title]);
308 EXPECT_EQ(31, hist2->tabs[0]->session_id);
309 EXPECT_EQ(32, hist2->tabs[1]->session_id);
310
311 NSMenuItem* item3 = [menu itemAtIndex:2];
312 MockBridge::HistoryItem* hist3 = bridge_->HistoryItemForMenuItem(item3);
313 EXPECT_TRUE(hist3);
314 EXPECT_EQ(42, hist3->session_id);
315 EXPECT_NSEQ(@"Apple", [item3 title]);
316
317 NSMenuItem* item4 = [menu itemAtIndex:3];
318 MockBridge::HistoryItem* hist4 = bridge_->HistoryItemForMenuItem(item4);
319 EXPECT_TRUE(hist4);
320 EXPECT_EQ(50, hist4->session_id);
321 EXPECT_EQ(3U, hist4->tabs.size());
322 // Do not test menu item title because it is localized.
323 NSMenu* submenu2 = [item4 submenu];
324 EXPECT_EQ(5U, [[submenu2 itemArray] count]);
325 // Do not test Restore All Tabs because it is localiced.
326 EXPECT_TRUE([[submenu2 itemAtIndex:1] isSeparatorItem]);
327 EXPECT_NSEQ(@"magic", [[submenu2 itemAtIndex:2] title]);
328 EXPECT_NSEQ(@"goats", [[submenu2 itemAtIndex:3] title]);
329 EXPECT_NSEQ(@"teleporter", [[submenu2 itemAtIndex:4] title]);
330 EXPECT_EQ(51, hist4->tabs[0]->session_id);
331 EXPECT_EQ(52, hist4->tabs[1]->session_id);
332 EXPECT_EQ(53, hist4->tabs[2]->session_id);
333 } 344 }
334 345
335 // Tests that we properly request an icon from the FaviconService. 346 // Tests that we properly request an icon from the FaviconService.
336 TEST_F(HistoryMenuBridgeTest, GetFaviconForHistoryItem) { 347 TEST_F(HistoryMenuBridgeTest, GetFaviconForHistoryItem) {
337 // Create a fake item. 348 // Create a fake item.
338 HistoryMenuBridge::HistoryItem item; 349 HistoryMenuBridge::HistoryItem item;
339 item.title = base::ASCIIToUTF16("Title"); 350 item.title = base::ASCIIToUTF16("Title");
340 item.url = GURL("http://google.com"); 351 item.url = GURL("http://google.com");
341 352
342 // Request the icon. 353 // Request the icon.
(...skipping 20 matching lines...) Expand all
363 image_result.image = gfx::Image::CreateFrom1xBitmap(bitmap); 374 image_result.image = gfx::Image::CreateFrom1xBitmap(bitmap);
364 GotFaviconData(&item, image_result); 375 GotFaviconData(&item, image_result);
365 376
366 // Make sure the callback works. 377 // Make sure the callback works.
367 EXPECT_FALSE(item.icon_requested); 378 EXPECT_FALSE(item.icon_requested);
368 EXPECT_TRUE(item.icon.get()); 379 EXPECT_TRUE(item.icon.get());
369 EXPECT_TRUE([item.menu_item image]); 380 EXPECT_TRUE([item.menu_item image]);
370 } 381 }
371 382
372 } // namespace 383 } // namespace
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698