blob: 08ccfab5565ae54a87f658fd61e2677e81346935 [file] [log] [blame] [edit]
// Copyright 2018-present the Material Components for iOS authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#import <XCTest/XCTest.h>
#import "MDCAlertController+ButtonForAction.h"
#import "MDCAlertController.h"
#import "MDCAlertControllerView.h"
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wprivate-header"
#import "MDCAlertActionManager.h"
#import "MDCAlertControllerView+Private.h"
#pragma clang diagnostic pop
NS_ASSUME_NONNULL_BEGIN
/** Category for @c MDCAlertController to expose the @c actionManager property. */
@interface MDCAlertController (Testing)
/** Manages the actions and the creation of buttons based off a given action. */
@property(nonatomic, nonnull, strong) MDCAlertActionManager *actionManager;
@end
@interface MDCAlertActionManagerTests : XCTestCase
@property(nonatomic, nullable, strong) MDCAlertActionManager *actionManager;
@property(nonatomic, nullable, strong) MDCAlertAction *action;
@end
@implementation MDCAlertActionManagerTests
- (void)actionButtonPressed:(id)button {
}
- (void)setUp {
[super setUp];
self.actionManager = [[MDCAlertActionManager alloc] init];
self.action = [MDCAlertAction actionWithTitle:@"title"
handler:^(MDCAlertAction *_Nonnull act){
}];
}
- (void)testAddingActionsDoesnotCreaetButtons {
// When
[self.actionManager addAction:self.action];
// Then
XCTAssertEqual([[self.actionManager actions] count], 1ul);
XCTAssertEqual([[self.actionManager buttonsInActionOrder] count], 0ul);
}
- (void)testActionManager_ButtonForActionReturnsNoButtonsWhenCalledBeforeThemingOrPresentation {
// Given
[self.actionManager addAction:self.action];
// When
UIButton *button = [self.actionManager buttonForAction:self.action];
// Then
XCTAssertNil(button);
XCTAssertEqual([[self.actionManager actions] count], 1ul);
XCTAssertEqual([[self.actionManager buttonsInActionOrder] count], 0ul);
}
- (void)testActionManager_AddingButtonToActionBeforeAlertIsPresentedReturnsDetachedButtons {
// Given
[self.actionManager addAction:self.action];
// When
UIButton *button = [self.actionManager createButtonForAction:self.action
target:self
selector:@selector(actionButtonPressed:)];
UIButton *button2 = [self.actionManager buttonForAction:self.action];
// Then
XCTAssertNotNil(button);
XCTAssertNil(button.superview);
XCTAssertEqual([[self.actionManager actions] count], 1ul);
XCTAssertEqual([[self.actionManager buttonsInActionOrder] count], 1ul);
XCTAssertEqual(button, button2);
XCTAssertEqual([self.actionManager actionForButton:button], self.action);
}
- (void)testAlertController_AddingActionsToAlertBeforePresentationCreatesDetachedButtons {
// Given
MDCAlertController *alert = [MDCAlertController alertControllerWithTitle:@"title" message:@"msg"];
MDCAlertAction *action2 = [MDCAlertAction actionWithTitle:@"action2"
handler:^(MDCAlertAction *_Nonnull act){
}];
// When
[alert addAction:self.action];
UIButton *button = [alert buttonForAction:self.action];
UIButton *button2 = [alert buttonForAction:action2];
// Then
XCTAssertEqual([alert.actions count], 1ul);
XCTAssertNotNil(button);
XCTAssertNil(button.superview);
XCTAssertNil(button2); // no button if the action hasn't been added first
}
- (void)testAlertController_AlertPresentationAttachesButtonsToViewHierarchy {
// Given
MDCAlertController *alert = [MDCAlertController alertControllerWithTitle:@"title" message:@"msg"];
[alert addAction:self.action];
UIButton *button = [alert buttonForAction:self.action];
// When (simulating alert presentation)
MDCAlertControllerView *alertView = (MDCAlertControllerView *)alert.view;
// Then
XCTAssertNotNil(button);
XCTAssertNotNil(button.superview);
XCTAssertEqual([[alertView.actionManager actions] count], 1ul);
XCTAssertEqual([[alertView.actionManager buttonsInActionOrder] count], 1ul);
XCTAssertEqual([alertView.actionManager buttonForAction:self.action], button);
XCTAssertEqual([alertView.actionManager actionForButton:button], self.action);
}
- (void)testAddingActionsToAlertBeforeAndAfterPresentationAddsAllButtonsToViewHierarchy {
// Given
MDCAlertController *alert = [MDCAlertController alertControllerWithTitle:@"title" message:@"msg"];
MDCAlertAction *action2 = [MDCAlertAction actionWithTitle:@"action2"
handler:^(MDCAlertAction *_Nonnull act){
}];
[alert addAction:self.action];
UIButton *button = [alert buttonForAction:self.action];
// When
MDCAlertControllerView *alertView = (MDCAlertControllerView *)alert.view;
[alert addAction:action2];
// Then
XCTAssertEqual([alert.actions count], 2ul);
XCTAssertNotNil(button);
XCTAssertNotNil(button.superview);
XCTAssertEqual([[alertView.actionManager buttonsInActionOrder] count], 2ul);
UIButton *button2 = [alert buttonForAction:action2];
XCTAssertNotNil(button2);
XCTAssertNotNil(button2.superview);
}
/**
* Verifies that a new action of the same setup of an added action is not considered as included.
*/
- (void)testSecondActionWithSameValuesShouldNotBeIncluded {
[self.actionManager addAction:self.action];
MDCAlertAction *clonedAction = [self.action copy];
XCTAssertFalse([self.actionManager hasAction:clonedAction]);
// Ensures that the cloned action can be added.
[self.actionManager addAction:clonedAction];
XCTAssertTrue([self.actionManager hasAction:clonedAction]);
}
/** Verifes that a button is not created for an action with the same setup that's not yet added. */
- (void)testButtonForActionShouldReturnNilForSameValueButDifferentActionObject {
[self.actionManager addAction:self.action];
MDCAlertAction *clonedAction = [self.action copy];
UIButton *button = [self.actionManager createButtonForAction:self.action
target:self
selector:@selector(actionButtonPressed:)];
XCTAssertNotNil(button);
XCTAssertNil([self.actionManager buttonForAction:clonedAction]);
}
/** Verifies that the buttons for two equal actions have different identities. */
- (void)testButtonsShouldBeUniqueWithActionsThatAreEqual {
MDCAlertAction *clonedAction = [self.action copy];
[self.actionManager addAction:self.action];
[self.actionManager addAction:clonedAction];
UIButton *button1 = [self.actionManager createButtonForAction:self.action
target:self
selector:@selector(actionButtonPressed:)];
UIButton *button2 = [self.actionManager createButtonForAction:clonedAction
target:self
selector:@selector(actionButtonPressed:)];
XCTAssertNotEqual(button1, button2);
}
- (void)testAddActionsResultsInSameButtonsOrderAsAddAction {
// Given
MDCAlertAction *actionOne = [MDCAlertAction actionWithTitle:@"Foo" handler:nil];
MDCAlertAction *actionTwo = [MDCAlertAction actionWithTitle:@"Bar" handler:nil];
MDCAlertController *alertOne = [[MDCAlertController alloc] init];
MDCAlertController *alertTwo = [[MDCAlertController alloc] init];
// When
[alertOne addActions:@[ actionOne, actionTwo ]];
[alertTwo addAction:actionOne];
[alertTwo addAction:actionTwo];
// Then
XCTAssertEqualObjects(alertOne.actionManager.actions, alertTwo.actionManager.actions);
}
- (void)testAddActionsWithButtonsInActionOrder {
// Given
MDCAlertAction *actionOne = [MDCAlertAction actionWithTitle:@"Foo" handler:nil];
MDCAlertAction *actionTwo = [MDCAlertAction actionWithTitle:@"Bar" handler:nil];
MDCAlertController *alertOne = [[MDCAlertController alloc] init];
// When
[alertOne addActions:@[ actionOne, actionTwo ]];
UIButton *buttonOne =
[alertOne.actionManager createButtonForAction:actionOne
target:self
selector:@selector(actionButtonPressed:)];
UIButton *buttonTwo =
[alertOne.actionManager createButtonForAction:actionTwo
target:self
selector:@selector(actionButtonPressed:)];
// Then
XCTAssertEqualObjects([buttonOne titleForState:UIControlStateNormal],
[actionOne.title uppercaseString]);
XCTAssertEqualObjects([buttonTwo titleForState:UIControlStateNormal],
[actionTwo.title uppercaseString]);
}
@end
NS_ASSUME_NONNULL_END