blob: 17dbfab9ea5caddaa750cee20d50950bd50822dd [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 <EarlGrey/EarlGrey.h>
#import <XCTest/XCTest.h>
#include "base/strings/sys_string_conversions.h"
#include "components/infobars/core/infobar.h"
#include "components/infobars/core/infobar_manager.h"
#import "ios/chrome/app/main_controller.h"
#include "ios/chrome/browser/infobars/infobar_manager_impl.h"
#import "ios/chrome/browser/tabs/tab.h"
#import "ios/chrome/browser/tabs/tab_model.h"
#import "ios/chrome/browser/ui/infobars/test_infobar_delegate.h"
#import "ios/chrome/test/app/chrome_test_util.h"
#import "ios/chrome/test/app/tab_test_util.h"
#import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
#import "ios/chrome/test/earl_grey/chrome_matchers.h"
#import "ios/chrome/test/earl_grey/chrome_test_case.h"
#import "ios/web/public/test/http_server/http_server.h"
#include "ios/web/public/test/http_server/http_server_util.h"
#include "url/gurl.h"
#include "url/url_constants.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
namespace {
// Timeout for how long to wait for an infobar to appear or disapper.
const CFTimeInterval kTimeout = 4.0;
// Returns the InfoBarManager for the current tab. Only works in normal
// (non-incognito) mode.
infobars::InfoBarManager* GetCurrentInfoBarManager() {
MainController* main_controller = chrome_test_util::GetMainController();
id<BrowserInterface> interface =
main_controller.interfaceProvider.mainInterface;
web::WebState* web_state = interface.tabModel.currentTab.webState;
if (web_state) {
return InfoBarManagerImpl::FromWebState(web_state);
}
return nullptr;
}
// Adds a TestInfoBar with |message| to the current tab.
bool AddTestInfoBarToCurrentTabWithMessage(NSString* message) {
infobars::InfoBarManager* manager = GetCurrentInfoBarManager();
TestInfoBarDelegate* test_infobar_delegate = new TestInfoBarDelegate(message);
return test_infobar_delegate->Create(manager);
}
// Verifies that a single TestInfoBar with |message| is either present or absent
// on the current tab.
void VerifyTestInfoBarVisibleForCurrentTab(bool visible, NSString* message) {
id<GREYMatcher> expected_visibility =
visible ? grey_minimumVisiblePercent(1.0f) : grey_notVisible();
NSString* condition_name =
visible ? @"Waiting for infobar to show" : @"Waiting for infobar to hide";
[[GREYCondition
conditionWithName:condition_name
block:^BOOL {
NSError* error = nil;
[[EarlGrey
selectElementWithMatcher:
chrome_test_util::StaticTextWithAccessibilityLabel(
message)] assertWithMatcher:expected_visibility
error:&error];
return error == nil;
}] waitWithTimeout:kTimeout];
}
// Verifies the number of Infobar currently in the InfobarManager (Thus in the
// InfobarContainer) is |number_of_infobars|.
void VerifyNumberOfInfobarsInManager(size_t number_of_infobars) {
infobars::InfoBarManager* manager = GetCurrentInfoBarManager();
GREYAssertEqual(number_of_infobars, manager->infobar_count(),
@"Incorrect number of infobars.");
}
} // namespace
// Tests functionality related to infobars.
@interface InfobarTestCase : ChromeTestCase
@end
@implementation InfobarTestCase
// Tests that page infobars don't persist on navigation.
- (void)testInfobarsDismissOnNavigate {
web::test::SetUpFileBasedHttpServer();
// Open a new tab and navigate to the test page.
const GURL testURL = web::test::HttpServer::MakeUrl(
"http://ios/testing/data/http_server_files/pony.html");
[ChromeEarlGrey loadURL:testURL];
[ChromeEarlGrey waitForMainTabCount:1];
// Infobar Message
NSString* infoBarMessage = @"TestInfoBar";
// Add a test infobar to the current tab. Verify that the infobar is present
// in the model and that the infobar view is visible on screen.
GREYAssert(AddTestInfoBarToCurrentTabWithMessage(infoBarMessage),
@"Failed to add infobar to test tab.");
VerifyTestInfoBarVisibleForCurrentTab(true, infoBarMessage);
VerifyNumberOfInfobarsInManager(1);
// Navigate to a different page. Verify that the infobar is dismissed and no
// longer visible on screen.
[ChromeEarlGrey loadURL:GURL(url::kAboutBlankURL)];
VerifyTestInfoBarVisibleForCurrentTab(false, infoBarMessage);
VerifyNumberOfInfobarsInManager(0);
}
// Tests that page infobars persist only on the tabs they are opened on, and
// that navigation in other tabs doesn't affect them.
- (void)testInfobarTabSwitch {
const GURL destinationURL = web::test::HttpServer::MakeUrl(
"http://ios/testing/data/http_server_files/destination.html");
const GURL ponyURL = web::test::HttpServer::MakeUrl(
"http://ios/testing/data/http_server_files/pony.html");
web::test::SetUpFileBasedHttpServer();
// Create the first tab and navigate to the test page.
[ChromeEarlGrey loadURL:destinationURL];
[ChromeEarlGrey waitForMainTabCount:1];
// Infobar Message
NSString* infoBarMessage = @"TestInfoBar";
// Create the second tab, navigate to the test page, and add the test infobar.
[ChromeEarlGrey openNewTab];
[ChromeEarlGrey loadURL:ponyURL];
[ChromeEarlGrey waitForMainTabCount:2];
VerifyTestInfoBarVisibleForCurrentTab(false, infoBarMessage);
VerifyNumberOfInfobarsInManager(0);
GREYAssert(AddTestInfoBarToCurrentTabWithMessage(infoBarMessage),
@"Failed to add infobar to second tab.");
VerifyTestInfoBarVisibleForCurrentTab(true, infoBarMessage);
VerifyNumberOfInfobarsInManager(1);
// Switch back to the first tab and make sure no infobar is visible.
chrome_test_util::SelectTabAtIndexInCurrentMode(0U);
VerifyTestInfoBarVisibleForCurrentTab(false, infoBarMessage);
VerifyNumberOfInfobarsInManager(0);
// Navigate to a different URL in the first tab, to verify that this
// navigation does not hide the infobar in the second tab.
[ChromeEarlGrey loadURL:ponyURL];
// Close the first tab. Verify that there is only one tab remaining and its
// infobar is visible.
[ChromeEarlGrey closeCurrentTab];
[ChromeEarlGrey waitForMainTabCount:1];
VerifyTestInfoBarVisibleForCurrentTab(true, infoBarMessage);
VerifyNumberOfInfobarsInManager(1);
}
// Tests that the Infobar dissapears once the "OK" button is tapped.
- (void)testInfobarButtonDismissal {
web::test::SetUpFileBasedHttpServer();
// Open a new tab and navigate to the test page.
const GURL testURL = web::test::HttpServer::MakeUrl(
"http://ios/testing/data/http_server_files/pony.html");
[ChromeEarlGrey loadURL:testURL];
[ChromeEarlGrey waitForMainTabCount:1];
// Infobar Message
NSString* infoBarMessage = @"TestInfoBar";
// Add a test infobar to the current tab. Verify that the infobar is present
// in the model and that the infobar view is visible on screen.
GREYAssert(AddTestInfoBarToCurrentTabWithMessage(infoBarMessage),
@"Failed to add infobar to test tab.");
VerifyTestInfoBarVisibleForCurrentTab(true, infoBarMessage);
VerifyNumberOfInfobarsInManager(1);
// Tap on "OK" which should dismiss the Infobar.
[[EarlGrey
selectElementWithMatcher:grey_allOf(grey_buttonTitle(@"OK"),
grey_sufficientlyVisible(), nil)]
performAction:grey_tap()];
VerifyTestInfoBarVisibleForCurrentTab(false, infoBarMessage);
VerifyNumberOfInfobarsInManager(0);
}
// Tests adding an Infobar on top of an existing one.
- (void)testInfobarTopMostVisible {
web::test::SetUpFileBasedHttpServer();
// Open a new tab and navigate to the test page.
const GURL testURL = web::test::HttpServer::MakeUrl(
"http://ios/testing/data/http_server_files/pony.html");
[ChromeEarlGrey loadURL:testURL];
[ChromeEarlGrey waitForMainTabCount:1];
// First Infobar Message
NSString* firstInfoBarMessage = @"TestFirstInfoBar";
// Add a test infobar to the current tab. Verify that the infobar is present
// in the model and that the infobar view is visible on screen.
GREYAssert(AddTestInfoBarToCurrentTabWithMessage(firstInfoBarMessage),
@"Failed to add infobar to test tab.");
VerifyTestInfoBarVisibleForCurrentTab(true, firstInfoBarMessage);
VerifyNumberOfInfobarsInManager(1);
// Second Infobar Message
NSString* secondInfoBarMessage = @"TestSecondInfoBar";
// Add a second test infobar to the current tab. Verify that the infobar is
// present in the model, and that only this second infobar is now visible on
// screen.
GREYAssert(AddTestInfoBarToCurrentTabWithMessage(secondInfoBarMessage),
@"Failed to add infobar to test tab.");
VerifyTestInfoBarVisibleForCurrentTab(true, secondInfoBarMessage);
VerifyTestInfoBarVisibleForCurrentTab(false, firstInfoBarMessage);
VerifyNumberOfInfobarsInManager(2);
}
// Tests that a taller Infobar layout is correct and the OK button is tappable.
- (void)testInfobarTallerLayout {
web::test::SetUpFileBasedHttpServer();
// Open a new tab and navigate to the test page.
const GURL testURL = web::test::HttpServer::MakeUrl(
"http://ios/testing/data/http_server_files/pony.html");
[ChromeEarlGrey loadURL:testURL];
[ChromeEarlGrey waitForMainTabCount:1];
// Infobar Message
NSString* firstInfoBarMessage =
@"This is a really long message that will cause this infobar height to "
@"increase since Confirm Infobar heights changes depending on its "
@"message.";
// Add a test infobar to the current tab. Verify that the infobar is present
// in the model and that the infobar view is visible on screen.
GREYAssert(AddTestInfoBarToCurrentTabWithMessage(firstInfoBarMessage),
@"Failed to add infobar to test tab.");
VerifyTestInfoBarVisibleForCurrentTab(true, firstInfoBarMessage);
VerifyNumberOfInfobarsInManager(1);
// Dismiss the Infobar.
[[EarlGrey
selectElementWithMatcher:grey_allOf(grey_buttonTitle(@"OK"),
grey_sufficientlyVisible(), nil)]
performAction:grey_tap()];
VerifyTestInfoBarVisibleForCurrentTab(false, firstInfoBarMessage);
VerifyNumberOfInfobarsInManager(0);
}
// Tests that adding an Infobar of lower height on top of a taller Infobar only
// displays the top shorter one, and that after dismissing the shorter Infobar
// the taller infobar is now completely displayed again.
- (void)testInfobarTopMostVisibleHeight {
web::test::SetUpFileBasedHttpServer();
// Open a new tab and navigate to the test page.
const GURL testURL = web::test::HttpServer::MakeUrl(
"http://ios/testing/data/http_server_files/pony.html");
[ChromeEarlGrey loadURL:testURL];
[ChromeEarlGrey waitForMainTabCount:1];
// First Infobar Message
NSString* firstInfoBarMessage =
@"This is a really long message that will cause this infobar height to "
@"increase since Confirm Infobar heights changes depending on its "
@"message.";
// Add a test infobar to the current tab. Verify that the infobar is present
// in the model and that the infobar view is visible on screen.
GREYAssert(AddTestInfoBarToCurrentTabWithMessage(firstInfoBarMessage),
@"Failed to add infobar to test tab.");
VerifyTestInfoBarVisibleForCurrentTab(true, firstInfoBarMessage);
VerifyNumberOfInfobarsInManager(1);
// Second Infobar Message
NSString* secondInfoBarMessage = @"TestSecondInfoBar";
// Add a second test infobar to the current tab. Verify that the infobar is
// present in the model, and that only this second infobar is now visible on
// screen.
GREYAssert(AddTestInfoBarToCurrentTabWithMessage(secondInfoBarMessage),
@"Failed to add infobar to test tab.");
VerifyTestInfoBarVisibleForCurrentTab(true, secondInfoBarMessage);
VerifyTestInfoBarVisibleForCurrentTab(false, firstInfoBarMessage);
VerifyNumberOfInfobarsInManager(2);
// Dismiss the second Infobar.
[[EarlGrey
selectElementWithMatcher:grey_allOf(grey_buttonTitle(@"OK"),
grey_sufficientlyVisible(), nil)]
performAction:grey_tap()];
VerifyTestInfoBarVisibleForCurrentTab(false, secondInfoBarMessage);
VerifyTestInfoBarVisibleForCurrentTab(true, firstInfoBarMessage);
VerifyNumberOfInfobarsInManager(1);
}
@end