Compare commits
17 Commits
Author | SHA1 | Date | |
---|---|---|---|
da0943b319 | |||
67875b1a9a | |||
aa3d7e37fc | |||
345b580601 | |||
61240777cf | |||
7588345b6d | |||
2fa26c37a9 | |||
c34c63c128 | |||
a26dadb224 | |||
277ffd22be | |||
e03aae2d56 | |||
9c60ce688b | |||
fdce2cf477 | |||
650cbd5a10 | |||
b160367744 | |||
6c115fb915 | |||
7a408899df |
6
.github/workflows/test.yml
vendored
6
.github/workflows/test.yml
vendored
@ -2,10 +2,12 @@ name: Tests
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master, develop ]
|
||||
branches:
|
||||
- master
|
||||
- develop
|
||||
- 'hotfix/**'
|
||||
tags: [ '*' ]
|
||||
pull_request:
|
||||
branches: [ master, develop ]
|
||||
|
||||
jobs:
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
# Wulkanowy
|
||||
|
||||
[](https://github.com/wulkanowy/wulkanowy/actions)
|
||||
[](https://github.com/wulkanowy/wulkanowy/actions)
|
||||
[](https://codecov.io/gh/wulkanowy/wulkanowy)
|
||||
[](https://discord.gg/vccAQBr)
|
||||
[](https://f-droid.org/packages/io.github.wulkanowy/)
|
||||
@ -34,7 +34,7 @@ Neoficiální klient deníku VULCAN UONET+ pro žáka a rodiče
|
||||
* podpora více účtů s možností přejmenování žáků
|
||||
* tmavý a černý (AMOLED) motiv
|
||||
* offline režim
|
||||
* žádné reklamy
|
||||
* volitelné reklamy na podporu projektu
|
||||
|
||||
## Stáhnout
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
# Wulkanowy
|
||||
|
||||
[](https://github.com/wulkanowy/wulkanowy/actions)
|
||||
[](https://github.com/wulkanowy/wulkanowy/actions)
|
||||
[](https://codecov.io/gh/wulkanowy/wulkanowy)
|
||||
[](https://discord.gg/vccAQBr)
|
||||
[](https://f-droid.org/packages/io.github.wulkanowy/)
|
||||
@ -21,7 +21,7 @@ Inoffizieller Android VULCAN UONET+ Registrierungsclient für Schüler und ihre
|
||||
* Prozentsatz der Anwesenheit
|
||||
* Prüfungen
|
||||
* Stundenplan
|
||||
* Unterricht abgeschlossen
|
||||
* abgeschlossene Unterrichtsstunden
|
||||
* Nachrichten
|
||||
* Hausaufgaben
|
||||
* Anmerkungen
|
||||
@ -34,7 +34,7 @@ Inoffizieller Android VULCAN UONET+ Registrierungsclient für Schüler und ihre
|
||||
* Unterstützung für mehrere Konten mit der Möglichkeit, den Namen des Schülers zu ändern
|
||||
* dunkles und schwarzes (AMOLED) Thema
|
||||
* Offline-Modus
|
||||
* keine Werbung
|
||||
* optionale Werbungen, die es uns ermöglichen das Projekt zu unterstützen
|
||||
|
||||
## Herunterladen
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
# Wulkanowy
|
||||
|
||||
[](https://github.com/wulkanowy/wulkanowy/actions)
|
||||
[](https://github.com/wulkanowy/wulkanowy/actions)
|
||||
[](https://codecov.io/gh/wulkanowy/wulkanowy)
|
||||
[](https://discord.gg/vccAQBr)
|
||||
[](https://f-droid.org/packages/io.github.wulkanowy/)
|
||||
@ -34,7 +34,7 @@ Unofficial android VULCAN UONET+ register client for both students and their par
|
||||
* support for multiple accounts with the ability to rename students
|
||||
* dark and black (AMOLED) theme
|
||||
* offline mode
|
||||
* no ads
|
||||
* optional ads which allow to support the project
|
||||
|
||||
## Download
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
# Wulkanowy
|
||||
|
||||
[](https://github.com/wulkanowy/wulkanowy/actions)
|
||||
[](https://github.com/wulkanowy/wulkanowy/actions)
|
||||
[](https://codecov.io/gh/wulkanowy/wulkanowy)
|
||||
[](https://discord.gg/vccAQBr)
|
||||
[](https://f-droid.org/packages/io.github.wulkanowy/)
|
||||
@ -34,7 +34,7 @@ Nieoficjalny klient dziennika VULCAN UONET+ dla ucznia i rodzica
|
||||
* obsługa wielu kont wraz z możliwością zmiany nazwy ucznia
|
||||
* ciemny i czarny (AMOLED) motyw
|
||||
* tryb offline
|
||||
* brak reklam
|
||||
* opcjonalne reklamy umożliwiające wsparcie projektu
|
||||
|
||||
## Pobierz
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
# Wulkanowy
|
||||
|
||||
[](https://github.com/wulkanowy/wulkanowy/actions)
|
||||
[](https://github.com/wulkanowy/wulkanowy/actions)
|
||||
[](https://codecov.io/gh/wulkanowy/wulkanowy)
|
||||
[](https://discord.gg/vccAQBr)
|
||||
[](https://f-droid.org/packages/io.github.wulkanowy/)
|
||||
@ -34,7 +34,7 @@ Neoficiálny klient denníka VULCAN UONET+ pre žiaka a rodičov
|
||||
* podpora viacerých účtov s možnosťou premenovania žiakov
|
||||
* tmavý a čierny (AMOLED) motív
|
||||
* offline režim
|
||||
* žiadne reklamy
|
||||
* voliteľné reklamy na podporu projektu
|
||||
|
||||
## Stiahnuť
|
||||
|
||||
|
@ -23,8 +23,8 @@ android {
|
||||
testApplicationId "io.github.tests.wulkanowy"
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 32
|
||||
versionCode 115
|
||||
versionName "1.8.0"
|
||||
versionCode 118
|
||||
versionName "1.8.3"
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
|
||||
resValue "string", "app_name", "Wulkanowy"
|
||||
@ -161,8 +161,8 @@ play {
|
||||
defaultToAppBundles = false
|
||||
track = 'production'
|
||||
releaseStatus = com.github.triplet.gradle.androidpublisher.ReleaseStatus.IN_PROGRESS
|
||||
userFraction = 0.25d
|
||||
updatePriority = 4
|
||||
userFraction = 0.10d
|
||||
updatePriority = 5
|
||||
enabled.set(false)
|
||||
}
|
||||
|
||||
@ -186,7 +186,7 @@ ext {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation "io.github.wulkanowy:sdk:1.8.0"
|
||||
implementation "io.github.wulkanowy:sdk:1.8.3"
|
||||
|
||||
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.8'
|
||||
|
||||
|
2439
app/schemas/io.github.wulkanowy.data.db.AppDatabase/54.json
Normal file
2439
app/schemas/io.github.wulkanowy.data.db.AppDatabase/54.json
Normal file
File diff suppressed because it is too large
Load Diff
@ -49,8 +49,8 @@ fun <T, U> Resource<T>.mapData(block: (T) -> U) = when (this) {
|
||||
|
||||
fun <T> Flow<Resource<T>>.logResourceStatus(name: String, showData: Boolean = false) = onEach {
|
||||
val description = when (it) {
|
||||
is Resource.Loading -> "started"
|
||||
is Resource.Intermediate -> "intermediate data received" + if (showData) " (data: `${it.data}`)" else ""
|
||||
is Resource.Loading -> "started"
|
||||
is Resource.Success -> "success" + if (showData) " (data: `${it.data}`)" else ""
|
||||
is Resource.Error -> "exception occurred: ${it.error}"
|
||||
}
|
||||
|
@ -56,7 +56,7 @@ import javax.inject.Singleton
|
||||
abstract class AppDatabase : RoomDatabase() {
|
||||
|
||||
companion object {
|
||||
const val VERSION_SCHEMA = 53
|
||||
const val VERSION_SCHEMA = 54
|
||||
|
||||
fun getMigrations(sharedPrefProvider: SharedPrefProvider, appInfo: AppInfo) = arrayOf(
|
||||
Migration2(),
|
||||
@ -107,6 +107,7 @@ abstract class AppDatabase : RoomDatabase() {
|
||||
Migration50(),
|
||||
Migration51(),
|
||||
Migration53(),
|
||||
Migration54(),
|
||||
)
|
||||
|
||||
fun newInstance(
|
||||
|
@ -13,4 +13,7 @@ interface TimetableDao : BaseDao<Timetable> {
|
||||
|
||||
@Query("SELECT * FROM Timetable WHERE diary_id = :diaryId AND student_id = :studentId AND date >= :from AND date <= :end")
|
||||
fun loadAll(diaryId: Int, studentId: Int, from: LocalDate, end: LocalDate): Flow<List<Timetable>>
|
||||
|
||||
@Query("SELECT * FROM Timetable WHERE diary_id = :diaryId AND student_id = :studentId AND date >= :from AND date <= :end")
|
||||
fun load(diaryId: Int, studentId: Int, from: LocalDate, end: LocalDate): List<Timetable>
|
||||
}
|
||||
|
@ -0,0 +1,26 @@
|
||||
package io.github.wulkanowy.data.db.migrations
|
||||
|
||||
import androidx.room.migration.Migration
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
|
||||
class Migration54 : Migration(53, 54) {
|
||||
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
migrateResman(database)
|
||||
removeTomaszowMazowieckiStudents(database)
|
||||
}
|
||||
|
||||
private fun migrateResman(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("""
|
||||
UPDATE Students SET
|
||||
scrapper_base_url = 'https://vulcan.net.pl',
|
||||
login_type = 'ADFSLightScoped',
|
||||
symbol = 'rzeszowprojekt'
|
||||
WHERE scrapper_base_url = 'https://resman.pl'
|
||||
""".trimIndent())
|
||||
}
|
||||
|
||||
private fun removeTomaszowMazowieckiStudents(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("DELETE FROM Students WHERE symbol = 'tomaszowmazowiecki'")
|
||||
}
|
||||
}
|
@ -3,17 +3,22 @@ package io.github.wulkanowy.data.mappers
|
||||
import io.github.wulkanowy.data.db.entities.Attendance
|
||||
import io.github.wulkanowy.data.db.entities.AttendanceSummary
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import io.github.wulkanowy.data.db.entities.Timetable
|
||||
import io.github.wulkanowy.sdk.pojo.Attendance as SdkAttendance
|
||||
import io.github.wulkanowy.sdk.pojo.AttendanceSummary as SdkAttendanceSummary
|
||||
|
||||
fun List<SdkAttendance>.mapToEntities(semester: Semester) = map {
|
||||
fun List<SdkAttendance>.mapToEntities(semester: Semester, lessons: List<Timetable>) = map {
|
||||
Attendance(
|
||||
studentId = semester.studentId,
|
||||
diaryId = semester.diaryId,
|
||||
date = it.date,
|
||||
timeId = it.timeId,
|
||||
number = it.number,
|
||||
subject = it.subject,
|
||||
subject = it.subject.ifBlank {
|
||||
lessons.find { lesson ->
|
||||
lesson.date == it.date && lesson.number == it.number
|
||||
}?.subject.orEmpty()
|
||||
},
|
||||
name = it.name,
|
||||
presence = it.presence,
|
||||
absence = it.absence,
|
||||
|
@ -2,16 +2,26 @@ package io.github.wulkanowy.data.mappers
|
||||
|
||||
import io.github.wulkanowy.data.db.entities.*
|
||||
import io.github.wulkanowy.sdk.pojo.MailboxType
|
||||
import timber.log.Timber
|
||||
import io.github.wulkanowy.sdk.pojo.Message as SdkMessage
|
||||
import io.github.wulkanowy.sdk.pojo.MessageAttachment as SdkMessageAttachment
|
||||
import io.github.wulkanowy.sdk.pojo.Recipient as SdkRecipient
|
||||
|
||||
fun List<SdkMessage>.mapToEntities(student: Student, mailbox: Mailbox?, allMailboxes: List<Mailbox>) = map {
|
||||
fun List<SdkMessage>.mapToEntities(
|
||||
student: Student,
|
||||
mailbox: Mailbox?,
|
||||
allMailboxes: List<Mailbox>
|
||||
): List<Message> = map {
|
||||
Message(
|
||||
messageGlobalKey = it.globalKey,
|
||||
mailboxKey = mailbox?.globalKey ?: allMailboxes.find { box ->
|
||||
box.fullName == it.mailbox
|
||||
}?.globalKey!!,
|
||||
}?.globalKey.let { mailboxKey ->
|
||||
if (mailboxKey == null) {
|
||||
Timber.e("Can't find ${it.mailbox} in $allMailboxes")
|
||||
"unknown"
|
||||
} else mailboxKey
|
||||
},
|
||||
email = student.email,
|
||||
messageId = it.id,
|
||||
correspondents = it.correspondents,
|
||||
|
@ -1,6 +1,7 @@
|
||||
package io.github.wulkanowy.data.repositories
|
||||
|
||||
import io.github.wulkanowy.data.db.dao.AttendanceDao
|
||||
import io.github.wulkanowy.data.db.dao.TimetableDao
|
||||
import io.github.wulkanowy.data.db.entities.Attendance
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import io.github.wulkanowy.data.db.entities.Student
|
||||
@ -9,8 +10,10 @@ import io.github.wulkanowy.data.networkBoundResource
|
||||
import io.github.wulkanowy.sdk.Sdk
|
||||
import io.github.wulkanowy.sdk.pojo.Absent
|
||||
import io.github.wulkanowy.utils.*
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.time.LocalDate
|
||||
import java.time.LocalDateTime
|
||||
import java.time.LocalTime
|
||||
@ -20,6 +23,7 @@ import javax.inject.Singleton
|
||||
@Singleton
|
||||
class AttendanceRepository @Inject constructor(
|
||||
private val attendanceDb: AttendanceDao,
|
||||
private val timetableDb: TimetableDao,
|
||||
private val sdk: Sdk,
|
||||
private val refreshHelper: AutoRefreshHelper,
|
||||
) {
|
||||
@ -48,10 +52,15 @@ class AttendanceRepository @Inject constructor(
|
||||
attendanceDb.loadAll(semester.diaryId, semester.studentId, start.monday, end.sunday)
|
||||
},
|
||||
fetch = {
|
||||
val lessons = withContext(Dispatchers.IO) {
|
||||
timetableDb.load(
|
||||
semester.diaryId, semester.studentId, start.monday, end.sunday
|
||||
)
|
||||
}
|
||||
sdk.init(student)
|
||||
.switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear)
|
||||
.getAttendance(start.monday, end.sunday, semester.semesterId)
|
||||
.mapToEntities(semester)
|
||||
.mapToEntities(semester, lessons)
|
||||
},
|
||||
saveFetchResult = { old, new ->
|
||||
attendanceDb.deleteAll(old uniqueSubtract new)
|
||||
|
@ -3,7 +3,7 @@ package io.github.wulkanowy.data.repositories
|
||||
import android.content.Context
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import io.github.wulkanowy.R
|
||||
import io.github.wulkanowy.data.Resource
|
||||
import io.github.wulkanowy.data.*
|
||||
import io.github.wulkanowy.data.db.SharedPrefProvider
|
||||
import io.github.wulkanowy.data.db.dao.MailboxDao
|
||||
import io.github.wulkanowy.data.db.dao.MessageAttachmentDao
|
||||
@ -14,9 +14,7 @@ import io.github.wulkanowy.data.enums.MessageFolder.RECEIVED
|
||||
import io.github.wulkanowy.data.enums.MessageFolder.TRASHED
|
||||
import io.github.wulkanowy.data.mappers.mapFromEntities
|
||||
import io.github.wulkanowy.data.mappers.mapToEntities
|
||||
import io.github.wulkanowy.data.networkBoundResource
|
||||
import io.github.wulkanowy.data.pojos.MessageDraft
|
||||
import io.github.wulkanowy.data.toFirstResult
|
||||
import io.github.wulkanowy.domain.messages.GetMailboxByStudentUseCase
|
||||
import io.github.wulkanowy.sdk.Sdk
|
||||
import io.github.wulkanowy.sdk.pojo.Folder
|
||||
@ -194,7 +192,9 @@ class MessageRepository @Inject constructor(
|
||||
it.isEmpty() || isExpired || forceRefresh
|
||||
},
|
||||
query = { mailboxDao.loadAll(student.email, student.symbol, student.schoolSymbol) },
|
||||
fetch = { sdk.init(student).getMailboxes().mapToEntities(student) },
|
||||
fetch = {
|
||||
sdk.init(student).getMailboxes().mapToEntities(student)
|
||||
},
|
||||
saveFetchResult = { old, new ->
|
||||
mailboxDao.deleteAll(old uniqueSubtract new)
|
||||
mailboxDao.insertAll(new uniqueSubtract old)
|
||||
@ -207,7 +207,11 @@ class MessageRepository @Inject constructor(
|
||||
val mailbox = getMailboxByStudentUseCase(student)
|
||||
|
||||
return if (mailbox == null) {
|
||||
getMailboxes(student, forceRefresh = true).toFirstResult()
|
||||
getMailboxes(student, forceRefresh = true)
|
||||
.onResourceError { throw it }
|
||||
.onResourceSuccess { Timber.i("Found ${it.size} new mailboxes") }
|
||||
.waitForResult()
|
||||
|
||||
getMailboxByStudentUseCase(student)
|
||||
} else mailbox
|
||||
}
|
||||
|
@ -17,10 +17,15 @@ class GetMailboxByStudentUseCase @Inject constructor(
|
||||
private fun List<Mailbox>.filterByStudent(student: Student): Mailbox? {
|
||||
val normalizedStudentName = student.studentName.normalizeStudentName()
|
||||
|
||||
return find {
|
||||
return singleOrNull {
|
||||
it.studentName.normalizeStudentName() == normalizedStudentName
|
||||
} ?: singleOrNull {
|
||||
it.studentName.normalizeStudentName() == normalizedStudentName
|
||||
&& it.schoolNameShort == student.schoolShortName
|
||||
} ?: singleOrNull {
|
||||
it.studentName.getFirstAndLastPart() == normalizedStudentName.getFirstAndLastPart()
|
||||
} ?: singleOrNull {
|
||||
it.studentName.getReversedName() == normalizedStudentName
|
||||
} ?: singleOrNull {
|
||||
it.studentName.getUnauthorizedVersion() == normalizedStudentName
|
||||
}
|
||||
@ -43,6 +48,14 @@ class GetMailboxByStudentUseCase @Inject constructor(
|
||||
return endParts.joinToString(" ")
|
||||
}
|
||||
|
||||
private fun String.getReversedName(): String {
|
||||
val parts = normalizeStudentName().split(" ")
|
||||
|
||||
return parts
|
||||
.asReversed()
|
||||
.joinToString(" ")
|
||||
}
|
||||
|
||||
private fun String.getUnauthorizedVersion(): String {
|
||||
return normalizeStudentName().split(" ")
|
||||
.joinToString(" ") {
|
||||
|
@ -33,18 +33,27 @@ sealed class DashboardItem(val type: Type) {
|
||||
}
|
||||
|
||||
data class HorizontalGroup(
|
||||
val unreadMessagesCount: Int? = null,
|
||||
val attendancePercentage: Double? = null,
|
||||
val luckyNumber: Int? = null,
|
||||
val unreadMessagesCount: Cell<Int?>? = null,
|
||||
val attendancePercentage: Cell<Double>? = null,
|
||||
val luckyNumber: Cell<Int>? = null,
|
||||
override val error: Throwable? = null,
|
||||
override val isLoading: Boolean = false
|
||||
) : DashboardItem(Type.HORIZONTAL_GROUP) {
|
||||
|
||||
data class Cell<T>(
|
||||
val data: T?,
|
||||
val error: Boolean,
|
||||
val isLoading: Boolean,
|
||||
) {
|
||||
val isHidden: Boolean
|
||||
get() = data == null && !error && !isLoading
|
||||
}
|
||||
|
||||
override val isDataLoaded
|
||||
get() = unreadMessagesCount != null || attendancePercentage != null || luckyNumber != null
|
||||
get() = unreadMessagesCount?.isLoading == false || attendancePercentage?.isLoading == false || luckyNumber?.isLoading == false
|
||||
|
||||
val isFullDataLoaded
|
||||
get() = luckyNumber != -1 && attendancePercentage != -1.0 && unreadMessagesCount != -1
|
||||
get() = luckyNumber?.isLoading != true && attendancePercentage?.isLoading != true && unreadMessagesCount?.isLoading != true
|
||||
}
|
||||
|
||||
data class Grades(
|
||||
|
@ -226,50 +226,71 @@ class DashboardPresenter @Inject constructor(
|
||||
|
||||
private fun loadHorizontalGroup(student: Student, forceRefresh: Boolean) {
|
||||
flow {
|
||||
val semester = semesterRepository.getCurrentSemester(student)
|
||||
val mailbox = messageRepository.getMailboxByStudent(student)
|
||||
val selectedTiles = preferencesRepository.selectedDashboardTiles
|
||||
|
||||
val flowSuccess = flowOf(Resource.Success(null))
|
||||
|
||||
val luckyNumberFlow = luckyNumberRepository.getLuckyNumber(student, forceRefresh)
|
||||
.mapResourceData {
|
||||
it ?: LuckyNumber(0, LocalDate.now(), 0)
|
||||
}
|
||||
.onResourceError { errorHandler.dispatch(it) }
|
||||
.takeIf { DashboardItem.Tile.LUCKY_NUMBER in selectedTiles } ?: flowSuccess
|
||||
|
||||
val messageFLow = messageRepository.getMessages(
|
||||
student = student,
|
||||
mailbox = mailbox,
|
||||
folder = MessageFolder.RECEIVED,
|
||||
forceRefresh = forceRefresh
|
||||
).takeIf { DashboardItem.Tile.MESSAGES in selectedTiles } ?: flowSuccess
|
||||
val messageFLow = flatResourceFlow {
|
||||
val mailbox = messageRepository.getMailboxByStudent(student)
|
||||
|
||||
val attendanceFlow = attendanceSummaryRepository.getAttendanceSummary(
|
||||
student = student,
|
||||
semester = semester,
|
||||
subjectId = -1,
|
||||
forceRefresh = forceRefresh
|
||||
).takeIf { DashboardItem.Tile.ATTENDANCE in selectedTiles } ?: flowSuccess
|
||||
messageRepository.getMessages(
|
||||
student = student,
|
||||
mailbox = mailbox,
|
||||
folder = MessageFolder.RECEIVED,
|
||||
forceRefresh = forceRefresh
|
||||
)
|
||||
}
|
||||
.onResourceError { errorHandler.dispatch(it) }
|
||||
.takeIf { DashboardItem.Tile.MESSAGES in selectedTiles } ?: flowSuccess
|
||||
|
||||
val attendanceFlow = flatResourceFlow {
|
||||
val semester = semesterRepository.getCurrentSemester(student)
|
||||
attendanceSummaryRepository.getAttendanceSummary(
|
||||
student = student,
|
||||
semester = semester,
|
||||
subjectId = -1,
|
||||
forceRefresh = forceRefresh
|
||||
)
|
||||
}
|
||||
.onResourceError { errorHandler.dispatch(it) }
|
||||
.takeIf { DashboardItem.Tile.ATTENDANCE in selectedTiles } ?: flowSuccess
|
||||
|
||||
emitAll(
|
||||
combine(
|
||||
luckyNumberFlow,
|
||||
messageFLow,
|
||||
attendanceFlow
|
||||
flow = luckyNumberFlow,
|
||||
flow2 = messageFLow,
|
||||
flow3 = attendanceFlow,
|
||||
) { luckyNumberResource, messageResource, attendanceResource ->
|
||||
val resList = listOf(luckyNumberResource, messageResource, attendanceResource)
|
||||
resList.firstNotNullOfOrNull { it.errorOrNull }?.let { throw it }
|
||||
val isLoading = resList.any { it is Resource.Loading }
|
||||
|
||||
val luckyNumber = luckyNumberResource.dataOrNull?.luckyNumber
|
||||
val messageCount = messageResource.dataOrNull?.count { it.unread }
|
||||
val attendancePercentage = attendanceResource.dataOrNull?.calculatePercentage()
|
||||
|
||||
DashboardItem.HorizontalGroup(
|
||||
isLoading = isLoading,
|
||||
attendancePercentage = if (attendancePercentage == 0.0 && isLoading) -1.0 else attendancePercentage,
|
||||
unreadMessagesCount = if (messageCount == 0 && isLoading) -1 else messageCount,
|
||||
luckyNumber = if (luckyNumber == 0 && isLoading) -1 else luckyNumber
|
||||
isLoading = resList.any { it is Resource.Loading },
|
||||
error = resList.map { it.errorOrNull }.let { errors ->
|
||||
if (errors.all { it != null }) {
|
||||
errors.firstOrNull()
|
||||
} else null
|
||||
},
|
||||
attendancePercentage = DashboardItem.HorizontalGroup.Cell(
|
||||
data = attendanceResource.dataOrNull?.calculatePercentage(),
|
||||
error = attendanceResource.errorOrNull != null,
|
||||
isLoading = attendanceResource is Resource.Loading,
|
||||
),
|
||||
unreadMessagesCount = DashboardItem.HorizontalGroup.Cell(
|
||||
data = messageResource.dataOrNull?.count { it.unread },
|
||||
error = messageResource.errorOrNull != null,
|
||||
isLoading = messageResource is Resource.Loading,
|
||||
),
|
||||
luckyNumber = DashboardItem.HorizontalGroup.Cell(
|
||||
data = luckyNumberResource.dataOrNull?.luckyNumber,
|
||||
error = luckyNumberResource.errorOrNull != null,
|
||||
isLoading = luckyNumberResource is Resource.Loading,
|
||||
)
|
||||
)
|
||||
})
|
||||
}
|
||||
@ -280,11 +301,8 @@ class DashboardPresenter @Inject constructor(
|
||||
|
||||
if (it.isLoading) {
|
||||
Timber.i("Loading horizontal group data started")
|
||||
|
||||
if (it.isFullDataLoaded) {
|
||||
firstLoadedItemList += DashboardItem.Type.HORIZONTAL_GROUP
|
||||
}
|
||||
} else {
|
||||
firstLoadedItemList += DashboardItem.Type.HORIZONTAL_GROUP
|
||||
Timber.i("Loading horizontal group result: Success")
|
||||
}
|
||||
}
|
||||
|
@ -171,81 +171,105 @@ class DashboardAdapter @Inject constructor() : RecyclerView.Adapter<RecyclerView
|
||||
position: Int
|
||||
) {
|
||||
val item = items[position] as DashboardItem.HorizontalGroup
|
||||
val unreadMessagesCount = item.unreadMessagesCount
|
||||
val attendancePercentage = item.attendancePercentage
|
||||
val luckyNumber = item.luckyNumber
|
||||
val error = item.error
|
||||
val isLoading = item.isLoading
|
||||
val binding = horizontalGroupViewHolder.binding
|
||||
val context = binding.root.context
|
||||
val isLoadingVisible =
|
||||
(isLoading && !item.isDataLoaded) || (isLoading && !item.isFullDataLoaded)
|
||||
(item.isLoading && !item.isDataLoaded) || (item.isLoading && !item.isFullDataLoaded)
|
||||
val isWideErrorShow = isLoadingVisible || item.error != null
|
||||
|
||||
with(horizontalGroupViewHolder.binding) {
|
||||
dashboardHorizontalGroupItemInfoContainer.isVisible = isWideErrorShow
|
||||
dashboardHorizontalGroupItemInfoProgress.isVisible = isLoadingVisible
|
||||
dashboardHorizontalGroupItemInfoErrorText.isVisible = item.error != null
|
||||
|
||||
bindLuckyNumber(item, isWideErrorShow)
|
||||
bindMessages(item, isWideErrorShow)
|
||||
bindAttendance(item, isWideErrorShow)
|
||||
}
|
||||
}
|
||||
|
||||
private fun ItemDashboardHorizontalGroupBinding.bindLuckyNumber(
|
||||
item: DashboardItem.HorizontalGroup,
|
||||
isWideErrorShow: Boolean
|
||||
) {
|
||||
with(dashboardHorizontalGroupItemLuckyValue) {
|
||||
isVisible = item.luckyNumber?.error != true
|
||||
text = if (item.luckyNumber?.data == 0) {
|
||||
context.getString(R.string.dashboard_horizontal_group_no_data)
|
||||
} else item.luckyNumber?.data?.toString()
|
||||
}
|
||||
dashboardHorizontalGroupItemLuckyError.isVisible = item.luckyNumber?.error == true
|
||||
with(dashboardHorizontalGroupItemLuckyContainer) {
|
||||
isVisible = item.luckyNumber?.isHidden == false && !isWideErrorShow
|
||||
setOnClickListener { onLuckyNumberTileClickListener() }
|
||||
|
||||
val isAttendanceHidden = item.attendancePercentage?.isHidden == true
|
||||
val isMessagesHidden = item.unreadMessagesCount?.isHidden == true
|
||||
val isLuckyNumberHidden = item.luckyNumber?.isHidden == true
|
||||
|
||||
updateLayoutParams<ViewGroup.MarginLayoutParams> {
|
||||
updateMarginsRelative(
|
||||
end = if (isAttendanceHidden && isMessagesHidden && !isLuckyNumberHidden) {
|
||||
0
|
||||
} else context.dpToPx(8f).toInt()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun ItemDashboardHorizontalGroupBinding.bindMessages(
|
||||
item: DashboardItem.HorizontalGroup,
|
||||
isWideErrorShow: Boolean
|
||||
) {
|
||||
dashboardHorizontalGroupItemMessageError.isVisible = item.unreadMessagesCount?.error == true
|
||||
with(dashboardHorizontalGroupItemMessageValue) {
|
||||
isVisible = item.unreadMessagesCount?.error != true
|
||||
text = item.unreadMessagesCount?.data.toString()
|
||||
}
|
||||
with(dashboardHorizontalGroupItemMessageContainer) {
|
||||
isVisible = item.unreadMessagesCount?.isHidden == false && !isWideErrorShow
|
||||
setOnClickListener { onMessageTileClickListener() }
|
||||
}
|
||||
}
|
||||
|
||||
private fun ItemDashboardHorizontalGroupBinding.bindAttendance(
|
||||
item: DashboardItem.HorizontalGroup,
|
||||
isWideErrorShow: Boolean
|
||||
) {
|
||||
val attendancePercentage = item.attendancePercentage?.data
|
||||
val attendanceColor = when {
|
||||
attendancePercentage == null || attendancePercentage == .0 -> {
|
||||
context.getThemeAttrColor(R.attr.colorOnSurface)
|
||||
root.context.getThemeAttrColor(R.attr.colorOnSurface)
|
||||
}
|
||||
attendancePercentage <= ATTENDANCE_SECOND_WARNING_THRESHOLD -> {
|
||||
context.getThemeAttrColor(R.attr.colorPrimary)
|
||||
root.context.getThemeAttrColor(R.attr.colorPrimary)
|
||||
}
|
||||
attendancePercentage <= ATTENDANCE_FIRST_WARNING_THRESHOLD -> {
|
||||
context.getThemeAttrColor(R.attr.colorTimetableChange)
|
||||
root.context.getThemeAttrColor(R.attr.colorTimetableChange)
|
||||
}
|
||||
else -> context.getThemeAttrColor(R.attr.colorOnSurface)
|
||||
else -> root.context.getThemeAttrColor(R.attr.colorOnSurface)
|
||||
}
|
||||
val attendanceString = if (attendancePercentage == null || attendancePercentage == .0) {
|
||||
context.getString(R.string.dashboard_horizontal_group_no_data)
|
||||
root.context.getString(R.string.dashboard_horizontal_group_no_data)
|
||||
} else {
|
||||
"%.2f%%".format(attendancePercentage)
|
||||
}
|
||||
|
||||
with(binding.dashboardHorizontalGroupItemAttendanceValue) {
|
||||
dashboardHorizontalGroupItemAttendanceError.isVisible =
|
||||
item.attendancePercentage?.error == true
|
||||
with(dashboardHorizontalGroupItemAttendanceValue) {
|
||||
isVisible = item.attendancePercentage?.error != true
|
||||
text = attendanceString
|
||||
setTextColor(attendanceColor)
|
||||
}
|
||||
|
||||
with(binding) {
|
||||
dashboardHorizontalGroupItemMessageValue.text = unreadMessagesCount.toString()
|
||||
dashboardHorizontalGroupItemLuckyValue.text = if (luckyNumber == 0) {
|
||||
context.getString(R.string.dashboard_horizontal_group_no_data)
|
||||
} else luckyNumber?.toString()
|
||||
|
||||
dashboardHorizontalGroupItemInfoContainer.isVisible = error != null || isLoadingVisible
|
||||
dashboardHorizontalGroupItemInfoProgress.isVisible = isLoadingVisible
|
||||
dashboardHorizontalGroupItemInfoErrorText.isVisible = error != null
|
||||
|
||||
with(dashboardHorizontalGroupItemLuckyContainer) {
|
||||
isVisible = luckyNumber != null && luckyNumber != -1 && !isLoadingVisible
|
||||
setOnClickListener { onLuckyNumberTileClickListener() }
|
||||
|
||||
updateLayoutParams<ViewGroup.MarginLayoutParams> {
|
||||
updateMarginsRelative(
|
||||
end = if (attendancePercentage == null && unreadMessagesCount == null && luckyNumber != null) {
|
||||
0
|
||||
} else {
|
||||
context.dpToPx(8f).toInt()
|
||||
}
|
||||
)
|
||||
with(dashboardHorizontalGroupItemAttendanceContainer) {
|
||||
isVisible = item.attendancePercentage?.isHidden == false && !isWideErrorShow
|
||||
setOnClickListener { onAttendanceTileClickListener() }
|
||||
updateLayoutParams<ConstraintLayout.LayoutParams> {
|
||||
matchConstraintPercentWidth = when {
|
||||
item.luckyNumber?.isHidden == true && item.unreadMessagesCount?.isHidden == true -> 1.0f
|
||||
item.luckyNumber?.isHidden == true || item.unreadMessagesCount?.isHidden == true -> 0.5f
|
||||
else -> 0.4f
|
||||
}
|
||||
}
|
||||
|
||||
with(dashboardHorizontalGroupItemAttendanceContainer) {
|
||||
isVisible =
|
||||
attendancePercentage != null && attendancePercentage != -1.0 && !isLoadingVisible
|
||||
updateLayoutParams<ConstraintLayout.LayoutParams> {
|
||||
matchConstraintPercentWidth = when {
|
||||
luckyNumber == null && unreadMessagesCount == null -> 1.0f
|
||||
luckyNumber == null || unreadMessagesCount == null -> 0.5f
|
||||
else -> 0.4f
|
||||
}
|
||||
}
|
||||
setOnClickListener { onAttendanceTileClickListener() }
|
||||
}
|
||||
|
||||
with(dashboardHorizontalGroupItemMessageContainer) {
|
||||
isVisible =
|
||||
unreadMessagesCount != null && unreadMessagesCount != -1 && !isLoadingVisible
|
||||
setOnClickListener { onMessageTileClickListener() }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -55,7 +55,7 @@ class SendMessagePresenter @Inject constructor(
|
||||
view.showMessageBackupDialog()
|
||||
}
|
||||
reason?.let {
|
||||
setSubject("Usprawiedliwenie")
|
||||
setSubject("Usprawiedliwienie")
|
||||
setContent(it)
|
||||
}
|
||||
message?.let {
|
||||
|
@ -2,9 +2,11 @@ package io.github.wulkanowy.utils
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.content.res.ColorStateList
|
||||
import android.graphics.*
|
||||
import android.text.TextPaint
|
||||
import android.util.DisplayMetrics.DENSITY_DEFAULT
|
||||
import android.widget.ImageView
|
||||
import androidx.annotation.*
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.graphics.ColorUtils
|
||||
@ -12,6 +14,7 @@ import androidx.core.graphics.applyCanvas
|
||||
import androidx.core.graphics.drawable.RoundedBitmapDrawable
|
||||
import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory
|
||||
import androidx.core.graphics.drawable.toBitmap
|
||||
import androidx.core.widget.ImageViewCompat
|
||||
|
||||
|
||||
@ColorInt
|
||||
@ -85,3 +88,7 @@ fun Context.createNameInitialsDrawable(
|
||||
return RoundedBitmapDrawableFactory.create(this.resources, bitmap)
|
||||
.apply { isCircular = true }
|
||||
}
|
||||
|
||||
fun ImageView.setTint(@ColorInt color: Int) {
|
||||
ImageViewCompat.setImageTintList(this, ColorStateList.valueOf(color))
|
||||
}
|
||||
|
@ -1,9 +1,8 @@
|
||||
Wersja 1.8.0
|
||||
Wersja 1.8.3
|
||||
|
||||
- naprawiliśmy liczenie średniej ucznia w ocenach klasy dla wykresu "Wszystkie"
|
||||
- zmieniliśmy kolejność przycisków akcji w podglądzie wiadomości
|
||||
- ulepszyliśmy oznaczenie nieodczytanych wiadomości
|
||||
- naprawiliśmy pokazywanie informacji o odczytanej wiadomości w wysłanych
|
||||
- dodaliśmy opcję ręcznego wybierania skrzynki pocztowej
|
||||
- naprawiliśmy logowanie dla użytkowników systemu Resman Rzeszów
|
||||
- dodaliśmy wsparcie dla nowej platformy z Tomaszowa Mazowieckiego
|
||||
- poprawiliśmy dopasowywanie skrzynek pocztowych do uczniów
|
||||
- naprawiliśmy literówkę w tytule wiadomości z szablonem usprawiedliwienia
|
||||
|
||||
Pełna lista zmian: https://github.com/wulkanowy/wulkanowy/releases
|
||||
|
9
app/src/main/res/drawable/ic_error_filled.xml
Normal file
9
app/src/main/res/drawable/ic_error_filled.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM13,17h-2v-2h2v2zM13,13h-2L11,7h2v6z"
|
||||
android:fillColor="#000000"/>
|
||||
</vector>
|
@ -37,9 +37,25 @@
|
||||
app:layout_constraintHorizontal_chainStyle="packed"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_goneMarginEnd="16dp"
|
||||
app:tint="?colorOnSurface"
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/dashboard_horizontal_group_item_lucky_error"
|
||||
android:layout_width="18dp"
|
||||
android:layout_height="18dp"
|
||||
android:layout_marginEnd="-4dp"
|
||||
android:layout_marginBottom="-4dp"
|
||||
android:background="@drawable/ic_circle"
|
||||
android:backgroundTint="?attr/colorSurface"
|
||||
android:contentDescription="@string/error_unknown"
|
||||
android:src="@drawable/ic_error_filled"
|
||||
app:layout_constraintBottom_toBottomOf="@id/dashboard_horizontal_group_item_lucky_icon"
|
||||
app:layout_constraintEnd_toEndOf="@id/dashboard_horizontal_group_item_lucky_icon"
|
||||
app:tint="?colorError"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/dashboard_horizontal_group_item_lucky_value"
|
||||
android:layout_width="wrap_content"
|
||||
@ -89,9 +105,25 @@
|
||||
app:layout_constraintHorizontal_chainStyle="packed"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_goneMarginEnd="16dp"
|
||||
app:tint="?colorOnSurface"
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/dashboard_horizontal_group_item_message_error"
|
||||
android:layout_width="18dp"
|
||||
android:layout_height="18dp"
|
||||
android:layout_marginEnd="-4dp"
|
||||
android:layout_marginBottom="-4dp"
|
||||
android:background="@drawable/ic_circle"
|
||||
android:backgroundTint="?attr/colorSurface"
|
||||
android:contentDescription="@string/error_unknown"
|
||||
android:src="@drawable/ic_error_filled"
|
||||
app:layout_constraintBottom_toBottomOf="@id/dashboard_horizontal_group_item_message_icon"
|
||||
app:layout_constraintEnd_toEndOf="@id/dashboard_horizontal_group_item_message_icon"
|
||||
app:tint="?colorError"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/dashboard_horizontal_group_item_message_value"
|
||||
android:layout_width="wrap_content"
|
||||
@ -106,7 +138,8 @@
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/dashboard_horizontal_group_item_message_icon"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="16" />
|
||||
tools:text="16"
|
||||
tools:visibility="visible" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
@ -145,9 +178,25 @@
|
||||
app:layout_constraintHorizontal_chainStyle="packed"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_goneMarginEnd="16dp"
|
||||
app:tint="?colorOnSurface"
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/dashboard_horizontal_group_item_attendance_error"
|
||||
android:layout_width="18dp"
|
||||
android:layout_height="18dp"
|
||||
android:layout_marginEnd="-4dp"
|
||||
android:layout_marginBottom="-4dp"
|
||||
android:background="@drawable/ic_circle"
|
||||
android:backgroundTint="?attr/colorSurface"
|
||||
android:contentDescription="@string/error_unknown"
|
||||
android:src="@drawable/ic_error_filled"
|
||||
app:layout_constraintBottom_toBottomOf="@id/dashboard_horizontal_group_item_attendance_icon"
|
||||
app:layout_constraintEnd_toEndOf="@id/dashboard_horizontal_group_item_attendance_icon"
|
||||
app:tint="?colorError"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/dashboard_horizontal_group_item_attendance_value"
|
||||
android:layout_width="wrap_content"
|
||||
@ -211,4 +260,4 @@
|
||||
android:indeterminate="true"
|
||||
app:indicatorSize="28dp" />
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
@ -6,8 +6,9 @@
|
||||
<item>Gdańska Platforma Edukacyjna</item>
|
||||
<item>Lubelski Portal Oświatowy</item>
|
||||
<item>EduNet Miasta Tarnowa</item>
|
||||
<item>ResMan Rzeszów</item>
|
||||
<item>Platforma Edukacyjna Koszalina</item>
|
||||
<item>Gmina-miasto Tomaszów Mazowiecki - System zarządzania oświatą</item>
|
||||
<item>ResMan Rzeszów</item>
|
||||
<item>Rawa Mazowiecka - Platforma vEdukacja</item>
|
||||
<item>Zduńska Wola - e-Urząd</item>
|
||||
<item>Sieradz - Portal oświatowy</item>
|
||||
@ -27,7 +28,6 @@
|
||||
<item>https://edu.gdansk.pl</item>
|
||||
<item>https://edu.lublin.eu</item>
|
||||
<item>https://umt.tarnow.pl</item>
|
||||
<item>https://resman.pl</item>
|
||||
<item>https://eduportal.koszalin.pl</item>
|
||||
<item>https://vulcan.net.pl/?login</item>
|
||||
<item>https://vulcan.net.pl/?login</item>
|
||||
@ -40,6 +40,8 @@
|
||||
<item>https://vulcan.net.pl/?login</item>
|
||||
<item>https://vulcan.net.pl/?login</item>
|
||||
<item>https://vulcan.net.pl/?login</item>
|
||||
<item>https://vulcan.net.pl/?login</item>
|
||||
<item>https://vulcan.net.pl/?login</item>
|
||||
<item>http://fakelog.cf/?email</item>
|
||||
</string-array>
|
||||
<string-array name="hosts_symbols">
|
||||
@ -48,8 +50,9 @@
|
||||
<item>gdansk</item>
|
||||
<item>lublin</item>
|
||||
<item>tarnow</item>
|
||||
<item>rzeszow</item>
|
||||
<item>koszalin</item>
|
||||
<item>tomaszowmazowieckiprojekt</item>
|
||||
<item>rzeszowprojekt</item>
|
||||
<item>rawamazowiecka</item>
|
||||
<item>zdunskawola</item>
|
||||
<item>sieradz</item>
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -3,6 +3,7 @@ package io.github.wulkanowy.data.db.migrations
|
||||
import android.content.Context
|
||||
import androidx.preference.PreferenceManager
|
||||
import androidx.room.Room
|
||||
import androidx.room.migration.Migration
|
||||
import androidx.room.testing.MigrationTestHelper
|
||||
import androidx.sqlite.db.framework.FrameworkSQLiteOpenHelperFactory
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
@ -16,7 +17,7 @@ abstract class AbstractMigrationTest {
|
||||
|
||||
val dbName = "migration-test"
|
||||
|
||||
val context: Context get() = ApplicationProvider.getApplicationContext()
|
||||
private val context: Context get() = ApplicationProvider.getApplicationContext()
|
||||
|
||||
@get:Rule
|
||||
val helper: MigrationTestHelper = MigrationTestHelper(
|
||||
@ -25,6 +26,10 @@ abstract class AbstractMigrationTest {
|
||||
FrameworkSQLiteOpenHelperFactory()
|
||||
)
|
||||
|
||||
fun runMigrationsAndValidate(migration: Migration) {
|
||||
helper.runMigrationsAndValidate(dbName, migration.endVersion, true, migration).close()
|
||||
}
|
||||
|
||||
fun getMigratedRoomDatabase(): AppDatabase {
|
||||
val database = Room.databaseBuilder(
|
||||
ApplicationProvider.getApplicationContext(),
|
||||
|
@ -33,7 +33,7 @@ class Migration12Test : AbstractMigrationTest() {
|
||||
close()
|
||||
}
|
||||
|
||||
helper.runMigrationsAndValidate(dbName, 12, true, Migration12())
|
||||
runMigrationsAndValidate(Migration12())
|
||||
|
||||
val db = getMigratedRoomDatabase()
|
||||
val students = runBlocking { db.studentDao.loadAll() }
|
||||
@ -49,6 +49,7 @@ class Migration12Test : AbstractMigrationTest() {
|
||||
assertEquals(2, studentId)
|
||||
assertEquals(6, classId)
|
||||
}
|
||||
db.close()
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -62,7 +63,7 @@ class Migration12Test : AbstractMigrationTest() {
|
||||
close()
|
||||
}
|
||||
|
||||
helper.runMigrationsAndValidate(dbName, 12, true, Migration12())
|
||||
runMigrationsAndValidate(Migration12())
|
||||
|
||||
val db = getMigratedRoomDatabase()
|
||||
val students = runBlocking { db.studentDao.loadAll() }
|
||||
@ -73,6 +74,7 @@ class Migration12Test : AbstractMigrationTest() {
|
||||
assertEquals(2, studentId)
|
||||
assertEquals(1, classId)
|
||||
}
|
||||
db.close()
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -88,7 +90,7 @@ class Migration12Test : AbstractMigrationTest() {
|
||||
close()
|
||||
}
|
||||
|
||||
helper.runMigrationsAndValidate(dbName, 12, true, Migration12())
|
||||
runMigrationsAndValidate(Migration12())
|
||||
|
||||
val db = getMigratedRoomDatabase()
|
||||
val students = runBlocking { db.studentDao.loadAll() }
|
||||
@ -107,6 +109,7 @@ class Migration12Test : AbstractMigrationTest() {
|
||||
assertEquals(studentId, 3)
|
||||
assertEquals(true, isCurrent)
|
||||
}
|
||||
db.close()
|
||||
}
|
||||
|
||||
private fun createStudent(db: SupportSQLiteDatabase, studentId: Int, isCurrent: Boolean) {
|
||||
|
@ -57,6 +57,8 @@ class Migration13Test : AbstractMigrationTest() {
|
||||
assertEquals("C", className)
|
||||
assertEquals("Publiczna szkoła Wulkanowego-fejka nr 2 w fakelog.cf", schoolName)
|
||||
}
|
||||
|
||||
db.close()
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -85,6 +87,8 @@ class Migration13Test : AbstractMigrationTest() {
|
||||
assertEquals("", className)
|
||||
assertEquals("Publiczna szkoła Wulkanowego-fejka nr 1 w fakelog.cf", schoolName)
|
||||
}
|
||||
|
||||
db.close()
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -148,6 +152,7 @@ class Migration13Test : AbstractMigrationTest() {
|
||||
assertFalse(semesters[2].second)
|
||||
assertTrue(semesters[3].second)
|
||||
}
|
||||
db.close()
|
||||
}
|
||||
|
||||
private fun getSemesters(db: SupportSQLiteDatabase, query: String): List<Pair<Semester, Boolean>> {
|
||||
|
@ -27,7 +27,7 @@ class Migration27Test : AbstractMigrationTest() {
|
||||
close()
|
||||
}
|
||||
|
||||
helper.runMigrationsAndValidate(dbName, 27, true, Migration27())
|
||||
runMigrationsAndValidate(Migration27())
|
||||
|
||||
val db = getMigratedRoomDatabase()
|
||||
val students = runBlocking { db.studentDao.loadAll() }
|
||||
@ -39,6 +39,8 @@ class Migration27Test : AbstractMigrationTest() {
|
||||
assertEquals(123, userLoginId)
|
||||
assertEquals("Student Jan", userName)
|
||||
}
|
||||
|
||||
db.close()
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -49,7 +51,7 @@ class Migration27Test : AbstractMigrationTest() {
|
||||
close()
|
||||
}
|
||||
|
||||
helper.runMigrationsAndValidate(dbName, 27, true, Migration27())
|
||||
runMigrationsAndValidate(Migration27())
|
||||
|
||||
val db = getMigratedRoomDatabase()
|
||||
val students = runBlocking { db.studentDao.loadAll() }
|
||||
@ -61,6 +63,8 @@ class Migration27Test : AbstractMigrationTest() {
|
||||
assertEquals(2, userLoginId)
|
||||
assertEquals("Unit Jan", userName)
|
||||
}
|
||||
|
||||
db.close()
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -73,7 +77,7 @@ class Migration27Test : AbstractMigrationTest() {
|
||||
close()
|
||||
}
|
||||
|
||||
helper.runMigrationsAndValidate(dbName, 27, true, Migration27())
|
||||
runMigrationsAndValidate(Migration27())
|
||||
|
||||
val db = getMigratedRoomDatabase()
|
||||
val students = runBlocking { db.studentDao.loadAll() }
|
||||
@ -90,6 +94,8 @@ class Migration27Test : AbstractMigrationTest() {
|
||||
assertEquals(333, userLoginId)
|
||||
assertEquals("Unit Tomasz", userName)
|
||||
}
|
||||
|
||||
db.close()
|
||||
}
|
||||
|
||||
private fun createStudent(db: SupportSQLiteDatabase, id: Long, userLoginId: Int, studentName: String) {
|
||||
|
@ -29,7 +29,7 @@ class Migration35Test : AbstractMigrationTest() {
|
||||
close()
|
||||
}
|
||||
|
||||
helper.runMigrationsAndValidate(dbName, 35, true, Migration35(AppInfo()))
|
||||
runMigrationsAndValidate(Migration35(AppInfo()))
|
||||
|
||||
val db = getMigratedRoomDatabase()
|
||||
val students = runBlocking { db.studentDao.loadAll() }
|
||||
@ -38,6 +38,8 @@ class Migration35Test : AbstractMigrationTest() {
|
||||
|
||||
assertTrue { students[0].avatarColor in AppInfo().defaultColorsForAvatar }
|
||||
assertTrue { students[1].avatarColor in AppInfo().defaultColorsForAvatar }
|
||||
|
||||
db.close()
|
||||
}
|
||||
|
||||
private fun createStudent(db: SupportSQLiteDatabase, id: Long) {
|
||||
|
@ -0,0 +1,130 @@
|
||||
package io.github.wulkanowy.data.db.migrations
|
||||
|
||||
import android.content.ContentValues
|
||||
import android.database.sqlite.SQLiteDatabase
|
||||
import android.os.Build
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
import dagger.hilt.android.testing.HiltAndroidTest
|
||||
import dagger.hilt.android.testing.HiltTestApplication
|
||||
import io.github.wulkanowy.sdk.Sdk
|
||||
import io.github.wulkanowy.sdk.Sdk.ScrapperLoginType.*
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.robolectric.RobolectricTestRunner
|
||||
import org.robolectric.annotation.Config
|
||||
import kotlin.random.Random
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
@HiltAndroidTest
|
||||
@RunWith(RobolectricTestRunner::class)
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
@Config(sdk = [Build.VERSION_CODES.O_MR1], application = HiltTestApplication::class)
|
||||
class Migration54Test : AbstractMigrationTest() {
|
||||
|
||||
@Test
|
||||
fun `don't touch unrelated students`() = runTest {
|
||||
with(helper.createDatabase(dbName, 53)) {
|
||||
createStudent(1, STANDARD, "vulcan.net.pl", "rzeszow", "Jan Michniewicz")
|
||||
createStudent(2, ADFSLight, "umt.tarnow.pl", "tarnow", "Joanna Marcinkiewicz")
|
||||
close()
|
||||
}
|
||||
|
||||
runMigrationsAndValidate(Migration54())
|
||||
val db = getMigratedRoomDatabase()
|
||||
val students = db.studentDao.loadAll()
|
||||
|
||||
assertEquals(2, students.size)
|
||||
with(students[0]) {
|
||||
assertEquals(STANDARD.name, loginType)
|
||||
assertEquals("https://vulcan.net.pl", scrapperBaseUrl)
|
||||
assertEquals("rzeszow", symbol)
|
||||
}
|
||||
with(students[1]) {
|
||||
assertEquals(ADFSLight.name, loginType)
|
||||
assertEquals("https://umt.tarnow.pl", scrapperBaseUrl)
|
||||
assertEquals("tarnow", symbol)
|
||||
}
|
||||
db.close()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `remove tomaszow mazowiecki students`() = runTest {
|
||||
with(helper.createDatabase(dbName, 53)) {
|
||||
createStudent(1, STANDARD, "vulcan.net.pl", "rzeszow", "Jan Michniewicz")
|
||||
createStudent(2, STANDARD, "vulcan.net.pl", "tomaszowmazowiecki", "Joanna Stec")
|
||||
createStudent(3, STANDARD, "vulcan.net.pl", "tomaszowmazowiecki", "Kacper Morawiecki")
|
||||
close()
|
||||
}
|
||||
|
||||
runMigrationsAndValidate(Migration54())
|
||||
val db = getMigratedRoomDatabase()
|
||||
val students = db.studentDao.loadAll()
|
||||
assertEquals(1, students.size)
|
||||
with(students[0]) {
|
||||
assertEquals("rzeszow", symbol)
|
||||
}
|
||||
db.close()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `migrate resman students`() = runTest {
|
||||
with(helper.createDatabase(dbName, 53)) {
|
||||
createStudent(1, ADFSLight, "resman.pl", "rzeszow", "Joanna Stec")
|
||||
createStudent(2, ADFSLight, "resman.pl", "rzeszow", "Kacper Morawiecki")
|
||||
createStudent(3, STANDARD, "vulcan.net.pl", "rzeszow", "Jan Michniewicz")
|
||||
close()
|
||||
}
|
||||
runMigrationsAndValidate(Migration54())
|
||||
val db = getMigratedRoomDatabase()
|
||||
val students = db.studentDao.loadAll()
|
||||
assertEquals(3, students.size)
|
||||
with(students[0]) {
|
||||
assertEquals(ADFSLightScoped.name, loginType)
|
||||
assertEquals("https://vulcan.net.pl", scrapperBaseUrl)
|
||||
assertEquals("rzeszowprojekt", symbol)
|
||||
}
|
||||
with(students[1]) {
|
||||
assertEquals(ADFSLightScoped.name, loginType)
|
||||
assertEquals("https://vulcan.net.pl", scrapperBaseUrl)
|
||||
assertEquals("rzeszowprojekt", symbol)
|
||||
}
|
||||
db.close()
|
||||
}
|
||||
|
||||
private fun SupportSQLiteDatabase.createStudent(
|
||||
id: Long,
|
||||
loginType: Sdk.ScrapperLoginType,
|
||||
host: String,
|
||||
symbol: String,
|
||||
studentName: String,
|
||||
) {
|
||||
insert("Students", SQLiteDatabase.CONFLICT_FAIL, ContentValues().apply {
|
||||
put("scrapper_base_url", "https://$host")
|
||||
put("mobile_base_url", "")
|
||||
put("login_type", loginType.name)
|
||||
put("login_mode", "SCRAPPER")
|
||||
put("certificate_key", "")
|
||||
put("private_key", "")
|
||||
put("is_parent", false)
|
||||
put("email", "jan@fakelog.cf")
|
||||
put("password", "******")
|
||||
put("symbol", symbol)
|
||||
put("student_id", Random.nextInt())
|
||||
put("user_login_id", id)
|
||||
put("user_name", studentName)
|
||||
put("student_name", studentName)
|
||||
put("school_id", "123")
|
||||
put("school_short", "")
|
||||
put("school_name", "")
|
||||
put("class_name", "")
|
||||
put("class_id", Random.nextInt())
|
||||
put("is_current", false)
|
||||
put("registration_date", "0")
|
||||
put("id", id)
|
||||
put("nick", "")
|
||||
put("avatar_color", "")
|
||||
})
|
||||
}
|
||||
}
|
@ -0,0 +1,143 @@
|
||||
package io.github.wulkanowy.data.mappers
|
||||
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import io.github.wulkanowy.data.db.entities.Timetable
|
||||
import io.github.wulkanowy.sdk.pojo.Attendance
|
||||
import io.github.wulkanowy.sdk.scrapper.attendance.SentExcuse
|
||||
import org.junit.Test
|
||||
import java.time.Instant
|
||||
import java.time.LocalDate
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
class AttendanceMapperTest {
|
||||
|
||||
@Test
|
||||
fun `map attendance when fallback is not necessary`() {
|
||||
val attendance = listOf(
|
||||
getSdkAttendance(1, LocalDate.of(2022, 11, 17), "Oryginalna 1"),
|
||||
getSdkAttendance(2, LocalDate.of(2022, 11, 17), "Oryginalna 2"),
|
||||
)
|
||||
val lessons = listOf(
|
||||
getEntityTimetable(1, LocalDate.of(2022, 11, 17), "Pierwsza"),
|
||||
getEntityTimetable(2, LocalDate.of(2022, 11, 17), "Druga"),
|
||||
)
|
||||
|
||||
val result = attendance.mapToEntities(getEntitySemester(), lessons)
|
||||
assertEquals("Oryginalna 1", result[0].subject)
|
||||
assertEquals("Oryginalna 2", result[1].subject)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `map attendance when fallback is not always necessary`() {
|
||||
val attendance = listOf(
|
||||
getSdkAttendance(1, LocalDate.of(2022, 11, 17), "Oryginalna 1"),
|
||||
getSdkAttendance(2, LocalDate.of(2022, 11, 17), ""),
|
||||
)
|
||||
val lessons = listOf(
|
||||
getEntityTimetable(1, LocalDate.of(2022, 11, 17), "Pierwsza"),
|
||||
getEntityTimetable(2, LocalDate.of(2022, 11, 17), "Druga"),
|
||||
)
|
||||
|
||||
val result = attendance.mapToEntities(getEntitySemester(), lessons)
|
||||
assertEquals("Oryginalna 1", result[0].subject)
|
||||
assertEquals("Druga", result[1].subject)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `map attendance when fallback is sometimes empty`() {
|
||||
val attendance = listOf(
|
||||
getSdkAttendance(1, LocalDate.of(2022, 11, 17), "Oryginalna 1"),
|
||||
getSdkAttendance(2, LocalDate.of(2022, 11, 17), ""),
|
||||
)
|
||||
val lessons = listOf(
|
||||
getEntityTimetable(1, LocalDate.of(2022, 11, 17), "Pierwsza"),
|
||||
)
|
||||
|
||||
val result = attendance.mapToEntities(getEntitySemester(), lessons)
|
||||
assertEquals("Oryginalna 1", result[0].subject)
|
||||
assertEquals("", result[1].subject)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `map attendance when fallback is empty`() {
|
||||
val attendance = listOf(
|
||||
getSdkAttendance(1, LocalDate.of(2022, 11, 17), ""),
|
||||
getSdkAttendance(2, LocalDate.of(2022, 11, 17), ""),
|
||||
)
|
||||
val lessons = listOf(
|
||||
getEntityTimetable(1, LocalDate.of(2022, 11, 18), "Pierwsza"),
|
||||
getEntityTimetable(2, LocalDate.of(2022, 10, 17), "Druga"),
|
||||
)
|
||||
|
||||
val result = attendance.mapToEntities(getEntitySemester(), lessons)
|
||||
assertEquals("", result[0].subject)
|
||||
assertEquals("", result[1].subject)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `map attendance with all subject fallback`() {
|
||||
val attendance = listOf(
|
||||
getSdkAttendance(1, LocalDate.of(2022, 11, 17)),
|
||||
getSdkAttendance(2, LocalDate.of(2022, 11, 17)),
|
||||
)
|
||||
val lessons = listOf(
|
||||
getEntityTimetable(1, LocalDate.of(2022, 11, 17), "Pierwsza"),
|
||||
getEntityTimetable(2, LocalDate.of(2022, 11, 17), "Druga"),
|
||||
)
|
||||
|
||||
val result = attendance.mapToEntities(getEntitySemester(), lessons)
|
||||
assertEquals("Pierwsza", result[0].subject)
|
||||
assertEquals("Druga", result[1].subject)
|
||||
}
|
||||
|
||||
private fun getSdkAttendance(number: Int, date: LocalDate, subject: String = "") = Attendance(
|
||||
number = number,
|
||||
name = "ABSENCE",
|
||||
subject = subject,
|
||||
date = date,
|
||||
timeId = 1,
|
||||
categoryId = 1,
|
||||
deleted = false,
|
||||
excuseStatus = SentExcuse.Status.WAITING,
|
||||
excusable = false,
|
||||
absence = false,
|
||||
excused = false,
|
||||
exemption = false,
|
||||
lateness = false,
|
||||
presence = false,
|
||||
)
|
||||
|
||||
private fun getEntityTimetable(number: Int, date: LocalDate, subject: String = "") = Timetable(
|
||||
number = number,
|
||||
start = Instant.now(),
|
||||
end = Instant.now(),
|
||||
date = date,
|
||||
subject = subject,
|
||||
subjectOld = "",
|
||||
group = "",
|
||||
room = "",
|
||||
roomOld = "",
|
||||
teacher = "",
|
||||
teacherOld = "",
|
||||
info = "",
|
||||
changes = false,
|
||||
canceled = false,
|
||||
studentId = 0,
|
||||
diaryId = 0,
|
||||
isStudentPlan = false,
|
||||
)
|
||||
|
||||
private fun getEntitySemester() = Semester(
|
||||
studentId = 0,
|
||||
diaryId = 0,
|
||||
kindergartenDiaryId = 0,
|
||||
diaryName = "",
|
||||
schoolYear = 0,
|
||||
semesterId = 0,
|
||||
semesterName = 0,
|
||||
start = LocalDate.now(),
|
||||
end = LocalDate.now(),
|
||||
classId = 0,
|
||||
unitId = 0
|
||||
)
|
||||
}
|
@ -2,6 +2,7 @@ package io.github.wulkanowy.data.repositories
|
||||
|
||||
import io.github.wulkanowy.data.dataOrNull
|
||||
import io.github.wulkanowy.data.db.dao.AttendanceDao
|
||||
import io.github.wulkanowy.data.db.dao.TimetableDao
|
||||
import io.github.wulkanowy.data.errorOrNull
|
||||
import io.github.wulkanowy.data.mappers.mapToEntities
|
||||
import io.github.wulkanowy.data.toFirstResult
|
||||
@ -29,6 +30,9 @@ class AttendanceRepositoryTest {
|
||||
@MockK
|
||||
private lateinit var attendanceDb: AttendanceDao
|
||||
|
||||
@MockK
|
||||
private lateinit var timetableDb: TimetableDao
|
||||
|
||||
@MockK(relaxUnitFun = true)
|
||||
private lateinit var refreshHelper: AutoRefreshHelper
|
||||
|
||||
@ -51,8 +55,9 @@ class AttendanceRepositoryTest {
|
||||
fun setUp() {
|
||||
MockKAnnotations.init(this)
|
||||
every { refreshHelper.shouldBeRefreshed(any()) } returns false
|
||||
coEvery { timetableDb.load(any(), any(), any(), any()) } returns emptyList()
|
||||
|
||||
attendanceRepository = AttendanceRepository(attendanceDb, sdk, refreshHelper)
|
||||
attendanceRepository = AttendanceRepository(attendanceDb, timetableDb, sdk, refreshHelper)
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -60,8 +65,8 @@ class AttendanceRepositoryTest {
|
||||
// prepare
|
||||
coEvery { sdk.getAttendance(startDate, endDate, 1) } returns remoteList
|
||||
coEvery { attendanceDb.loadAll(1, 1, startDate, endDate) } returnsMany listOf(
|
||||
flowOf(remoteList.mapToEntities(semester)),
|
||||
flowOf(remoteList.mapToEntities(semester))
|
||||
flowOf(remoteList.mapToEntities(semester, emptyList())),
|
||||
flowOf(remoteList.mapToEntities(semester, emptyList()))
|
||||
)
|
||||
coEvery { attendanceDb.insertAll(any()) } returns listOf(1, 2, 3)
|
||||
coEvery { attendanceDb.deleteAll(any()) } just Runs
|
||||
@ -83,9 +88,9 @@ class AttendanceRepositoryTest {
|
||||
// prepare
|
||||
coEvery { sdk.getAttendance(startDate, endDate, 1) } returns remoteList
|
||||
coEvery { attendanceDb.loadAll(1, 1, startDate, endDate) } returnsMany listOf(
|
||||
flowOf(remoteList.dropLast(1).mapToEntities(semester)),
|
||||
flowOf(remoteList.dropLast(1).mapToEntities(semester)), // after fetch end before save result
|
||||
flowOf(remoteList.mapToEntities(semester))
|
||||
flowOf(remoteList.dropLast(1).mapToEntities(semester, emptyList())),
|
||||
flowOf(remoteList.dropLast(1).mapToEntities(semester, emptyList())), // after fetch end before save result
|
||||
flowOf(remoteList.mapToEntities(semester, emptyList()))
|
||||
)
|
||||
coEvery { attendanceDb.insertAll(any()) } returns listOf(1, 2, 3)
|
||||
coEvery { attendanceDb.deleteAll(any()) } just Runs
|
||||
@ -100,7 +105,7 @@ class AttendanceRepositoryTest {
|
||||
coVerify { attendanceDb.loadAll(1, 1, startDate, endDate) }
|
||||
coVerify {
|
||||
attendanceDb.insertAll(match {
|
||||
it.size == 1 && it[0] == remoteList.mapToEntities(semester)[1]
|
||||
it.size == 1 && it[0] == remoteList.mapToEntities(semester, emptyList())[1]
|
||||
})
|
||||
}
|
||||
coVerify { attendanceDb.deleteAll(match { it.isEmpty() }) }
|
||||
@ -111,9 +116,9 @@ class AttendanceRepositoryTest {
|
||||
// prepare
|
||||
coEvery { sdk.getAttendance(startDate, endDate, 1) } returns remoteList.dropLast(1)
|
||||
coEvery { attendanceDb.loadAll(1, 1, startDate, endDate) } returnsMany listOf(
|
||||
flowOf(remoteList.mapToEntities(semester)),
|
||||
flowOf(remoteList.mapToEntities(semester)), // after fetch end before save result
|
||||
flowOf(remoteList.dropLast(1).mapToEntities(semester))
|
||||
flowOf(remoteList.mapToEntities(semester, emptyList())),
|
||||
flowOf(remoteList.mapToEntities(semester, emptyList())), // after fetch end before save result
|
||||
flowOf(remoteList.dropLast(1).mapToEntities(semester, emptyList()))
|
||||
)
|
||||
coEvery { attendanceDb.insertAll(any()) } returns listOf(1, 2, 3)
|
||||
coEvery { attendanceDb.deleteAll(any()) } just Runs
|
||||
@ -129,7 +134,7 @@ class AttendanceRepositoryTest {
|
||||
coVerify { attendanceDb.insertAll(match { it.isEmpty() }) }
|
||||
coVerify {
|
||||
attendanceDb.deleteAll(match {
|
||||
it.size == 1 && it[0] == remoteList.mapToEntities(semester)[1]
|
||||
it.size == 1 && it[0] == remoteList.mapToEntities(semester, emptyList())[1]
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -64,6 +64,18 @@ class GetMailboxByStudentUseCaseTest {
|
||||
assertEquals(expectedMailbox, selectedMailbox)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `get mailbox for user with reversed name`() = runTest {
|
||||
val student = getStudentEntity(
|
||||
userName = "Kowalski Jan",
|
||||
studentName = "Jan Kowalski",
|
||||
)
|
||||
val expectedMailbox = getMailboxEntity("Kowalski Jan")
|
||||
coEvery { mailboxDao.loadAll(any()) } returns listOf(expectedMailbox)
|
||||
|
||||
assertEquals(expectedMailbox, systemUnderTest(student))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `get mailbox for unique non-authorized student`() = runTest {
|
||||
val student = getStudentEntity(
|
||||
@ -148,8 +160,29 @@ class GetMailboxByStudentUseCaseTest {
|
||||
assertEquals(expectedMailbox, systemUnderTest(student))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `get mailbox for student with mailboxes from two different schools`() = runTest {
|
||||
val student = getStudentEntity(
|
||||
userName = "Kamil Bednarek",
|
||||
studentName = "Kamil Bednarek",
|
||||
schoolShortName = "CKZiU",
|
||||
)
|
||||
val mailbox1 = getMailboxEntity(
|
||||
studentName = "Kamil Bednarek",
|
||||
schoolShortName = "ZSTiO",
|
||||
)
|
||||
val mailbox2 = getMailboxEntity(
|
||||
studentName = "Kamil Bednarek",
|
||||
schoolShortName = "CKZiU",
|
||||
)
|
||||
coEvery { mailboxDao.loadAll(any()) } returns listOf(mailbox1, mailbox2)
|
||||
|
||||
assertEquals(mailbox2, systemUnderTest(student))
|
||||
}
|
||||
|
||||
private fun getMailboxEntity(
|
||||
studentName: String,
|
||||
schoolShortName: String = "test",
|
||||
) = Mailbox(
|
||||
globalKey = "",
|
||||
fullName = "",
|
||||
@ -158,13 +191,14 @@ class GetMailboxByStudentUseCaseTest {
|
||||
schoolId = "",
|
||||
symbol = "",
|
||||
studentName = studentName,
|
||||
schoolNameShort = "",
|
||||
schoolNameShort = schoolShortName,
|
||||
type = MailboxType.STUDENT,
|
||||
)
|
||||
|
||||
private fun getStudentEntity(
|
||||
studentName: String,
|
||||
userName: String,
|
||||
schoolShortName: String = "test",
|
||||
) = Student(
|
||||
scrapperBaseUrl = "http://fakelog.cf",
|
||||
email = "jan@fakelog.cf",
|
||||
@ -180,7 +214,7 @@ class GetMailboxByStudentUseCaseTest {
|
||||
privateKey = "",
|
||||
registrationDate = Instant.now(),
|
||||
schoolName = "",
|
||||
schoolShortName = "test",
|
||||
schoolShortName = schoolShortName,
|
||||
schoolSymbol = "",
|
||||
studentId = 1,
|
||||
studentName = studentName,
|
||||
|
@ -31,6 +31,7 @@ allprojects {
|
||||
mavenCentral()
|
||||
google()
|
||||
maven { url "https://jitpack.io" }
|
||||
maven { url "https://s01.oss.sonatype.org/content/repositories/snapshots/" }
|
||||
maven { url "https://developer.huawei.com/repo/" }
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user