mirror of
https://github.com/hmalik144/Farmr.git
synced 2025-12-10 02:25:19 +00:00
- Test suite expanded
- config.yml updated -
This commit is contained in:
@@ -1,26 +1,130 @@
|
||||
# Use the latest 2.1 version of CircleCI pipeline process engine.
|
||||
# See: https://circleci.com/docs/configuration-reference
|
||||
# See: https://circleci.com/docs/2.0/configuration-reference
|
||||
# For a detailed guide to building and testing on Android, read the docs:
|
||||
# https://circleci.com/docs/2.0/language-android/ for more details.
|
||||
version: 2.1
|
||||
|
||||
# Define a job to be invoked later in a workflow.
|
||||
# See: https://circleci.com/docs/configuration-reference/#jobs
|
||||
jobs:
|
||||
say-hello:
|
||||
# Specify the execution environment. You can specify an image from Docker Hub or use one of our convenience images from CircleCI's Developer Hub.
|
||||
# See: https://circleci.com/docs/configuration-reference/#executor-job
|
||||
docker:
|
||||
- image: cimg/base:stable
|
||||
# Add steps to the job
|
||||
# See: https://circleci.com/docs/configuration-reference/#steps
|
||||
# Orbs are reusable packages of CircleCI configuration that you may share across projects, enabling you to create encapsulated, parameterized commands, jobs, and executors that can be used across multiple projects.
|
||||
# See: https://circleci.com/docs/2.0/orb-intro/
|
||||
orbs:
|
||||
android: circleci/android@2.3.0
|
||||
|
||||
commands:
|
||||
setup_repo:
|
||||
description: checkout repo and android dependencies
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
name: "Say hello"
|
||||
command: "echo Hello, World!"
|
||||
|
||||
# Orchestrate jobs using workflows
|
||||
# See: https://circleci.com/docs/configuration-reference/#workflows
|
||||
name: Give gradle permissions
|
||||
command: |
|
||||
sudo chmod +x ./gradlew
|
||||
- android/restore-gradle-cache
|
||||
run_tests:
|
||||
description: run tests for flavour specified
|
||||
steps:
|
||||
# The next step will run the unit tests
|
||||
- run:
|
||||
name: Run local unit tests
|
||||
command: |
|
||||
./gradlew testDebugUnitTest
|
||||
- android/save-gradle-cache
|
||||
- store_artifacts:
|
||||
path: app/build/reports
|
||||
destination: reports
|
||||
- store_test_results:
|
||||
path: app/build/test-results
|
||||
run_ui_tests:
|
||||
description: run instrumentation and espresso tests
|
||||
steps:
|
||||
- android/start-emulator-and-run-tests:
|
||||
post-emulator-launch-assemble-command: ./gradlew assembleAndroidTest
|
||||
test-command: ./gradlew connectedDebugAndroidTest --continue
|
||||
system-image: system-images;android-26;google_apis;x86
|
||||
# store screenshots for failed ui tests
|
||||
- when:
|
||||
condition: on_fail
|
||||
steps:
|
||||
- store_artifacts:
|
||||
path: app/build/outputs/connected_android_test_additional_output/debugAndroidTest/connected
|
||||
destination: connected_android_test
|
||||
# store test reports
|
||||
- store_artifacts:
|
||||
path: app/build/reports/androidTests/connected
|
||||
destination: reports
|
||||
- store_test_results:
|
||||
path: app/build/outputs/androidTest-results/connected
|
||||
deploy_to_play_store:
|
||||
description: deploy to playstore
|
||||
steps:
|
||||
# The next step will run the unit tests
|
||||
- android/decode-keystore:
|
||||
keystore-location: "./app/keystore.jks"
|
||||
- run:
|
||||
name: Setup playstore key
|
||||
command: |
|
||||
echo "$GOOGLE_PLAY_KEY" > "google-play-key.json"
|
||||
- run:
|
||||
name: Run fastlane command to deploy to playstore
|
||||
command: |
|
||||
pwd
|
||||
bundle exec fastlane deploy
|
||||
- store_test_results:
|
||||
path: fastlane/report.xml
|
||||
# Define a job to be invoked later in a workflow.
|
||||
# See: https://circleci.com/docs/2.0/configuration-reference/#jobs
|
||||
jobs:
|
||||
# Below is the definition of your job to build and test your app, you can rename and customize it as you want.
|
||||
build-and-test:
|
||||
# These next lines define the Android machine image executor.
|
||||
# See: https://circleci.com/docs/2.0/executor-types/
|
||||
executor:
|
||||
name: android/android-machine
|
||||
tag: 2023.05.1
|
||||
# Add steps to the job
|
||||
# See: https://circleci.com/docs/2.0/configuration-reference/#steps
|
||||
steps:
|
||||
- setup_repo
|
||||
- run_tests
|
||||
run_instrumentation_test:
|
||||
# These next lines define the Android machine image executor.
|
||||
# See: https://circleci.com/docs/2.0/executor-types/
|
||||
executor:
|
||||
name: android/android-machine
|
||||
tag: 2023.05.1
|
||||
# Add steps to the job
|
||||
# See: https://circleci.com/docs/2.0/configuration-reference/#steps
|
||||
steps:
|
||||
- setup_repo
|
||||
- run_ui_tests
|
||||
deploy-to-playstore:
|
||||
docker:
|
||||
- image: cimg/android:2023.07-browsers
|
||||
auth:
|
||||
username: ${DOCKER_USERNAME}
|
||||
password: ${DOCKER_PASSWORD}
|
||||
steps:
|
||||
- setup_repo
|
||||
- deploy_to_play_store
|
||||
# Invoke jobs via workflows
|
||||
# See: https://circleci.com/docs/2.0/configuration-reference/#workflows
|
||||
workflows:
|
||||
say-hello-workflow:
|
||||
version: 2
|
||||
build-release:
|
||||
jobs:
|
||||
- say-hello
|
||||
- build-and-test:
|
||||
context: appttude
|
||||
- run_instrumentation_test:
|
||||
context: appttude
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- release
|
||||
- deploy-to-playstore:
|
||||
context: appttude
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
- release
|
||||
requires:
|
||||
- build-and-test
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -88,7 +88,7 @@ gen-external-apklibs
|
||||
.idea/uiDesigner.xml
|
||||
.idea/assetWizardSettings.xml
|
||||
.idea/gradle.xml
|
||||
.idea/jarRepositorie
|
||||
.idea/jarRepositories.xml
|
||||
|
||||
# Gem/fastlane
|
||||
Gemfile.lock
|
||||
|
||||
22
.idea/androidTestResultsUserPreferences.xml
generated
22
.idea/androidTestResultsUserPreferences.xml
generated
@@ -1,22 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="AndroidTestResultsUserPreferences">
|
||||
<option name="androidTestResultsTableState">
|
||||
<map>
|
||||
<entry key="1283002349">
|
||||
<value>
|
||||
<AndroidTestResultsTableState>
|
||||
<option name="preferredColumnWidths">
|
||||
<map>
|
||||
<entry key="Duration" value="90" />
|
||||
<entry key="Pixel_6_Pro_API_31" value="120" />
|
||||
<entry key="Tests" value="360" />
|
||||
</map>
|
||||
</option>
|
||||
</AndroidTestResultsTableState>
|
||||
</value>
|
||||
</entry>
|
||||
</map>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
||||
127
.idea/assetWizardSettings.xml
generated
127
.idea/assetWizardSettings.xml
generated
@@ -1,127 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="WizardSettings">
|
||||
<option name="children">
|
||||
<map>
|
||||
<entry key="imageWizard">
|
||||
<value>
|
||||
<PersistentState>
|
||||
<option name="children">
|
||||
<map>
|
||||
<entry key="imageAssetPanel">
|
||||
<value>
|
||||
<PersistentState>
|
||||
<option name="children">
|
||||
<map>
|
||||
<entry key="actionbar">
|
||||
<value>
|
||||
<PersistentState>
|
||||
<option name="children">
|
||||
<map>
|
||||
<entry key="clipArt">
|
||||
<value>
|
||||
<PersistentState>
|
||||
<option name="values">
|
||||
<map>
|
||||
<entry key="color" value="000000" />
|
||||
<entry key="opacityPercent" value="80" />
|
||||
</map>
|
||||
</option>
|
||||
</PersistentState>
|
||||
</value>
|
||||
</entry>
|
||||
</map>
|
||||
</option>
|
||||
<option name="values">
|
||||
<map>
|
||||
<entry key="theme" value="HOLO_DARK" />
|
||||
<entry key="themeColor" value="ffffff" />
|
||||
</map>
|
||||
</option>
|
||||
</PersistentState>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="launcher">
|
||||
<value>
|
||||
<PersistentState>
|
||||
<option name="children">
|
||||
<map>
|
||||
<entry key="foregroundImage">
|
||||
<value>
|
||||
<PersistentState>
|
||||
<option name="values">
|
||||
<map>
|
||||
<entry key="color" value="000000" />
|
||||
<entry key="scalingPercent" value="69" />
|
||||
</map>
|
||||
</option>
|
||||
</PersistentState>
|
||||
</value>
|
||||
</entry>
|
||||
</map>
|
||||
</option>
|
||||
<option name="values">
|
||||
<map>
|
||||
<entry key="foregroundImage" value="C:\Users\h_mal\Desktop\Farmr\farmicon.png" />
|
||||
<entry key="outputName" value="ic_launcher_release" />
|
||||
</map>
|
||||
</option>
|
||||
</PersistentState>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="launcherLegacy">
|
||||
<value>
|
||||
<PersistentState>
|
||||
<option name="children">
|
||||
<map>
|
||||
<entry key="clipArt">
|
||||
<value>
|
||||
<PersistentState>
|
||||
<option name="values">
|
||||
<map>
|
||||
<entry key="color" value="000000" />
|
||||
</map>
|
||||
</option>
|
||||
</PersistentState>
|
||||
</value>
|
||||
</entry>
|
||||
</map>
|
||||
</option>
|
||||
</PersistentState>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="notification">
|
||||
<value>
|
||||
<PersistentState>
|
||||
<option name="children">
|
||||
<map>
|
||||
<entry key="clipArt">
|
||||
<value>
|
||||
<PersistentState>
|
||||
<option name="values">
|
||||
<map>
|
||||
<entry key="color" value="000000" />
|
||||
</map>
|
||||
</option>
|
||||
</PersistentState>
|
||||
</value>
|
||||
</entry>
|
||||
</map>
|
||||
</option>
|
||||
</PersistentState>
|
||||
</value>
|
||||
</entry>
|
||||
</map>
|
||||
</option>
|
||||
</PersistentState>
|
||||
</value>
|
||||
</entry>
|
||||
</map>
|
||||
</option>
|
||||
</PersistentState>
|
||||
</value>
|
||||
</entry>
|
||||
</map>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
||||
BIN
.idea/caches/build_file_checksums.ser
generated
BIN
.idea/caches/build_file_checksums.ser
generated
Binary file not shown.
BIN
.idea/caches/gradle_models.ser
generated
BIN
.idea/caches/gradle_models.ser
generated
Binary file not shown.
6
.idea/compiler.xml
generated
6
.idea/compiler.xml
generated
@@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="CompilerConfiguration">
|
||||
<bytecodeTargetLevel target="17" />
|
||||
</component>
|
||||
</project>
|
||||
21
.idea/gradle.xml
generated
21
.idea/gradle.xml
generated
@@ -1,21 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="GradleMigrationSettings" migrationVersion="1" />
|
||||
<component name="GradleSettings">
|
||||
<option name="linkedExternalProjectsSettings">
|
||||
<GradleProjectSettings>
|
||||
<option name="delegatedBuild" value="false" />
|
||||
<option name="testRunner" value="GRADLE" />
|
||||
<option name="distributionType" value="DEFAULT_WRAPPED" />
|
||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||
<option name="gradleJvm" value="jbr-17" />
|
||||
<option name="modules">
|
||||
<set>
|
||||
<option value="$PROJECT_DIR$" />
|
||||
<option value="$PROJECT_DIR$/app" />
|
||||
</set>
|
||||
</option>
|
||||
</GradleProjectSettings>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
||||
30
.idea/jarRepositories.xml
generated
30
.idea/jarRepositories.xml
generated
@@ -1,30 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="RemoteRepositoriesConfiguration">
|
||||
<remote-repository>
|
||||
<option name="id" value="central" />
|
||||
<option name="name" value="Maven Central repository" />
|
||||
<option name="url" value="https://repo1.maven.org/maven2" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="jboss.community" />
|
||||
<option name="name" value="JBoss Community repository" />
|
||||
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="BintrayJCenter" />
|
||||
<option name="name" value="BintrayJCenter" />
|
||||
<option name="url" value="https://jcenter.bintray.com/" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="maven" />
|
||||
<option name="name" value="maven" />
|
||||
<option name="url" value="https://jitpack.io" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="Google" />
|
||||
<option name="name" value="Google" />
|
||||
<option name="url" value="https://dl.google.com/dl/android/maven2/" />
|
||||
</remote-repository>
|
||||
</component>
|
||||
</project>
|
||||
47
.idea/misc.xml
generated
47
.idea/misc.xml
generated
@@ -1,47 +0,0 @@
|
||||
<project version="4">
|
||||
<component name="NullableNotNullManager">
|
||||
<option name="myDefaultNullable" value="android.support.annotation.Nullable" />
|
||||
<option name="myDefaultNotNull" value="android.support.annotation.NonNull" />
|
||||
<option name="myNullables">
|
||||
<value>
|
||||
<list size="12">
|
||||
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
|
||||
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
|
||||
<item index="2" class="java.lang.String" itemvalue="javax.annotation.CheckForNull" />
|
||||
<item index="3" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
|
||||
<item index="4" class="java.lang.String" itemvalue="android.support.annotation.Nullable" />
|
||||
<item index="5" class="java.lang.String" itemvalue="androidx.annotation.Nullable" />
|
||||
<item index="6" class="java.lang.String" itemvalue="androidx.annotation.RecentlyNullable" />
|
||||
<item index="7" class="java.lang.String" itemvalue="android.annotation.Nullable" />
|
||||
<item index="8" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.qual.Nullable" />
|
||||
<item index="9" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NullableDecl" />
|
||||
<item index="10" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NullableType" />
|
||||
<item index="11" class="java.lang.String" itemvalue="com.android.annotations.Nullable" />
|
||||
</list>
|
||||
</value>
|
||||
</option>
|
||||
<option name="myNotNulls">
|
||||
<value>
|
||||
<list size="11">
|
||||
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
|
||||
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
|
||||
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
|
||||
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.NonNull" />
|
||||
<item index="4" class="java.lang.String" itemvalue="androidx.annotation.NonNull" />
|
||||
<item index="5" class="java.lang.String" itemvalue="androidx.annotation.RecentlyNonNull" />
|
||||
<item index="6" class="java.lang.String" itemvalue="android.annotation.NonNull" />
|
||||
<item index="7" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.qual.NonNull" />
|
||||
<item index="8" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NonNullDecl" />
|
||||
<item index="9" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NonNullType" />
|
||||
<item index="10" class="java.lang.String" itemvalue="com.android.annotations.NonNull" />
|
||||
</list>
|
||||
</value>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="jbr-17" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||
</component>
|
||||
<component name="ProjectType">
|
||||
<option name="id" value="Android" />
|
||||
</component>
|
||||
</project>
|
||||
12
.idea/modules.xml
generated
12
.idea/modules.xml
generated
@@ -1,12 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/Farmr.iml" filepath="$PROJECT_DIR$/.idea/modules/Farmr.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/app/Farmr.app.iml" filepath="$PROJECT_DIR$/.idea/modules/app/Farmr.app.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/app/Farmr.app.androidTest.iml" filepath="$PROJECT_DIR$/.idea/modules/app/Farmr.app.androidTest.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/app/Farmr.app.main.iml" filepath="$PROJECT_DIR$/.idea/modules/app/Farmr.app.main.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/app/Farmr.app.unitTest.iml" filepath="$PROJECT_DIR$/.idea/modules/app/Farmr.app.unitTest.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
6
.idea/vcs.xml
generated
6
.idea/vcs.xml
generated
@@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
@@ -10,7 +10,7 @@ android {
|
||||
targetSdkVersion 31
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
|
||||
testInstrumentationRunner 'com.appttude.h_mal.farmr.application.TestRunner'
|
||||
vectorDrawables.useSupportLibrary = true
|
||||
}
|
||||
buildTypes {
|
||||
@@ -19,6 +19,7 @@ android {
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
useLibrary 'android.test.mock'
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.appttude.h_mal.farmr.application
|
||||
|
||||
import androidx.test.espresso.IdlingRegistry
|
||||
import androidx.test.espresso.idling.CountingIdlingResource
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import com.appttude.h_mal.farmr.base.BaseApplication
|
||||
import com.appttude.h_mal.farmr.data.legacydb.LegacyDatabase
|
||||
import com.appttude.h_mal.farmr.data.prefs.PreferenceProvider
|
||||
import com.appttude.h_mal.farmr.model.Shift
|
||||
|
||||
class TestAppClass : BaseApplication() {
|
||||
private val idlingResources = CountingIdlingResource("Data_loader")
|
||||
|
||||
lateinit var database: LegacyDatabase
|
||||
lateinit var preferenceProvider: PreferenceProvider
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
IdlingRegistry.getInstance().register(idlingResources)
|
||||
}
|
||||
|
||||
override fun createDatabase(): LegacyDatabase {
|
||||
database =
|
||||
LegacyDatabase(InstrumentationRegistry.getInstrumentation().context.contentResolver)
|
||||
return database
|
||||
}
|
||||
|
||||
override fun createPrefs(): PreferenceProvider {
|
||||
preferenceProvider = PreferenceProvider(this)
|
||||
return preferenceProvider
|
||||
}
|
||||
|
||||
fun addToDatabase(shift: Shift) = database.insertShiftDataIntoDatabase(shift)
|
||||
fun addShiftsToDatabase(shifts: List<Shift>) = shifts.forEach { addToDatabase(it) }
|
||||
fun clearDatabase() = database.deleteAllShiftsInDatabase()
|
||||
fun cleanPrefs() = preferenceProvider.clearPrefs()
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.appttude.h_mal.farmr.application
|
||||
|
||||
import android.app.Application
|
||||
import android.content.Context
|
||||
import androidx.test.runner.AndroidJUnitRunner
|
||||
|
||||
class TestRunner : AndroidJUnitRunner() {
|
||||
@Throws(
|
||||
InstantiationException::class,
|
||||
IllegalAccessException::class,
|
||||
ClassNotFoundException::class
|
||||
)
|
||||
override fun newApplication(
|
||||
cl: ClassLoader?,
|
||||
className: String?,
|
||||
context: Context?
|
||||
): Application {
|
||||
return super.newApplication(cl, TestAppClass::class.java.name, context)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -19,6 +19,7 @@ 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.assertNull
|
||||
import org.junit.After
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
|
||||
@@ -31,6 +32,11 @@ class ShiftProviderTest {
|
||||
private val contentResolver: ContentResolver
|
||||
get() = providerRule.resolver
|
||||
|
||||
@After
|
||||
fun tearDown() {
|
||||
contentResolver.delete(CONTENT_URI, null, null)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun insertEntry_queryEntry_assertEntry() {
|
||||
// Arrange
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
package com.appttude.h_mal.farmr.data.ui.robots
|
||||
|
||||
import com.appttude.h_mal.farmr.R
|
||||
import com.appttude.h_mal.farmr.base.BaseRecyclerAdapter.CurrentViewHolder
|
||||
import com.appttude.h_mal.farmr.data.ui.BaseTestRobot
|
||||
|
||||
fun homeScreen(func: HomeScreenRobot.() -> Unit) = HomeScreenRobot().apply { func() }
|
||||
class HomeScreenRobot : BaseTestRobot() {
|
||||
|
||||
fun clickOnItem(position: Int) = clickViewInRecyclerAtPosition<CurrentViewHolder>(R.id.list_item_view, position)
|
||||
fun clickOnItemWithText(text: String) = clickOnRecyclerItemWithText<CurrentViewHolder>(R.id.list_item_view, text)
|
||||
fun clickOnEdit(position: Int) = clickViewInRecycler<CurrentViewHolder>(R.id.list_item_view, R.id.imageView)
|
||||
fun clickFab() = clickButton(R.id.fab1)
|
||||
fun clickOnInfo() = clickButton(R.id.action_favorite)
|
||||
// fun clearFilter() =
|
||||
// fun applySort() =
|
||||
|
||||
|
||||
// fun verifyCurrentLocation(location: String) = matchText(R.id.location_main_4, location)
|
||||
// fun refresh() = pullToRefresh(R.id.swipe_refresh)
|
||||
// fun isDisplayed() = matchViewWaitFor(R.id.temp_main_4)
|
||||
// fun verifyUnableToRetrieve() {
|
||||
// matchText(R.id.header_text, R.string.retrieve_warning)
|
||||
// matchText(R.id.body_text, R.string.empty_retrieve_warning)
|
||||
// }
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
package com.appttude.h_mal.farmr.data.ui.tests
|
||||
|
||||
import com.appttude.h_mal.farmr.data.ui.BaseTest
|
||||
import com.appttude.h_mal.farmr.data.ui.robots.addScreen
|
||||
import com.appttude.h_mal.farmr.data.ui.robots.homeScreen
|
||||
import com.appttude.h_mal.farmr.data.ui.robots.viewScreen
|
||||
import com.appttude.h_mal.farmr.model.ShiftType
|
||||
import com.appttude.h_mal.farmr.ui.MainActivity
|
||||
import org.junit.Test
|
||||
|
||||
class ShiftTests: BaseTest<MainActivity>(MainActivity::class.java) {
|
||||
|
||||
// Add a shift successfully
|
||||
@Test
|
||||
fun test1() {
|
||||
homeScreen {
|
||||
clickFab()
|
||||
}
|
||||
addScreen {
|
||||
setDescription("This is a description")
|
||||
setDate(2023, 2, 11)
|
||||
clickShiftType(ShiftType.HOURLY)
|
||||
setTimeIn(12,0)
|
||||
setTimeOut(14, 30)
|
||||
setBreakTime(30)
|
||||
setRateOfPay(10f)
|
||||
assertDuration("2.0 hours")
|
||||
assertTotalPay("£20.00")
|
||||
submit()
|
||||
}
|
||||
homeScreen {
|
||||
sc("This is a description")
|
||||
}
|
||||
}
|
||||
|
||||
// Edit a shift successfully
|
||||
@Test
|
||||
fun test2() {
|
||||
homeScreen {
|
||||
clickOnItemWithText("Edit this shift")
|
||||
}
|
||||
addScreen {
|
||||
setRateOfPay(20f)
|
||||
assertDuration("2.0 hours")
|
||||
assertTotalPay("£40.00")
|
||||
submit()
|
||||
}
|
||||
homeScreen {
|
||||
clickOnItemWithText("Edit this shift")
|
||||
}
|
||||
viewScreen {
|
||||
matchDescription("Edit this shift")
|
||||
matchDuration("2 Hours 0 minutes")
|
||||
matchTotalPay("2.0 hours @ £20.00 per Hour\nEquals:£40.00")
|
||||
}
|
||||
}
|
||||
|
||||
// filter the list with date from
|
||||
@Test
|
||||
fun test3() {}
|
||||
|
||||
// filter the list with date to
|
||||
@Test
|
||||
fun test4() {}
|
||||
|
||||
// Add a shift as piece rate
|
||||
@Test
|
||||
fun test5() {}
|
||||
|
||||
// Validate the details screen
|
||||
@Test
|
||||
fun test6() {}
|
||||
|
||||
// filter, sort, order and then reset
|
||||
@Test
|
||||
fun test7() {}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
package com.appttude.h_mal.farmr.data.ui.utils
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.appttude.h_mal.farmr.data.ui
|
||||
package com.appttude.h_mal.farmr.ui
|
||||
|
||||
import android.Manifest
|
||||
import android.app.Activity
|
||||
@@ -6,7 +6,9 @@ import android.content.Intent
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.test.core.app.ActivityScenario
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
import androidx.test.espresso.Espresso
|
||||
import androidx.test.espresso.UiController
|
||||
import androidx.test.espresso.ViewAction
|
||||
@@ -15,13 +17,16 @@ import androidx.test.espresso.matcher.RootMatchers.withDecorView
|
||||
import androidx.test.espresso.matcher.ViewMatchers
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import androidx.test.rule.GrantPermissionRule
|
||||
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 kotlinx.coroutines.runBlocking
|
||||
import org.hamcrest.Matcher
|
||||
import org.hamcrest.Matchers
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.kodein.di.android.kodein
|
||||
|
||||
@Suppress("EmptyMethod")
|
||||
open class BaseTest<A : Activity>(
|
||||
@@ -30,7 +35,7 @@ open class BaseTest<A : Activity>(
|
||||
) {
|
||||
|
||||
lateinit var scenario: ActivityScenario<A>
|
||||
private lateinit var testApp: ShiftApplication
|
||||
private lateinit var testApp: TestAppClass
|
||||
private lateinit var testActivity: Activity
|
||||
private lateinit var decorView: View
|
||||
|
||||
@@ -38,7 +43,7 @@ open class BaseTest<A : Activity>(
|
||||
var permissionRule = GrantPermissionRule.grant(Manifest.permission.READ_EXTERNAL_STORAGE)
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
open fun setUp() {
|
||||
val startIntent =
|
||||
Intent(InstrumentationRegistry.getInstrumentation().targetContext, activity)
|
||||
if (intentBundle != null) {
|
||||
@@ -46,13 +51,17 @@ open class BaseTest<A : Activity>(
|
||||
}
|
||||
|
||||
testApp =
|
||||
InstrumentationRegistry.getInstrumentation().targetContext.applicationContext as ShiftApplication
|
||||
InstrumentationRegistry.getInstrumentation().targetContext.applicationContext as TestAppClass
|
||||
kodein(testApp)
|
||||
runBlocking {
|
||||
beforeLaunch()
|
||||
}
|
||||
|
||||
scenario = ActivityScenario.launch(startIntent)
|
||||
scenario.onActivity {
|
||||
testApp =
|
||||
InstrumentationRegistry.getInstrumentation().targetContext.applicationContext as TestAppClass
|
||||
onLaunch()
|
||||
decorView = it.window.decorView
|
||||
testActivity = it
|
||||
}
|
||||
@@ -67,6 +76,7 @@ open class BaseTest<A : Activity>(
|
||||
}
|
||||
|
||||
open fun beforeLaunch() {}
|
||||
open fun onLaunch() {}
|
||||
open fun afterLaunch() {}
|
||||
open fun testFinished() {}
|
||||
|
||||
@@ -88,4 +98,13 @@ open class BaseTest<A : Activity>(
|
||||
waitFor(3500)
|
||||
}
|
||||
}
|
||||
|
||||
fun navigateBack() = Espresso.pressBack()
|
||||
|
||||
fun addRandomShifts() {
|
||||
testApp.addShiftsToDatabase(getShifts())
|
||||
}
|
||||
|
||||
fun clearDataBase() = testApp.clearDatabase()
|
||||
fun clearPrefs() = testApp.cleanPrefs()
|
||||
}
|
||||
@@ -1,12 +1,18 @@
|
||||
package com.appttude.h_mal.farmr.data.ui
|
||||
package com.appttude.h_mal.farmr.ui
|
||||
|
||||
import android.content.res.Resources
|
||||
import android.view.View
|
||||
import android.widget.DatePicker
|
||||
import android.widget.TimePicker
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.appcompat.widget.AppCompatButton
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.recyclerview.widget.RecyclerView.ViewHolder
|
||||
import androidx.test.espresso.Espresso.onData
|
||||
import androidx.test.espresso.Espresso.onView
|
||||
import androidx.test.espresso.Espresso.openActionBarOverflowOrOptionsMenu
|
||||
import androidx.test.espresso.UiController
|
||||
import androidx.test.espresso.ViewAction
|
||||
import androidx.test.espresso.ViewInteraction
|
||||
import androidx.test.espresso.action.ViewActions
|
||||
import androidx.test.espresso.action.ViewActions.click
|
||||
@@ -14,11 +20,15 @@ import androidx.test.espresso.action.ViewActions.swipeDown
|
||||
import androidx.test.espresso.assertion.ViewAssertions.matches
|
||||
import androidx.test.espresso.contrib.PickerActions
|
||||
import androidx.test.espresso.contrib.RecyclerViewActions
|
||||
import androidx.test.espresso.matcher.RootMatchers.isDialog
|
||||
import androidx.test.espresso.matcher.ViewMatchers.*
|
||||
import com.appttude.h_mal.farmr.data.ui.utils.EspressoHelper.waitForView
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import com.appttude.h_mal.farmr.ui.utils.EspressoHelper.waitForView
|
||||
import org.hamcrest.CoreMatchers.allOf
|
||||
import org.hamcrest.CoreMatchers.anything
|
||||
import org.hamcrest.CoreMatchers.equalTo
|
||||
import org.hamcrest.Matcher
|
||||
import org.hamcrest.Matchers
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
open class BaseTestRobot {
|
||||
@@ -54,6 +64,17 @@ open class BaseTestRobot {
|
||||
.atPosition(position).perform(click())
|
||||
}
|
||||
|
||||
fun clickOnMenuItem(menuId: Int) {
|
||||
openActionBarOverflowOrOptionsMenu(InstrumentationRegistry.getInstrumentation().context)
|
||||
onView(withText(menuId)).perform(click())
|
||||
}
|
||||
|
||||
fun clickDialogButton(text: String) {
|
||||
onView(withText(text)).inRoot(isDialog())
|
||||
.check(matches(isDisplayed()))
|
||||
.perform(click());
|
||||
}
|
||||
|
||||
fun <VH : ViewHolder> scrollToRecyclerItem(recyclerId: Int, text: String): ViewInteraction? {
|
||||
return matchView(recyclerId)
|
||||
.perform(
|
||||
@@ -88,14 +109,6 @@ open class BaseTestRobot {
|
||||
)
|
||||
}
|
||||
|
||||
fun <VH : ViewHolder> clickViewInRecycler(recyclerId: Int, text: String) {
|
||||
matchView(recyclerId)
|
||||
.perform(
|
||||
// scrollTo will fail the test if no item matches.
|
||||
RecyclerViewActions.actionOnItem<VH>(hasDescendant(withText(text)), click())
|
||||
)
|
||||
}
|
||||
|
||||
fun <VH : ViewHolder> clickViewInRecycler(recyclerId: Int, resIdForString: Int) {
|
||||
matchView(recyclerId)
|
||||
.perform(
|
||||
@@ -107,21 +120,50 @@ open class BaseTestRobot {
|
||||
)
|
||||
}
|
||||
|
||||
fun <VH : ViewHolder> clickViewInRecyclerAtPosition(recyclerId: Int, position: Int) {
|
||||
fun <VH : ViewHolder> clickRecyclerAtPosition(recyclerId: Int, position: Int) {
|
||||
matchView(recyclerId)
|
||||
.perform(
|
||||
// scrollTo will fail the test if no item matches.
|
||||
RecyclerViewActions.scrollToPosition<VH>(position),
|
||||
RecyclerViewActions.actionOnItemAtPosition<VH>(position, click())
|
||||
RecyclerViewActions.actionOnItemAtPosition<VH>(position, click()),
|
||||
)
|
||||
}
|
||||
|
||||
fun <VH : ViewHolder> clickViewInRecyclerAtPosition(recyclerId: Int, position: Int, subViewId: Int) {
|
||||
matchView(recyclerId)
|
||||
.perform(
|
||||
// scrollTo will fail the test if no item matches.
|
||||
RecyclerViewActions.scrollToPosition<VH>(position),
|
||||
RecyclerViewActions.actionOnItemAtPosition<VH>(position, object : ViewAction {
|
||||
override fun getDescription(): String {
|
||||
return "click on subview in RecyclerView at position: $position"
|
||||
}
|
||||
|
||||
override fun getConstraints(): Matcher<View> {
|
||||
return Matchers.allOf(
|
||||
isAssignableFrom(
|
||||
RecyclerView::class.java
|
||||
), isDisplayed()
|
||||
)
|
||||
}
|
||||
|
||||
override fun perform(uiController: UiController?, view: View?) {
|
||||
view?.findViewById<View>(subViewId)?.performClick()
|
||||
}
|
||||
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
fun <VH : ViewHolder> clickOnRecyclerItemWithText(recyclerId: Int, text: String) {
|
||||
scrollToRecyclerItem<VH>(recyclerId, text)
|
||||
?.perform(
|
||||
matchView(recyclerId).perform(
|
||||
// scrollTo will fail the test if no item matches.
|
||||
RecyclerViewActions.scrollTo<VH>(
|
||||
hasDescendant(withText(text))
|
||||
),
|
||||
RecyclerViewActions.actionOnItem<VH>(
|
||||
withChild(withText(text)), click()
|
||||
hasDescendant(withText(text)),
|
||||
click()
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -144,9 +186,17 @@ open class BaseTestRobot {
|
||||
day
|
||||
)
|
||||
)
|
||||
onView(
|
||||
allOf(
|
||||
withClassName(equalTo(AppCompatButton::class.java.name)),
|
||||
withText("OK")
|
||||
)
|
||||
).perform(
|
||||
click()
|
||||
)
|
||||
}
|
||||
|
||||
fun selectTextInSpinner(id: Int, text:String) {
|
||||
fun selectTextInSpinner(id: Int, text: String) {
|
||||
clickButton(id)
|
||||
onView(withSpinnerText(text)).perform(click())
|
||||
}
|
||||
@@ -157,5 +207,13 @@ open class BaseTestRobot {
|
||||
hours, minutes
|
||||
)
|
||||
)
|
||||
onView(
|
||||
allOf(
|
||||
withClassName(equalTo(AppCompatButton::class.java.name)),
|
||||
withText("OK")
|
||||
)
|
||||
).perform(
|
||||
click()
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
package com.appttude.h_mal.farmr.data.ui.robots
|
||||
package com.appttude.h_mal.farmr.ui.robots
|
||||
|
||||
import com.appttude.h_mal.farmr.R
|
||||
import com.appttude.h_mal.farmr.data.ui.BaseTestRobot
|
||||
import com.appttude.h_mal.farmr.model.ShiftType
|
||||
import com.appttude.h_mal.farmr.ui.BaseTestRobot
|
||||
|
||||
fun addScreen(func: AddItemScreenRobot.() -> Unit) = AddItemScreenRobot().apply { func() }
|
||||
class AddItemScreenRobot : BaseTestRobot() {
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.appttude.h_mal.farmr.data.ui.robots
|
||||
package com.appttude.h_mal.farmr.ui.robots
|
||||
|
||||
import com.appttude.h_mal.farmr.R
|
||||
import com.appttude.h_mal.farmr.data.ui.BaseTestRobot
|
||||
import com.appttude.h_mal.farmr.ui.BaseTestRobot
|
||||
import com.appttude.h_mal.farmr.model.ShiftType
|
||||
|
||||
fun filterScreen(func: FilterScreenRobot.() -> Unit) = FilterScreenRobot().apply { func() }
|
||||
@@ -0,0 +1,29 @@
|
||||
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.base.BaseRecyclerAdapter.CurrentViewHolder
|
||||
import com.appttude.h_mal.farmr.model.Order
|
||||
import com.appttude.h_mal.farmr.model.Sortable
|
||||
import com.appttude.h_mal.farmr.ui.BaseTestRobot
|
||||
|
||||
fun homeScreen(func: HomeScreenRobot.() -> Unit) = HomeScreenRobot().apply { func() }
|
||||
class HomeScreenRobot : BaseTestRobot() {
|
||||
|
||||
fun clickOnItemWithText(text: String) = clickOnRecyclerItemWithText<CurrentViewHolder>(R.id.list_item_view, text)
|
||||
fun clickOnItemAtPosition(position: Int) = clickRecyclerAtPosition<CurrentViewHolder>(R.id.list_item_view, position)
|
||||
fun clickOnEdit(position: Int) = clickViewInRecyclerAtPosition<CurrentViewHolder>(R.id.list_item_view, position, R.id.imageView)
|
||||
fun clickFab() = clickButton(R.id.fab1)
|
||||
fun clickOnInfoIcon() = clickButton(R.id.action_favorite)
|
||||
fun clickFilterInMenu() = clickOnMenuItem(R.string.filter)
|
||||
fun clickClearFilterInMenu() = clickOnMenuItem(R.string.clear)
|
||||
fun clickSortInMenu() = clickOnMenuItem(R.string.sort)
|
||||
|
||||
fun applySort(sortable: Sortable, order: Order = Order.ASCENDING) {
|
||||
clickSortInMenu()
|
||||
val label = sortable.label
|
||||
clickDialogButton(label)
|
||||
val orderLabel = order.label
|
||||
clickDialogButton(orderLabel)
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.appttude.h_mal.farmr.data.ui.robots
|
||||
package com.appttude.h_mal.farmr.ui.robots
|
||||
|
||||
import com.appttude.h_mal.farmr.R
|
||||
import com.appttude.h_mal.farmr.data.ui.BaseTestRobot
|
||||
import com.appttude.h_mal.farmr.ui.BaseTestRobot
|
||||
import com.appttude.h_mal.farmr.model.ShiftType
|
||||
|
||||
fun viewScreen(func: ViewItemScreenRobot.() -> Unit) = ViewItemScreenRobot().apply { func() }
|
||||
@@ -0,0 +1,142 @@
|
||||
package com.appttude.h_mal.farmr.ui.tests
|
||||
|
||||
import com.appttude.h_mal.farmr.model.Order
|
||||
import com.appttude.h_mal.farmr.model.ShiftType
|
||||
import com.appttude.h_mal.farmr.model.Sortable
|
||||
import com.appttude.h_mal.farmr.ui.BaseTest
|
||||
import com.appttude.h_mal.farmr.ui.MainActivity
|
||||
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.homeScreen
|
||||
import com.appttude.h_mal.farmr.ui.robots.viewScreen
|
||||
import com.appttude.h_mal.farmr.utils.ID
|
||||
import org.junit.Test
|
||||
|
||||
class ShiftTests : BaseTest<MainActivity>(MainActivity::class.java) {
|
||||
|
||||
override fun afterLaunch() {
|
||||
super.afterLaunch()
|
||||
addRandomShifts()
|
||||
|
||||
// Content resolver hard to mock
|
||||
// Dirty technique to have a populated list
|
||||
homeScreen {
|
||||
clickFab()
|
||||
navigateBack()
|
||||
}
|
||||
}
|
||||
|
||||
override fun testFinished() {
|
||||
super.testFinished()
|
||||
clearDataBase()
|
||||
clearPrefs()
|
||||
}
|
||||
|
||||
// Add a shift successfully
|
||||
@Test
|
||||
fun openAddScreen_addNewShift_newShiftCreated() {
|
||||
homeScreen {
|
||||
clickFab()
|
||||
}
|
||||
addScreen {
|
||||
setDescription("This is a description")
|
||||
setDate(2023, 2, 11)
|
||||
clickShiftType(ShiftType.HOURLY)
|
||||
setTimeIn(12, 0)
|
||||
setTimeOut(14, 30)
|
||||
setBreakTime(30)
|
||||
setRateOfPay(10f)
|
||||
assertDuration("2.0 hours")
|
||||
assertTotalPay("£20.00")
|
||||
submit()
|
||||
}
|
||||
homeScreen {
|
||||
clickOnItemWithText("This is a description")
|
||||
}
|
||||
}
|
||||
|
||||
// Edit a shift successfully
|
||||
@Test
|
||||
fun test2() {
|
||||
homeScreen {
|
||||
clickOnEdit(0)
|
||||
}
|
||||
addScreen {
|
||||
setDescription("Edited this shift")
|
||||
setTimeIn(12, 0)
|
||||
setTimeOut(14, 30)
|
||||
setBreakTime(30)
|
||||
setRateOfPay(20f)
|
||||
assertDuration("2.0 hours")
|
||||
assertTotalPay("£40.00")
|
||||
submit()
|
||||
}
|
||||
homeScreen {
|
||||
clickOnItemWithText("Edited this shift")
|
||||
}
|
||||
viewScreen {
|
||||
matchDescription("Edited this shift")
|
||||
matchDuration("2 Hours 0 Minutes (+ 30 minutes break)")
|
||||
matchTotalPay("2.0 Hours @ £20.00 per Hour\nEquals: £40.00")
|
||||
}
|
||||
}
|
||||
|
||||
// filter the list with date from
|
||||
@Test
|
||||
fun test3() {
|
||||
homeScreen {
|
||||
applySort(Sortable.TYPE, Order.DESCENDING)
|
||||
clickOnItemAtPosition(0)
|
||||
viewScreen {
|
||||
matchDescription("Day five")
|
||||
matchShiftType(ShiftType.PIECE)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// filter the list with date to
|
||||
@Test
|
||||
fun test4() {
|
||||
homeScreen {
|
||||
clickFilterInMenu()
|
||||
}
|
||||
filterScreen {
|
||||
setDateIn(2023,8,3)
|
||||
setDateOut(2023,8,6)
|
||||
submit()
|
||||
}
|
||||
homeScreen {
|
||||
clickOnItemAtPosition(0)
|
||||
}
|
||||
}
|
||||
|
||||
// Add a shift as piece rate
|
||||
@Test
|
||||
fun test5() {
|
||||
homeScreen {
|
||||
clickFab()
|
||||
}
|
||||
addScreen {
|
||||
setDescription("This is a description")
|
||||
setDate(2023, 2, 11)
|
||||
clickShiftType(ShiftType.PIECE)
|
||||
setRateOfPay(10f)
|
||||
setUnits(1f)
|
||||
assertTotalPay("£10.00")
|
||||
submit()
|
||||
}
|
||||
homeScreen {
|
||||
clickOnItemWithText("This is a description")
|
||||
}
|
||||
}
|
||||
|
||||
// Validate the details screen
|
||||
@Test
|
||||
fun test6() {
|
||||
}
|
||||
|
||||
// filter, sort, order and then reset
|
||||
@Test
|
||||
fun test7() {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
package com.appttude.h_mal.farmr.ui.utils
|
||||
@@ -0,0 +1,103 @@
|
||||
package com.appttude.h_mal.farmr.ui.utils
|
||||
|
||||
import com.appttude.h_mal.farmr.model.Shift
|
||||
import com.appttude.h_mal.farmr.model.ShiftType
|
||||
|
||||
fun getShifts() = listOf(
|
||||
Shift(
|
||||
ShiftType.HOURLY,
|
||||
"Day one",
|
||||
"2023-08-01",
|
||||
"12:00",
|
||||
"13:00",
|
||||
1f,
|
||||
0,
|
||||
0f,
|
||||
10f,
|
||||
10f
|
||||
),
|
||||
Shift(
|
||||
ShiftType.HOURLY,
|
||||
"Day two",
|
||||
"2023-08-02",
|
||||
"12:00",
|
||||
"13:00",
|
||||
1f,
|
||||
0,
|
||||
0f,
|
||||
10f,
|
||||
10f
|
||||
),
|
||||
Shift(
|
||||
ShiftType.HOURLY,
|
||||
"Day three",
|
||||
"2023-08-03",
|
||||
"12:00",
|
||||
"13:00",
|
||||
1f,
|
||||
30,
|
||||
0f,
|
||||
10f,
|
||||
5f
|
||||
),
|
||||
Shift(
|
||||
ShiftType.HOURLY,
|
||||
"Day four",
|
||||
"2023-08-04",
|
||||
"12:00",
|
||||
"13:00",
|
||||
1f,
|
||||
30,
|
||||
0f,
|
||||
10f,
|
||||
5f
|
||||
),
|
||||
Shift(
|
||||
ShiftType.PIECE,
|
||||
"Day five",
|
||||
"2023-08-05",
|
||||
"",
|
||||
"",
|
||||
0f,
|
||||
0,
|
||||
1f,
|
||||
10f,
|
||||
10f
|
||||
),
|
||||
Shift(
|
||||
ShiftType.PIECE,
|
||||
"Day six",
|
||||
"2023-08-06",
|
||||
"",
|
||||
"",
|
||||
0f,
|
||||
0,
|
||||
1f,
|
||||
10f,
|
||||
10f
|
||||
),
|
||||
Shift(
|
||||
ShiftType.PIECE,
|
||||
"Day seven",
|
||||
"2023-08-07",
|
||||
"",
|
||||
"",
|
||||
0f,
|
||||
0,
|
||||
1f,
|
||||
10f,
|
||||
10f
|
||||
),
|
||||
Shift(
|
||||
ShiftType.PIECE,
|
||||
"Day eight",
|
||||
"2023-08-08",
|
||||
"",
|
||||
"",
|
||||
0f,
|
||||
0,
|
||||
1f,
|
||||
10f,
|
||||
10f
|
||||
)
|
||||
)
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.appttude.h_mal.farmr.data.ui.utils
|
||||
package com.appttude.h_mal.farmr.ui.utils
|
||||
|
||||
import android.os.SystemClock.sleep
|
||||
import android.view.View
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.appttude.h_mal.farmr.data.ui.utils
|
||||
package com.appttude.h_mal.farmr.ui.utils
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.Observer
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.appttude.h_mal.farmr.base
|
||||
|
||||
import android.app.Application
|
||||
import com.appttude.h_mal.farmr.data.RepositoryImpl
|
||||
import com.appttude.h_mal.farmr.data.legacydb.LegacyDatabase
|
||||
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
|
||||
|
||||
abstract class BaseApplication() : Application(), KodeinAware {
|
||||
|
||||
// Kodein creation of modules to be retrieve within the app
|
||||
override val kodein = Kodein.lazy {
|
||||
import(androidXModule(this@BaseApplication))
|
||||
|
||||
bind() from singleton { createDatabase() }
|
||||
bind() from singleton { createPrefs() }
|
||||
bind() from singleton { RepositoryImpl(instance(), instance()) }
|
||||
|
||||
bind() from provider { ApplicationViewModelFactory(instance()) }
|
||||
}
|
||||
|
||||
abstract fun createDatabase(): LegacyDatabase
|
||||
abstract fun createPrefs(): PreferenceProvider
|
||||
}
|
||||
@@ -3,12 +3,13 @@ package com.appttude.h_mal.farmr.data.legacydb
|
||||
import android.content.ContentResolver
|
||||
import android.net.Uri
|
||||
import android.provider.BaseColumns
|
||||
import com.appttude.h_mal.farmr.BuildConfig
|
||||
|
||||
/**
|
||||
* Created by h_mal on 26/12/2017.
|
||||
*/
|
||||
object ShiftsContract {
|
||||
const val CONTENT_AUTHORITY = "com.appttude.h_mal.farmr"
|
||||
const val CONTENT_AUTHORITY = BuildConfig.APPLICATION_ID
|
||||
val BASE_CONTENT_URI = Uri.parse("content://$CONTENT_AUTHORITY")
|
||||
const val PATH_SHIFTS = "shifts"
|
||||
|
||||
|
||||
@@ -62,4 +62,8 @@ class PreferenceProvider(
|
||||
)
|
||||
}
|
||||
|
||||
fun clearPrefs() {
|
||||
preference.edit().clear().apply()
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,11 +1,10 @@
|
||||
package com.appttude.h_mal.farmr.di
|
||||
|
||||
import android.app.Application
|
||||
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.prefs.PreferenceProvider
|
||||
import com.appttude.h_mal.farmr.viewmodel.ApplicationViewModelFactory
|
||||
import com.appttude.h_mal.farmr.viewmodel.MainViewModel
|
||||
import org.kodein.di.Kodein
|
||||
import org.kodein.di.KodeinAware
|
||||
import org.kodein.di.android.x.androidXModule
|
||||
@@ -14,15 +13,12 @@ import org.kodein.di.generic.instance
|
||||
import org.kodein.di.generic.provider
|
||||
import org.kodein.di.generic.singleton
|
||||
|
||||
class ShiftApplication: Application(), KodeinAware {
|
||||
// Kodein creation of modules to be retrieve within the app
|
||||
override val kodein = Kodein.lazy {
|
||||
import(androidXModule(this@ShiftApplication))
|
||||
class ShiftApplication: BaseApplication() {
|
||||
|
||||
bind() from singleton { LegacyDatabase(contentResolver) }
|
||||
bind() from singleton { PreferenceProvider(this@ShiftApplication) }
|
||||
bind() from singleton { RepositoryImpl(instance(), instance()) }
|
||||
|
||||
bind() from provider { ApplicationViewModelFactory(instance()) }
|
||||
override fun createDatabase(): LegacyDatabase {
|
||||
return LegacyDatabase(contentResolver)
|
||||
}
|
||||
|
||||
override fun createPrefs() = PreferenceProvider(this)
|
||||
}
|
||||
|
||||
|
||||
@@ -11,5 +11,9 @@ enum class Sortable(val label: String) {
|
||||
|
||||
companion object {
|
||||
val entries = Sortable.values()
|
||||
|
||||
fun getEnumByType(label: String): Sortable {
|
||||
return Sortable.values().first { it.label == label }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,7 @@ import com.appttude.h_mal.farmr.model.Success
|
||||
import com.appttude.h_mal.farmr.utils.ID
|
||||
import com.appttude.h_mal.farmr.utils.createDialog
|
||||
import com.appttude.h_mal.farmr.utils.displayToast
|
||||
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.popBackStack
|
||||
@@ -158,8 +159,8 @@ class FragmentAddItem : BaseFragment<SubmissionViewModel>(R.layout.fragment_add_
|
||||
mUnits = units
|
||||
}
|
||||
}
|
||||
mPayRateEditText.setText(rateOfPay.formatToTwoDpString())
|
||||
mTotalPayTextView.text = totalPay.formatToTwoDpString()
|
||||
mPayRateEditText.setText(rateOfPay.formatAsCurrencyString())
|
||||
mTotalPayTextView.text = totalPay.formatAsCurrencyString()
|
||||
|
||||
calculateTotalPay()
|
||||
}
|
||||
@@ -267,7 +268,7 @@ class FragmentAddItem : BaseFragment<SubmissionViewModel>(R.layout.fragment_add_
|
||||
(mUnits ?: 0f) * mPayRate
|
||||
}
|
||||
}
|
||||
mTotalPayTextView.text = total.formatToTwoDpString()
|
||||
mTotalPayTextView.text = total.formatAsCurrencyString()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -155,7 +155,7 @@ class FragmentMain : BaseFragment<MainViewModel>(R.layout.fragment_main), BackPr
|
||||
.setSingleChoiceItems(
|
||||
groupName,
|
||||
checkedItem
|
||||
) { p0, p1 -> sort = Sortable.valueOf(groupName[p1]) }
|
||||
) { p0, p1 -> sort = Sortable.getEnumByType(groupName[p1]) }
|
||||
.setPositiveButton("Ascending") { dialog, id ->
|
||||
viewModel.setSortAndOrder(sort)
|
||||
dialog.dismiss()
|
||||
|
||||
@@ -4,6 +4,7 @@ import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.view.View
|
||||
import android.widget.RelativeLayout
|
||||
import androidx.core.app.ActivityOptionsCompat
|
||||
@@ -16,8 +17,7 @@ class SplashScreen : Activity() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_splash)
|
||||
val bundle = ActivityOptionsCompat.makeCustomAnimation(this, R.anim.hyperspace_jump, android.R.anim.fade_out).toBundle()
|
||||
val relativeLayout = findViewById<View>(R.id.splash_layout) as RelativeLayout
|
||||
|
||||
val i = Intent(this@SplashScreen, MainActivity::class.java)
|
||||
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_CLEAR_TASK)
|
||||
Handler().postDelayed({
|
||||
@@ -27,11 +27,11 @@ class SplashScreen : Activity() {
|
||||
startActivity(i)
|
||||
overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out)
|
||||
// finish();
|
||||
}, SPLASH_TIME_OUT.toLong())
|
||||
}, SPLASH_TIME_OUT)
|
||||
}
|
||||
|
||||
companion object {
|
||||
// Splash screen timer
|
||||
private const val SPLASH_TIME_OUT = 2000
|
||||
const val SPLASH_TIME_OUT: Long = 2000
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user