Skip to content

Commit

Permalink
[feature-notification] --> sub feature complete "Select Interest" "Re…
Browse files Browse the repository at this point in the history
…ceive Notification" "View Notification in App" "Open Link on Tap"

[pending] --> acceptance test for mentioned features. Will add in next commit.
  • Loading branch information
syedahmedjamil committed Jan 21, 2024
1 parent 7ae812f commit 09135b6
Show file tree
Hide file tree
Showing 104 changed files with 2,044 additions and 475 deletions.
51 changes: 42 additions & 9 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import java.util.Properties
import java.io.FileInputStream
import java.util.Properties

plugins {
alias(libs.plugins.androidApplication)
Expand All @@ -9,6 +9,7 @@ plugins {
id("com.google.firebase.crashlytics")
id("com.google.firebase.appdistribution")
id("androidx.navigation.safeargs.kotlin")
id("com.google.dagger.hilt.android")
}
val keystorePropertiesFile = rootProject.file("app/keystore.properties")
val keystoreProperties = Properties()
Expand All @@ -23,10 +24,11 @@ android {
minSdk = 24
targetSdk = 33
versionCode = project.property("versionCode").toString().toInt()
versionName = "1.2.0"
versionName = "1.3.0"
testApplicationId = "com.github.syedahmedjamil.pushernotif.test"
//testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
testInstrumentationRunner = "io.cucumber.android.runner.CucumberAndroidJUnitRunner"
// testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
// testInstrumentationRunner = "io.cucumber.android.runner.CucumberAndroidJUnitRunner"
testInstrumentationRunner = "com.github.syedahmedjamil.pushernotif.test.CustomRunner"
//apk file name
setProperty("archivesBaseName", "${rootProject.name}-${versionName}-${versionCode}")

Expand Down Expand Up @@ -88,15 +90,37 @@ android {
}

testOptions {
unitTests {
isIncludeAndroidResources = true
isReturnDefaultValues = true
}
animationsDisabled = true
packaging {
jniLibs {
useLegacyPackaging = true
}
}
}

kapt {
correctErrorTypes = true
}

packaging {
resources.excludes.addAll(
listOf(
"META-INF/LICENSE.md",
"META-INF/LICENSE-notice.md"
)
)
}

dependencies {

//project
implementation(project(":data"))
implementation(project(":domain"))
implementation(project(":usecases"))
implementation(project(":usecase"))
implementation(project(":core"))

//local
Expand All @@ -108,28 +132,37 @@ android {
implementation(libs.androidx.constraintlayout)
implementation("androidx.datastore:datastore-preferences:1.0.0")
implementation("androidx.lifecycle:lifecycle-livedata-ktx:2.6.2") // for asLiveData method
implementation("com.google.firebase:firebase-iid:21.1.0")
implementation("com.google.firebase:firebase-iid:21.1.0") // for pusher
implementation(platform("com.google.firebase:firebase-bom:32.7.0"))
implementation("com.google.firebase:firebase-messaging")
implementation("com.pusher:push-notifications-android:1.9.2")
implementation("androidx.navigation:navigation-ui-ktx:2.7.6")
implementation("androidx.navigation:navigation-fragment-ktx:2.7.6")
implementation("com.squareup.picasso:picasso:2.8")
implementation("com.google.dagger:hilt-android:2.50")
kapt("com.google.dagger:hilt-android-compiler:2.50")
implementation("androidx.test.espresso:espresso-idling-resource:3.5.1") // for EspressoIdlingResource

//test
testImplementation(project(":shared-test"))
testImplementation(libs.junit)
testImplementation(libs.androidx.junit.ktx)
testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.7.3") //for runTest and dispatchers
testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.7.3") // for runTest and dispatchers
testImplementation("androidx.arch.core:core-testing:2.2.0") // for instant task executor rule

//androidTest
androidTestImplementation(project(":shared-test"))
androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core)
androidTestImplementation(libs.cucumber.android)
androidTestImplementation(libs.androidx.rules)
androidTestImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.7.3")
androidTestImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.7.3") // for runTest and dispatchers
androidTestImplementation("com.squareup.okhttp3:okhttp:3.12.0")
androidTestImplementation("androidx.test.uiautomator:uiautomator:2.3.0-alpha03")
androidTestImplementation("com.google.dagger:hilt-android-testing:2.50")
kaptAndroidTest("com.google.dagger:hilt-android-compiler:2.50")
androidTestImplementation("io.cucumber:cucumber-android-hilt:7.14.0")
androidTestImplementation("io.mockk:mockk-android:1.13.9")
androidTestImplementation("androidx.fragment:fragment-testing:1.6.2") // for DataBindingIdlingResource
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Feature: Delete Notifications
User deletes all locally stored notifications


Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Feature: View Notifications
User cal view all locally stored notifications
5 changes: 5 additions & 0 deletions app/src/androidTest/assets/test_notification.preferences_pb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@

�
$216b9ffe-1bf7-4ec5-89a5-1c6283ec37d9o*m{"body":"test","date":"test","image":"test","interest":"test1","link":"test","subText":"test","title":"test"}
�
$cd2467e0-28eb-46dc-b5ad-74b08638b21do*m{"body":"test","date":"test","image":"test","interest":"test2","link":"test","subText":"test","title":"test"}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.github.syedahmedjamil.pushernotif.test

import android.content.Intent
import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.Preferences
import androidx.test.core.app.ActivityScenario
import com.github.syedahmedjamil.pushernotif.ui.MainActivity
import io.cucumber.java.After
import javax.inject.Inject

class ActivityScenarioHolder {

private lateinit var scenario: ActivityScenario<MainActivity>


@Inject
lateinit var dataStore: DataStore<Preferences>

fun launch(intent: Intent) {
scenario = ActivityScenario.launch<MainActivity>(intent)
}

fun getScenario(): ActivityScenario<MainActivity> {
return scenario
}
/**
* Close activity after scenario
*/
@After
fun close() {
scenario.close()

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.github.syedahmedjamil.pushernotif.test

import android.app.Application
import android.content.Context
import com.github.syedahmedjamil.pushernotif.BaseApplication
import dagger.hilt.android.testing.CustomTestApplication
import io.cucumber.android.runner.CucumberAndroidJUnitRunner

@CustomTestApplication(BaseApplication::class)
interface CustomHiltTestApplication

class CustomRunner : CucumberAndroidJUnitRunner() {

override fun newApplication(cl: ClassLoader?, name: String?, context: Context?): Application {
return super.newApplication(cl, CustomHiltTestApplication_Application::class.java.name, context)
}
}
Original file line number Diff line number Diff line change
@@ -1,33 +1,65 @@
package com.github.syedahmedjamil.pushernotif.test.acceptance

import androidx.test.core.app.ActivityScenario
import android.content.Intent
import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.edit
import androidx.test.core.app.ApplicationProvider
import com.github.syedahmedjamil.pushernotif.MyApplication
import androidx.test.espresso.IdlingRegistry
import com.github.syedahmedjamil.pushernotif.test.ActivityScenarioHolder
import com.github.syedahmedjamil.pushernotif.test.dsl.CucumberDsl
import com.github.syedahmedjamil.pushernotif.test.util.DataBindingIdlingResource
import com.github.syedahmedjamil.pushernotif.test.util.monitorActivity
import com.github.syedahmedjamil.pushernotif.ui.MainActivity
import com.github.syedahmedjamil.pushernotif.util.EspressoIdlingResource
import dagger.hilt.android.testing.HiltAndroidTest
import io.cucumber.java.After
import io.cucumber.java.Before
import io.cucumber.java.en.And
import io.cucumber.java.en.Given
import io.cucumber.java.en.Then
import io.cucumber.java.en.When
import io.cucumber.java.en.And
import kotlinx.coroutines.runBlocking
import javax.inject.Inject

@HiltAndroidTest
class FeatureInstanceSteps(
val scenarioHolder: ActivityScenarioHolder
) {

class FeatureInstanceSteps {
private val dsl = CucumberDsl()

private lateinit var activityScenario: ActivityScenario<MainActivity>
@Inject
lateinit var dataStore: DataStore<Preferences>


private val dataBindingIdlingResource = DataBindingIdlingResource()

@Before
fun setup() {
activityScenario = ActivityScenario.launch(MainActivity::class.java)
fun setUp() {
IdlingRegistry.getInstance().register(EspressoIdlingResource.countingIdlingResource)
IdlingRegistry.getInstance().register(dataBindingIdlingResource)
scenarioHolder.launch(
Intent(
ApplicationProvider.getApplicationContext(),
MainActivity::class.java
)
)
dataBindingIdlingResource.monitorActivity(scenarioHolder.getScenario())
}

@After
fun tearDown() {
activityScenario.close()
(ApplicationProvider.getApplicationContext() as MyApplication).appContainer.reset()
IdlingRegistry.getInstance().unregister(EspressoIdlingResource.countingIdlingResource)
IdlingRegistry.getInstance().unregister(dataBindingIdlingResource)
runBlocking {
dataStore.edit {
it.clear()
}
}
}


@Given("I am on the {string} screen")
fun iAmOnThePage(arg0: String) {
dsl.instance.assertScreenTitle(arg0)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.github.syedahmedjamil.pushernotif

import androidx.test.core.app.ActivityScenario
import com.github.syedahmedjamil.pushernotif.ui.MainActivity
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent


@Module
@InstallIn(SingletonComponent::class)
object TestModule {

@Provides
fun provideActivityScenario(): ActivityScenario<MainActivity> =
ActivityScenario.launch(MainActivity::class.java)
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@ package com.github.syedahmedjamil.pushernotif.test.integration
import android.content.Context
import androidx.test.core.app.ApplicationProvider
import com.github.syedahmedjamil.pushernotif.AppContainer
import com.github.syedahmedjamil.pushernotif.usecases.AddInterestUseCase
import com.github.syedahmedjamil.pushernotif.usecases.GetInterestsUseCase
import com.github.syedahmedjamil.pushernotif.usecases.RemoveInterestUseCase
import com.github.syedahmedjamil.pushernotif.usecases.SubscribeUseCase
import com.github.syedahmedjamil.pushernotif.domain.ImageLoader
import com.github.syedahmedjamil.pushernotif.usecases.AddNotificationUseCase
import com.github.syedahmedjamil.pushernotif.usecases.GetNotificationsUseCase
import org.junit.Assert
import org.junit.Test

Expand All @@ -21,34 +20,20 @@ class AppContainerTest {
}

@Test
fun test_appContainer_has_a_addInterestUseCase_singleton() {
val useCase1: AddInterestUseCase = appContainer.addInterestUseCase
val useCase2: AddInterestUseCase = appContainer.addInterestUseCase
Assert.assertNotNull(useCase1)
Assert.assertEquals(useCase1, useCase2)
fun test_appContainer_has_a_addNotificationUseCase() {
val dep: AddNotificationUseCase = appContainer.addNotificationUseCase
Assert.assertNotNull(dep)
}

@Test
fun test_appContainer_has_a_getInterestsUseCase_singleton() {
val useCase1: GetInterestsUseCase = appContainer.getInterestsUseCase
val useCase2: GetInterestsUseCase = appContainer.getInterestsUseCase
Assert.assertNotNull(useCase1)
Assert.assertEquals(useCase1, useCase2)
fun test_appContainer_has_a_getNotificationsUseCase() {
val dep: GetNotificationsUseCase = appContainer.getNotificationsUseCase
Assert.assertNotNull(dep)
}

@Test
fun test_appContainer_has_a_removeInterestUseCase_singleton() {
val useCase1: RemoveInterestUseCase = appContainer.removeInterestUseCase
val useCase2: RemoveInterestUseCase = appContainer.removeInterestUseCase
Assert.assertNotNull(useCase1)
Assert.assertEquals(useCase1, useCase2)
}

@Test
fun test_appContainer_has_a_subscribeUseCase_singleton() {
val useCase1: SubscribeUseCase = appContainer.subscribeUseCase
val useCase2: SubscribeUseCase = appContainer.subscribeUseCase
Assert.assertNotNull(useCase1)
Assert.assertEquals(useCase1, useCase2)
fun test_appContainer_has_a_imageLoader() {
val dep: ImageLoader = appContainer.imageLoader
Assert.assertNotNull(dep)
}
}
Loading

0 comments on commit 09135b6

Please sign in to comment.