a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell/*
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell * The contents of this file are subject to the terms of the Common Development and
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell * Distribution License (the License). You may not use this file except in compliance with the
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell * License.
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell *
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell * specific language governing permission and limitations under the License.
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell *
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell * When distributing Covered Software, include this CDDL Header Notice in each file and include
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell * Header, with the fields enclosed by brackets [] replaced by your own identifying
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell * information: "Portions copyright [year] [name of copyright owner]".
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell *
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell * Copyright 2016 ForgeRock AS.
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell */
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell#import <OCMock/OCMock.h>
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell#import <UIKit/UIKit.h>
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell#import <XCTest/XCTest.h>
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell#import "FRAAccountTableViewController.h"
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell#import "FRAApplicationAssembly.h"
ff2edace1e77f0e80bc2f5da30344d21c3274885Craig McDonnell#import "FRAHotpOathMechanism.h"
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell#import "FRAIdentityModel.h"
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell#import "FRAIdentity.h"
6a2ae9c7fb4d2c40d75cab0edaf940f22c18224fDiego Colantoni#import "FRAModelsFromDatabase.h"
ff2edace1e77f0e80bc2f5da30344d21c3274885Craig McDonnell#import "FRAModelUtils.h"
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell#import "FRANotification.h"
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell#import "FRAPushMechanism.h"
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell#import "FRAPushMechanismTableViewCell.h"
ff2edace1e77f0e80bc2f5da30344d21c3274885Craig McDonnell#import "FRATotpOathMechanism.h"
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell@interface FRAAccountTableViewControllerTests : XCTestCase
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell@end
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell@implementation FRAAccountTableViewControllerTests {
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell FRAAccountTableViewController *viewController;
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell FRAIdentity *identity;
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell NSIndexPath *oathMechanismIndexPath;
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell NSIndexPath *pushMechanismIndexPath;
ff2edace1e77f0e80bc2f5da30344d21c3274885Craig McDonnell FRAModelUtils *modelUtils;
6a2ae9c7fb4d2c40d75cab0edaf940f22c18224fDiego Colantoni id mockModelsFromDatabase;
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell}
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell- (void)setUp {
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell [super setUp];
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell
6a2ae9c7fb4d2c40d75cab0edaf940f22c18224fDiego Colantoni mockModelsFromDatabase = OCMClassMock([FRAModelsFromDatabase class]);
6a2ae9c7fb4d2c40d75cab0edaf940f22c18224fDiego Colantoni OCMStub([mockModelsFromDatabase allIdentitiesWithDatabase:[OCMArg any] identityDatabase:[OCMArg any] identityModel:[OCMArg any] error:[OCMArg anyObjectRef]]).andReturn(@[]);
6a2ae9c7fb4d2c40d75cab0edaf940f22c18224fDiego Colantoni
ff2edace1e77f0e80bc2f5da30344d21c3274885Craig McDonnell identity = [FRAIdentity identityWithDatabase:nil identityModel:nil accountName:@"Alice" issuer:@"ForgeRock" image:nil backgroundColor:nil];
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell // load accounts controller from storyboard
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:[NSBundle mainBundle]];
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell viewController = [storyboard instantiateViewControllerWithIdentifier:@"AccountTableViewController"];
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell viewController.identity = identity;
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell oathMechanismIndexPath = [NSIndexPath indexPathForRow:1 inSection:0];
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell pushMechanismIndexPath = [NSIndexPath indexPathForRow:2 inSection:0];
ff2edace1e77f0e80bc2f5da30344d21c3274885Craig McDonnell
ff2edace1e77f0e80bc2f5da30344d21c3274885Craig McDonnell modelUtils = [[FRAModelUtils alloc] init];
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell}
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell- (void)tearDown {
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell [self simulateUnloadingOfView];
6a2ae9c7fb4d2c40d75cab0edaf940f22c18224fDiego Colantoni [mockModelsFromDatabase stopMocking];
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell [super tearDown];
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell}
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell- (void)testDisplaysIssuerAndAccountNameForIdentity {
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell // Given
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell // When
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell [self simulateLoadingOfView];
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell // Then
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell XCTAssertEqual(viewController.issuer.text, @"ForgeRock");
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell XCTAssertEqual(viewController.accountName.text, @"Alice");
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell}
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell- (void)testShowsNoMechanismsIfIdentityHasNoneRegistered {
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell // Given
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell // When
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell [self simulateLoadingOfView];
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell // Then
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell XCTAssertFalse([self isShowingCellAtIndexPath:oathMechanismIndexPath], @"OATH mechanism UI should not be displayed");
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell XCTAssertFalse([self isShowingCellAtIndexPath:pushMechanismIndexPath], @"Push mechanism UI should not be displayed");
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell}
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell
ff2edace1e77f0e80bc2f5da30344d21c3274885Craig McDonnell- (void)testShowsOathMechanismIfIdentityHasOneRegistered {
ff2edace1e77f0e80bc2f5da30344d21c3274885Craig McDonnell // Given
ff2edace1e77f0e80bc2f5da30344d21c3274885Craig McDonnell FRAHotpOathMechanism *mechanism = [modelUtils demoOathMechanism];
ff2edace1e77f0e80bc2f5da30344d21c3274885Craig McDonnell
ff2edace1e77f0e80bc2f5da30344d21c3274885Craig McDonnell [identity addMechanism:mechanism error:nil];
ff2edace1e77f0e80bc2f5da30344d21c3274885Craig McDonnell
ff2edace1e77f0e80bc2f5da30344d21c3274885Craig McDonnell // When
ff2edace1e77f0e80bc2f5da30344d21c3274885Craig McDonnell [self simulateLoadingOfView];
ff2edace1e77f0e80bc2f5da30344d21c3274885Craig McDonnell
ff2edace1e77f0e80bc2f5da30344d21c3274885Craig McDonnell // Then
ff2edace1e77f0e80bc2f5da30344d21c3274885Craig McDonnell XCTAssertTrue([self isShowingCellAtIndexPath:oathMechanismIndexPath], @"OATH mechanism UI should be displayed");
ff2edace1e77f0e80bc2f5da30344d21c3274885Craig McDonnell XCTAssertFalse([self isShowingCellAtIndexPath:pushMechanismIndexPath], @"Push mechanism UI should not be displayed");
ff2edace1e77f0e80bc2f5da30344d21c3274885Craig McDonnell}
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell- (void)testShowsPushMechanismIfIdentityHasOneRegistered {
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell // Given
ff2edace1e77f0e80bc2f5da30344d21c3274885Craig McDonnell FRAPushMechanism *pushMechanism = [FRAPushMechanism pushMechanismWithDatabase:nil identityModel:nil];
ff2edace1e77f0e80bc2f5da30344d21c3274885Craig McDonnell [identity addMechanism:pushMechanism error:nil];
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell // When
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell [self simulateLoadingOfView];
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell // Then
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell XCTAssertFalse([self isShowingCellAtIndexPath:oathMechanismIndexPath], @"OATH mechanism UI should not be displayed");
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell XCTAssertTrue([self isShowingCellAtIndexPath:pushMechanismIndexPath], @"Push mechanism UI should be displayed");
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell}
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell- (void)testShowsCountOfPendingNotificationsIfIdentityHasRegisteredPushMechanism {
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell // Given
ff2edace1e77f0e80bc2f5da30344d21c3274885Craig McDonnell FRAPushMechanism *pushMechanism = [FRAPushMechanism pushMechanismWithDatabase:nil identityModel:nil];
ff2edace1e77f0e80bc2f5da30344d21c3274885Craig McDonnell [pushMechanism addNotification:[self pendingNotification] error:nil];
ff2edace1e77f0e80bc2f5da30344d21c3274885Craig McDonnell [pushMechanism addNotification:[self pendingNotification] error:nil];
ff2edace1e77f0e80bc2f5da30344d21c3274885Craig McDonnell [pushMechanism addNotification:[self approvedNotification] error:nil];
ff2edace1e77f0e80bc2f5da30344d21c3274885Craig McDonnell [identity addMechanism:pushMechanism error:nil];
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell // When
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell [self simulateLoadingOfView];
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell // Then
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell XCTAssertEqualObjects([self pushMechanismTableViewCell].notificationsBadge.text, @"2");
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell}
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell- (void)simulateLoadingOfView {
ff2edace1e77f0e80bc2f5da30344d21c3274885Craig McDonnell if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_8_4) {
ff2edace1e77f0e80bc2f5da30344d21c3274885Craig McDonnell [viewController view]; // force IBOutlets etc to be initialized
ff2edace1e77f0e80bc2f5da30344d21c3274885Craig McDonnell } else {
ff2edace1e77f0e80bc2f5da30344d21c3274885Craig McDonnell [viewController loadViewIfNeeded]; // force IBOutlets etc to be initialized
ff2edace1e77f0e80bc2f5da30344d21c3274885Craig McDonnell }
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell XCTAssertNotNil(viewController.view);
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell [viewController viewWillAppear:YES];
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell}
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell- (void)simulateUnloadingOfView {
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell [viewController viewWillDisappear:YES];
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell}
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell- (BOOL)isShowingCellAtIndexPath:(NSIndexPath *)indexPath {
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell return [viewController tableView:viewController.tableView heightForRowAtIndexPath:indexPath] > 0;
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell}
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell- (FRANotification *)pendingNotification {
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell return [FRANotification notificationWithDatabase:nil
ff2edace1e77f0e80bc2f5da30344d21c3274885Craig McDonnell identityModel:nil
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell messageId:@"dummy"
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell challenge:@"dummy"
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell timeReceived:[NSDate date]
ff2edace1e77f0e80bc2f5da30344d21c3274885Craig McDonnell timeToLive:120.0
ff2edace1e77f0e80bc2f5da30344d21c3274885Craig McDonnell loadBalancerCookieData:nil];
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell}
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell- (FRANotification *)approvedNotification {
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell FRANotification *notification = [self pendingNotification];
6a2ae9c7fb4d2c40d75cab0edaf940f22c18224fDiego Colantoni [notification approveWithHandler:nil error:nil];
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell return notification;
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell}
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell- (FRAOathMechanismTableViewCell *)oathMechanismTableViewCell {
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell return (FRAOathMechanismTableViewCell*) [viewController tableView:viewController.tableView cellForRowAtIndexPath:oathMechanismIndexPath];
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell}
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell- (FRAPushMechanismTableViewCell *)pushMechanismTableViewCell {
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell return (FRAPushMechanismTableViewCell*) [viewController tableView:viewController.tableView cellForRowAtIndexPath:pushMechanismIndexPath];
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell}
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell
a3970d0ea62388e4ede01470a6436eb5c6c92353Craig McDonnell@end