diff --git a/.idea/gradle.xml b/.idea/gradle.xml
index c8bc96c..95c9dc8 100644
--- a/.idea/gradle.xml
+++ b/.idea/gradle.xml
@@ -11,11 +11,11 @@
-
diff --git a/example/.gitignore b/example/.gitignore
new file mode 100644
index 0000000..42afabf
--- /dev/null
+++ b/example/.gitignore
@@ -0,0 +1 @@
+/build
\ No newline at end of file
diff --git a/example/build.gradle b/example/build.gradle
new file mode 100644
index 0000000..596cc26
--- /dev/null
+++ b/example/build.gradle
@@ -0,0 +1,53 @@
+plugins {
+ id 'com.android.application'
+ id 'kotlin-android'
+}
+
+android {
+ compileSdkVersion 30
+ buildToolsVersion "30.0.3"
+
+ defaultConfig {
+ applicationId "dohun.kim.gatabuta.example"
+ minSdkVersion 21
+ targetSdkVersion 30
+ versionCode 1
+ versionName "1.0"
+
+ testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ }
+ }
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+ kotlinOptions {
+ jvmTarget = '1.8'
+ }
+ buildFeatures {
+ dataBinding true
+ }
+}
+
+dependencies {
+ implementation project(':gatabuta-livedata')
+
+ implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
+ implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.3'
+ implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.3'
+ testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.4.3'
+ implementation 'androidx.core:core-ktx:1.3.2'
+ implementation 'androidx.appcompat:appcompat:1.2.0'
+ implementation 'com.google.android.material:material:1.3.0'
+ implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
+ testImplementation 'junit:junit:4.+'
+ testImplementation "androidx.arch.core:core-testing:2.1.0"
+ androidTestImplementation 'androidx.test.ext:junit:1.1.2'
+ androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
+}
\ No newline at end of file
diff --git a/example/proguard-rules.pro b/example/proguard-rules.pro
new file mode 100644
index 0000000..481bb43
--- /dev/null
+++ b/example/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
\ No newline at end of file
diff --git a/example/src/main/AndroidManifest.xml b/example/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..9735bf1
--- /dev/null
+++ b/example/src/main/AndroidManifest.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/example/src/main/java/dohun/kim/gatabuta/example/MainActivity.kt b/example/src/main/java/dohun/kim/gatabuta/example/MainActivity.kt
new file mode 100644
index 0000000..d02cba1
--- /dev/null
+++ b/example/src/main/java/dohun/kim/gatabuta/example/MainActivity.kt
@@ -0,0 +1,23 @@
+package dohun.kim.gatabuta.example
+
+import androidx.appcompat.app.AppCompatActivity
+import android.os.Bundle
+import androidx.databinding.DataBindingUtil
+import androidx.lifecycle.ViewModelProvider
+import dohun.kim.gatabuta.example.databinding.ActivityMainBinding
+
+class MainActivity : AppCompatActivity() {
+
+ private lateinit var binding: ActivityMainBinding
+
+ private val viewModel: MainViewModel by lazy {
+ MainViewModel()
+ }
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
+ binding.lifecycleOwner = this
+ binding.viewModel = viewModel
+ }
+}
diff --git a/example/src/main/java/dohun/kim/gatabuta/example/MainViewModel.kt b/example/src/main/java/dohun/kim/gatabuta/example/MainViewModel.kt
new file mode 100644
index 0000000..41ac298
--- /dev/null
+++ b/example/src/main/java/dohun/kim/gatabuta/example/MainViewModel.kt
@@ -0,0 +1,19 @@
+package dohun.kim.gatabuta.example
+
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.ViewModel
+
+class MainViewModel : ViewModel() {
+
+ private val _money = MutableLiveData()
+ val money: LiveData = _money
+
+ private val _nonNullableMoney = MutableLiveData(0)
+ val nonNullableMoney: LiveData = _nonNullableMoney
+
+ fun increaseMoney() {
+ _money.value = money.value?.plus(1) ?: 1
+ _nonNullableMoney.value = nonNullableMoney.value?.plus(1) ?: 1
+ }
+}
\ No newline at end of file
diff --git a/example/src/main/res/drawable-v24/ic_launcher_foreground.xml b/example/src/main/res/drawable-v24/ic_launcher_foreground.xml
new file mode 100644
index 0000000..2b068d1
--- /dev/null
+++ b/example/src/main/res/drawable-v24/ic_launcher_foreground.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/example/src/main/res/drawable/ic_launcher_background.xml b/example/src/main/res/drawable/ic_launcher_background.xml
new file mode 100644
index 0000000..07d5da9
--- /dev/null
+++ b/example/src/main/res/drawable/ic_launcher_background.xml
@@ -0,0 +1,170 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/example/src/main/res/layout/activity_main.xml b/example/src/main/res/layout/activity_main.xml
new file mode 100644
index 0000000..bed99fe
--- /dev/null
+++ b/example/src/main/res/layout/activity_main.xml
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/example/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/example/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
new file mode 100644
index 0000000..eca70cf
--- /dev/null
+++ b/example/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/example/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/example/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
new file mode 100644
index 0000000..eca70cf
--- /dev/null
+++ b/example/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/example/src/main/res/mipmap-hdpi/ic_launcher.png b/example/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..a571e60
Binary files /dev/null and b/example/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/example/src/main/res/mipmap-hdpi/ic_launcher_round.png b/example/src/main/res/mipmap-hdpi/ic_launcher_round.png
new file mode 100644
index 0000000..61da551
Binary files /dev/null and b/example/src/main/res/mipmap-hdpi/ic_launcher_round.png differ
diff --git a/example/src/main/res/mipmap-mdpi/ic_launcher.png b/example/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..c41dd28
Binary files /dev/null and b/example/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/example/src/main/res/mipmap-mdpi/ic_launcher_round.png b/example/src/main/res/mipmap-mdpi/ic_launcher_round.png
new file mode 100644
index 0000000..db5080a
Binary files /dev/null and b/example/src/main/res/mipmap-mdpi/ic_launcher_round.png differ
diff --git a/example/src/main/res/mipmap-xhdpi/ic_launcher.png b/example/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..6dba46d
Binary files /dev/null and b/example/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/example/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/example/src/main/res/mipmap-xhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..da31a87
Binary files /dev/null and b/example/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ
diff --git a/example/src/main/res/mipmap-xxhdpi/ic_launcher.png b/example/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..15ac681
Binary files /dev/null and b/example/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/example/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/example/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..b216f2d
Binary files /dev/null and b/example/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ
diff --git a/example/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/example/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..f25a419
Binary files /dev/null and b/example/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/example/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/example/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..e96783c
Binary files /dev/null and b/example/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ
diff --git a/example/src/main/res/values-night/themes.xml b/example/src/main/res/values-night/themes.xml
new file mode 100644
index 0000000..68320a1
--- /dev/null
+++ b/example/src/main/res/values-night/themes.xml
@@ -0,0 +1,16 @@
+
+
+
+
\ No newline at end of file
diff --git a/example/src/main/res/values/colors.xml b/example/src/main/res/values/colors.xml
new file mode 100644
index 0000000..f8c6127
--- /dev/null
+++ b/example/src/main/res/values/colors.xml
@@ -0,0 +1,10 @@
+
+
+ #FFBB86FC
+ #FF6200EE
+ #FF3700B3
+ #FF03DAC5
+ #FF018786
+ #FF000000
+ #FFFFFFFF
+
\ No newline at end of file
diff --git a/example/src/main/res/values/strings.xml b/example/src/main/res/values/strings.xml
new file mode 100644
index 0000000..e16a3ca
--- /dev/null
+++ b/example/src/main/res/values/strings.xml
@@ -0,0 +1,3 @@
+
+ example
+
\ No newline at end of file
diff --git a/example/src/main/res/values/themes.xml b/example/src/main/res/values/themes.xml
new file mode 100644
index 0000000..5452811
--- /dev/null
+++ b/example/src/main/res/values/themes.xml
@@ -0,0 +1,16 @@
+
+
+
+
\ No newline at end of file
diff --git a/example/src/test/java/dohun/kim/gatabuta/example/MainCoroutineRule.kt b/example/src/test/java/dohun/kim/gatabuta/example/MainCoroutineRule.kt
new file mode 100644
index 0000000..2ae122d
--- /dev/null
+++ b/example/src/test/java/dohun/kim/gatabuta/example/MainCoroutineRule.kt
@@ -0,0 +1,22 @@
+package dohun.kim.gatabuta.example
+
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.test.TestCoroutineScope
+import kotlinx.coroutines.test.resetMain
+import kotlinx.coroutines.test.setMain
+import org.junit.rules.TestWatcher
+import org.junit.runner.Description
+import kotlin.coroutines.ContinuationInterceptor
+
+class MainCoroutineRule : TestWatcher(), TestCoroutineScope by TestCoroutineScope() {
+ override fun starting(description: Description?) {
+ super.starting(description)
+ Dispatchers.setMain(this.coroutineContext[ContinuationInterceptor] as CoroutineDispatcher)
+ }
+
+ override fun finished(description: Description?) {
+ super.finished(description)
+ Dispatchers.resetMain()
+ }
+}
\ No newline at end of file
diff --git a/example/src/test/java/dohun/kim/gatabuta/example/MainViewModelTest.kt b/example/src/test/java/dohun/kim/gatabuta/example/MainViewModelTest.kt
new file mode 100644
index 0000000..d0b62f6
--- /dev/null
+++ b/example/src/test/java/dohun/kim/gatabuta/example/MainViewModelTest.kt
@@ -0,0 +1,38 @@
+package dohun.kim.gatabuta.example
+
+import androidx.arch.core.executor.testing.InstantTaskExecutorRule
+import dohun.kim.gatabuta.gatabuta_livedata.equalTo
+import dohun.kim.gatabuta.gatabuta_livedata.isNull
+import dohun.kim.gatabuta.gatabuta_livedata.test
+import kotlinx.coroutines.runBlocking
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+
+class MainViewModelTest {
+
+ private lateinit var viewModel: MainViewModel
+
+ @get:Rule
+ val mainCoroutineRule = MainCoroutineRule()
+
+ @get:Rule
+ val instantTaskExecutorRule = InstantTaskExecutorRule()
+
+ @Before
+ fun init() {
+ viewModel = MainViewModel()
+ }
+
+ @Test
+ fun increaseTest() = runBlocking {
+ viewModel.money.test.isNull()
+ viewModel.nonNullableMoney.test equalTo 0L
+
+ viewModel.increaseMoney()
+
+ viewModel.money.test equalTo 1L
+ viewModel.nonNullableMoney.test equalTo 1L
+ }
+}
+
diff --git a/gatabuta-livedata/src/main/java/dohun/kim/gatabuta/gatabuta_livedata/Bools.kt b/gatabuta-livedata/src/main/java/dohun/kim/gatabuta/gatabuta_livedata/Bools.kt
index 6d27d79..ef3eeee 100644
--- a/gatabuta-livedata/src/main/java/dohun/kim/gatabuta/gatabuta_livedata/Bools.kt
+++ b/gatabuta-livedata/src/main/java/dohun/kim/gatabuta/gatabuta_livedata/Bools.kt
@@ -3,10 +3,10 @@ package dohun.kim.gatabuta.gatabuta_livedata
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
-suspend fun LiveDataTest.isTrue() {
+suspend fun LiveDataTest.isTrue() {
assertTrue(value() == true)
}
-suspend fun LiveDataTest.isFalse() {
+suspend fun LiveDataTest.isFalse() {
assertFalse(value() == true)
}
diff --git a/gatabuta-livedata/src/main/java/dohun/kim/gatabuta/gatabuta_livedata/CharSequences.kt b/gatabuta-livedata/src/main/java/dohun/kim/gatabuta/gatabuta_livedata/CharSequences.kt
index d2ba133..18be491 100644
--- a/gatabuta-livedata/src/main/java/dohun/kim/gatabuta/gatabuta_livedata/CharSequences.kt
+++ b/gatabuta-livedata/src/main/java/dohun/kim/gatabuta/gatabuta_livedata/CharSequences.kt
@@ -3,17 +3,17 @@ package dohun.kim.gatabuta.gatabuta_livedata
import org.junit.Assert.assertEquals
import org.junit.Assert.fail
-suspend fun LiveDataTest.isBlank() {
+suspend fun LiveDataTest.isBlank() {
if (value()?.isNotBlank() == true) {
fail()
}
}
-suspend infix fun LiveDataTest.hasLength(expected: Int?) {
+suspend infix fun LiveDataTest.hasLength(expected: Int?) {
assertEquals(expected, value()?.length)
}
-suspend fun LiveDataTest.isEmpty() {
+suspend fun LiveDataTest.isEmpty() {
if (value()?.isNotEmpty() == true) {
fail()
}
diff --git a/gatabuta-livedata/src/main/java/dohun/kim/gatabuta/gatabuta_livedata/Collections.kt b/gatabuta-livedata/src/main/java/dohun/kim/gatabuta/gatabuta_livedata/Collections.kt
index feb6778..ca482a6 100644
--- a/gatabuta-livedata/src/main/java/dohun/kim/gatabuta/gatabuta_livedata/Collections.kt
+++ b/gatabuta-livedata/src/main/java/dohun/kim/gatabuta/gatabuta_livedata/Collections.kt
@@ -3,17 +3,17 @@ package dohun.kim.gatabuta.gatabuta_livedata
import org.junit.Assert
import org.junit.Assert.fail
-suspend infix fun > LiveDataTest.hasSize(expected: Int?) {
+suspend infix fun > LiveDataTest.hasSize(expected: Int?) {
Assert.assertEquals(expected, value()?.size)
}
-suspend fun > LiveDataTest.isEmpty() {
+suspend fun > LiveDataTest.isEmpty() {
if (value()?.isNotEmpty() == true) {
fail()
}
}
-suspend fun > LiveDataTest.isNotEmpty() {
+suspend fun > LiveDataTest.isNotEmpty() {
if (value()?.isEmpty() == true) {
fail()
}
diff --git a/gatabuta-livedata/src/main/java/dohun/kim/gatabuta/gatabuta_livedata/LiveDataTest.kt b/gatabuta-livedata/src/main/java/dohun/kim/gatabuta/gatabuta_livedata/LiveDataTest.kt
index bb5b38a..abf4fbd 100644
--- a/gatabuta-livedata/src/main/java/dohun/kim/gatabuta/gatabuta_livedata/LiveDataTest.kt
+++ b/gatabuta-livedata/src/main/java/dohun/kim/gatabuta/gatabuta_livedata/LiveDataTest.kt
@@ -3,36 +3,32 @@ package dohun.kim.gatabuta.gatabuta_livedata
import androidx.lifecycle.LiveData
import org.junit.Assert.*
-class LiveDataTest(private val liveData: LiveData) {
+class LiveDataTest(private val liveData: LiveData) {
suspend fun value(): T? = liveData.getOrAwaitValue()
}
/**
* Start test scope
*/
-val LiveData.test: LiveDataTest
+val LiveData.test: LiveDataTest
get() = LiveDataTest(this)
-infix fun LiveData.test(block: LiveDataTest.() -> Unit) {
- block.invoke(LiveDataTest(this))
-}
-
/**
* Assertion extensions
*/
-suspend infix fun LiveDataTest.equalTo(expected: Any?) {
+suspend infix fun LiveDataTest.equalTo(expected: Any?) {
assertEquals(expected, value())
}
-suspend infix fun LiveDataTest.notEqualTo(expected: Any?) {
+suspend infix fun LiveDataTest.notEqualTo(expected: Any?) {
assertNotEquals(expected, value())
}
-suspend fun LiveDataTest.isNull() {
+suspend fun LiveDataTest.isNull() {
assertNull(value())
}
-suspend fun LiveDataTest.isNotNull() {
+suspend fun LiveDataTest.isNotNull() {
assertNotNull(value())
}
diff --git a/gatabuta-livedata/src/main/java/dohun/kim/gatabuta/gatabuta_livedata/getOrAwaitValue.kt b/gatabuta-livedata/src/main/java/dohun/kim/gatabuta/gatabuta_livedata/getOrAwaitValue.kt
index be36df2..98ed727 100644
--- a/gatabuta-livedata/src/main/java/dohun/kim/gatabuta/gatabuta_livedata/getOrAwaitValue.kt
+++ b/gatabuta-livedata/src/main/java/dohun/kim/gatabuta/gatabuta_livedata/getOrAwaitValue.kt
@@ -12,7 +12,7 @@ import kotlinx.coroutines.withTimeout
*
* @link https://medium.com/androiddevelopers/unit-testing-livedata-and-other-common-observability-problems-bb477262eb04
*/
-internal suspend fun LiveData.getOrAwaitValue(): T? =
+internal suspend fun LiveData.getOrAwaitValue(): T? =
try {
withTimeout(200) {
this@getOrAwaitValue.asFlow().first()
diff --git a/settings.gradle b/settings.gradle
index ca0b4ab..1664faa 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -1,2 +1,3 @@
include ':gatabuta-livedata'
-rootProject.name = "Gatabuta"
\ No newline at end of file
+rootProject.name = "Gatabuta"
+include ':example'