mirror of
				https://github.com/mihonapp/mihon.git
				synced 2025-10-31 14:27:57 +01:00 
			
		
		
		
	Partial migration of data package to Kotlin
This commit is contained in:
		
							
								
								
									
										15
									
								
								app/src/test/java/eu/kanade/tachiyomi/CustomBuildConfig.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								app/src/test/java/eu/kanade/tachiyomi/CustomBuildConfig.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | ||||
| package eu.kanade.tachiyomi; | ||||
|  | ||||
| public class CustomBuildConfig { | ||||
|     public static final boolean DEBUG = Boolean.parseBoolean("true"); | ||||
|     public static final String APPLICATION_ID = "eu.kanade.tachiyomi"; | ||||
|     public static final String BUILD_TYPE = "debug"; | ||||
|     public static final String FLAVOR = ""; | ||||
|     public static final int VERSION_CODE = 4; | ||||
|     public static final String VERSION_NAME = "0.1.3"; | ||||
|     // Fields from default config. | ||||
|     public static final String BUILD_TIME = "2016-02-19T14:49Z"; | ||||
|     public static final String COMMIT_COUNT = "482"; | ||||
|     public static final String COMMIT_SHA = "e52c498"; | ||||
|     public static final boolean INCLUDE_UPDATER = true; | ||||
| } | ||||
| @@ -1,9 +1,24 @@ | ||||
| package eu.kanade.tachiyomi; | ||||
|  | ||||
| import eu.kanade.tachiyomi.injection.component.DaggerAppComponent; | ||||
| import eu.kanade.tachiyomi.injection.module.AppModule; | ||||
|  | ||||
| public class TestApp extends App { | ||||
|  | ||||
|     @Override | ||||
|     protected DaggerAppComponent.Builder prepareAppComponent() { | ||||
|         return DaggerAppComponent.builder() | ||||
|                 .appModule(new AppModule(this)) | ||||
|                 .dataModule(new TestDataModule()); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     protected void setupEventBus() { | ||||
|         // Do nothing | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     protected void setupAcra() { | ||||
|         // Do nothing | ||||
|     } | ||||
| } | ||||
|   | ||||
							
								
								
									
										29
									
								
								app/src/test/java/eu/kanade/tachiyomi/TestDataModule.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								app/src/test/java/eu/kanade/tachiyomi/TestDataModule.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | ||||
| package eu.kanade.tachiyomi; | ||||
|  | ||||
| import android.app.Application; | ||||
|  | ||||
| import org.mockito.Mockito; | ||||
|  | ||||
| import eu.kanade.tachiyomi.data.database.DatabaseHelper; | ||||
| import eu.kanade.tachiyomi.data.network.NetworkHelper; | ||||
| import eu.kanade.tachiyomi.data.source.SourceManager; | ||||
| import eu.kanade.tachiyomi.injection.module.DataModule; | ||||
|  | ||||
| public class TestDataModule extends DataModule { | ||||
|  | ||||
|     @Override | ||||
|     public DatabaseHelper provideDatabaseHelper(Application app) { | ||||
|         return Mockito.mock(DatabaseHelper.class, Mockito.RETURNS_DEEP_STUBS); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public NetworkHelper provideNetworkHelper(Application app) { | ||||
|         return Mockito.mock(NetworkHelper.class); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public SourceManager provideSourceManager(Application app) { | ||||
|         return Mockito.mock(SourceManager.class, Mockito.RETURNS_DEEP_STUBS); | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -1,16 +0,0 @@ | ||||
| package eu.kanade.tachiyomi; | ||||
|  | ||||
| import java.lang.annotation.ElementType; | ||||
| import java.lang.annotation.Retention; | ||||
| import java.lang.annotation.RetentionPolicy; | ||||
| import java.lang.annotation.Target; | ||||
|  | ||||
| /** | ||||
|  * Created by len on 1/10/15. | ||||
|  */ | ||||
|  | ||||
| @Target(ElementType.TYPE) | ||||
| @Retention(RetentionPolicy.RUNTIME) | ||||
| public @interface UseModule { | ||||
|     Class value(); | ||||
| } | ||||
| @@ -0,0 +1,140 @@ | ||||
| package eu.kanade.tachiyomi.data.library; | ||||
|  | ||||
| import android.app.AlarmManager; | ||||
| import android.content.Context; | ||||
| import android.content.Intent; | ||||
| import android.os.Build; | ||||
| import android.os.SystemClock; | ||||
|  | ||||
| import org.assertj.core.data.Offset; | ||||
| import org.junit.Before; | ||||
| import org.junit.Test; | ||||
| import org.junit.runner.RunWith; | ||||
| import org.robolectric.RobolectricGradleTestRunner; | ||||
| import org.robolectric.annotation.Config; | ||||
| import org.robolectric.shadows.ShadowAlarmManager; | ||||
| import org.robolectric.shadows.ShadowApplication; | ||||
| import org.robolectric.shadows.ShadowPendingIntent; | ||||
|  | ||||
| import eu.kanade.tachiyomi.CustomBuildConfig; | ||||
| import eu.kanade.tachiyomi.data.preference.PreferencesHelper; | ||||
|  | ||||
| import static org.assertj.core.api.Assertions.assertThat; | ||||
| import static org.mockito.Mockito.spy; | ||||
| import static org.robolectric.Shadows.shadowOf; | ||||
|  | ||||
| @Config(constants = CustomBuildConfig.class, sdk = Build.VERSION_CODES.LOLLIPOP) | ||||
| @RunWith(RobolectricGradleTestRunner.class) | ||||
| public class LibraryUpdateAlarmTest { | ||||
|  | ||||
|     ShadowApplication app; | ||||
|     Context context; | ||||
|     ShadowAlarmManager alarmManager; | ||||
|  | ||||
|     @Before | ||||
|     public void setup() { | ||||
|         app = ShadowApplication.getInstance(); | ||||
|         context = spy(app.getApplicationContext()); | ||||
|  | ||||
|         alarmManager = shadowOf((AlarmManager) context.getSystemService(Context.ALARM_SERVICE)); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     public void testLibraryIntentHandling() { | ||||
|         Intent intent = new Intent(LibraryUpdateAlarm.LIBRARY_UPDATE_ACTION); | ||||
|         assertThat(app.hasReceiverForIntent(intent)).isTrue(); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     public void testAlarmIsNotStarted() { | ||||
|         assertThat(alarmManager.getNextScheduledAlarm()).isNull(); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     public void testAlarmIsNotStartedWhenBootReceivedAndSettingZero() { | ||||
|         LibraryUpdateAlarm alarm = new LibraryUpdateAlarm(); | ||||
|         alarm.onReceive(context, new Intent(Intent.ACTION_BOOT_COMPLETED)); | ||||
|  | ||||
|         assertThat(alarmManager.getNextScheduledAlarm()).isNull(); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     public void testAlarmIsStartedWhenBootReceivedAndSettingNotZero() { | ||||
|         PreferencesHelper prefs = new PreferencesHelper(context); | ||||
|         prefs.libraryUpdateInterval().set(1); | ||||
|  | ||||
|         LibraryUpdateAlarm alarm = new LibraryUpdateAlarm(); | ||||
|         alarm.onReceive(context, new Intent(Intent.ACTION_BOOT_COMPLETED)); | ||||
|  | ||||
|         assertThat(alarmManager.getNextScheduledAlarm()).isNotNull(); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     public void testOnlyOneAlarmExists() { | ||||
|         PreferencesHelper prefs = new PreferencesHelper(context); | ||||
|         prefs.libraryUpdateInterval().set(1); | ||||
|  | ||||
|         LibraryUpdateAlarm.startAlarm(context); | ||||
|         LibraryUpdateAlarm.startAlarm(context); | ||||
|         LibraryUpdateAlarm.startAlarm(context); | ||||
|  | ||||
|         assertThat(alarmManager.getScheduledAlarms()).hasSize(1); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     public void testLibraryWillBeUpdatedWhenAlarmFired() { | ||||
|         PreferencesHelper prefs = new PreferencesHelper(context); | ||||
|         prefs.libraryUpdateInterval().set(1); | ||||
|  | ||||
|         Intent expectedIntent = new Intent(context, LibraryUpdateAlarm.class); | ||||
|         expectedIntent.setAction(LibraryUpdateAlarm.LIBRARY_UPDATE_ACTION); | ||||
|  | ||||
|         LibraryUpdateAlarm.startAlarm(context); | ||||
|  | ||||
|         ShadowAlarmManager.ScheduledAlarm scheduledAlarm = alarmManager.getNextScheduledAlarm(); | ||||
|         ShadowPendingIntent pendingIntent = shadowOf(scheduledAlarm.operation); | ||||
|         assertThat(pendingIntent.isBroadcastIntent()).isTrue(); | ||||
|         assertThat(pendingIntent.getSavedIntents()).hasSize(1); | ||||
|         assertThat(expectedIntent.getComponent()).isEqualTo(pendingIntent.getSavedIntents()[0].getComponent()); | ||||
|         assertThat(expectedIntent.getAction()).isEqualTo(pendingIntent.getSavedIntents()[0].getAction()); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     public void testLibraryUpdateServiceIsStartedWhenUpdateIntentIsReceived() { | ||||
|         Intent intent = new Intent(context, LibraryUpdateService.class); | ||||
|         assertThat(app.getNextStartedService()).isNotEqualTo(intent); | ||||
|  | ||||
|         LibraryUpdateAlarm alarm = new LibraryUpdateAlarm(); | ||||
|         alarm.onReceive(context, new Intent(LibraryUpdateAlarm.LIBRARY_UPDATE_ACTION)); | ||||
|  | ||||
|         assertThat(app.getNextStartedService()).isEqualTo(intent); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     public void testReceiverDoesntReactToNullActions() { | ||||
|         PreferencesHelper prefs = new PreferencesHelper(context); | ||||
|         prefs.libraryUpdateInterval().set(1); | ||||
|  | ||||
|         Intent intent = new Intent(context, LibraryUpdateService.class); | ||||
|  | ||||
|         LibraryUpdateAlarm alarm = new LibraryUpdateAlarm(); | ||||
|         alarm.onReceive(context, new Intent()); | ||||
|  | ||||
|         assertThat(app.getNextStartedService()).isNotEqualTo(intent); | ||||
|         assertThat(alarmManager.getScheduledAlarms()).hasSize(0); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     public void testAlarmFiresCloseToDesiredTime() { | ||||
|         int hours = 2; | ||||
|         LibraryUpdateAlarm.startAlarm(context, hours); | ||||
|  | ||||
|         long shouldRunAt = SystemClock.elapsedRealtime() + (hours * 60 * 60 * 1000); | ||||
|  | ||||
|         // Margin error of 3 seconds | ||||
|         Offset<Long> offset = Offset.offset(3 * 1000L); | ||||
|  | ||||
|         assertThat(alarmManager.getNextScheduledAlarm().triggerAtTime).isCloseTo(shouldRunAt, offset); | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,130 @@ | ||||
| package eu.kanade.tachiyomi.data.library; | ||||
|  | ||||
| import android.content.Context; | ||||
| import android.content.Intent; | ||||
| import android.os.Build; | ||||
| import android.util.Pair; | ||||
|  | ||||
| import org.junit.Before; | ||||
| import org.junit.Test; | ||||
| import org.junit.runner.RunWith; | ||||
| import org.robolectric.Robolectric; | ||||
| import org.robolectric.RobolectricGradleTestRunner; | ||||
| import org.robolectric.annotation.Config; | ||||
| import org.robolectric.shadows.ShadowApplication; | ||||
|  | ||||
| import java.util.ArrayList; | ||||
| import java.util.List; | ||||
|  | ||||
| import eu.kanade.tachiyomi.CustomBuildConfig; | ||||
| import eu.kanade.tachiyomi.data.database.models.Chapter; | ||||
| import eu.kanade.tachiyomi.data.database.models.Manga; | ||||
| import eu.kanade.tachiyomi.data.source.base.Source; | ||||
| import rx.Observable; | ||||
|  | ||||
| import static org.mockito.Matchers.any; | ||||
| import static org.mockito.Matchers.anyInt; | ||||
| import static org.mockito.Matchers.eq; | ||||
| import static org.mockito.Mockito.mock; | ||||
| import static org.mockito.Mockito.never; | ||||
| import static org.mockito.Mockito.times; | ||||
| import static org.mockito.Mockito.verify; | ||||
| import static org.mockito.Mockito.when; | ||||
|  | ||||
| @Config(constants = CustomBuildConfig.class, sdk = Build.VERSION_CODES.LOLLIPOP) | ||||
| @RunWith(RobolectricGradleTestRunner.class) | ||||
| public class LibraryUpdateServiceTest { | ||||
|  | ||||
|     ShadowApplication app; | ||||
|     Context context; | ||||
|     LibraryUpdateService service; | ||||
|     Source source; | ||||
|  | ||||
|     @Before | ||||
|     public void setup() { | ||||
|         app = ShadowApplication.getInstance(); | ||||
|         context = app.getApplicationContext(); | ||||
|         service = Robolectric.setupService(LibraryUpdateService.class); | ||||
|         source = mock(Source.class); | ||||
|         when(service.sourceManager.get(anyInt())).thenReturn(source); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     public void testStartCommand() { | ||||
|         service.onStartCommand(new Intent(), 0, 0); | ||||
|         verify(service.db).getFavoriteMangas(); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     public void testLifecycle() { | ||||
|         // Smoke test | ||||
|         Robolectric.buildService(LibraryUpdateService.class) | ||||
|                 .attach() | ||||
|                 .create() | ||||
|                 .startCommand(0, 0) | ||||
|                 .destroy() | ||||
|                 .get(); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     public void testUpdateManga() { | ||||
|         Manga manga = Manga.create("manga1"); | ||||
|         List<Chapter> chapters = createChapters("/chapter1", "/chapter2"); | ||||
|  | ||||
|         when(source.pullChaptersFromNetwork(manga.url)).thenReturn(Observable.just(chapters)); | ||||
|         when(service.db.insertOrRemoveChapters(manga, chapters)) | ||||
|                 .thenReturn(Observable.just(Pair.create(2, 0))); | ||||
|  | ||||
|         service.updateManga(manga).subscribe(); | ||||
|  | ||||
|         verify(service.db).insertOrRemoveChapters(manga, chapters); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     public void testContinuesUpdatingWhenAMangaFails() { | ||||
|         Manga manga1 = Manga.create("manga1"); | ||||
|         Manga manga2 = Manga.create("manga2"); | ||||
|         Manga manga3 = Manga.create("manga3"); | ||||
|  | ||||
|         List<Manga> favManga = createManga("manga1", "manga2", "manga3"); | ||||
|  | ||||
|         List<Chapter> chapters = createChapters("/chapter1", "/chapter2"); | ||||
|         List<Chapter> chapters3 = createChapters("/achapter1", "/achapter2"); | ||||
|  | ||||
|         when(service.db.getFavoriteMangas().executeAsBlocking()).thenReturn(favManga); | ||||
|  | ||||
|         // One of the updates will fail | ||||
|         when(source.pullChaptersFromNetwork("manga1")).thenReturn(Observable.just(chapters)); | ||||
|         when(source.pullChaptersFromNetwork("manga2")).thenReturn(Observable.error(new Exception())); | ||||
|         when(source.pullChaptersFromNetwork("manga3")).thenReturn(Observable.just(chapters3)); | ||||
|  | ||||
|         when(service.db.insertOrRemoveChapters(manga1, chapters)).thenReturn(Observable.just(Pair.create(2, 0))); | ||||
|         when(service.db.insertOrRemoveChapters(manga3, chapters)).thenReturn(Observable.just(Pair.create(2, 0))); | ||||
|  | ||||
|         service.updateLibrary().subscribe(); | ||||
|  | ||||
|         // There are 3 network attempts and 2 insertions (1 request failed) | ||||
|         verify(source, times(3)).pullChaptersFromNetwork(any()); | ||||
|         verify(service.db, times(2)).insertOrRemoveChapters(any(), any()); | ||||
|         verify(service.db, never()).insertOrRemoveChapters(eq(manga2), any()); | ||||
|     } | ||||
|  | ||||
|     private List<Chapter> createChapters(String... urls) { | ||||
|         List<Chapter> list = new ArrayList<>(); | ||||
|         for (String url : urls) { | ||||
|             Chapter c = Chapter.create(); | ||||
|             c.url = url; | ||||
|             list.add(c); | ||||
|         } | ||||
|         return list; | ||||
|     } | ||||
|  | ||||
|     private List<Manga> createManga(String... urls) { | ||||
|         List<Manga> list = new ArrayList<>(); | ||||
|         for (String url : urls) { | ||||
|             Manga m = Manga.create(url); | ||||
|             list.add(m); | ||||
|         } | ||||
|         return list; | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user