-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #115 from azrael8576/feat/fake-api-integration
Integrate FakeRetrofitAtNetwork for API mock
- Loading branch information
Showing
9 changed files
with
240 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
15 changes: 15 additions & 0 deletions
15
core/network/src/demo/kotlin/com/wei/amazingtalker/core/network/di/FlavoredNetworkModule.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package com.wei.amazingtalker.core.network.di | ||
|
||
import com.wei.amazingtalker.core.network.AtNetworkDataSource | ||
import com.wei.amazingtalker.core.network.fake.FakeRetrofitAtNetwork | ||
import dagger.Binds | ||
import dagger.Module | ||
import dagger.hilt.InstallIn | ||
import dagger.hilt.components.SingletonComponent | ||
|
||
@Module | ||
@InstallIn(SingletonComponent::class) | ||
internal interface FlavoredNetworkModule { | ||
@Binds | ||
fun binds(implementation: FakeRetrofitAtNetwork): AtNetworkDataSource | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
{ | ||
"available": [ | ||
{ | ||
"start": "2024-02-05T11:30:00Z", | ||
"end": "2024-02-05T12:00:00Z" | ||
}, | ||
{ | ||
"start": "2024-02-05T13:00:00Z", | ||
"end": "2024-02-05T20:30:00Z" | ||
}, | ||
{ | ||
"start": "2024-02-06T11:30:00Z", | ||
"end": "2024-02-06T12:00:00Z" | ||
}, | ||
{ | ||
"start": "2024-02-06T14:00:00Z", | ||
"end": "2024-02-06T17:00:00Z" | ||
}, | ||
{ | ||
"start": "2024-02-06T18:00:00Z", | ||
"end": "2024-02-06T20:30:00Z" | ||
}, | ||
{ | ||
"start": "2024-02-07T12:30:00Z", | ||
"end": "2024-02-07T17:00:00Z" | ||
}, | ||
{ | ||
"start": "2024-02-07T18:00:00Z", | ||
"end": "2024-02-07T20:30:00Z" | ||
}, | ||
{ | ||
"start": "2024-02-08T12:00:00Z", | ||
"end": "2024-02-08T13:00:00Z" | ||
}, | ||
{ | ||
"start": "2024-02-08T14:00:00Z", | ||
"end": "2024-02-08T20:00:00Z" | ||
}, | ||
{ | ||
"start": "2024-02-09T12:00:00Z", | ||
"end": "2024-02-09T15:00:00Z" | ||
}, | ||
{ | ||
"start": "2024-02-10T04:30:00Z", | ||
"end": "2024-02-10T08:30:00Z" | ||
} | ||
], | ||
"booked": [ | ||
{ | ||
"start": "2024-02-05T12:00:00Z", | ||
"end": "2024-02-05T13:00:00Z" | ||
}, | ||
{ | ||
"start": "2024-02-06T12:00:00Z", | ||
"end": "2024-02-06T14:00:00Z" | ||
}, | ||
{ | ||
"start": "2024-02-06T17:00:00Z", | ||
"end": "2024-02-06T18:00:00Z" | ||
}, | ||
{ | ||
"start": "2024-02-07T11:30:00Z", | ||
"end": "2024-02-07T12:30:00Z" | ||
}, | ||
{ | ||
"start": "2024-02-07T17:00:00Z", | ||
"end": "2024-02-07T18:00:00Z" | ||
}, | ||
{ | ||
"start": "2024-02-08T13:00:00Z", | ||
"end": "2024-02-08T14:00:00Z" | ||
}, | ||
{ | ||
"start": "2024-02-09T11:00:00Z", | ||
"end": "2024-02-09T12:00:00Z" | ||
} | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import androidx.annotation.VisibleForTesting | ||
import com.wei.amazingtalker.core.network.fake.FakeAssetManager | ||
import java.io.File | ||
import java.io.InputStream | ||
import java.util.Properties | ||
|
||
/** | ||
* This class helps with loading Android `/assets` files, especially when running JVM unit tests. | ||
* It must remain on the root package for an easier [Class.getResource] with relative paths. | ||
* @see <a href="https://developer.android.com/reference/tools/gradle-api/7.3/com/android/build/api/dsl/UnitTestOptions">UnitTestOptions</a> | ||
*/ | ||
@VisibleForTesting | ||
internal object JvmUnitTestFakeAssetManager : FakeAssetManager { | ||
private val config = | ||
requireNotNull(javaClass.getResource("com/android/tools/test_config.properties")) { | ||
""" | ||
Missing Android resources properties file. | ||
Did you forget to enable the feature in the gradle build file? | ||
android.testOptions.unitTests.isIncludeAndroidResources = true | ||
""".trimIndent() | ||
} | ||
private val properties = Properties().apply { config.openStream().use(::load) } | ||
private val assets = File(properties["android_merged_assets"].toString()) | ||
|
||
override fun open(fileName: String): InputStream = File(assets, fileName).inputStream() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
7 changes: 7 additions & 0 deletions
7
core/network/src/main/java/com/wei/amazingtalker/core/network/fake/FakeAssetManager.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package com.wei.amazingtalker.core.network.fake | ||
|
||
import java.io.InputStream | ||
|
||
fun interface FakeAssetManager { | ||
fun open(fileName: String): InputStream | ||
} |
99 changes: 99 additions & 0 deletions
99
core/network/src/main/java/com/wei/amazingtalker/core/network/fake/FakeRetrofitAtNetwork.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
package com.wei.amazingtalker.core.network.fake | ||
|
||
import JvmUnitTestFakeAssetManager | ||
import com.wei.amazingtalker.core.network.AtDispatchers | ||
import com.wei.amazingtalker.core.network.AtNetworkDataSource | ||
import com.wei.amazingtalker.core.network.Dispatcher | ||
import com.wei.amazingtalker.core.network.model.NetworkTeacherSchedule | ||
import com.wei.amazingtalker.core.network.model.NetworkTimeSlots | ||
import kotlinx.coroutines.CoroutineDispatcher | ||
import kotlinx.coroutines.withContext | ||
import kotlinx.serialization.ExperimentalSerializationApi | ||
import kotlinx.serialization.json.Json | ||
import kotlinx.serialization.json.decodeFromStream | ||
import java.time.Duration | ||
import java.time.ZonedDateTime | ||
import java.time.format.DateTimeFormatter | ||
import javax.inject.Inject | ||
|
||
/** | ||
* Mocks network data source for teacher availability, using static JSON assets for development and testing. | ||
*/ | ||
class FakeRetrofitAtNetwork | ||
@Inject | ||
constructor( | ||
@Dispatcher(AtDispatchers.IO) private val ioDispatcher: CoroutineDispatcher, | ||
private val networkJson: Json, | ||
private val assets: FakeAssetManager = JvmUnitTestFakeAssetManager, | ||
) : AtNetworkDataSource { | ||
/** | ||
* Fetches mocked teacher availability based on a given start time, adjusting time slots dynamically. | ||
* | ||
* @param teacherName Name of the teacher (unused in mock). | ||
* @param startedAt Start time to adjust availability slots. | ||
* @return Adjusted {@link NetworkTeacherSchedule} with available and booked slots. | ||
*/ | ||
@OptIn(ExperimentalSerializationApi::class) | ||
override suspend fun getTeacherAvailability( | ||
teacherName: String, | ||
startedAt: String?, | ||
): NetworkTeacherSchedule = | ||
withContext(ioDispatcher) { | ||
// Parse the input time, rounding down to the nearest hour if necessary | ||
val inputTime = ZonedDateTime.parse(startedAt).withMinute(0).withSecond(0).withNano(0) | ||
val baseTime = ZonedDateTime.parse("2024-02-04T16:00Z") | ||
|
||
// Calculate the difference in hours between the input time and the base time | ||
val hoursDiff = Duration.between(baseTime, inputTime).toHours() | ||
|
||
// Decode the schedule from the JSON asset | ||
val schedule: NetworkTeacherSchedule = | ||
assets.open(TEACHER_SCHEDULE_ASSET).use { inputStream -> | ||
networkJson.decodeFromStream(inputStream) | ||
} | ||
|
||
// Adjust the schedule times based on the calculated difference | ||
adjustScheduleTimes(schedule, hoursDiff) | ||
} | ||
|
||
/** | ||
* Adjusts the provided schedule's time slots based on the hour difference. | ||
*/ | ||
private fun adjustScheduleTimes( | ||
schedule: NetworkTeacherSchedule, | ||
hoursDiff: Long, | ||
): NetworkTeacherSchedule { | ||
return schedule.copy( | ||
available = adjustTimeSlots(schedule.available, hoursDiff), | ||
booked = adjustTimeSlots(schedule.booked, hoursDiff), | ||
) | ||
} | ||
|
||
/** | ||
* Adjusts a list of time slots by the specified hours difference. | ||
*/ | ||
private fun adjustTimeSlots( | ||
slots: List<NetworkTimeSlots>, | ||
hoursDiff: Long, | ||
): List<NetworkTimeSlots> { | ||
return slots.map { slot -> | ||
slot.adjustByHours(hoursDiff) | ||
} | ||
} | ||
|
||
/** | ||
* Adjusts the start and end times of a NetworkTimeSlot by the given hours difference. | ||
*/ | ||
private fun NetworkTimeSlots.adjustByHours(hoursDiff: Long): NetworkTimeSlots { | ||
val formatter = DateTimeFormatter.ISO_ZONED_DATE_TIME | ||
val adjustedStart = | ||
ZonedDateTime.parse(this.startUtc, formatter).plusHours(hoursDiff).format(formatter) | ||
val adjustedEnd = | ||
ZonedDateTime.parse(this.endUtc, formatter).plusHours(hoursDiff).format(formatter) | ||
return this.copy(startUtc = adjustedStart, endUtc = adjustedEnd) | ||
} | ||
|
||
companion object { | ||
private const val TEACHER_SCHEDULE_ASSET = "teacher_schedule.json" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
## This file provides default values to modules using the secrets-gradle-plugin. It is necessary | ||
# because the secrets properties file is not under source control so CI builds will fail without | ||
# default values. | ||
BACKEND_URL="https://tw.amazingtalker.com/v1/guest/" | ||
BACKEND_URL="http://example.com" |