package pub.devrel.easypermissions;

import android.Manifest;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.android.controller.ActivityController;
import org.robolectric.annotation.Config;
import org.robolectric.shadows.support.v4.SupportFragmentController;

import java.util.ArrayList;

import pub.devrel.easypermissions.testhelper.TestActivity;
import pub.devrel.easypermissions.testhelper.TestFragment;
import pub.devrel.easypermissions.testhelper.TestAppCompatActivity;

import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;

/**
 * Low-API (SDK = 19) tests for {@link pub.devrel.easypermissions.EasyPermissions}.
 */
@RunWith(RobolectricTestRunner.class)
@Config(sdk = 19)
public class EasyPermissionsLowApiTest {

    private static final String RATIONALE = "RATIONALE";
    private static final String[] ALL_PERMS = new String[]{
            Manifest.permission.READ_SMS, Manifest.permission.ACCESS_FINE_LOCATION};

    private TestActivity spyActivity;
    private TestAppCompatActivity spyAppCompatActivity;
    private TestFragment spyFragment;
    private ActivityController<TestActivity> activityController;
    private ActivityController<TestAppCompatActivity> appCompatActivityController;
    private SupportFragmentController<TestFragment> supportController;
    @Captor
    private ArgumentCaptor<Integer> integerCaptor;
    @Captor
    private ArgumentCaptor<ArrayList<String>> listCaptor;

    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
        setUpActivityAndFragment();
    }

    @After
    public void tearDown() {
        tearDownActivityAndFragment();
    }

    // ------ General tests ------

    @Test
    public void shouldHavePermission_whenHasPermissionsBeforeMarshmallow() {
        assertThat(EasyPermissions.hasPermissions(RuntimeEnvironment.application,
                Manifest.permission.ACCESS_COARSE_LOCATION)).isTrue();
    }

    // ------ From Activity ------

    @Test
    public void shouldCallbackOnPermissionGranted_whenRequestFromActivity() {
        EasyPermissions.requestPermissions(spyActivity, RATIONALE, TestActivity.REQUEST_CODE, ALL_PERMS);

        verify(spyActivity, times(1))
                .onPermissionsGranted(integerCaptor.capture(), listCaptor.capture());
        assertThat(integerCaptor.getValue()).isEqualTo(TestActivity.REQUEST_CODE);
        assertThat(listCaptor.getValue()).containsAllIn(ALL_PERMS);
    }

    // ------ From Support Activity ------

    @Test
    public void shouldCallbackOnPermissionGranted_whenRequestFromSupportActivity() {
        EasyPermissions.requestPermissions(spyAppCompatActivity, RATIONALE, TestAppCompatActivity.REQUEST_CODE, ALL_PERMS);

        verify(spyAppCompatActivity, times(1))
                .onPermissionsGranted(integerCaptor.capture(), listCaptor.capture());
        assertThat(integerCaptor.getValue()).isEqualTo(TestAppCompatActivity.REQUEST_CODE);
        assertThat(listCaptor.getValue()).containsAllIn(ALL_PERMS);
    }

    @Test
    public void shouldCallbackOnPermissionGranted_whenRequestFromFragment() {
        EasyPermissions.requestPermissions(spyFragment, RATIONALE, TestFragment.REQUEST_CODE, ALL_PERMS);

        verify(spyFragment, times(1))
                .onPermissionsGranted(integerCaptor.capture(), listCaptor.capture());
        assertThat(integerCaptor.getValue()).isEqualTo(TestFragment.REQUEST_CODE);
        assertThat(listCaptor.getValue()).containsAllIn(ALL_PERMS);
    }

    private void setUpActivityAndFragment() {
        activityController = Robolectric.buildActivity(TestActivity.class)
                .create().start().resume();
        appCompatActivityController = Robolectric.buildActivity(TestAppCompatActivity.class)
                .create().start().resume();
        supportController = SupportFragmentController.of(new TestFragment())
                .create().start().resume();

        spyActivity = Mockito.spy(activityController.get());
        spyAppCompatActivity = Mockito.spy(appCompatActivityController.get());
        spyFragment = Mockito.spy(supportController.get());
    }

    private void tearDownActivityAndFragment() {
        activityController.pause().stop().destroy();
        appCompatActivityController.pause().stop().destroy();
        supportController.pause().stop().destroy();
    }
}

@@ -803,16 +803,90 @@
 ctivity;
+%0Aimport pub.devrel.easypermissions.testhelper.TestSupportFragmentActivity;
 %0A%0Aimport
@@ -1442,32 +1442,100 @@
 ty spyActivity;%0A
+    private TestSupportFragmentActivity spySupportFragmentActivity;%0A
     private Test
@@ -1669,32 +1669,127 @@
 vityController;%0A
+    private ActivityController%3CTestSupportFragmentActivity%3E supportFragmentActivityController;%0A
     private Acti
@@ -3193,16 +3193,571 @@
 mSupport
+FragmentActivity() %7B%0A        EasyPermissions.requestPermissions(spySupportFragmentActivity, RATIONALE, TestSupportFragmentActivity.REQUEST_CODE, ALL_PERMS);%0A%0A        verify(spySupportFragmentActivity, times(1))%0A                .onPermissionsGranted(integerCaptor.capture(), listCaptor.capture());%0A        assertThat(integerCaptor.getValue()).isEqualTo(TestSupportFragmentActivity.REQUEST_CODE);%0A        assertThat(listCaptor.getValue()).containsAllIn(ALL_PERMS);%0A    %7D%0A%0A%0A    @Test%0A    public void shouldCallbackOnPermissionGranted_whenRequestFromAppCompat
 Activity
@@ -4820,32 +4820,181 @@
 art().resume();%0A
+        supportFragmentActivityController = Robolectric.buildActivity(TestSupportFragmentActivity.class)%0A                .create().start().resume();%0A
         appCompa
@@ -5232,24 +5232,24 @@
 .resume();%0A%0A
-
         spyA
@@ -5289,32 +5289,123 @@
 troller.get());%0A
+        spySupportFragmentActivity = Mockito.spy(supportFragmentActivityController.get());%0A
         spyAppCo

Add test