31
31
import static com .google .firebase .appdistribution .impl .FeedbackActivity .RELEASE_NAME_EXTRA_KEY ;
32
32
import static com .google .firebase .appdistribution .impl .FeedbackActivity .SCREENSHOT_URI_EXTRA_KEY ;
33
33
import static com .google .firebase .appdistribution .impl .TestUtils .assertTaskFailure ;
34
+ import static java .util .stream .Collectors .toList ;
34
35
import static org .junit .Assert .assertEquals ;
35
36
import static org .junit .Assert .assertFalse ;
36
37
import static org .junit .Assert .assertNotNull ;
37
38
import static org .junit .Assert .assertNull ;
38
39
import static org .junit .Assert .assertTrue ;
40
+ import static org .mockito .ArgumentMatchers .any ;
39
41
import static org .mockito .Mockito .doReturn ;
40
42
import static org .mockito .Mockito .never ;
41
43
import static org .mockito .Mockito .spy ;
53
55
import android .content .pm .PackageInfo ;
54
56
import android .net .Uri ;
55
57
import android .os .Bundle ;
58
+ import android .util .Log ;
56
59
import androidx .test .core .app .ApplicationProvider ;
57
60
import androidx .test .core .content .pm .ApplicationInfoBuilder ;
58
61
import androidx .test .core .content .pm .PackageInfoBuilder ;
74
77
import java .util .concurrent .ExecutorService ;
75
78
import java .util .concurrent .Executors ;
76
79
import java .util .concurrent .Future ;
80
+ import java .util .function .Predicate ;
81
+ import org .junit .After ;
77
82
import org .junit .Before ;
78
83
import org .junit .Test ;
79
84
import org .junit .runner .RunWith ;
80
- import org .mockito .ArgumentCaptor ;
81
85
import org .mockito .Mock ;
82
86
import org .mockito .MockitoAnnotations ;
83
87
import org .robolectric .Robolectric ;
84
88
import org .robolectric .RobolectricTestRunner ;
89
+ import org .robolectric .RuntimeEnvironment ;
90
+ import org .robolectric .android .controller .ActivityController ;
85
91
import org .robolectric .shadows .ShadowAlertDialog ;
92
+ import org .robolectric .shadows .ShadowLog ;
86
93
import org .robolectric .shadows .ShadowPackageManager ;
87
94
88
95
@ RunWith (RobolectricTestRunner .class )
@@ -122,6 +129,7 @@ public class FirebaseAppDistributionServiceImplTest {
122
129
.setDownloadUrl (TEST_URL );
123
130
124
131
private FirebaseAppDistributionImpl firebaseAppDistribution ;
132
+ private ActivityController <TestActivity > activityController ;
125
133
private TestActivity activity ;
126
134
private FirebaseApp firebaseApp ;
127
135
private ExecutorService taskExecutor = Executors .newSingleThreadExecutor ();
@@ -190,11 +198,19 @@ public void setup() throws FirebaseAppDistributionException {
190
198
packageInfo .setLongVersionCode (INSTALLED_VERSION_CODE );
191
199
shadowPackageManager .installPackage (packageInfo );
192
200
193
- activity = spy (Robolectric .buildActivity (TestActivity .class ).create ().get ());
201
+ activityController = Robolectric .buildActivity (TestActivity .class ).setup ();
202
+ activity = spy (activityController .get ());
194
203
TestUtils .mockForegroundActivity (mockLifecycleNotifier , activity );
195
204
when (mockScreenshotTaker .takeScreenshot ()).thenReturn (Tasks .forResult (TEST_SCREENSHOT_URI ));
196
205
}
197
206
207
+ @ After
208
+ public void tearDown () {
209
+ if (activityController != null ) {
210
+ activityController .close ();
211
+ }
212
+ }
213
+
198
214
@ Test
199
215
public void checkForNewRelease_whenCheckForNewReleaseFails_throwsError () {
200
216
when (mockNewReleaseFetcher .checkForNewRelease ())
@@ -635,18 +651,43 @@ public void updateApp_withApkReleaseAvailable_returnsSameApkTask() {
635
651
@ Test
636
652
public void startFeedback_signsInTesterAndStartsActivity () throws InterruptedException {
637
653
when (mockReleaseIdentifier .identifyRelease ()).thenReturn (Tasks .forResult ("release-name" ));
654
+
638
655
firebaseAppDistribution .startFeedback ("Some terms and conditions" );
639
656
TestUtils .awaitAsyncOperations (taskExecutor );
640
657
641
- ArgumentCaptor <Intent > argument = ArgumentCaptor .forClass (Intent .class );
642
- verify (activity ).startActivity (argument .capture ());
643
658
verify (mockTesterSignInManager ).signInTester ();
644
- assertThat (argument .getValue ().getStringExtra (RELEASE_NAME_EXTRA_KEY ))
645
- .isEqualTo ("release-name" );
646
- assertThat (argument .getValue ().getStringExtra (SCREENSHOT_URI_EXTRA_KEY ))
659
+ Intent expectedIntent = new Intent (activity , FeedbackActivity .class );
660
+ Intent actualIntent = shadowOf (RuntimeEnvironment .getApplication ()).getNextStartedActivity ();
661
+ assertEquals (expectedIntent .getComponent (), actualIntent .getComponent ());
662
+ assertThat (actualIntent .getStringExtra (RELEASE_NAME_EXTRA_KEY )).isEqualTo ("release-name" );
663
+ assertThat (actualIntent .getStringExtra (SCREENSHOT_URI_EXTRA_KEY ))
647
664
.isEqualTo (TEST_SCREENSHOT_URI .toString ());
648
- assertThat (argument . getValue () .getStringExtra (INFO_TEXT_EXTRA_KEY ))
665
+ assertThat (actualIntent .getStringExtra (INFO_TEXT_EXTRA_KEY ))
649
666
.isEqualTo ("Some terms and conditions" );
667
+ assertThat (firebaseAppDistribution .isFeedbackInProgress ()).isTrue ();
668
+ }
669
+
670
+ @ Test
671
+ public void startFeedback_calledMultipleTimes_onlyStartsOnce () throws InterruptedException {
672
+ when (mockReleaseIdentifier .identifyRelease ()).thenReturn (Tasks .forResult ("release-name" ));
673
+
674
+ firebaseAppDistribution .startFeedback ("Some terms and conditions" );
675
+ firebaseAppDistribution .startFeedback ("Some other terms and conditions" );
676
+ TestUtils .awaitAsyncOperations (taskExecutor );
677
+
678
+ verify (activity , times (1 )).startActivity (any ());
679
+ }
680
+
681
+ @ Test
682
+ public void startFeedback_closingActivity_setsInProgressToFalse () throws InterruptedException {
683
+ when (mockReleaseIdentifier .identifyRelease ()).thenReturn (Tasks .forResult ("release-name" ));
684
+
685
+ firebaseAppDistribution .startFeedback ("Some terms and conditions" );
686
+ TestUtils .awaitAsyncOperations (taskExecutor );
687
+ // Simulate destroying the feedback activity
688
+ firebaseAppDistribution .onActivityDestroyed (new FeedbackActivity ());
689
+
690
+ assertThat (firebaseAppDistribution .isFeedbackInProgress ()).isFalse ();
650
691
}
651
692
652
693
@ Test
@@ -656,16 +697,58 @@ public void startFeedback_screenshotFails_startActivityWithNoScreenshot()
656
697
.thenReturn (
657
698
Tasks .forException (new FirebaseAppDistributionException ("Error" , Status .UNKNOWN )));
658
699
when (mockReleaseIdentifier .identifyRelease ()).thenReturn (Tasks .forResult ("release-name" ));
700
+
659
701
firebaseAppDistribution .startFeedback ("Some terms and conditions" );
660
702
TestUtils .awaitAsyncOperations (taskExecutor );
661
703
662
- ArgumentCaptor <Intent > argument = ArgumentCaptor .forClass (Intent .class );
663
- verify (activity ).startActivity (argument .capture ());
664
704
verify (mockTesterSignInManager ).signInTester ();
665
- assertThat (argument .getValue ().getStringExtra (RELEASE_NAME_EXTRA_KEY ))
666
- .isEqualTo ("release-name" );
667
- assertThat (argument .getValue ().hasExtra (SCREENSHOT_URI_EXTRA_KEY )).isFalse ();
668
- assertThat (argument .getValue ().getStringExtra (INFO_TEXT_EXTRA_KEY ))
705
+ Intent expectedIntent = new Intent (activity , FeedbackActivity .class );
706
+ Intent actualIntent = shadowOf (RuntimeEnvironment .getApplication ()).getNextStartedActivity ();
707
+ assertEquals (expectedIntent .getComponent (), actualIntent .getComponent ());
708
+ assertThat (actualIntent .getStringExtra (RELEASE_NAME_EXTRA_KEY )).isEqualTo ("release-name" );
709
+ assertThat (actualIntent .getStringExtra (SCREENSHOT_URI_EXTRA_KEY )).isNull ();
710
+ assertThat (actualIntent .getStringExtra (INFO_TEXT_EXTRA_KEY ))
669
711
.isEqualTo ("Some terms and conditions" );
712
+ assertThat (firebaseAppDistribution .isFeedbackInProgress ()).isTrue ();
713
+ }
714
+
715
+ @ Test
716
+ public void startFeedback_signInTesterFails_logsAndSetsInProgressToFalse ()
717
+ throws InterruptedException {
718
+ when (mockReleaseIdentifier .identifyRelease ()).thenReturn (Tasks .forResult ("release-name" ));
719
+ FirebaseAppDistributionException exception =
720
+ new FirebaseAppDistributionException ("Error" , Status .UNKNOWN );
721
+ when (mockTesterSignInManager .signInTester ()).thenReturn (Tasks .forException (exception ));
722
+
723
+ firebaseAppDistribution .startFeedback ("Some terms and conditions" );
724
+ TestUtils .awaitAsyncOperations (taskExecutor );
725
+
726
+ assertThat (firebaseAppDistribution .isFeedbackInProgress ()).isFalse ();
727
+ assertLoggedError ("Failed to launch feedback flow" , exception );
728
+ }
729
+
730
+ @ Test
731
+ public void startFeedback_cantIdentifyRelease_logsAndSetsInProgressToFalse ()
732
+ throws InterruptedException {
733
+ FirebaseAppDistributionException exception =
734
+ new FirebaseAppDistributionException ("Error" , Status .UNKNOWN );
735
+ when (mockReleaseIdentifier .identifyRelease ()).thenReturn (Tasks .forException (exception ));
736
+
737
+ firebaseAppDistribution .startFeedback ("Some terms and conditions" );
738
+ TestUtils .awaitAsyncOperations (taskExecutor );
739
+
740
+ assertThat (firebaseAppDistribution .isFeedbackInProgress ()).isFalse ();
741
+ assertLoggedError ("Failed to launch feedback flow" , exception );
742
+ }
743
+
744
+ private static void assertLoggedError (String partialMessage , Throwable e ) {
745
+ Predicate <ShadowLog .LogItem > predicate =
746
+ log ->
747
+ log .type == Log .ERROR
748
+ && log .msg .contains (partialMessage )
749
+ && (e != null ? log .throwable == e : true );
750
+ List <ShadowLog .LogItem > matchingLogs =
751
+ ShadowLog .getLogs ().stream ().filter (predicate ).collect (toList ());
752
+ assertThat (matchingLogs ).hasSize (1 );
670
753
}
671
754
}
0 commit comments