BUYPaymentProviderTests.m 9.56 KB
//
//  BUYPaymentProviderTests.m
//  Mobile Buy SDK
//
//  Created by Shopify.
//  Copyright (c) 2015 Shopify Inc. All rights reserved.
//
//  Permission is hereby granted, free of charge, to any person obtaining a copy
//  of this software and associated documentation files (the "Software"), to deal
//  in the Software without restriction, including without limitation the rights
//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//  copies of the Software, and to permit persons to whom the Software is
//  furnished to do so, subject to the following conditions:
//
//  The above copyright notice and this permission notice shall be included in
//  all copies or substantial portions of the Software.
//
//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
//  THE SOFTWARE.
//

@import XCTest;

#import <Buy/Buy.h>

#import "BUYApplePayPaymentProvider.h"
#import "BUYWebCheckoutPaymentProvider.h"
#import "BUYClientTestBase.h"
#import "BUYPaymentController.h"
#import "BUYFakeSafariController.h"
#import <OHHTTPStubs/OHHTTPStubs.h>

extern Class SafariViewControllerClass;

@interface BUYPaymentController (Private)
- (id <BUYPaymentProvider>)providerForType:(NSString *)type;
@end

@interface BUYPaymentProviderTests : XCTestCase <BUYPaymentProviderDelegate>

@property (nonatomic) NSMutableDictionary <NSString *, XCTestExpectation *> *expectations;
@property (nonatomic) BUYModelManager *modelManager;

@end

@implementation BUYPaymentProviderTests

- (void)setUp
{
	[super setUp];
	self.modelManager = [BUYModelManager modelManager];
	self.expectations = [@{} mutableCopy];
	
	/* ---------------------------------
	 * We need to kick off the provider
	 * class initialization before setting
	 * the fake safari controller to
	 * prevent it getting overriden.
	 */
	[BUYWebCheckoutPaymentProvider class];
	SafariViewControllerClass = [BUYFakeSafariController class];
}

- (void)tearDown
{
	[super tearDown];
	[OHHTTPStubs removeAllStubs];
}

- (BUYClient *)client
{
	return [[BUYClient alloc] initWithShopDomain:BUYShopDomain_Placeholder apiKey:BUYAPIKey_Placeholder appId:BUYAppId_Placeholder];
}

- (BUYCheckout *)checkout
{
	return [self.modelManager insertCheckoutWithJSONDictionary:nil];
}

- (void)mockRequests
{
	// This mocks a getShop, and createCheckout request
	[OHHTTPStubs stubRequestsPassingTest:^BOOL(NSURLRequest * _Nonnull request) {
		return YES;
	} withStubResponse:^OHHTTPStubsResponse * _Nonnull(NSURLRequest * _Nonnull request) {
		return [BUYPaymentProviderTests responseForRequest:request];
	}];
}

+ (OHHTTPStubsResponse *)responseForRequest:(NSURLRequest *)request
{
	NSURLComponents *components = [NSURLComponents componentsWithURL:request.URL resolvingAgainstBaseURL:NO];
	
	if ([components.path isEqualToString:@"/meta.json"]) {
		return [OHHTTPStubsResponse responseWithJSONObject:@{@"id": @"123", @"name": @"test_shop", @"country": @"US", @"currency": @"USD"} statusCode:200 headers:nil];
	}
	else if ([components.path isEqualToString:@"/api/checkouts.json"]) {
		return [OHHTTPStubsResponse responseWithJSONObject:@{@"checkout":@{@"payment_due": @(99), @"web_checkout_url": @"https://example.com"}} statusCode:200 headers:nil];
	}
	
	return nil;
}

#pragma mark - Apple Pay

- (void)testAppleAvailability
{
	BUYApplePayPaymentProvider *applePay = [[BUYApplePayPaymentProvider alloc] initWithClient:self.client merchantID:@"merchant.id.1"];
	XCTAssertTrue(applePay.isAvailable);
	
	BUYApplePayPaymentProvider *applePay2 = [[BUYApplePayPaymentProvider alloc] initWithClient:self.client merchantID:@""];
	XCTAssertFalse(applePay2.isAvailable);
}

- (void)testApplePayPresentationCallbacks
{
	[self mockRequests];
	
	BUYApplePayPaymentProvider *applePay = [[BUYApplePayPaymentProvider alloc] initWithClient:self.client merchantID:@"merchant.id.1"];
	applePay.delegate = self;
	
	self.expectations[@"presentController"] = [self expectationWithDescription:NSStringFromSelector(_cmd)];

	[applePay startCheckout:self.checkout];
	
	[self waitForExpectationsWithTimeout:1 handler:^(NSError *error) {
		XCTAssertNil(error);
	}];
}

- (void)testApplePayProvider
{
	BUYApplePayPaymentProvider *applePay1 = [[BUYApplePayPaymentProvider alloc] initWithClient:self.client merchantID:@"merchant.id.1"];
	XCTAssertEqualObjects(applePay1.merchantID, @"merchant.id.1");
	
	// 4 default networks should be configured
	XCTAssertEqual(applePay1.supportedNetworks.count, 4);
	
	applePay1.supportedNetworks = @[PKPaymentNetworkMasterCard];
	XCTAssertEqual(applePay1.supportedNetworks.count, 1);
	XCTAssertEqualObjects(applePay1.supportedNetworks[0], PKPaymentNetworkMasterCard);
}

- (void)testCanShowApplePaySetup
{
	BUYApplePayPaymentProvider *applePay = [[BUYApplePayPaymentProvider alloc] initWithClient:self.client merchantID:@"merchant.id.1"];
	XCTAssertTrue(applePay.canShowApplePaySetup);
	
	BUYApplePayPaymentProvider *applePay2 = [[BUYApplePayPaymentProvider alloc] initWithClient:self.client merchantID:@""];
	XCTAssertFalse(applePay2.canShowApplePaySetup);
}

- (void)testFailedApplePayCallbacks
{
	[OHHTTPStubs stubRequestsPassingTest:^BOOL(NSURLRequest * _Nonnull request) {
		return YES;
	} withStubResponse:^OHHTTPStubsResponse * _Nonnull(NSURLRequest * _Nonnull request) {
		return [OHHTTPStubsResponse responseWithJSONObject:@{} statusCode:400 headers:nil];
	}];
	BUYApplePayPaymentProvider *applePay = [[BUYApplePayPaymentProvider alloc] initWithClient:self.client merchantID:@"merchant.id.1"];
	applePay.delegate = self;
	
	self.expectations[@"failedCheckout"] = [self expectationWithDescription:NSStringFromSelector(_cmd)];
	self.expectations[@"failedShop"] = [self expectationWithDescription:NSStringFromSelector(_cmd)];
	
	[applePay startCheckout:self.checkout];
	
	[self waitForExpectationsWithTimeout:1 handler:^(NSError *error) {
		XCTAssertNil(error);
	}];
}

#pragma mark - Web

- (void)testWebAvailability
{
	BUYWebCheckoutPaymentProvider *webProvider = [[BUYWebCheckoutPaymentProvider alloc] initWithClient:self.client];
	XCTAssertTrue(webProvider.isAvailable);
}

- (void)testWebPresentationCallbacks
{
	[self mockRequests];
	
	BUYWebCheckoutPaymentProvider *webProvider = [[BUYWebCheckoutPaymentProvider alloc] initWithClient:self.client];
	webProvider.delegate = self;
	
	self.expectations[@"presentController"] = [self expectationWithDescription:NSStringFromSelector(_cmd)];

	[webProvider startCheckout:self.checkout];
	
	[self waitForExpectationsWithTimeout:1 handler:^(NSError *error) {
		XCTAssertNil(error);
	}];
}

#pragma mark - Payment Controller

- (void)testPaymentController
{
	BUYPaymentController *controller = [[BUYPaymentController alloc] init];
	BUYApplePayPaymentProvider *applePay1 = [[BUYApplePayPaymentProvider alloc] initWithClient:self.client merchantID:@"merchant.id.1"];

	[controller addPaymentProvider:applePay1];
	
	XCTAssertEqual(controller.providers.count, 1);
	
	id <BUYPaymentProvider> provider = [controller providerForType:BUYApplePayPaymentProviderId];
	XCTAssertEqualObjects(provider, applePay1);
	
	BUYWebCheckoutPaymentProvider *webProvider = [[BUYWebCheckoutPaymentProvider alloc] initWithClient:self.client];
	[controller addPaymentProvider:webProvider];
	
	XCTAssertEqual(controller.providers.count, 2);
	provider = [controller providerForType:BUYWebPaymentProviderId];
	XCTAssertEqualObjects(provider, webProvider);

	// Attempt to add an alternate Apple Pay provider
	BUYApplePayPaymentProvider *applePay2 = [[BUYApplePayPaymentProvider alloc] initWithClient:self.client merchantID:@"merchant.id.2"];
	[controller addPaymentProvider:applePay2];
	XCTAssertEqual(controller.providers.count, 2);
}

- (void)testStartingPaymentWithPaymentController
{
	[self mockRequests];
	
	BUYPaymentController *controller = [[BUYPaymentController alloc] init];
	BUYWebCheckoutPaymentProvider *webProvider = [[BUYWebCheckoutPaymentProvider alloc] initWithClient:self.client];
	webProvider.delegate = self;
	[controller addPaymentProvider:webProvider];

	self.expectations[@"presentController"] = [self expectationWithDescription:NSStringFromSelector(_cmd)];

	[controller startCheckout:self.checkout withProviderType:BUYWebPaymentProviderId];
	
	[self waitForExpectationsWithTimeout:1 handler:^(NSError *error) {
		XCTAssertNil(error);
	}];
}

#pragma mark - Payment Provider delegate

- (void)paymentProvider:(id <BUYPaymentProvider>)provider wantsControllerPresented:(UIViewController *)controller
{
	[self.expectations[@"presentController"] fulfill];
}

- (void)paymentProviderWantsControllerDismissed:(id <BUYPaymentProvider>)provider
{
	
}

- (void)paymentProviderWillStartCheckout:(id <BUYPaymentProvider>)provider
{
	
}

- (void)paymentProviderDidDismissCheckout:(id <BUYPaymentProvider>)provider
{
	
}

- (void)paymentProvider:(id <BUYPaymentProvider>)provider didFailToUpdateCheckoutWithError:(NSError *)error
{
}

- (void)paymentProvider:(id <BUYPaymentProvider>)provider didFailWithError:(NSError *)error;
{
	if (self.expectations[@"failedCheckout"]) {
		[self.expectations[@"failedCheckout"] fulfill];
		[self.expectations removeObjectForKey:@"failedCheckout"];
	}
	
	if (self.expectations[@"failedShop"]) {
		[self.expectations[@"failedShop"] fulfill];
		[self.expectations removeObjectForKey:@"failedShop"];
	}
}

- (void)paymentProvider:(id <BUYPaymentProvider>)provider didCompleteCheckout:(BUYCheckout *)checkout withStatus:(BUYStatus)status
{
	
}


@end