From e910c7a48efc16219cb8701cdf4c5ae09470dacc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Pich?= Date: Sat, 2 Mar 2019 19:15:37 +0100 Subject: [PATCH] Mitigate notifications from old grades (#258) Fixes #257 --- app/build.gradle | 1 + .../TestInternetObservingStrategy.kt | 19 +++ .../AttendanceLocalTest.kt | 3 +- .../CompletedLessonsLocalTest.kt | 3 +- .../{local => exam}/ExamLocalTest.kt | 3 +- .../repositories/grade/GradeEntityFactory.kt | 34 ++++++ .../data/repositories/grade/GradeLocalTest.kt | 49 ++++++++ .../repositories/grade/GradeRepositoryTest.kt | 115 ++++++++++++++++++ .../LuckyNumberLocalTest.kt | 3 +- .../RecipientLocalTest.kt | 3 +- .../{local => student}/StudentLocalTest.kt | 3 +- .../TimetableLocalTest.kt | 3 +- .../repositories/grade/GradeRepository.kt | 3 +- 13 files changed, 227 insertions(+), 15 deletions(-) create mode 100644 app/src/androidTest/java/io/github/wulkanowy/data/repositories/TestInternetObservingStrategy.kt rename app/src/androidTest/java/io/github/wulkanowy/data/repositories/{local => attendance}/AttendanceLocalTest.kt (93%) rename app/src/androidTest/java/io/github/wulkanowy/data/repositories/{local => completedlessons}/CompletedLessonsLocalTest.kt (93%) rename app/src/androidTest/java/io/github/wulkanowy/data/repositories/{local => exam}/ExamLocalTest.kt (93%) create mode 100644 app/src/androidTest/java/io/github/wulkanowy/data/repositories/grade/GradeEntityFactory.kt create mode 100644 app/src/androidTest/java/io/github/wulkanowy/data/repositories/grade/GradeLocalTest.kt create mode 100644 app/src/androidTest/java/io/github/wulkanowy/data/repositories/grade/GradeRepositoryTest.kt rename app/src/androidTest/java/io/github/wulkanowy/data/repositories/{local => luckynumber}/LuckyNumberLocalTest.kt (91%) rename app/src/androidTest/java/io/github/wulkanowy/data/repositories/{local => recipient}/RecipientLocalTest.kt (94%) rename app/src/androidTest/java/io/github/wulkanowy/data/repositories/{local => student}/StudentLocalTest.kt (93%) rename app/src/androidTest/java/io/github/wulkanowy/data/repositories/{local => timetable}/TimetableLocalTest.kt (93%) diff --git a/app/build.gradle b/app/build.gradle index 4cda75fa..66542f78 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -119,6 +119,7 @@ dependencies { testImplementation "org.mockito:mockito-inline:2.23.4" testImplementation 'org.threeten:threetenbp:1.3.8' + androidTestImplementation "io.mockk:mockk-android:1.9" androidTestImplementation 'androidx.test:core:1.1.0' androidTestImplementation 'androidx.test:runner:1.1.1' androidTestImplementation 'androidx.test.ext:junit:1.1.0' diff --git a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/TestInternetObservingStrategy.kt b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/TestInternetObservingStrategy.kt new file mode 100644 index 00000000..7dc93c4a --- /dev/null +++ b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/TestInternetObservingStrategy.kt @@ -0,0 +1,19 @@ +package io.github.wulkanowy.data.repositories + +import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingStrategy +import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.error.ErrorHandler +import io.reactivex.Observable +import io.reactivex.Single + +class TestInternetObservingStrategy : InternetObservingStrategy { + + override fun checkInternetConnectivity(host: String?, port: Int, timeoutInMs: Int, httpResponse: Int, errorHandler: ErrorHandler?): Single { + return Single.just(true) + } + + override fun observeInternetConnectivity(initialIntervalInMs: Int, intervalInMs: Int, host: String?, port: Int, timeoutInMs: Int, httpResponse: Int, errorHandler: ErrorHandler?): Observable { + return Observable.just(true) + } + + override fun getDefaultPingHost() = "localhost" +} diff --git a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/local/AttendanceLocalTest.kt b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/attendance/AttendanceLocalTest.kt similarity index 93% rename from app/src/androidTest/java/io/github/wulkanowy/data/repositories/local/AttendanceLocalTest.kt rename to app/src/androidTest/java/io/github/wulkanowy/data/repositories/attendance/AttendanceLocalTest.kt index 03a8c095..ee65cf84 100644 --- a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/local/AttendanceLocalTest.kt +++ b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/attendance/AttendanceLocalTest.kt @@ -1,4 +1,4 @@ -package io.github.wulkanowy.data.repositories.local +package io.github.wulkanowy.data.repositories.attendance import androidx.room.Room import androidx.test.core.app.ApplicationProvider @@ -6,7 +6,6 @@ import androidx.test.ext.junit.runners.AndroidJUnit4 import io.github.wulkanowy.data.db.AppDatabase import io.github.wulkanowy.data.db.entities.Attendance import io.github.wulkanowy.data.db.entities.Semester -import io.github.wulkanowy.data.repositories.attendance.AttendanceLocal import org.junit.After import org.junit.Before import org.junit.Test diff --git a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/local/CompletedLessonsLocalTest.kt b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/completedlessons/CompletedLessonsLocalTest.kt similarity index 93% rename from app/src/androidTest/java/io/github/wulkanowy/data/repositories/local/CompletedLessonsLocalTest.kt rename to app/src/androidTest/java/io/github/wulkanowy/data/repositories/completedlessons/CompletedLessonsLocalTest.kt index 62335b05..014f0b8b 100644 --- a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/local/CompletedLessonsLocalTest.kt +++ b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/completedlessons/CompletedLessonsLocalTest.kt @@ -1,4 +1,4 @@ -package io.github.wulkanowy.data.repositories.local +package io.github.wulkanowy.data.repositories.completedlessons import androidx.room.Room import androidx.test.core.app.ApplicationProvider @@ -6,7 +6,6 @@ import androidx.test.ext.junit.runners.AndroidJUnit4 import io.github.wulkanowy.data.db.AppDatabase import io.github.wulkanowy.data.db.entities.CompletedLesson import io.github.wulkanowy.data.db.entities.Semester -import io.github.wulkanowy.data.repositories.completedlessons.CompletedLessonsLocal import org.junit.After import org.junit.Before import org.junit.Test diff --git a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/local/ExamLocalTest.kt b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/exam/ExamLocalTest.kt similarity index 93% rename from app/src/androidTest/java/io/github/wulkanowy/data/repositories/local/ExamLocalTest.kt rename to app/src/androidTest/java/io/github/wulkanowy/data/repositories/exam/ExamLocalTest.kt index f383a41c..dc66fa42 100644 --- a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/local/ExamLocalTest.kt +++ b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/exam/ExamLocalTest.kt @@ -1,4 +1,4 @@ -package io.github.wulkanowy.data.repositories.local +package io.github.wulkanowy.data.repositories.exam import androidx.room.Room import androidx.test.core.app.ApplicationProvider @@ -6,7 +6,6 @@ import androidx.test.ext.junit.runners.AndroidJUnit4 import io.github.wulkanowy.data.db.AppDatabase import io.github.wulkanowy.data.db.entities.Exam import io.github.wulkanowy.data.db.entities.Semester -import io.github.wulkanowy.data.repositories.exam.ExamLocal import org.junit.After import org.junit.Before import org.junit.Test diff --git a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/grade/GradeEntityFactory.kt b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/grade/GradeEntityFactory.kt new file mode 100644 index 00000000..485e5692 --- /dev/null +++ b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/grade/GradeEntityFactory.kt @@ -0,0 +1,34 @@ +package io.github.wulkanowy.data.repositories.grade + +import io.github.wulkanowy.api.toDate +import org.threeten.bp.LocalDate +import io.github.wulkanowy.api.grades.Grade as GradeRemote +import io.github.wulkanowy.data.db.entities.Grade as GradeLocal + +fun createGradeLocal(value: Int, weight: Int, date: LocalDate, desc: String, semesterId: Int = 1): GradeLocal { + return GradeLocal( + semesterId = semesterId, + studentId = 1, + modifier = .0, + teacher = "", + subject = "", + date = date, + color = "", + comment = "", + description = desc, + entry = "", + gradeSymbol = "", + value = value, + weight = "", + weightValue = weight + ) +} + +fun createGradeApi(value: Int, weight: Int, date: LocalDate, desc: String): GradeRemote { + return GradeRemote().apply { + this.value = value + this.weightValue = weight + this.date = date.toDate() + this.description = desc + } +} diff --git a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/grade/GradeLocalTest.kt b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/grade/GradeLocalTest.kt new file mode 100644 index 00000000..2756723f --- /dev/null +++ b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/grade/GradeLocalTest.kt @@ -0,0 +1,49 @@ +package io.github.wulkanowy.data.repositories.grade + +import androidx.room.Room +import androidx.test.core.app.ApplicationProvider +import androidx.test.ext.junit.runners.AndroidJUnit4 +import io.github.wulkanowy.data.db.AppDatabase +import io.github.wulkanowy.data.db.entities.Semester +import org.junit.After +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.threeten.bp.LocalDate +import kotlin.test.assertEquals + +@RunWith(AndroidJUnit4::class) +class GradeLocalTest { + + private lateinit var gradeLocal: GradeLocal + + private lateinit var testDb: AppDatabase + + @Before + fun createDb() { + testDb = Room.inMemoryDatabaseBuilder(ApplicationProvider.getApplicationContext(), AppDatabase::class.java).build() + gradeLocal = GradeLocal(testDb.gradeDao) + } + + @After + fun closeDb() { + testDb.close() + } + + @Test + fun saveAndReadTest() { + gradeLocal.saveGrades(listOf( + createGradeLocal(5, 3, LocalDate.of(2018, 9, 10), "", 1), + createGradeLocal(4, 4, LocalDate.of(2019, 2, 27), "", 2), + createGradeLocal(3, 5, LocalDate.of(2019, 2, 28), "", 2) + )) + + val grades = gradeLocal + .getGrades(Semester(1, 2, "", 2, 3, true, 1, 1)) + .blockingGet() + + assertEquals(2, grades.size) + assertEquals(grades[0].date, LocalDate.of(2019, 2, 27)) + assertEquals(grades[1].date, LocalDate.of(2019, 2, 28)) + } +} diff --git a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/grade/GradeRepositoryTest.kt b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/grade/GradeRepositoryTest.kt new file mode 100644 index 00000000..6b419178 --- /dev/null +++ b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/grade/GradeRepositoryTest.kt @@ -0,0 +1,115 @@ +package io.github.wulkanowy.data.repositories.grade + +import android.os.Build.VERSION_CODES.P +import androidx.room.Room +import androidx.test.core.app.ApplicationProvider.getApplicationContext +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.SdkSuppress +import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings +import io.github.wulkanowy.api.Api +import io.github.wulkanowy.api.toDate +import io.github.wulkanowy.data.db.AppDatabase +import io.github.wulkanowy.data.db.entities.Grade +import io.github.wulkanowy.data.db.entities.Semester +import io.github.wulkanowy.data.db.entities.Student +import io.github.wulkanowy.data.repositories.TestInternetObservingStrategy +import io.mockk.MockKAnnotations +import io.mockk.every +import io.mockk.impl.annotations.MockK +import io.mockk.impl.annotations.SpyK +import io.reactivex.Single +import org.junit.After +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.threeten.bp.LocalDate +import org.threeten.bp.LocalDate.of +import org.threeten.bp.LocalDateTime +import kotlin.test.assertFalse +import kotlin.test.assertTrue +import io.github.wulkanowy.api.grades.Grade as GradeApi + +@SdkSuppress(minSdkVersion = P) +@RunWith(AndroidJUnit4::class) +class GradeRepositoryTest { + + @SpyK + private var mockApi = Api() + + private val settings = InternetObservingSettings.builder() + .strategy(TestInternetObservingStrategy()) + .build() + + @MockK + private lateinit var semesterMock: Semester + + @MockK + private lateinit var studentMock: Student + + private lateinit var gradeRemote: GradeRemote + + private lateinit var gradeLocal: GradeLocal + + private lateinit var testDb: AppDatabase + + @Before + fun initApi() { + MockKAnnotations.init(this) + testDb = Room.inMemoryDatabaseBuilder(getApplicationContext(), AppDatabase::class.java).build() + gradeLocal = GradeLocal(testDb.gradeDao) + gradeRemote = GradeRemote(mockApi) + + every { mockApi.diaryId } returns 1 + every { studentMock.registrationDate } returns LocalDateTime.of(2019, 2, 27, 12, 0) + every { semesterMock.studentId } returns 1 + every { semesterMock.semesterId } returns 1 + every { semesterMock.diaryId } returns 1 + } + + @After + fun closeDb() { + testDb.close() + } + + @Test + fun markOlderThanRegisterDateAsRead() { + every { mockApi.getGrades(1) } returns Single.just(listOf( + createGradeApi(5, 4, of(2019, 2, 25), "Ocena pojawiła się"), + createGradeApi(5, 4, of(2019, 2, 26), "przed zalogowanie w aplikacji"), + createGradeApi(5, 4, of(2019, 2, 27), "Ocena z dnia logowania"), + createGradeApi(5, 4, of(2019, 2, 28), "Ocena jeszcze nowsza") + )) + + val grades = GradeRepository(settings, gradeLocal, gradeRemote) + .getGrades(studentMock, semesterMock, true).blockingGet().sortedByDescending { it.date } + + assertFalse { grades[0].isRead } + assertFalse { grades[1].isRead } + assertTrue { grades[2].isRead } + assertTrue { grades[3].isRead } + } + + @Test + fun mitigateOldGradesNotifications() { + gradeLocal.saveGrades(listOf( + createGradeLocal(5, 3, of(2019, 2, 25), "Jedna ocena"), + createGradeLocal(4, 4, of(2019, 2, 26), "Druga"), + createGradeLocal(3, 5, of(2019, 2, 27), "Trzecia") + )) + + every { mockApi.getGrades(1) } returns Single.just(listOf( + createGradeApi(5, 2, of(2019, 2, 25), "Ocena ma datę, jest inna, ale nie zostanie powiadomiona"), + createGradeApi(4, 3, of(2019, 2, 26), "starszą niż ostatnia lokalnie"), + createGradeApi(3, 4, of(2019, 2, 27), "Ta jest z tego samego dnia co ostatnia lokalnie"), + createGradeApi(2, 5, of(2019, 2, 28), "Ta jest już w ogóle nowa") + )) + + val grades = GradeRepository(settings, gradeLocal, gradeRemote) + .getGrades(studentMock, semesterMock, true).blockingGet().sortedByDescending { it.date } + + assertFalse { grades[0].isRead } + assertFalse { grades[1].isRead } + assertTrue { grades[2].isRead } + assertTrue { grades[3].isRead } + } +} diff --git a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/local/LuckyNumberLocalTest.kt b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/luckynumber/LuckyNumberLocalTest.kt similarity index 91% rename from app/src/androidTest/java/io/github/wulkanowy/data/repositories/local/LuckyNumberLocalTest.kt rename to app/src/androidTest/java/io/github/wulkanowy/data/repositories/luckynumber/LuckyNumberLocalTest.kt index b4076bec..a656ac05 100644 --- a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/local/LuckyNumberLocalTest.kt +++ b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/luckynumber/LuckyNumberLocalTest.kt @@ -1,4 +1,4 @@ -package io.github.wulkanowy.data.repositories.local +package io.github.wulkanowy.data.repositories.luckynumber import androidx.room.Room import androidx.test.core.app.ApplicationProvider @@ -6,7 +6,6 @@ import androidx.test.ext.junit.runners.AndroidJUnit4 import io.github.wulkanowy.data.db.AppDatabase import io.github.wulkanowy.data.db.entities.LuckyNumber import io.github.wulkanowy.data.db.entities.Semester -import io.github.wulkanowy.data.repositories.luckynumber.LuckyNumberLocal import org.junit.After import org.junit.Before import org.junit.Test diff --git a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/local/RecipientLocalTest.kt b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/recipient/RecipientLocalTest.kt similarity index 94% rename from app/src/androidTest/java/io/github/wulkanowy/data/repositories/local/RecipientLocalTest.kt rename to app/src/androidTest/java/io/github/wulkanowy/data/repositories/recipient/RecipientLocalTest.kt index 4932d814..1f6562a2 100644 --- a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/local/RecipientLocalTest.kt +++ b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/recipient/RecipientLocalTest.kt @@ -1,4 +1,4 @@ -package io.github.wulkanowy.data.repositories.local +package io.github.wulkanowy.data.repositories.recipient import androidx.room.Room import androidx.test.core.app.ApplicationProvider @@ -7,7 +7,6 @@ import io.github.wulkanowy.data.db.AppDatabase import io.github.wulkanowy.data.db.entities.Recipient import io.github.wulkanowy.data.db.entities.ReportingUnit import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.data.repositories.recipient.RecipientLocal import org.junit.After import org.junit.Before import org.junit.Test diff --git a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/local/StudentLocalTest.kt b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/student/StudentLocalTest.kt similarity index 93% rename from app/src/androidTest/java/io/github/wulkanowy/data/repositories/local/StudentLocalTest.kt rename to app/src/androidTest/java/io/github/wulkanowy/data/repositories/student/StudentLocalTest.kt index 6152d0d7..c31bc806 100644 --- a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/local/StudentLocalTest.kt +++ b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/student/StudentLocalTest.kt @@ -1,4 +1,4 @@ -package io.github.wulkanowy.data.repositories.local +package io.github.wulkanowy.data.repositories.student import android.content.Context import androidx.room.Room @@ -7,7 +7,6 @@ import androidx.test.ext.junit.runners.AndroidJUnit4 import io.github.wulkanowy.data.db.AppDatabase import io.github.wulkanowy.data.db.SharedPrefHelper import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.data.repositories.student.StudentLocal import org.junit.After import org.junit.Before import org.junit.Test diff --git a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/local/TimetableLocalTest.kt b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/timetable/TimetableLocalTest.kt similarity index 93% rename from app/src/androidTest/java/io/github/wulkanowy/data/repositories/local/TimetableLocalTest.kt rename to app/src/androidTest/java/io/github/wulkanowy/data/repositories/timetable/TimetableLocalTest.kt index c90c7333..bc0615c6 100644 --- a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/local/TimetableLocalTest.kt +++ b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/timetable/TimetableLocalTest.kt @@ -1,4 +1,4 @@ -package io.github.wulkanowy.data.repositories.local +package io.github.wulkanowy.data.repositories.timetable import androidx.room.Room import androidx.test.core.app.ApplicationProvider @@ -6,7 +6,6 @@ import androidx.test.ext.junit.runners.AndroidJUnit4 import io.github.wulkanowy.data.db.AppDatabase import io.github.wulkanowy.data.db.entities.Semester import io.github.wulkanowy.data.db.entities.Timetable -import io.github.wulkanowy.data.repositories.timetable.TimetableLocal import org.junit.After import org.junit.Before import org.junit.Test diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/grade/GradeRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/grade/GradeRepository.kt index 8ff3a86f..f304ecee 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/grade/GradeRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/grade/GradeRepository.kt @@ -27,10 +27,11 @@ class GradeRepository @Inject constructor( }.flatMap { newGrades -> local.getGrades(semester).toSingle(emptyList()) .doOnSuccess { oldGrades -> + val notifyBreakDate = oldGrades.maxBy { it.date }?.date ?: student.registrationDate.toLocalDate() local.deleteGrades(oldGrades - newGrades) local.saveGrades((newGrades - oldGrades) .onEach { - if (student.registrationDate <= it.date.atStartOfDay()) { + if (it.date >= notifyBreakDate) { if (notify) it.isNotified = false it.isRead = false }