Merge pull request #20 from hmalik144/fastlane_setup

Fastlane setup
This commit is contained in:
2023-08-29 21:19:37 +01:00
committed by GitHub
35 changed files with 392 additions and 359 deletions

View File

@@ -1,113 +0,0 @@
<component name="ProjectCodeStyleConfiguration">
<code_scheme name="Project" version="173">
<codeStyleSettings language="XML">
<arrangement>
<rules>
<section>
<rule>
<match>
<AND>
<NAME>xmlns:android</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>xmlns:.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:id</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:name</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>name</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>style</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
<order>ANDROID_ATTRIBUTE_ORDER</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>.*</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
</rules>
</arrangement>
</codeStyleSettings>
</code_scheme>
</component>

3
Gemfile Normal file
View File

@@ -0,0 +1,3 @@
source "https://rubygems.org"
gem "fastlane"

View File

@@ -2,19 +2,34 @@ apply plugin: 'com.android.application'
apply plugin: 'org.jetbrains.kotlin.android' apply plugin: 'org.jetbrains.kotlin.android'
apply plugin: 'kotlin-kapt' apply plugin: 'kotlin-kapt'
def relStorePassword = System.getenv("RELEASE_STORE_PASSWORD")
def relKeyPassword = System.getenv("RELEASE_KEY_PASSWORD")
def relKeyAlias = System.getenv("RELEASE_KEY_ALIAS")
def keystorePath = "/keystore.jks"
def keystore = file(keystorePath).exists() ? file(keystorePath) : null
android { android {
compileSdkVersion 31 compileSdkVersion 31
defaultConfig { defaultConfig {
applicationId "com.appttude.h_mal.farmr" applicationId "com.appttude.h_mal.farmr"
minSdkVersion 21 minSdkVersion 21
targetSdkVersion 31 targetSdkVersion 31
versionCode 1 versionCode 2
versionName "1.0" versionName "2.0"
testInstrumentationRunner 'com.appttude.h_mal.farmr.application.TestRunner' testInstrumentationRunner 'com.appttude.h_mal.farmr.application.TestRunner'
vectorDrawables.useSupportLibrary = true vectorDrawables.useSupportLibrary = true
} }
signingConfigs {
release {
storePassword relStorePassword
keyPassword relKeyPassword
keyAlias relKeyAlias
storeFile keystore
}
}
buildTypes { buildTypes {
release { release {
signingConfig signingConfigs.release
minifyEnabled false minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
} }

View File

@@ -3,6 +3,7 @@ package com.appttude.h_mal.farmr.data
import android.content.ContentResolver import android.content.ContentResolver
import android.content.ContentValues import android.content.ContentValues
import androidx.test.rule.provider.ProviderTestRule import androidx.test.rule.provider.ProviderTestRule
import com.appttude.h_mal.farmr.data.legacydb.ShiftProvider
import com.appttude.h_mal.farmr.data.legacydb.ShiftsContract.CONTENT_AUTHORITY import com.appttude.h_mal.farmr.data.legacydb.ShiftsContract.CONTENT_AUTHORITY
import com.appttude.h_mal.farmr.data.legacydb.ShiftsContract.ShiftsEntry.COLUMN_SHIFT_BREAK import com.appttude.h_mal.farmr.data.legacydb.ShiftsContract.ShiftsEntry.COLUMN_SHIFT_BREAK
import com.appttude.h_mal.farmr.data.legacydb.ShiftsContract.ShiftsEntry.COLUMN_SHIFT_DATE import com.appttude.h_mal.farmr.data.legacydb.ShiftsContract.ShiftsEntry.COLUMN_SHIFT_DATE
@@ -16,7 +17,6 @@ import com.appttude.h_mal.farmr.data.legacydb.ShiftsContract.ShiftsEntry.COLUMN_
import com.appttude.h_mal.farmr.data.legacydb.ShiftsContract.ShiftsEntry.COLUMN_SHIFT_UNIT import com.appttude.h_mal.farmr.data.legacydb.ShiftsContract.ShiftsEntry.COLUMN_SHIFT_UNIT
import com.appttude.h_mal.farmr.data.legacydb.ShiftsContract.ShiftsEntry.CONTENT_URI import com.appttude.h_mal.farmr.data.legacydb.ShiftsContract.ShiftsEntry.CONTENT_URI
import com.appttude.h_mal.farmr.data.legacydb.ShiftsContract.ShiftsEntry._ID import com.appttude.h_mal.farmr.data.legacydb.ShiftsContract.ShiftsEntry._ID
import com.appttude.h_mal.farmr.data.legacydb.ShiftProvider
import junit.framework.TestCase.assertEquals import junit.framework.TestCase.assertEquals
import junit.framework.TestCase.assertNull import junit.framework.TestCase.assertNull
import org.junit.After import org.junit.After

View File

@@ -6,9 +6,7 @@ import android.content.Intent
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.view.View import android.view.View
import androidx.lifecycle.Lifecycle
import androidx.test.core.app.ActivityScenario import androidx.test.core.app.ActivityScenario
import androidx.test.core.app.ApplicationProvider
import androidx.test.espresso.Espresso import androidx.test.espresso.Espresso
import androidx.test.espresso.UiController import androidx.test.espresso.UiController
import androidx.test.espresso.ViewAction import androidx.test.espresso.ViewAction
@@ -18,7 +16,6 @@ import androidx.test.espresso.matcher.ViewMatchers
import androidx.test.platform.app.InstrumentationRegistry import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.rule.GrantPermissionRule import androidx.test.rule.GrantPermissionRule
import com.appttude.h_mal.farmr.application.TestAppClass import com.appttude.h_mal.farmr.application.TestAppClass
import com.appttude.h_mal.farmr.di.ShiftApplication
import com.appttude.h_mal.farmr.ui.utils.getShifts import com.appttude.h_mal.farmr.ui.utils.getShifts
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import org.hamcrest.Matcher import org.hamcrest.Matcher

View File

@@ -1,8 +1,8 @@
package com.appttude.h_mal.farmr.ui.robots package com.appttude.h_mal.farmr.ui.robots
import com.appttude.h_mal.farmr.R import com.appttude.h_mal.farmr.R
import com.appttude.h_mal.farmr.ui.BaseTestRobot
import com.appttude.h_mal.farmr.model.ShiftType import com.appttude.h_mal.farmr.model.ShiftType
import com.appttude.h_mal.farmr.ui.BaseTestRobot
fun filterScreen(func: FilterScreenRobot.() -> Unit) = FilterScreenRobot().apply { func() } fun filterScreen(func: FilterScreenRobot.() -> Unit) = FilterScreenRobot().apply { func() }
class FilterScreenRobot : BaseTestRobot() { class FilterScreenRobot : BaseTestRobot() {

View File

@@ -1,6 +1,5 @@
package com.appttude.h_mal.farmr.ui.robots package com.appttude.h_mal.farmr.ui.robots
import androidx.test.espresso.matcher.RootMatchers.isDialog
import com.appttude.h_mal.farmr.R import com.appttude.h_mal.farmr.R
import com.appttude.h_mal.farmr.base.BaseRecyclerAdapter.CurrentViewHolder import com.appttude.h_mal.farmr.base.BaseRecyclerAdapter.CurrentViewHolder
import com.appttude.h_mal.farmr.model.Order import com.appttude.h_mal.farmr.model.Order

View File

@@ -1,8 +1,8 @@
package com.appttude.h_mal.farmr.ui.robots package com.appttude.h_mal.farmr.ui.robots
import com.appttude.h_mal.farmr.R import com.appttude.h_mal.farmr.R
import com.appttude.h_mal.farmr.ui.BaseTestRobot
import com.appttude.h_mal.farmr.model.ShiftType import com.appttude.h_mal.farmr.model.ShiftType
import com.appttude.h_mal.farmr.ui.BaseTestRobot
fun viewScreen(func: ViewItemScreenRobot.() -> Unit) = ViewItemScreenRobot().apply { func() } fun viewScreen(func: ViewItemScreenRobot.() -> Unit) = ViewItemScreenRobot().apply { func() }
class ViewItemScreenRobot : BaseTestRobot() { class ViewItemScreenRobot : BaseTestRobot() {

View File

@@ -9,7 +9,6 @@ import com.appttude.h_mal.farmr.ui.robots.addScreen
import com.appttude.h_mal.farmr.ui.robots.filterScreen import com.appttude.h_mal.farmr.ui.robots.filterScreen
import com.appttude.h_mal.farmr.ui.robots.homeScreen import com.appttude.h_mal.farmr.ui.robots.homeScreen
import com.appttude.h_mal.farmr.ui.robots.viewScreen import com.appttude.h_mal.farmr.ui.robots.viewScreen
import com.appttude.h_mal.farmr.utils.ID
import org.junit.Test import org.junit.Test
class ShiftTests : BaseTest<MainActivity>(MainActivity::class.java) { class ShiftTests : BaseTest<MainActivity>(MainActivity::class.java) {

View File

@@ -40,7 +40,7 @@
<provider <provider
android:name="androidx.core.content.FileProvider" android:name="androidx.core.content.FileProvider"
android:authorities="com.appttude.h_mal.farmr.provider" android:authorities="${applicationId}.provider"
android:exported="false" android:exported="false"
android:grantUriPermissions="true"> android:grantUriPermissions="true">
<meta-data <meta-data

View File

@@ -4,14 +4,12 @@ import android.os.Bundle
import android.view.View import android.view.View
import androidx.annotation.LayoutRes import androidx.annotation.LayoutRes
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.fragment.app.createViewModelLazy
import androidx.lifecycle.ViewModelLazy import androidx.lifecycle.ViewModelLazy
import com.appttude.h_mal.farmr.model.ViewState import com.appttude.h_mal.farmr.model.ViewState
import com.appttude.h_mal.farmr.utils.getGenericClassAt import com.appttude.h_mal.farmr.utils.getGenericClassAt
import com.appttude.h_mal.farmr.utils.popBackStack import com.appttude.h_mal.farmr.utils.popBackStack
import com.appttude.h_mal.farmr.viewmodel.ApplicationViewModelFactory import com.appttude.h_mal.farmr.viewmodel.ApplicationViewModelFactory
import org.kodein.di.KodeinAware import org.kodein.di.KodeinAware
import org.kodein.di.android.kodein
import org.kodein.di.android.x.kodein import org.kodein.di.android.x.kodein
import org.kodein.di.generic.instance import org.kodein.di.generic.instance
import kotlin.properties.Delegates import kotlin.properties.Delegates

View File

@@ -4,7 +4,6 @@ import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import com.appttude.h_mal.farmr.model.ViewState import com.appttude.h_mal.farmr.model.ViewState
import java.lang.Exception
open class BaseViewModel: ViewModel() { open class BaseViewModel: ViewModel() {

View File

@@ -3,7 +3,6 @@ package com.appttude.h_mal.farmr.data.legacydb
import android.content.ContentResolver import android.content.ContentResolver
import android.content.ContentUris import android.content.ContentUris
import android.content.ContentValues import android.content.ContentValues
import android.content.Context
import android.database.Cursor import android.database.Cursor
import android.net.Uri import android.net.Uri
import com.appttude.h_mal.farmr.data.legacydb.ShiftsContract.ShiftsEntry.COLUMN_SHIFT_BREAK import com.appttude.h_mal.farmr.data.legacydb.ShiftsContract.ShiftsEntry.COLUMN_SHIFT_BREAK
@@ -19,7 +18,6 @@ import com.appttude.h_mal.farmr.data.legacydb.ShiftsContract.ShiftsEntry.COLUMN_
import com.appttude.h_mal.farmr.data.legacydb.ShiftsContract.ShiftsEntry.CONTENT_URI import com.appttude.h_mal.farmr.data.legacydb.ShiftsContract.ShiftsEntry.CONTENT_URI
import com.appttude.h_mal.farmr.data.legacydb.ShiftsContract.ShiftsEntry._ID import com.appttude.h_mal.farmr.data.legacydb.ShiftsContract.ShiftsEntry._ID
import com.appttude.h_mal.farmr.model.Shift import com.appttude.h_mal.farmr.model.Shift
import com.appttude.h_mal.farmr.model.ShiftType
class LegacyDatabase(private val resolver: ContentResolver) { class LegacyDatabase(private val resolver: ContentResolver) {

View File

@@ -19,22 +19,24 @@ class ShiftProvider : ContentProvider() {
return true return true
} }
override fun query(uri: Uri, projection: Array<String>?, selection: String?, selectionArgs: Array<String>?, override fun query(
sortOrder: String?): Cursor? { uri: Uri, projection: Array<String>?, selection: String?, selectionArgs: Array<String>?,
var selection = selection sortOrder: String?
var selectionArgs = selectionArgs ): Cursor {
val database = mDbHelper!!.readableDatabase val database = mDbHelper!!.readableDatabase
val cursor: Cursor val cursor: Cursor = when (sUriMatcher.match(uri)) {
val match = sUriMatcher.match(uri) SHIFTS -> database.query(
when (match) { ShiftsEntry.TABLE_NAME, projection, selection, selectionArgs,
SHIFTS -> cursor = database.query(ShiftsEntry.TABLE_NAME, projection, selection, selectionArgs, null, null, sortOrder
null, null, sortOrder) )
SHIFT_ID -> { SHIFT_ID -> {
selection = ShiftsEntry._ID + "=?" val mSelection = ShiftsEntry._ID + "=?"
selectionArgs = arrayOf(ContentUris.parseId(uri).toString()) val mSelectionArgs = arrayOf(ContentUris.parseId(uri).toString())
cursor = database.query(ShiftsEntry.TABLE_NAME, projection, selection, selectionArgs, database.query(
null, null, sortOrder) ShiftsEntry.TABLE_NAME, projection, mSelection, mSelectionArgs,
null, null, sortOrder
)
} }
else -> throw IllegalArgumentException("Cannot query $uri") else -> throw IllegalArgumentException("Cannot query $uri")
@@ -44,26 +46,25 @@ class ShiftProvider : ContentProvider() {
} }
override fun insert(uri: Uri, contentValues: ContentValues?): Uri? { override fun insert(uri: Uri, contentValues: ContentValues?): Uri? {
val match = sUriMatcher.match(uri) return when (sUriMatcher.match(uri)) {
return when (match) {
SHIFTS -> insertShift(uri, contentValues) SHIFTS -> insertShift(uri, contentValues)
else -> throw IllegalArgumentException("Insertion is not supported for $uri") else -> throw IllegalArgumentException("Insertion is not supported for $uri")
} }
} }
private fun insertShift(uri: Uri, values: ContentValues?): Uri? { private fun insertShift(uri: Uri, values: ContentValues?): Uri? {
val description = values!!.getAsString(ShiftsEntry.COLUMN_SHIFT_DESCRIPTION) values!!.getAsString(ShiftsEntry.COLUMN_SHIFT_DESCRIPTION)
?: throw IllegalArgumentException("Description required") ?: throw IllegalArgumentException("Description required")
val date = values.getAsString(ShiftsEntry.COLUMN_SHIFT_DATE) values.getAsString(ShiftsEntry.COLUMN_SHIFT_DATE)
?: throw IllegalArgumentException("Date required") ?: throw IllegalArgumentException("Date required")
val timeIn = values.getAsString(ShiftsEntry.COLUMN_SHIFT_TIME_IN) values.getAsString(ShiftsEntry.COLUMN_SHIFT_TIME_IN)
?: throw IllegalArgumentException("Time In required") ?: throw IllegalArgumentException("Time In required")
val timeOut = values.getAsString(ShiftsEntry.COLUMN_SHIFT_TIME_OUT) values.getAsString(ShiftsEntry.COLUMN_SHIFT_TIME_OUT)
?: throw IllegalArgumentException("Time Out required") ?: throw IllegalArgumentException("Time Out required")
val duration = values.getAsFloat(ShiftsEntry.COLUMN_SHIFT_DURATION) val duration = values.getAsFloat(ShiftsEntry.COLUMN_SHIFT_DURATION)
require(duration >= 0) { "Duration cannot be negative" } require(duration >= 0) { "Duration cannot be negative" }
val shiftType = values.getAsString(ShiftsEntry.COLUMN_SHIFT_TYPE) values.getAsString(ShiftsEntry.COLUMN_SHIFT_TYPE)
?: throw IllegalArgumentException("Shift type required") ?: throw IllegalArgumentException("Shift type required")
val shiftUnits = values.getAsFloat(ShiftsEntry.COLUMN_SHIFT_UNIT) val shiftUnits = values.getAsFloat(ShiftsEntry.COLUMN_SHIFT_UNIT)
require(shiftUnits >= 0) { "Units cannot be negative" } require(shiftUnits >= 0) { "Units cannot be negative" }
val payRate = values.getAsFloat(ShiftsEntry.COLUMN_SHIFT_PAYRATE) val payRate = values.getAsFloat(ShiftsEntry.COLUMN_SHIFT_PAYRATE)
@@ -82,43 +83,47 @@ class ShiftProvider : ContentProvider() {
return ContentUris.withAppendedId(uri, id) return ContentUris.withAppendedId(uri, id)
} }
override fun update(uri: Uri, contentValues: ContentValues?, selection: String?, override fun update(
selectionArgs: Array<String>?): Int { uri: Uri, contentValues: ContentValues?, selection: String?,
var selection = selection selectionArgs: Array<String>?
var selectionArgs = selectionArgs ): Int {
val match = sUriMatcher.match(uri) return when (sUriMatcher.match(uri)) {
return when (match) {
SHIFTS -> updateShift(uri, contentValues, selection, selectionArgs) SHIFTS -> updateShift(uri, contentValues, selection, selectionArgs)
SHIFT_ID -> { SHIFT_ID -> {
selection = ShiftsEntry._ID + "=?" val mSelection = ShiftsEntry._ID + "=?"
selectionArgs = arrayOf(ContentUris.parseId(uri).toString()) val mSelectionArgs = arrayOf(ContentUris.parseId(uri).toString())
updateShift(uri, contentValues, selection, selectionArgs) updateShift(uri, contentValues, mSelection, mSelectionArgs)
} }
else -> throw IllegalArgumentException("Update is not supported for $uri") else -> throw IllegalArgumentException("Update is not supported for $uri")
} }
} }
private fun updateShift(uri: Uri, values: ContentValues?, selection: String?, selectionArgs: Array<String>?): Int { private fun updateShift(
uri: Uri,
values: ContentValues?,
selection: String?,
selectionArgs: Array<String>?
): Int {
if (values!!.containsKey(ShiftsEntry.COLUMN_SHIFT_DESCRIPTION)) { if (values!!.containsKey(ShiftsEntry.COLUMN_SHIFT_DESCRIPTION)) {
val description = values.getAsString(ShiftsEntry.COLUMN_SHIFT_DESCRIPTION) values.getAsString(ShiftsEntry.COLUMN_SHIFT_DESCRIPTION)
?: throw IllegalArgumentException("description required") ?: throw IllegalArgumentException("description required")
} }
if (values.containsKey(ShiftsEntry.COLUMN_SHIFT_DATE)) { if (values.containsKey(ShiftsEntry.COLUMN_SHIFT_DATE)) {
val date = values.getAsString(ShiftsEntry.COLUMN_SHIFT_DATE) values.getAsString(ShiftsEntry.COLUMN_SHIFT_DATE)
?: throw IllegalArgumentException("date required") ?: throw IllegalArgumentException("date required")
} }
if (values.containsKey(ShiftsEntry.COLUMN_SHIFT_TIME_IN)) { if (values.containsKey(ShiftsEntry.COLUMN_SHIFT_TIME_IN)) {
val timeIn = values.getAsString(ShiftsEntry.COLUMN_SHIFT_TIME_IN) values.getAsString(ShiftsEntry.COLUMN_SHIFT_TIME_IN)
?: throw IllegalArgumentException("time in required") ?: throw IllegalArgumentException("time in required")
} }
if (values.containsKey(ShiftsEntry.COLUMN_SHIFT_TIME_OUT)) { if (values.containsKey(ShiftsEntry.COLUMN_SHIFT_TIME_OUT)) {
val timeOut = values.getAsString(ShiftsEntry.COLUMN_SHIFT_TIME_OUT) values.getAsString(ShiftsEntry.COLUMN_SHIFT_TIME_OUT)
?: throw IllegalArgumentException("time out required") ?: throw IllegalArgumentException("time out required")
} }
if (values.containsKey(ShiftsEntry.COLUMN_SHIFT_BREAK)) { if (values.containsKey(ShiftsEntry.COLUMN_SHIFT_BREAK)) {
val breaks = values.getAsString(ShiftsEntry.COLUMN_SHIFT_BREAK) values.getAsString(ShiftsEntry.COLUMN_SHIFT_BREAK)
?: throw IllegalArgumentException("break required") ?: throw IllegalArgumentException("break required")
} }
if (values.size() == 0) { if (values.size() == 0) {
return 0 return 0
@@ -132,17 +137,15 @@ class ShiftProvider : ContentProvider() {
} }
override fun delete(uri: Uri, selection: String?, selectionArgs: Array<String>?): Int { override fun delete(uri: Uri, selection: String?, selectionArgs: Array<String>?): Int {
var selection = selection
var selectionArgs = selectionArgs
val database = mDbHelper!!.writableDatabase val database = mDbHelper!!.writableDatabase
val rowsDeleted: Int val rowsDeleted: Int = when (sUriMatcher.match(uri)) {
val match = sUriMatcher.match(uri) SHIFTS -> database.delete(ShiftsEntry.TABLE_NAME, selection, selectionArgs)
when (match) {
SHIFTS -> rowsDeleted = database.delete(ShiftsEntry.TABLE_NAME, selection, selectionArgs)
SHIFT_ID -> { SHIFT_ID -> {
selection = ShiftsEntry._ID + "=?" val mSelection = ShiftsEntry._ID + "=?"
selectionArgs = arrayOf(ContentUris.parseId(uri).toString()) val mSelectionArgs = arrayOf(ContentUris.parseId(uri).toString())
rowsDeleted = database.delete(ShiftsEntry.TABLE_NAME, selection, selectionArgs)
database.delete(ShiftsEntry.TABLE_NAME, mSelection, mSelectionArgs)
} }
else -> throw IllegalArgumentException("Deletion is not supported for $uri") else -> throw IllegalArgumentException("Deletion is not supported for $uri")
@@ -169,7 +172,11 @@ class ShiftProvider : ContentProvider() {
init { init {
sUriMatcher.addURI(ShiftsContract.CONTENT_AUTHORITY, ShiftsContract.PATH_SHIFTS, SHIFTS) sUriMatcher.addURI(ShiftsContract.CONTENT_AUTHORITY, ShiftsContract.PATH_SHIFTS, SHIFTS)
sUriMatcher.addURI(ShiftsContract.CONTENT_AUTHORITY, ShiftsContract.PATH_SHIFTS + "/#", SHIFT_ID) sUriMatcher.addURI(
ShiftsContract.CONTENT_AUTHORITY,
ShiftsContract.PATH_SHIFTS + "/#",
SHIFT_ID
)
} }
} }

View File

@@ -3,13 +3,12 @@ package com.appttude.h_mal.farmr.data.legacydb
import android.content.ContentResolver import android.content.ContentResolver
import android.net.Uri import android.net.Uri
import android.provider.BaseColumns import android.provider.BaseColumns
import com.appttude.h_mal.farmr.BuildConfig
/** /**
* Created by h_mal on 26/12/2017. * Created by h_mal on 26/12/2017.
*/ */
object ShiftsContract { object ShiftsContract {
const val CONTENT_AUTHORITY = BuildConfig.APPLICATION_ID const val CONTENT_AUTHORITY = "com.appttude.h_mal.farmr"
val BASE_CONTENT_URI = Uri.parse("content://$CONTENT_AUTHORITY") val BASE_CONTENT_URI = Uri.parse("content://$CONTENT_AUTHORITY")
const val PATH_SHIFTS = "shifts" const val PATH_SHIFTS = "shifts"

View File

@@ -1,17 +1,8 @@
package com.appttude.h_mal.farmr.di package com.appttude.h_mal.farmr.di
import com.appttude.h_mal.farmr.base.BaseApplication import com.appttude.h_mal.farmr.base.BaseApplication
import com.appttude.h_mal.farmr.data.RepositoryImpl
import com.appttude.h_mal.farmr.data.legacydb.LegacyDatabase import com.appttude.h_mal.farmr.data.legacydb.LegacyDatabase
import com.appttude.h_mal.farmr.data.prefs.PreferenceProvider import com.appttude.h_mal.farmr.data.prefs.PreferenceProvider
import com.appttude.h_mal.farmr.viewmodel.ApplicationViewModelFactory
import org.kodein.di.Kodein
import org.kodein.di.KodeinAware
import org.kodein.di.android.x.androidXModule
import org.kodein.di.generic.bind
import org.kodein.di.generic.instance
import org.kodein.di.generic.provider
import org.kodein.di.generic.singleton
class ShiftApplication: BaseApplication() { class ShiftApplication: BaseApplication() {

View File

@@ -1,10 +1,7 @@
package com.appttude.h_mal.farmr.model package com.appttude.h_mal.farmr.model
import com.appttude.h_mal.farmr.data.legacydb.ShiftObject
import com.appttude.h_mal.farmr.utils.calculateDuration import com.appttude.h_mal.farmr.utils.calculateDuration
import com.appttude.h_mal.farmr.utils.convertTimeStringToHourMinutesPair
import com.appttude.h_mal.farmr.utils.formatToTwoDp import com.appttude.h_mal.farmr.utils.formatToTwoDp
import java.io.IOException
data class Shift( data class Shift(
val type: ShiftType, val type: ShiftType,

View File

@@ -10,8 +10,6 @@ enum class Sortable(val label: String) {
TOTALPAY("Total Pay"); TOTALPAY("Total Pay");
companion object { companion object {
val entries = Sortable.values()
fun getEnumByType(label: String): Sortable { fun getEnumByType(label: String): Sortable {
return Sortable.values().first { it.label == label } return Sortable.values().first { it.label == label }
} }

View File

@@ -26,7 +26,6 @@ import com.appttude.h_mal.farmr.utils.setDatePicker
import com.appttude.h_mal.farmr.utils.setTimePicker import com.appttude.h_mal.farmr.utils.setTimePicker
import com.appttude.h_mal.farmr.utils.show import com.appttude.h_mal.farmr.utils.show
import com.appttude.h_mal.farmr.utils.validateField import com.appttude.h_mal.farmr.utils.validateField
import com.appttude.h_mal.farmr.viewmodel.MainViewModel
import com.appttude.h_mal.farmr.viewmodel.SubmissionViewModel import com.appttude.h_mal.farmr.viewmodel.SubmissionViewModel
class FragmentAddItem : BaseFragment<SubmissionViewModel>(R.layout.fragment_add_item), class FragmentAddItem : BaseFragment<SubmissionViewModel>(R.layout.fragment_add_item),
@@ -120,6 +119,7 @@ class FragmentAddItem : BaseFragment<SubmissionViewModel>(R.layout.fragment_add_
private fun setupViewAfterViewCreated() { private fun setupViewAfterViewCreated() {
id = arguments?.getLong(ID) id = arguments?.getLong(ID)
wholeView.hide()
val title = when (arguments?.containsKey(ID)) { val title = when (arguments?.containsKey(ID)) {
true -> { true -> {

View File

@@ -1,12 +1,10 @@
package com.appttude.h_mal.farmr.ui package com.appttude.h_mal.farmr.ui
import android.Manifest import android.Manifest
import android.annotation.SuppressLint
import android.app.Activity import android.app.Activity
import android.app.AlertDialog import android.app.AlertDialog
import android.content.Intent import android.content.Intent
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.net.Uri
import android.os.Bundle import android.os.Bundle
import android.view.MenuItem import android.view.MenuItem
import android.view.View import android.view.View
@@ -95,7 +93,7 @@ class FragmentMain : BaseFragment<MainViewModel>(R.layout.fragment_main), BackPr
AlertDialog.Builder(context) AlertDialog.Builder(context)
.setTitle("Help & Support:") .setTitle("Help & Support:")
.setView(R.layout.dialog_layout) .setView(R.layout.dialog_layout)
.setPositiveButton(android.R.string.yes) { arg0, arg1 -> arg0.dismiss() } .setPositiveButton(android.R.string.ok) { arg0, _ -> arg0.dismiss() }
.create().show() .create().show()
return true return true
} }
@@ -120,12 +118,11 @@ class FragmentMain : BaseFragment<MainViewModel>(R.layout.fragment_main), BackPr
AlertDialog.Builder(context) AlertDialog.Builder(context)
.setTitle("Export?") .setTitle("Export?")
.setMessage("Exporting current filtered data. Continue?") .setMessage("Exporting current filtered data. Continue?")
.setNegativeButton(android.R.string.no, null) .setNegativeButton(android.R.string.cancel, null)
.setPositiveButton(android.R.string.yes) { arg0, arg1 -> exportData() } .setPositiveButton(android.R.string.ok) { _, _ -> exportData() }
.create().show() .create().show()
} else { } else {
Toast.makeText(context, "Storage permissions required", Toast.LENGTH_SHORT) displayToast("Storage permissions required")
.show()
} }
return true return true
} }
@@ -134,7 +131,7 @@ class FragmentMain : BaseFragment<MainViewModel>(R.layout.fragment_main), BackPr
AlertDialog.Builder(context) AlertDialog.Builder(context)
.setTitle("Info:") .setTitle("Info:")
.setMessage(viewModel.getInformation()) .setMessage(viewModel.getInformation())
.setPositiveButton(android.R.string.yes) { arg0, arg1 -> .setPositiveButton(android.R.string.ok) { arg0, _ ->
arg0.dismiss() arg0.dismiss()
}.create().show() }.create().show()
return true return true
@@ -144,7 +141,7 @@ class FragmentMain : BaseFragment<MainViewModel>(R.layout.fragment_main), BackPr
} }
private fun sortData() { private fun sortData() {
val groupName = Sortable.entries.map { it.label }.toTypedArray() val groupName = Sortable.values().map { it.label }.toTypedArray()
var sort = Sortable.ID var sort = Sortable.ID
val sortAndOrder = viewModel.getSortAndOrder() val sortAndOrder = viewModel.getSortAndOrder()
@@ -155,11 +152,11 @@ class FragmentMain : BaseFragment<MainViewModel>(R.layout.fragment_main), BackPr
.setSingleChoiceItems( .setSingleChoiceItems(
groupName, groupName,
checkedItem checkedItem
) { p0, p1 -> sort = Sortable.getEnumByType(groupName[p1]) } ) { _, p1 -> sort = Sortable.getEnumByType(groupName[p1]) }
.setPositiveButton("Ascending") { dialog, id -> .setPositiveButton("Ascending") { dialog, _ ->
viewModel.setSortAndOrder(sort) viewModel.setSortAndOrder(sort)
dialog.dismiss() dialog.dismiss()
}.setNegativeButton("Descending") { dialog, id -> }.setNegativeButton("Descending") { dialog, _ ->
viewModel.setSortAndOrder(sort, Order.DESCENDING) viewModel.setSortAndOrder(sort, Order.DESCENDING)
dialog.dismiss() dialog.dismiss()
} }
@@ -210,25 +207,25 @@ class FragmentMain : BaseFragment<MainViewModel>(R.layout.fragment_main), BackPr
super.onRequestPermissionsResult(requestCode, permissions, grantResults) super.onRequestPermissionsResult(requestCode, permissions, grantResults)
println("request code$requestCode") println("request code$requestCode")
if (requestCode == MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE) { if (requestCode == MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE) {
if (grantResults.size > 0 if (grantResults.isNotEmpty()
&& grantResults[0] == PackageManager.PERMISSION_GRANTED && grantResults[0] == PackageManager.PERMISSION_GRANTED
) { ) {
exportDialog() exportDialog()
} else { } else {
Toast.makeText(context, "Storage Permissions denied", Toast.LENGTH_SHORT).show() displayToast("Storage Permissions denied")
} }
} }
} }
fun exportDialog() { private fun exportDialog() {
AlertDialog.Builder(context) AlertDialog.Builder(context)
.setTitle("Export?") .setTitle("Export?")
.setMessage("Exporting current filtered data. Continue?") .setMessage("Exporting current filtered data. Continue?")
.setNegativeButton(android.R.string.no, null) .setNegativeButton(android.R.string.cancel, null)
.setPositiveButton(android.R.string.yes) { arg0, arg1 -> exportData() }.create().show() .setPositiveButton(android.R.string.ok) { _, _ -> exportData() }.create().show()
} }
fun checkStoragePermissions(activity: Activity?): Boolean { private fun checkStoragePermissions(activity: Activity?): Boolean {
var status = false var status = false
val permission = ActivityCompat.checkSelfPermission( val permission = ActivityCompat.checkSelfPermission(
activity!!, activity!!,

View File

@@ -12,7 +12,6 @@ import com.appttude.h_mal.farmr.data.legacydb.ShiftObject
import com.appttude.h_mal.farmr.model.ShiftType import com.appttude.h_mal.farmr.model.ShiftType
import com.appttude.h_mal.farmr.utils.CURRENCY import com.appttude.h_mal.farmr.utils.CURRENCY
import com.appttude.h_mal.farmr.utils.formatAsCurrencyString import com.appttude.h_mal.farmr.utils.formatAsCurrencyString
import com.appttude.h_mal.farmr.utils.formatToTwoDpString
import com.appttude.h_mal.farmr.utils.hide import com.appttude.h_mal.farmr.utils.hide
import com.appttude.h_mal.farmr.utils.navigateToFragment import com.appttude.h_mal.farmr.utils.navigateToFragment
import com.appttude.h_mal.farmr.utils.show import com.appttude.h_mal.farmr.utils.show

View File

@@ -1,11 +1,7 @@
package com.appttude.h_mal.farmr.ui package com.appttude.h_mal.farmr.ui
import android.Manifest import android.Manifest
import android.R.string.cancel
import android.R.string.ok
import android.app.Activity import android.app.Activity
import android.app.AlertDialog
import android.content.Intent
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.os.Bundle import android.os.Bundle
import android.view.Menu import android.view.Menu
@@ -14,10 +10,7 @@ import androidx.core.app.ActivityCompat
import com.appttude.h_mal.farmr.R import com.appttude.h_mal.farmr.R
import com.appttude.h_mal.farmr.base.BackPressedListener import com.appttude.h_mal.farmr.base.BackPressedListener
import com.appttude.h_mal.farmr.base.BaseActivity import com.appttude.h_mal.farmr.base.BaseActivity
import com.appttude.h_mal.farmr.utils.createDialog
import com.appttude.h_mal.farmr.utils.popBackStack import com.appttude.h_mal.farmr.utils.popBackStack
import com.appttude.h_mal.farmr.viewmodel.MainViewModel
import kotlin.system.exitProcess
class MainActivity : BaseActivity() { class MainActivity : BaseActivity() {
private lateinit var toolbar: Toolbar private lateinit var toolbar: Toolbar

View File

@@ -1,5 +1,6 @@
package com.appttude.h_mal.farmr.ui package com.appttude.h_mal.farmr.ui
import android.annotation.SuppressLint
import android.app.AlertDialog import android.app.AlertDialog
import android.os.Bundle import android.os.Bundle
import android.view.ViewGroup import android.view.ViewGroup
@@ -28,6 +29,7 @@ class ShiftListAdapter(
return BaseRecyclerAdapter.CurrentViewHolder(currentViewHolder) return BaseRecyclerAdapter.CurrentViewHolder(currentViewHolder)
} }
@SuppressLint("SetTextI18n")
override fun onBindViewHolder(holder: BaseRecyclerAdapter.CurrentViewHolder, position: Int) { override fun onBindViewHolder(holder: BaseRecyclerAdapter.CurrentViewHolder, position: Int) {
val view = holder.itemView val view = holder.itemView
val data = getItem(position) val data = getItem(position)
@@ -90,8 +92,8 @@ class ShiftListAdapter(
view.setOnLongClickListener { view.setOnLongClickListener {
AlertDialog.Builder(it.context) AlertDialog.Builder(it.context)
.setMessage("Are you sure you want to delete") .setMessage("Are you sure you want to delete")
.setPositiveButton("delete") { dialog, id -> longPressCallback.invoke(data.id) } .setPositiveButton("delete") { _, _ -> longPressCallback.invoke(data.id) }
.setNegativeButton("cancel") { dialog, id -> .setNegativeButton("cancel") { dialog, _ ->
dialog?.dismiss() dialog?.dismiss()
} }
.create().show() .create().show()

View File

@@ -1,18 +1,17 @@
package com.appttude.h_mal.farmr.ui package com.appttude.h_mal.farmr.ui
import android.annotation.SuppressLint
import android.app.Activity import android.app.Activity
import android.content.Intent import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.os.Handler import android.os.Handler
import android.os.Looper import android.os.Looper
import android.view.View
import android.widget.RelativeLayout
import androidx.core.app.ActivityOptionsCompat
import com.appttude.h_mal.farmr.R import com.appttude.h_mal.farmr.R
/** /**
* Created by h_mal on 27/06/2017. * Created by h_mal on 27/06/2017.
*/ */
@SuppressLint("CustomSplashScreen")
class SplashScreen : Activity() { class SplashScreen : Activity() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
@@ -20,13 +19,9 @@ class SplashScreen : Activity() {
val i = Intent(this@SplashScreen, MainActivity::class.java) val i = Intent(this@SplashScreen, MainActivity::class.java)
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_CLEAR_TASK) i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_CLEAR_TASK)
Handler().postDelayed({ Handler(Looper.getMainLooper()).postDelayed({
// This method will be executed once the timer is over
// Start your app main activity
// startActivity(i,bundle);
startActivity(i) startActivity(i)
overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out) overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out)
// finish();
}, SPLASH_TIME_OUT) }, SPLASH_TIME_OUT)
} }

View File

@@ -19,9 +19,7 @@ import androidx.annotation.AnimRes
import androidx.annotation.IdRes import androidx.annotation.IdRes
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentTransaction
import com.appttude.h_mal.farmr.R import com.appttude.h_mal.farmr.R
import com.appttude.h_mal.farmr.ui.FragmentAddItem
import java.util.Calendar import java.util.Calendar
fun View.show() { fun View.show() {
@@ -161,12 +159,12 @@ fun EditText.setDatePicker(onSelected: (String) -> Unit) {
} }
val mDatePicker = DatePickerDialog( val mDatePicker = DatePickerDialog(
(this.context), (this.context),
{ datepicker, selectedyear, selectedmonth, selectedday -> { _, selectedYear, selectedMonth, selectedDay ->
var currentMonth = selectedmonth var currentMonth = selectedMonth
val dateString = StringBuilder().append(selectedyear).append("-") val dateString = StringBuilder().append(selectedYear).append("-")
.append(String.format("%02d", (currentMonth + 1.also { currentMonth = it }))) .append(String.format("%02d", (currentMonth + 1.also { currentMonth = it })))
.append("-") .append("-")
.append(String.format("%02d", selectedday)) .append(String.format("%02d", selectedDay))
.toString() .toString()
setText(dateString) setText(dateString)
onSelected.invoke(dateString) onSelected.invoke(dateString)

View File

@@ -35,6 +35,5 @@ class InfoViewModel(
stringBuilder.append(" (+ ").append(shiftObject.breakMins).append(" minutes break)") stringBuilder.append(" (+ ").append(shiftObject.breakMins).append(" minutes break)")
} }
return stringBuilder.toString() return stringBuilder.toString()
} }
} }

View File

@@ -22,7 +22,6 @@ import com.appttude.h_mal.farmr.model.Order
import com.appttude.h_mal.farmr.model.ShiftType import com.appttude.h_mal.farmr.model.ShiftType
import com.appttude.h_mal.farmr.model.Sortable import com.appttude.h_mal.farmr.model.Sortable
import com.appttude.h_mal.farmr.model.Success import com.appttude.h_mal.farmr.model.Success
import com.appttude.h_mal.farmr.utils.CURRENCY
import com.appttude.h_mal.farmr.utils.convertDateString import com.appttude.h_mal.farmr.utils.convertDateString
import com.appttude.h_mal.farmr.utils.formatAsCurrencyString import com.appttude.h_mal.farmr.utils.formatAsCurrencyString
import com.appttude.h_mal.farmr.utils.sortedByOrder import com.appttude.h_mal.farmr.utils.sortedByOrder
@@ -239,7 +238,7 @@ class MainViewModel(
val data = shiftLiveData.value!!.applyFilters() val data = shiftLiveData.value!!.applyFilters()
.sortList(sortAndOrder.first, sortAndOrder.second) .sortList(sortAndOrder.first, sortAndOrder.second)
var currentRow = 0 var currentRow = 0
val cells = data.mapIndexed { index, shift -> val cells = data.map { shift ->
currentRow += 1 currentRow += 1
listOf( listOf(
Label(0, currentRow, shift.id.toString()), Label(0, currentRow, shift.id.toString()),

View File

@@ -2,9 +2,9 @@ package com.appttude.h_mal.farmr.viewmodel
import com.appttude.h_mal.farmr.base.BaseViewModel import com.appttude.h_mal.farmr.base.BaseViewModel
import com.appttude.h_mal.farmr.data.Repository import com.appttude.h_mal.farmr.data.Repository
import com.appttude.h_mal.farmr.data.prefs.DESCRIPTION
import com.appttude.h_mal.farmr.data.prefs.DATE_IN import com.appttude.h_mal.farmr.data.prefs.DATE_IN
import com.appttude.h_mal.farmr.data.prefs.DATE_OUT import com.appttude.h_mal.farmr.data.prefs.DATE_OUT
import com.appttude.h_mal.farmr.data.prefs.DESCRIPTION
import com.appttude.h_mal.farmr.data.prefs.TYPE import com.appttude.h_mal.farmr.data.prefs.TYPE
import com.appttude.h_mal.farmr.model.FilterStore import com.appttude.h_mal.farmr.model.FilterStore

View File

@@ -10,7 +10,6 @@ import io.mockk.mockk
import org.junit.Before import org.junit.Before
import org.junit.Test import org.junit.Test
import org.mockito.ArgumentMatchers.anyLong import org.mockito.ArgumentMatchers.anyLong
import java.util.UUID
import kotlin.test.assertEquals import kotlin.test.assertEquals
import kotlin.test.assertIs import kotlin.test.assertIs

View File

@@ -2,9 +2,12 @@ package com.appttude.h_mal.farmr.utils
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.lifecycle.Observer import androidx.lifecycle.Observer
import com.appttude.h_mal.farmr.data.legacydb.ShiftObject
import com.appttude.h_mal.farmr.model.ShiftType
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import org.mockito.ArgumentMatchers
import java.util.concurrent.CountDownLatch import java.util.concurrent.CountDownLatch
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
import java.util.concurrent.TimeoutException import java.util.concurrent.TimeoutException
@@ -36,4 +39,111 @@ fun <T> LiveData<T>.getOrAwaitValue(
fun sleep(millis: Long = 1000) { fun sleep(millis: Long = 1000) {
runBlocking(Dispatchers.Default) { delay(millis) } runBlocking(Dispatchers.Default) { delay(millis) }
} }
fun getShifts() = listOf(
ShiftObject(
ArgumentMatchers.anyLong(),
ShiftType.HOURLY.type,
"Day one",
"2023-08-01",
"12:00",
"13:00",
1f,
ArgumentMatchers.anyInt(),
ArgumentMatchers.anyFloat(),
10f,
10f
),
ShiftObject(
ArgumentMatchers.anyLong(),
ShiftType.HOURLY.type,
"Day two",
"2023-08-02",
"12:00",
"13:00",
1f,
ArgumentMatchers.anyInt(),
ArgumentMatchers.anyFloat(),
10f,
10f
),
ShiftObject(
ArgumentMatchers.anyLong(),
ShiftType.HOURLY.type,
"Day three",
"2023-08-03",
"12:00",
"13:00",
1f,
30,
ArgumentMatchers.anyFloat(),
10f,
5f
),
ShiftObject(
ArgumentMatchers.anyLong(),
ShiftType.HOURLY.type,
"Day four",
"2023-08-04",
"12:00",
"13:00",
1f,
30,
ArgumentMatchers.anyFloat(),
10f,
5f
),
ShiftObject(
ArgumentMatchers.anyLong(),
ShiftType.PIECE.type,
"Day five",
"2023-08-05",
ArgumentMatchers.anyString(),
ArgumentMatchers.anyString(),
ArgumentMatchers.anyFloat(),
ArgumentMatchers.anyInt(),
1f,
10f,
10f
),
ShiftObject(
ArgumentMatchers.anyLong(),
ShiftType.PIECE.type,
"Day six",
"2023-08-06",
ArgumentMatchers.anyString(),
ArgumentMatchers.anyString(),
ArgumentMatchers.anyFloat(),
ArgumentMatchers.anyInt(),
1f,
10f,
10f
),
ShiftObject(
ArgumentMatchers.anyLong(),
ShiftType.PIECE.type,
"Day seven",
"2023-08-07",
ArgumentMatchers.anyString(),
ArgumentMatchers.anyString(),
ArgumentMatchers.anyFloat(),
ArgumentMatchers.anyInt(),
1f,
10f,
10f
),
ShiftObject(
ArgumentMatchers.anyLong(),
ShiftType.PIECE.type,
"Day eight",
"2023-08-08",
ArgumentMatchers.anyString(),
ArgumentMatchers.anyString(),
ArgumentMatchers.anyFloat(),
ArgumentMatchers.anyInt(),
1f,
10f,
10f
),
)

View File

@@ -0,0 +1,93 @@
package com.appttude.h_mal.farmr.viewmodel
import android.os.Bundle
import com.appttude.h_mal.farmr.data.legacydb.ShiftObject
import com.appttude.h_mal.farmr.utils.ID
import io.mockk.every
import io.mockk.mockk
import org.junit.Assert.assertEquals
import org.junit.Test
import org.mockito.ArgumentMatchers.anyLong
import kotlin.test.assertIs
class InfoViewModelTest : ShiftViewModelTest<InfoViewModel>() {
@Test
fun retrieveData_validBundleAndId_successfulRetrieval() {
// Arrange
val id = anyLong()
val shift = mockk<ShiftObject>()
val bundle = mockk<Bundle>()
// Act
every { repository.readSingleShiftFromDatabase(id) }.returns(shift)
every { bundle.getLong(ID) }.returns(id)
viewModel.retrieveData(bundle)
// Assert
assertIs<ShiftObject>(retrieveCurrentData())
assertEquals(
retrieveCurrentData(),
shift
)
}
@Test
fun retrieveData_noValidBundleAndId_unsuccessfulRetrieval() {
// Arrange
val id = anyLong()
val shift = mockk<ShiftObject>()
val bundle = mockk<Bundle>()
// Act
every { repository.readSingleShiftFromDatabase(id) }.returns(shift)
every { bundle.getLong(ID) }.returns(id)
viewModel.retrieveData(null)
// Assert
assertEquals(
retrieveCurrentError(),
"Failed to retrieve shift"
)
}
@Test
fun retrieveData_validBundleNoShift_successfulRetrieval() {
// Arrange
val id = anyLong()
val bundle = mockk<Bundle>()
// Act
every { repository.readSingleShiftFromDatabase(id) }.returns(null)
every { bundle.getLong(ID) }.returns(id)
viewModel.retrieveData(bundle)
// Assert
assertEquals(
retrieveCurrentError(),
"Failed to retrieve shift"
)
}
@Test
fun buildDurationSummary_validHourlyShift_successfulRetrieval() {
// Arrange
val shift = getShifts()[0]
val shiftWithBreak = getShifts()[3]
// Act
val summary = viewModel.buildDurationSummary(shift)
val summaryWithBreak = viewModel.buildDurationSummary(shiftWithBreak)
// Assert
assertEquals(
"1 Hours 0 Minutes ",
summary
)
assertEquals(
"1 Hours 0 Minutes (+ 30 minutes break)",
summaryWithBreak
)
}
}

View File

@@ -10,17 +10,14 @@ import com.appttude.h_mal.farmr.data.prefs.TYPE
import com.appttude.h_mal.farmr.model.ShiftType import com.appttude.h_mal.farmr.model.ShiftType
import com.appttude.h_mal.farmr.model.ViewState import com.appttude.h_mal.farmr.model.ViewState
import com.appttude.h_mal.farmr.utils.getOrAwaitValue import com.appttude.h_mal.farmr.utils.getOrAwaitValue
import com.appttude.h_mal.farmr.utils.getShifts
import io.mockk.every import io.mockk.every
import io.mockk.mockk import io.mockk.mockk
import org.junit.Assert.assertThrows import org.junit.Assert.assertThrows
import org.junit.Before import org.junit.Before
import org.junit.Rule import org.junit.Rule
import org.junit.Test import org.junit.Test
import org.mockito.ArgumentMatchers.anyFloat
import org.mockito.ArgumentMatchers.anyInt
import org.mockito.ArgumentMatchers.anyList import org.mockito.ArgumentMatchers.anyList
import org.mockito.ArgumentMatchers.anyLong
import org.mockito.ArgumentMatchers.anyString
import java.util.concurrent.TimeoutException import java.util.concurrent.TimeoutException
import kotlin.test.assertEquals import kotlin.test.assertEquals
@@ -130,110 +127,4 @@ class MainViewModelTest {
Pair(TYPE, type) Pair(TYPE, type)
) )
private fun getShifts() = listOf(
ShiftObject(
anyLong(),
ShiftType.HOURLY.type,
"Day one",
"2023-08-01",
"12:00",
"13:00",
1f,
anyInt(),
anyFloat(),
10f,
10f
),
ShiftObject(
anyLong(),
ShiftType.HOURLY.type,
"Day two",
"2023-08-02",
"12:00",
"13:00",
1f,
anyInt(),
anyFloat(),
10f,
10f
),
ShiftObject(
anyLong(),
ShiftType.HOURLY.type,
"Day three",
"2023-08-03",
"12:00",
"13:00",
1f,
30,
anyFloat(),
10f,
5f
),
ShiftObject(
anyLong(),
ShiftType.HOURLY.type,
"Day four",
"2023-08-04",
"12:00",
"13:00",
1f,
30,
anyFloat(),
10f,
5f
),
ShiftObject(
anyLong(),
ShiftType.PIECE.type,
"Day five",
"2023-08-05",
anyString(),
anyString(),
anyFloat(),
anyInt(),
1f,
10f,
10f
),
ShiftObject(
anyLong(),
ShiftType.PIECE.type,
"Day six",
"2023-08-06",
anyString(),
anyString(),
anyFloat(),
anyInt(),
1f,
10f,
10f
),
ShiftObject(
anyLong(),
ShiftType.PIECE.type,
"Day seven",
"2023-08-07",
anyString(),
anyString(),
anyFloat(),
anyInt(),
1f,
10f,
10f
),
ShiftObject(
anyLong(),
ShiftType.PIECE.type,
"Day eight",
"2023-08-08",
anyString(),
anyString(),
anyFloat(),
anyInt(),
1f,
10f,
10f
),
)
} }

2
fastlane/Appfile Normal file
View File

@@ -0,0 +1,2 @@
json_key_file("google-play-key.json") # Path to the json secret file - Follow https://docs.fastlane.tools/actions/supply/#setup to get one
package_name("com.appttude.h_mal.farmr") # e.g. com.krausefx.app

29
fastlane/Fastfile Normal file
View File

@@ -0,0 +1,29 @@
# This file contains the fastlane.tools configuration
# You can find the documentation at https://docs.fastlane.tools
#
# For a list of all available actions, check out
#
# https://docs.fastlane.tools/actions
#
# For a list of all available plugins, check out
#
# https://docs.fastlane.tools/plugins/available-plugins
#
# Uncomment the line if you want fastlane to automatically update itself
# update_fastlane
default_platform(:android)
platform :android do
desc "Runs all the tests"
lane :test do
gradle(task: "test")
end
desc "Deploy a new version to the Google Play"
lane :deploy do
gradle(task: "clean assembleRelease")
upload_to_play_store
end
end

40
fastlane/README.md Normal file
View File

@@ -0,0 +1,40 @@
fastlane documentation
----
# Installation
Make sure you have the latest version of the Xcode command line tools installed:
```sh
xcode-select --install
```
For _fastlane_ installation instructions, see [Installing _fastlane_](https://docs.fastlane.tools/#installing-fastlane)
# Available Actions
## Android
### android test
```sh
[bundle exec] fastlane android test
```
Runs all the tests
### android deploy
```sh
[bundle exec] fastlane android deploy
```
Deploy a new version to the Google Play
----
This README.md is auto-generated and will be re-generated every time [_fastlane_](https://fastlane.tools) is run.
More information about _fastlane_ can be found on [fastlane.tools](https://fastlane.tools).
The documentation of _fastlane_ can be found on [docs.fastlane.tools](https://docs.fastlane.tools).