blob: 5f7b5a9f30bc3cd142385c9e60c75f026773909c [file] [log] [blame]
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import "ios/chrome/browser/ui/reading_list/reading_list_collection_view_controller.h"
#include <unordered_set>
#import "base/mac/foundation_util.h"
#include "base/memory/ptr_util.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/sys_string_conversions.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/default_clock.h"
#include "components/favicon/core/large_icon_service.h"
#include "components/favicon/core/test/mock_favicon_service.h"
#include "components/reading_list/core/reading_list_model.h"
#include "components/reading_list/core/reading_list_model_impl.h"
#include "components/reading_list/core/reading_list_model_storage.h"
#include "components/url_formatter/url_formatter.h"
#include "ios/chrome/browser/browser_state/test_chrome_browser_state.h"
#include "ios/chrome/browser/favicon/ios_chrome_large_icon_service_factory.h"
#import "ios/chrome/browser/ui/collection_view/collection_view_model.h"
#import "ios/chrome/browser/ui/reading_list/reading_list_collection_view_item.h"
#import "ios/chrome/browser/ui/reading_list/reading_list_mediator.h"
#include "ios/web/public/test/test_web_thread_bundle.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/platform_test.h"
#import "third_party/ocmock/OCMock/OCMock.h"
#import "third_party/ocmock/gtest_support.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
using favicon::PostReply;
using testing::_;
#pragma mark - ReadingListCollectionViewControllerTest
class ReadingListCollectionViewControllerTest : public testing::Test {
public:
ReadingListCollectionViewControllerTest() {}
~ReadingListCollectionViewControllerTest() override {}
testing::StrictMock<favicon::MockFaviconService> mock_favicon_service_;
std::unique_ptr<ReadingListModelImpl> reading_list_model_;
ReadingListMediator* mediator_;
std::unique_ptr<favicon::LargeIconService> large_icon_service_;
ReadingListCollectionViewController* reading_list_view_controller_;
id mock_delegate_;
void SetUp() override {
testing::Test::SetUp();
EXPECT_CALL(mock_favicon_service_,
GetLargestRawFaviconForPageURL(_, _, _, _, _))
.WillRepeatedly(PostReply<5>(favicon_base::FaviconRawBitmapResult()));
reading_list_model_.reset(new ReadingListModelImpl(
nullptr, nullptr, base::MakeUnique<base::DefaultClock>()));
mediator_ =
[[ReadingListMediator alloc] initWithModel:reading_list_model_.get()];
large_icon_service_.reset(new favicon::LargeIconService(
&mock_favicon_service_, base::ThreadTaskRunnerHandle::Get(),
/*image_fetcher=*/nullptr));
reading_list_view_controller_ = [[ReadingListCollectionViewController alloc]
initWithDataSource:mediator_
largeIconService:large_icon_service_.get()
toolbar:nil];
mock_delegate_ = [OCMockObject
niceMockForProtocol:@protocol(
ReadingListCollectionViewControllerDelegate)];
[reading_list_view_controller_ setDelegate:mock_delegate_];
}
private:
web::TestWebThreadBundle thread_bundle_;
DISALLOW_COPY_AND_ASSIGN(ReadingListCollectionViewControllerTest);
};
// Tests that reading list items are displayed.
TEST_F(ReadingListCollectionViewControllerTest, DisplaysItems) {
// Prefill some items.
reading_list_model_->AddEntry(GURL("https://chromium.org"), "news",
reading_list::ADDED_VIA_CURRENT_APP);
reading_list_model_->AddEntry(GURL("https://mail.chromium.org"), "mail",
reading_list::ADDED_VIA_CURRENT_APP);
reading_list_model_->AddEntry(GURL("https://foo.bar"), "Foo",
reading_list::ADDED_VIA_CURRENT_APP);
reading_list_model_->SetReadStatus(GURL("https://foo.bar"), true);
// Load view.
[reading_list_view_controller_ view];
// There are two sections: Read and Unread.
DCHECK([reading_list_view_controller_.collectionView numberOfSections] == 2);
// There are two unread articles.
DCHECK([reading_list_view_controller_.collectionView
numberOfItemsInSection:0] == 2);
// There is one read article.
DCHECK([reading_list_view_controller_.collectionView
numberOfItemsInSection:1] == 1);
}
// Tests that the view controller is dismissed when Done button is pressed.
TEST_F(ReadingListCollectionViewControllerTest, GetsDismissed) {
// Load view.
[reading_list_view_controller_ view];
[[mock_delegate_ expect]
dismissReadingListCollectionViewController:reading_list_view_controller_];
// Simulate tap on "Done" button.
UIBarButtonItem* done =
reading_list_view_controller_.navigationItem.rightBarButtonItem;
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
// Since @selector stored in done.action is a method returning void, there is
// no potential for memory leak. It is OK to ignore this warning here.
[done.target performSelector:done.action];
#pragma clang diagnostic pop
EXPECT_OCMOCK_VERIFY(mock_delegate_);
}
// Tests that when an item is selected, the article is opened with UrlLoader and
// the view controller is dismissed.
TEST_F(ReadingListCollectionViewControllerTest, OpensItems) {
NSIndexPath* indexPath = [NSIndexPath indexPathForItem:1 inSection:0];
GURL url("https://chromium.org");
GURL url2("https://chromium.org/2");
reading_list_model_->AddEntry(url, "chromium",
reading_list::ADDED_VIA_CURRENT_APP);
reading_list_model_->AddEntry(url2, "chromium - 2",
reading_list::ADDED_VIA_CURRENT_APP);
ReadingListCollectionViewItem* readingListItem =
base::mac::ObjCCastStrict<ReadingListCollectionViewItem>(
[[reading_list_view_controller_ collectionViewModel]
itemAtIndexPath:indexPath]);
[[mock_delegate_ expect]
readingListCollectionViewController:reading_list_view_controller_
openItem:readingListItem];
// Simulate touch on second cell.
[reading_list_view_controller_
collectionView:reading_list_view_controller_.collectionView
didSelectItemAtIndexPath:indexPath];
EXPECT_OCMOCK_VERIFY(mock_delegate_);
}
// Tests that the ReadingListCollectionView is creating
// ReadingListCollectionViewItem with the correct informations.
TEST_F(ReadingListCollectionViewControllerTest,
TestItemInitializationUndistilled) {
// Setup.
GURL url("https://chromium.org");
std::string title("Chromium");
reading_list_model_->AddEntry(url, title,
reading_list::ADDED_VIA_CURRENT_APP);
// Load view.
[reading_list_view_controller_ view];
DCHECK([reading_list_view_controller_.collectionView
numberOfItemsInSection:0] == 1);
NSIndexPath* indexPath = [NSIndexPath indexPathForItem:0 inSection:0];
ReadingListCollectionViewItem* readingListItem =
base::mac::ObjCCastStrict<ReadingListCollectionViewItem>(
[[reading_list_view_controller_ collectionViewModel]
itemAtIndexPath:indexPath]);
EXPECT_EQ(base::SysNSStringToUTF8([readingListItem title]), title);
EXPECT_EQ([readingListItem url], url);
EXPECT_EQ(base::SysNSStringToUTF16([readingListItem subtitle]),
url_formatter::FormatUrl(url));
EXPECT_EQ([readingListItem faviconPageURL], url);
EXPECT_EQ([readingListItem distillationState],
ReadingListUIDistillationStatusPending);
}
// Tests that the ReadingListCollectionView is creating
// ReadingListCollectionViewItem with the correct informations for distilled
// items.
TEST_F(ReadingListCollectionViewControllerTest,
TestItemInitializationDistilled) {
// Setup.
GURL url("https://chromium.org");
std::string title("Chromium");
GURL distilled_url("https://chromium.org/distilled");
base::FilePath distilled_path("/distilled/path");
reading_list_model_->AddEntry(url, title,
reading_list::ADDED_VIA_CURRENT_APP);
int64_t size = 50;
reading_list_model_->SetEntryDistilledInfo(url, distilled_path, distilled_url,
size, base::Time::FromTimeT(100));
// Load view.
[reading_list_view_controller_ view];
DCHECK([reading_list_view_controller_.collectionView
numberOfItemsInSection:0] == 1);
NSIndexPath* indexPath = [NSIndexPath indexPathForItem:0 inSection:0];
ReadingListCollectionViewItem* readingListItem =
base::mac::ObjCCastStrict<ReadingListCollectionViewItem>(
[[reading_list_view_controller_ collectionViewModel]
itemAtIndexPath:indexPath]);
EXPECT_EQ(base::SysNSStringToUTF8([readingListItem title]), title);
EXPECT_EQ([readingListItem url], url);
EXPECT_EQ(base::SysNSStringToUTF16([readingListItem subtitle]),
url_formatter::FormatUrl(url));
EXPECT_EQ([readingListItem faviconPageURL], distilled_url);
EXPECT_EQ([readingListItem distillationState],
ReadingListUIDistillationStatusSuccess);
}