// // BITAuthenticatorTests.m // HockeySDK // // Created by Andreas Linde on 13.03.13. // // #import #import #import #import #import "HockeySDK.h" #import "HockeySDKPrivate.h" #import "BITHockeyHelper.h" #import "BITAuthenticator_Private.h" #import "BITHockeyBaseManagerPrivate.h" #import "BITTestHelper.h" #import "BITHockeyAppClient.h" @interface MyDevice : NSObject - (NSString*) uniqueIdentifier; @end @implementation MyDevice - (NSString*) uniqueIdentifier {return @"reallyUnique";} @end @interface MyDeviceWithIdentifierForVendor : MyDevice @property (copy) NSUUID *identifierForVendor; @end @implementation MyDeviceWithIdentifierForVendor - (instancetype)init { self = [super init]; if( self ) { _identifierForVendor = [NSUUID UUID]; } return self; } @end static void *kInstallationIdentification = &kInstallationIdentification; @interface BITAuthenticatorTests : XCTestCase @property(nonatomic, strong) BITAuthenticator *sut; @end @implementation BITAuthenticatorTests - (void)setUp { [super setUp]; self.sut = [[BITAuthenticator alloc] initWithAppIdentifier:nil appEnvironment:BITEnvironmentOther]; } - (void)tearDown { [self.sut cleanupInternalStorage]; self.sut = nil; [super tearDown]; } #pragma mark - Setup helpers - (NSDictionary *)jsonFromFixture:(NSString *)fixture { NSString *dataString = [BITTestHelper jsonFixture:fixture]; NSData *data = [dataString dataUsingEncoding:NSUTF8StringEncoding]; NSError *error = nil; NSDictionary *json = (NSDictionary *)[NSJSONSerialization JSONObjectWithData:data options:0 error:&error]; return json; } #pragma mark - Setup Tests - (void) testThatItInstantiates { XCTAssertNotNil(self.sut, @"Should be there"); } #pragma mark - Persistence Tests - (void) testThatLastAuthenticatedVersionIsPersisted { self.sut.lastAuthenticatedVersion = @"1.2.1"; self.sut = [[BITAuthenticator alloc] initWithAppIdentifier:nil appEnvironment:BITEnvironmentAppStore]; assertThat(self.sut.lastAuthenticatedVersion, equalTo(@"1.2.1")); } - (void) testThatCleanupWorks { self.sut.lastAuthenticatedVersion = @"1.2"; self.sut.identified = YES; self.sut.validated = YES; [self.sut cleanupInternalStorage]; assertThat(self.sut.lastAuthenticatedVersion, equalTo(nil)); assertThat(self.sut.installationIdentifier, equalTo(nil)); assertThatBool(self.sut.isIdentified, isFalse()); assertThatBool(self.sut.isValidated, isFalse()); } #pragma mark - Initial defaults - (void) testDefaultValues { assertThatBool(self.sut.restrictApplicationUsage, isFalse()); assertThatBool(self.sut.isIdentified, isFalse()); assertThatBool(self.sut.isValidated, isFalse()); assertThat(self.sut.authenticationSecret, equalTo(nil)); assertThat(self.sut.installationIdentifier, equalTo(nil)); assertThat(self.sut.installationIdentifierParameterString, equalTo(@"uuid")); } #pragma mark - General identification tests - (void) testThatIsDoesntShowMoreThanOneAuthenticationController { id delegateMock = mockProtocol(@protocol(BITAuthenticatorDelegate)); self.sut.delegate = delegateMock; self.sut.identificationType = BITAuthenticatorIdentificationTypeDevice; [self.sut identifyWithCompletion:nil]; [self.sut identifyWithCompletion:nil]; [self.sut identifyWithCompletion:nil]; [verifyCount(delegateMock, times(1)) authenticator:self.sut willShowAuthenticationController:(id)anything()]; } - (void) testThatChangingIdentificationTypeResetsIdentifiedFlag { self.sut.identified = YES; self.sut.identificationType = BITAuthenticatorIdentificationTypeHockeyAppUser; assertThatBool(self.sut.identified, isFalse()); } - (void) testThatAfterChangingIdentificationTypeIdentificationIsRedone { [self.sut storeInstallationIdentifier:@"meh" withType:BITAuthenticatorIdentificationTypeHockeyAppEmail]; self.sut.identified = YES; self.sut.identificationType = BITAuthenticatorIdentificationTypeHockeyAppUser; [self.sut identifyWithCompletion:nil]; assertThatBool(self.sut.identified, isFalse()); assertThat(self.sut.installationIdentifier, nilValue()); } - (void) testThatIdentifyingAnAlreadyIdentifiedInstanceDoesNothing { id delegateMock = mockProtocol(@protocol(BITAuthenticatorDelegate)); self.sut.delegate = delegateMock; self.sut.identificationType = BITAuthenticatorIdentificationTypeHockeyAppEmail; [self.sut storeInstallationIdentifier:@"meh" withType:BITAuthenticatorIdentificationTypeHockeyAppEmail]; self.sut.identified = YES; [self.sut identifyWithCompletion:nil]; [verifyCount(delegateMock, never()) authenticator:self.sut willShowAuthenticationController:(id)anything()]; } #pragma mark - Anonymous identification type - (void) testAnonymousIdentification { self.sut.identificationType = BITAuthenticatorIdentificationTypeAnonymous; assertThatBool(self.sut.isIdentified, isFalse()); [self.sut identifyWithCompletion:^(BOOL identified, NSError *error) { assertThatBool(identified, isTrue()); assertThat(error, equalTo(nil)); }]; assertThatBool(self.sut.isIdentified, isTrue()); assertThat(self.sut.installationIdentifier, notNilValue()); } //anoynmous users can't be validated - (void) testAnonymousValidation { self.sut.identificationType = BITAuthenticatorIdentificationTypeAnonymous; assertThatBool(self.sut.isValidated, isFalse()); [self.sut validateWithCompletion:^(BOOL __unused validated, NSError *error) { assertThatBool(self.sut.validated, isFalse()); assertThat(error, notNilValue()); }]; assertThatBool(self.sut.isValidated, isFalse()); } #pragma mark - Device identification type - (void) testDeviceIdentificationShowsViewController { self.sut.identificationType = BITAuthenticatorIdentificationTypeDevice; id delegateMock = mockProtocol(@protocol(BITAuthenticatorDelegate)); self.sut.delegate = delegateMock; [self.sut identifyWithCompletion:nil]; [verifyCount(delegateMock, times(1)) authenticator:self.sut willShowAuthenticationController:(id)anything()]; } #pragma mark - Web auth identification type - (void) testWebAuthIdentificationShowsViewController { self.sut.identificationType = BITAuthenticatorIdentificationTypeWebAuth; id delegateMock = mockProtocol(@protocol(BITAuthenticatorDelegate)); self.sut.delegate = delegateMock; [self.sut identifyWithCompletion:nil]; [verifyCount(delegateMock, times(1)) authenticator:self.sut willShowAuthenticationController:(id)anything()]; } #pragma mark - Email identification type - (void) testEmailIdentificationFailsWithMissingSecret { self.sut.identificationType = BITAuthenticatorIdentificationTypeHockeyAppEmail; [self.sut identifyWithCompletion:^(BOOL identified, NSError *error) { assertThatBool(identified, isFalse()); assertThat(error, notNilValue()); }]; } - (void) testEmailIdentificationShowsViewController { self.sut.identificationType = BITAuthenticatorIdentificationTypeHockeyAppEmail; self.sut.authenticationSecret = @"mySecret"; id delegateMock = mockProtocol(@protocol(BITAuthenticatorDelegate)); self.sut.delegate = delegateMock; [self.sut identifyWithCompletion:nil]; [verifyCount(delegateMock, times(1)) authenticator:self.sut willShowAuthenticationController:(id)anything()]; } - (void) testEmailValidationFailsWithMissingSecret { self.sut.identificationType = BITAuthenticatorIdentificationTypeHockeyAppEmail; [self.sut validateWithCompletion:^(BOOL validated, NSError *error) { assertThatBool(validated, isFalse()); assertThat(error, notNilValue()); }]; } #pragma mark - User identification type - (void) testUserIdentificationShowsViewController { self.sut.identificationType = BITAuthenticatorIdentificationTypeHockeyAppUser; id delegateMock = mockProtocol(@protocol(BITAuthenticatorDelegate)); self.sut.delegate = delegateMock; [self.sut identifyWithCompletion:nil]; [verifyCount(delegateMock, times(1)) authenticator:self.sut willShowAuthenticationController:(id)anything()]; } #pragma mark - Generic validation tests - (void) testThatValidationFailsIfNotIdentified { self.sut.identified = NO; self.sut.identificationType = BITAuthenticatorIdentificationTypeHockeyAppUser; [self.sut validateWithCompletion:^(BOOL validated, NSError *error) { assertThatBool(validated, isFalse()); assertThatLong(error.code, equalToLong(BITAuthenticatorNotIdentified)); }]; } #pragma mark - Authentication - (void) testThatEnabledRestrictionTriggersValidation { id mockAuthenticator = OCMPartialMock(self.sut); self.sut.authenticationSecret = @"sekret"; self.sut.restrictApplicationUsage = YES; self.sut.identificationType = BITAuthenticatorIdentificationTypeHockeyAppEmail; [self.sut storeInstallationIdentifier:@"asd" withType:BITAuthenticatorIdentificationTypeHockeyAppEmail]; OCMExpect([mockAuthenticator validateWithCompletion:(id)anything()]); [self.sut authenticate]; OCMVerifyAll(mockAuthenticator); } #pragma mark - Lifetime checks - (void) testThatValidationTriggersOnDidBecomeActive { id delegateMock = mockProtocol(@protocol(BITAuthenticatorDelegate)); self.sut.delegate = delegateMock; self.sut.identificationType = BITAuthenticatorIdentificationTypeDevice; self.sut.restrictApplicationUsage = YES; [self.sut applicationDidBecomeActive:nil]; [verify(delegateMock) authenticator:self.sut willShowAuthenticationController:(id)anything()]; } #pragma mark - Validation helper checks - (void) testThatValidationTriggersOnNewVersion { self.sut.restrictApplicationUsage = YES; self.sut.restrictionEnforcementFrequency = BITAuthenticatorAppRestrictionEnforcementOnFirstLaunch; self.sut.identificationType = BITAuthenticatorIdentificationTypeDevice; self.sut.validated = YES; self.sut.lastAuthenticatedVersion = @"111xxx"; assertThatBool(self.sut.needsValidation, isTrue()); } - (void) testThatValidationDoesNotTriggerOnSameVersion { self.sut.restrictApplicationUsage = YES; self.sut.restrictionEnforcementFrequency = BITAuthenticatorAppRestrictionEnforcementOnFirstLaunch; self.sut.validated = YES; self.sut.lastAuthenticatedVersion = self.sut.executableUUID; assertThatBool(self.sut.needsValidation, isFalse()); } @end