/*
* Copyright 2014 serso aka se.solovyev
*
* 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.
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Contact details
*
* Email: se.solovyev@gmail.com
* Site: http://se.solovyev.org
*/
package org.solovyev.android.checkout;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
import android.app.Activity;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import javax.annotation.Nonnull;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyObject;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.solovyev.android.checkout.PurchaseFlowTest.newOkIntent;
import static org.solovyev.android.checkout.ResponseCodes.NULL_INTENT;
@RunWith(RobolectricTestRunner.class)
@Config(manifest = Config.NONE)
public class ActivityCheckoutTest {
@Nonnull
private Billing mBilling;
@Nonnull
private ActivityCheckout mCheckout;
@Before
public void setUp() throws Exception {
mBilling = Tests.newBilling();
mCheckout = Checkout.forActivity(new Activity(), mBilling);
}
@Test
public void testShouldCreatePurchaseFlow() throws Exception {
mCheckout.createPurchaseFlow(100, mock(RequestListener.class));
assertNotNull(mCheckout.getPurchaseFlow(100));
}
@Test
public void testShouldCreateDefaultPurchaseFlow() throws Exception {
mCheckout.createPurchaseFlow(mock(RequestListener.class));
assertNotNull(mCheckout.getPurchaseFlow());
}
@Test
public void testShouldCreateOneShotPurchaseFlow() throws Exception {
mCheckout.createOneShotPurchaseFlow(101, mock(RequestListener.class));
assertNotNull(mCheckout.getPurchaseFlow(101));
}
@Test
public void testShouldCreateDefaultOneShotPurchaseFlow() throws Exception {
mCheckout.createPurchaseFlow(mock(RequestListener.class));
assertNotNull(mCheckout.getPurchaseFlow());
}
@Test
public void testDestroyShouldRemovePurchaseFlow() throws Exception {
mCheckout.createPurchaseFlow(102, mock(RequestListener.class));
mCheckout.destroyPurchaseFlow(102);
verifyPurchaseFlowDoesntExist(102);
}
private void verifyPurchaseFlowDoesntExist(int requestCode) {
try {
mCheckout.getPurchaseFlow(requestCode);
fail();
} catch (IllegalArgumentException e) {
// ok
}
}
private void verifyPurchaseFlowDoesntExist() {
try {
mCheckout.getPurchaseFlow();
fail();
} catch (IllegalArgumentException e) {
// ok
}
}
@Test
public void testDestroyShouldRemoveDefaultPurchaseFlow() throws Exception {
mCheckout.createPurchaseFlow(mock(RequestListener.class));
mCheckout.destroyPurchaseFlow();
verifyPurchaseFlowDoesntExist();
}
@Test
public void testDestroyShouldCancelPurchaseFlow() throws Exception {
final CancellableRequestListener l = mock(CancellableRequestListener.class);
mCheckout.createPurchaseFlow(l);
mCheckout.destroyPurchaseFlow();
verify(l).cancel();
}
@Test
public void testOneShotPurchaseFlowShouldBeRemovedOnError() throws Exception {
RequestListener l = mock(RequestListener.class);
mCheckout.createOneShotPurchaseFlow(l);
mCheckout.onActivityResult(ActivityCheckout.DEFAULT_REQUEST_CODE, Activity.RESULT_CANCELED, null);
verify(l).onError(eq(NULL_INTENT), any(Exception.class));
verifyPurchaseFlowDoesntExist();
}
@Test
public void testOneShotPurchaseFlowShouldBeRemovedOnSuccess() throws Exception {
final PurchaseVerifier verifier = mock(PurchaseVerifier.class);
Tests.mockVerifier(verifier, true);
mBilling.setPurchaseVerifier(verifier);
final RequestListener l = mock(RequestListener.class);
mCheckout.createOneShotPurchaseFlow(l);
mCheckout.onActivityResult(ActivityCheckout.DEFAULT_REQUEST_CODE, Activity.RESULT_OK, newOkIntent());
verify(l).onSuccess(anyObject());
verifyPurchaseFlowDoesntExist();
}
@Test
public void testPurchaseWithOneShotPurchaseFlow() throws Exception {
final PurchaseVerifier verifier = mock(PurchaseVerifier.class);
Tests.mockVerifier(verifier, true);
final CountDownLatch verifierWaiter = new CountDownLatch(1);
mBilling.setPurchaseVerifier(new PurchaseVerifier() {
@Nonnull
private Executor background = Executors.newSingleThreadExecutor();
@Override
public void verify(@Nonnull final List<Purchase> list, @Nonnull final RequestListener<List<Purchase>> requestListener) {
background.execute(new Runnable() {
@Override
public void run() {
try {
verifierWaiter.await();
} catch (InterruptedException e) {
}
requestListener.onSuccess(list);
}
});
}
});
final CountDownLatch listenerWaiter = new CountDownLatch(1);
final RequestListener<Purchase> l = new RequestListener<Purchase>() {
@Override
public void onSuccess(@Nonnull Purchase purchase) {
listenerWaiter.countDown();
}
@Override
public void onError(int i, @Nonnull Exception e) {
}
};
mCheckout.createOneShotPurchaseFlow(l);
mCheckout.onActivityResult(ActivityCheckout.DEFAULT_REQUEST_CODE, Activity.RESULT_OK, newOkIntent());
verifierWaiter.countDown();
listenerWaiter.await(200, TimeUnit.MILLISECONDS);
verifyPurchaseFlowDoesntExist();
}
}