Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
FreshRSS-Android
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Locked Files
Issues
30
Issues
30
List
Boards
Labels
Service Desk
Milestones
Merge Requests
2
Merge Requests
2
Requirements
Requirements
List
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Security & Compliance
Security & Compliance
Dependency List
License Compliance
Operations
Operations
Environments
Packages & Registries
Packages & Registries
Package Registry
Container Registry
Analytics
Analytics
CI / CD
Code Review
Insights
Issue
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Christophe Henry
FreshRSS-Android
Commits
45146842
Commit
45146842
authored
Feb 19, 2020
by
Christophe Henry
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'big-refacto' into 'develop'
Big refacto See merge request
!73
parents
fae4f7e9
a445c602
Pipeline
#3582
passed with stage
in 0 seconds
Changes
46
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
46 changed files
with
1145 additions
and
672 deletions
+1145
-672
Jenkinsfile
Jenkinsfile
+62
-115
app/.gitignore
app/.gitignore
+1
-0
app/build.gradle
app/build.gradle
+17
-14
app/src/androidTest/java/fr/chenry/android/freshrss/ExampleInstrumentedTestActivity.kt
...henry/android/freshrss/ExampleInstrumentedTestActivity.kt
+0
-22
app/src/androidTest/java/fr/chenry/android/freshrss/store/database/FreshRSSDabatabaseBaseTest.kt
...oid/freshrss/store/database/FreshRSSDabatabaseBaseTest.kt
+11
-22
app/src/androidTest/java/fr/chenry/android/freshrss/store/database/FreshRSSDabatabaseMigrationsTest.kt
...eshrss/store/database/FreshRSSDabatabaseMigrationsTest.kt
+4
-4
app/src/androidTest/java/fr/chenry/android/freshrss/store/database/FreshRSSDabatabaseTest.kt
...android/freshrss/store/database/FreshRSSDabatabaseTest.kt
+97
-0
app/src/androidTest/java/fr/chenry/android/freshrss/utils/SubscriptionsTestUtils.kt
...r/chenry/android/freshrss/utils/SubscriptionsTestUtils.kt
+20
-0
app/src/androidTest/java/fr/chenry/android/freshrss/utils/TestUtils.kt
...idTest/java/fr/chenry/android/freshrss/utils/TestUtils.kt
+173
-0
app/src/main/AndroidManifest.xml
app/src/main/AndroidManifest.xml
+1
-1
app/src/main/java/fr/chenry/android/freshrss/FreshRSSApplication.kt
...in/java/fr/chenry/android/freshrss/FreshRSSApplication.kt
+37
-7
app/src/main/java/fr/chenry/android/freshrss/RefresherService.kt
.../main/java/fr/chenry/android/freshrss/RefresherService.kt
+7
-5
app/src/main/java/fr/chenry/android/freshrss/activities/LoginActivity.kt
...va/fr/chenry/android/freshrss/activities/LoginActivity.kt
+33
-28
app/src/main/java/fr/chenry/android/freshrss/activities/MainActivity.kt
...ava/fr/chenry/android/freshrss/activities/MainActivity.kt
+21
-52
app/src/main/java/fr/chenry/android/freshrss/activities/StartActivity.kt
...va/fr/chenry/android/freshrss/activities/StartActivity.kt
+10
-6
app/src/main/java/fr/chenry/android/freshrss/components/subscriptionarticles/SubscriptionArticlesFragment.kt
...ents/subscriptionarticles/SubscriptionArticlesFragment.kt
+0
-1
app/src/main/java/fr/chenry/android/freshrss/components/subscriptions/MainSubscriptionFragment.kt
...hrss/components/subscriptions/MainSubscriptionFragment.kt
+43
-89
app/src/main/java/fr/chenry/android/freshrss/components/subscriptions/SubscriptionsFragment.kt
...reshrss/components/subscriptions/SubscriptionsFragment.kt
+1
-7
app/src/main/java/fr/chenry/android/freshrss/components/subscriptions/adapters/SubscriptionsFlexibleAdapter.kt
...ts/subscriptions/adapters/SubscriptionsFlexibleAdapter.kt
+2
-3
app/src/main/java/fr/chenry/android/freshrss/store/Store.kt
app/src/main/java/fr/chenry/android/freshrss/store/Store.kt
+15
-24
app/src/main/java/fr/chenry/android/freshrss/store/database/Converters.kt
...a/fr/chenry/android/freshrss/store/database/Converters.kt
+3
-5
app/src/main/java/fr/chenry/android/freshrss/store/database/FreshRSSDabatabase.kt
...nry/android/freshrss/store/database/FreshRSSDabatabase.kt
+26
-45
app/src/main/java/fr/chenry/android/freshrss/store/database/migrations/fr.chenry.android.freshrss.store.database.FreshRSSDabatabase/8.json
...android.freshrss.store.database.FreshRSSDabatabase/8.json
+220
-0
app/src/main/java/fr/chenry/android/freshrss/store/database/models/Account.kt
.../chenry/android/freshrss/store/database/models/Account.kt
+14
-3
app/src/main/java/fr/chenry/android/freshrss/store/database/models/Subscription.kt
...ry/android/freshrss/store/database/models/Subscription.kt
+21
-15
app/src/main/java/fr/chenry/android/freshrss/store/viewmodels/AccountVM.kt
.../fr/chenry/android/freshrss/store/viewmodels/AccountVM.kt
+9
-10
app/src/main/java/fr/chenry/android/freshrss/utils/BurgerMenuDrawerListener.kt
...chenry/android/freshrss/utils/BurgerMenuDrawerListener.kt
+162
-19
app/src/main/java/fr/chenry/android/freshrss/utils/KotlinExtensions.kt
...java/fr/chenry/android/freshrss/utils/KotlinExtensions.kt
+10
-14
app/src/main/java/fr/chenry/android/freshrss/utils/NotificationHelper.kt
...va/fr/chenry/android/freshrss/utils/NotificationHelper.kt
+2
-16
app/src/main/res/drawable/grey_circle_background.xml
app/src/main/res/drawable/grey_circle_background.xml
+0
-10
app/src/main/res/drawable/red_circle_background.xml
app/src/main/res/drawable/red_circle_background.xml
+0
-10
app/src/main/res/layout/activity_login.xml
app/src/main/res/layout/activity_login.xml
+2
-1
app/src/main/res/layout/activity_main.xml
app/src/main/res/layout/activity_main.xml
+1
-0
app/src/main/res/layout/emotional_image_subtext.xml
app/src/main/res/layout/emotional_image_subtext.xml
+1
-1
app/src/main/res/layout/fast_scroller.xml
app/src/main/res/layout/fast_scroller.xml
+0
-7
app/src/main/res/layout/fragment_main_subscription.xml
app/src/main/res/layout/fragment_main_subscription.xml
+1
-2
app/src/main/res/layout/fragment_subscription_article_detail.xml
.../main/res/layout/fragment_subscription_article_detail.xml
+9
-7
app/src/main/res/layout/fragment_subscriptions.xml
app/src/main/res/layout/fragment_subscriptions.xml
+3
-4
app/src/main/res/layout/loader.xml
app/src/main/res/layout/loader.xml
+1
-1
app/src/main/res/layout/menu_badge.xml
app/src/main/res/layout/menu_badge.xml
+0
-23
app/src/main/res/layout/navigation_drawer_header.xml
app/src/main/res/layout/navigation_drawer_header.xml
+49
-41
app/src/main/res/navigation/nav_graph.xml
app/src/main/res/navigation/nav_graph.xml
+1
-1
app/src/main/res/values/dimens.xml
app/src/main/res/values/dimens.xml
+1
-1
app/src/main/res/values/strings.xml
app/src/main/res/values/strings.xml
+2
-1
app/src/main/res/values/styles.xml
app/src/main/res/values/styles.xml
+52
-29
freshrss.xmlformat.prefs
freshrss.xmlformat.prefs
+0
-6
No files found.
Jenkinsfile
View file @
45146842
...
...
@@ -2,15 +2,17 @@ pipeline {
agent
{
docker
{
image
"bitriseio/docker-android"
args
"-v /etc/passwd:/etc/passwd:ro -u root --privileged"
args
"-v /etc/passwd:/etc/passwd:ro "
+
"-v /home/android/android-sdk-linux/:/opt/android-sdk-linux/:rw "
+
"-u root --privileged"
}
}
environment
{
MIN_SDK_VERSION
=
2
1
MIN_SDK_VERSION
=
2
3
MAX_SDK_VERSION
=
28
MIN_SDK_IMAGE
=
"system-images;android-$MIN_SDK_VERSION;default;x86_64"
MAX_SDK_IMAGE
=
"system-images;android-$MAX_SDK_VERSION;default;x86_64"
MIN_SDK_IMAGE
=
"system-images;android-$MIN_SDK_VERSION;default;x86_64"
.
toString
()
MAX_SDK_IMAGE
=
"system-images;android-$MAX_SDK_VERSION;default;x86_64"
.
toString
()
ANDROID_HOME
=
"/opt/android-sdk-linux"
}
...
...
@@ -18,6 +20,17 @@ pipeline {
buildDiscarder
(
logRotator
(
numToKeepStr:
"2"
))
skipStagesAfterUnstable
()
gitLabConnection
(
'GitlabFeneas'
)
gitlabBuilds
(
builds:
[
'Compile'
,
'Lint'
,
'Unit tests'
,
'Instrumented tests on min SDK image'
,
'Instrumented tests on max SDK image'
])
disableConcurrentBuilds
()
newContainerPerStage
()
timestamps
()
timeout
(
time:
30
,
unit:
'MINUTES'
)
}
triggers
{
...
...
@@ -35,128 +48,74 @@ pipeline {
addCiMessage:
true
,
addVoteOnMergeRequest:
true
,
acceptMergeRequestOnSuccess:
false
,
cancelPendingBuildsOnUpdate:
true
)
}
libraries
{
lib
(
"android-pipeline-steps"
)
}
stages
{
stage
(
"Pre"
)
{
steps
{
updateGitlabCommitStatus
name:
"Job"
,
state:
"running"
updateGitlabCommitStatus
name:
"Pre"
,
state:
"running"
library
"android-pipeline-steps"
}
post
{
failure
{
updateGitlabCommitStatus
name:
"Pre"
,
state:
"failed"
}
success
{
updateGitlabCommitStatus
name:
"Pre"
,
state:
"success"
}
}
}
stage
(
"Compile"
)
{
steps
{
updateGitlabCommitStatus
name:
"Compile"
,
state:
"running"
sh
"./gradlew compileReleaseSources"
}
post
{
failure
{
updateGitlabCommitStatus
name:
"Compile"
,
state:
"failed"
}
success
{
updateGitlabCommitStatus
name:
"Compile"
,
state:
"success"
gitlabCommitStatus
(
"Compile"
)
{
sh
"./gradlew compileReleaseSources"
}
}
}
stage
(
"Lint"
)
{
steps
{
updateGitlabCommitStatus
name:
"Lint"
,
state:
"running"
sh
"./gradlew spotlessApply lint"
sh
"./gradlew lintRelease --continue"
androidLint
pattern:
"**/lint-results-*.xml"
publishHTML
([
allowMissing
:
false
,
alwaysLinkToLastBuild:
true
,
keepAll
:
false
,
reportDir
:
"$WORKSPACE/app/build/reports/"
,
reportFiles
:
"lint-results-release.html"
,
reportName
:
"HTML Report"
,
reportTitles
:
""
])
}
post
{
failure
{
updateGitlabCommitStatus
name:
"Lint"
,
state:
"failed"
}
success
{
updateGitlabCommitStatus
name:
"Lint"
,
state:
"success"
gitlabCommitStatus
(
"Lint"
)
{
sh
"./gradlew spotlessCheck lint"
androidLint
pattern:
"**/lint-results-*.xml"
publishHTML
([
allowMissing
:
false
,
alwaysLinkToLastBuild:
true
,
keepAll
:
false
,
reportDir
:
"$WORKSPACE/app/build/reports/"
,
reportFiles
:
"lint-results-release.html"
,
reportName
:
"HTML Report"
,
reportTitles
:
""
])
}
}
}
stage
(
"Unit tests"
)
{
steps
{
updateGitlabCommitStatus
name:
"Unit tests"
,
state:
"running"
sh
"./gradlew testReleaseUnitTest --info"
junit
"**/test-results/**/*.xml"
publishHTML
([
allowMissing
:
false
,
alwaysLinkToLastBuild:
true
,
keepAll
:
false
,
reportDir
:
"$WORKSPACE/app/build/reports/tests/testReleaseUnitTest"
,
reportFiles
:
"index.html"
,
reportName
:
"Junit test report"
,
reportTitles
:
""
])
}
post
{
failure
{
updateGitlabCommitStatus
name:
"Unit tests"
,
state:
"failed"
}
success
{
updateGitlabCommitStatus
name:
"Unit tests"
,
state:
"success"
gitlabCommitStatus
(
"Unit tests"
)
{
sh
"./gradlew testReleaseUnitTest --info"
junit
"**/test-results/**/*.xml"
publishHTML
([
allowMissing
:
false
,
alwaysLinkToLastBuild:
true
,
keepAll
:
false
,
reportDir
:
"$WORKSPACE/app/build/reports/tests/testReleaseUnitTest"
,
reportFiles
:
"index.html"
,
reportName
:
"Junit test report"
,
reportTitles
:
""
])
}
}
}
stage
(
"Instrumented tests"
)
{
parallel
{
stage
(
"on min SDK level"
)
{
steps
{
sh
"echo ${env.MIN_SDK_IMAGE}"
updateGitlabCommitStatus
name:
"Instrumented tests on target SDK image"
,
state:
"running"
withAvd
(
hardwareProfile:
"Nexus 5X"
,
systemImage:
env
.
MIN_SDK_IMAGE
,
headless:
true
)
{
sh
"./gradlew clean connectedDebugAndroidTest"
}
}
post
{
failure
{
updateGitlabCommitStatus
name:
"Instrumented tests on min SDK image"
,
state:
"failed"
}
success
{
updateGitlabCommitStatus
name:
"Instrumented tests on min SDK image"
,
state:
"success"
}
stage
(
"on min SDK level"
)
{
steps
{
gitlabCommitStatus
(
"Instrumented tests on min SDK image"
)
{
withAvd
(
hardwareProfile:
"Nexus 5X"
,
systemImage:
env
.
MIN_SDK_IMAGE
,
headless:
true
)
{
sh
"./gradlew clean connectedCheck"
}
}
}
}
stage
(
"on max SDK level"
)
{
steps
{
sh
"echo ${env.MAX_SDK_IMAGE}"
updateGitlabCommitStatus
name:
"Instrumented tests on target SDK image"
,
state:
"running"
withAvd
(
hardwareProfile:
"Nexus 5X"
,
systemImage:
env
.
MAX_SDK_IMAGE
,
headless:
true
)
{
sh
"./gradlew clean connectedDebugAndroidTest"
}
}
post
{
failure
{
updateGitlabCommitStatus
name:
"Instrumented tests on target SDK image"
,
state:
"failed"
}
success
{
updateGitlabCommitStatus
name:
"Instrumented tests on target SDK image"
,
state:
"success"
}
stage
(
"on max SDK level"
)
{
steps
{
gitlabCommitStatus
(
"Instrumented tests on max SDK image"
)
{
withAvd
(
hardwareProfile:
"Nexus 5X"
,
systemImage:
env
.
MAX_SDK_IMAGE
,
headless:
true
)
{
sh
"./gradlew clean connectedCheck"
}
}
}
...
...
@@ -171,16 +130,4 @@ pipeline {
// }
// }
}
post
{
always
{
sh
"chown -R jenkins ${env.WORKSPACE}"
}
failure
{
updateGitlabCommitStatus
name:
"Job"
,
state:
"failed"
}
success
{
updateGitlabCommitStatus
name:
"Job"
,
state:
"success"
}
}
}
\ No newline at end of file
app/.gitignore
View file @
45146842
/build
/src/main/assets/*.properties
/release/
/src/main/java/intellij.gdsl
app/build.gradle
View file @
45146842
...
...
@@ -16,6 +16,7 @@ android {
versionCode
12
versionName
"1.2.2"
testInstrumentationRunner
"androidx.test.runner.AndroidJUnitRunner"
testInstrumentationRunnerArguments
clearPackageData:
'true'
javaCompileOptions
{
annotationProcessorOptions
{
arguments
=
[
"room.schemaLocation"
:
schema_location
]
...
...
@@ -96,28 +97,22 @@ spotless {
"max_line_length"
:
120
,
])
}
format
"xml"
,
{
target
fileTree
(
"."
)
{
include
"**/*.xml"
exclude
"**/build/**"
}
eclipseWtp
(
"xml"
).
configFile
"$rootDir/freshrss.xmlformat.prefs"
.
toString
()
}
}
dependencies
{
def
appcompat_version
=
"1.1.0"
def
activity_version
=
"1.1.0"
def
fragment_version
=
"1.2.1"
def
lifecycle_version
=
"2.2.0"
def
room_version
=
'2.2.3'
def
room_version
=
"2.2.3"
def
roomigrant_version
=
"0.1.7"
def
fuel_version
=
"2.0.1"
def
jackson_version
=
'2.10.2'
def
espresso_version
=
"3.2.0"
def
test_runnner_version
=
"1.2.0"
def
promise_version
=
"3.3.0"
def
android_navigation
=
"1.0.0"
def
jsoup_version
=
"1.12.1"
def
acraVersion
=
"5.1.3"
def
jsoup_version
=
'1.12.2'
def
acraVersion
=
'5.5.0'
def
autoservice_version
=
"1.0-rc6"
// Linter
...
...
@@ -133,13 +128,18 @@ dependencies {
// AndroidX
implementation
"androidx.appcompat:appcompat:$appcompat_version"
implementation
"androidx.appcompat:appcompat-resources:$appcompat_version"
implementation
"androidx.activity:activity-ktx:$activity_version"
implementation
"androidx.fragment:fragment-ktx:$fragment_version"
implementation
"androidx.core:core-ktx:1.1.0"
implementation
'androidx.core:core-ktx:1.2.0'
implementation
"androidx.constraintlayout:constraintlayout:1.1.3"
implementation
"androidx.recyclerview:recyclerview:1.1.0"
implementation
"androidx.preference:preference-ktx:1.1.0"
implementation
"com.google.android.material:material:1.2.0-alpha04"
// AndroidX testing
implementation
"androidx.fragment:fragment-testing:$fragment_version"
// ViewModel and LiveData
implementation
"androidx.lifecycle:lifecycle-runtime-ktx:$lifecycle_version"
implementation
"androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
...
...
@@ -154,6 +154,7 @@ dependencies {
// Room & roomigrant
kapt
"androidx.room:room-compiler:$room_version"
implementation
"androidx.room:room-ktx:$room_version"
implementation
"androidx.room:room-runtime:$room_version"
implementation
"androidx.room:room-rxjava2:$room_version"
androidTestImplementation
"androidx.room:room-testing:$room_version"
...
...
@@ -185,9 +186,11 @@ dependencies {
implementation
"ch.acra:acra-notification:$acraVersion"
// Tests
testImplementation
'junit:junit:4.13'
androidTestImplementation
"androidx.test:runner:$test_runnner_version"
testImplementation
"junit:junit:4.13"
androidTestImplementation
"androidx.test:runner:1.2.0"
androidTestImplementation
"androidx.test.ext:junit:1.1.1"
androidTestImplementation
"androidx.test.espresso:espresso-core:$espresso_version"
androidTestImplementation
"com.github.javafaker:javafaker:1.0.2"
// Debug
debugImplementation
"com.facebook.stetho:stetho:1.5.1"
...
...
app/src/androidTest/java/fr/chenry/android/freshrss/ExampleInstrumentedTestActivity.kt
deleted
100644 → 0
View file @
fae4f7e9
package
fr.chenry.android.freshrss
import
androidx.test.InstrumentationRegistry
import
androidx.test.runner.AndroidJUnit4
import
org.junit.Assert.assertEquals
import
org.junit.Test
import
org.junit.runner.RunWith
/**
* Instrumented test, which will execute on an Android device.
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
@RunWith
(
AndroidJUnit4
::
class
)
class
ExampleInstrumentedTestActivity
{
@Test
fun
useAppContext
()
{
// Context of the app under test.
val
appContext
=
InstrumentationRegistry
.
getTargetContext
()
assertEquals
(
"fr.chenry.android.freshrss"
,
appContext
.
packageName
)
}
}
app/src/androidTest/java/fr/chenry/android/freshrss/store/database/FreshRSSDabatabaseBaseTest.kt
View file @
45146842
...
...
@@ -5,14 +5,9 @@ import androidx.room.testing.MigrationTestHelper
import
androidx.sqlite.db.SupportSQLiteDatabase
import
androidx.sqlite.db.framework.FrameworkSQLiteOpenHelperFactory
import
androidx.test.platform.app.InstrumentationRegistry
import
androidx.test.runner.AndroidJUnit4
import
org.junit.Rule
import
org.junit.runner.RunWith
@RunWith
(
AndroidJUnit4
::
class
)
abstract
class
FreshRSSDabatabaseBaseTest
{
open
val
testDB
get
()
=
"migration-test"
@
get
:
Rule
...
...
@@ -22,23 +17,17 @@ abstract class FreshRSSDabatabaseBaseTest {
FrameworkSQLiteOpenHelperFactory
()
)
val
instrumentation
get
()
=
InstrumentationRegistry
.
getInstrumentation
()
val
assets
get
()
=
instrumentation
.
context
.
assets
val
context
get
()
=
instrumentation
.
context
val
targetContext
get
()
=
instrumentation
.
targetContext
private
lateinit
var
_database
:
SQLiteDatabase
val
database
:
SQLiteDatabase
get
()
{
if
(!
::
_database
.
isInitialized
||
!
_database
.
isOpen
)
{
_database
=
SQLiteDatabase
.
openDatabase
(
targetContext
.
getDatabasePath
(
testDB
).
absolutePath
,
null
,
SQLiteDatabase
.
OPEN_READWRITE
)
}
return
_database
}
val
instrumentation
inline
get
()
=
InstrumentationRegistry
.
getInstrumentation
()
val
context
inline
get
()
=
instrumentation
.
targetContext
val
assets
inline
get
()
=
instrumentation
.
context
.
assets
val
database
:
SQLiteDatabase
by
lazy
{
SQLiteDatabase
.
openDatabase
(
context
.
getDatabasePath
(
testDB
).
absolutePath
,
null
,
SQLiteDatabase
.
OPEN_READWRITE
)
}
fun
createDatabaseFromScratch
(
targetVersion
:
Int
)
{
fun
createDatabaseFromScratch
(
targetVersion
:
Int
=
FreshRSSDabatabase_Migrations
.
build
().
size
)
{
helper
.
createDatabase
(
testDB
,
1
).
apply
{
execSQLWithImports
(
this
,
"migration-test-1-before"
)
migrateDatabase
(
this
,
1
,
targetVersion
)
...
...
@@ -60,7 +49,7 @@ abstract class FreshRSSDabatabaseBaseTest {
}
}
fun
execSQLWithImports
(
sqlMgr
:
SupportSQLiteDatabase
,
name
:
String
)
{
private
fun
execSQLWithImports
(
sqlMgr
:
SupportSQLiteDatabase
,
name
:
String
)
{
val
importRegex
=
"^--\\s*import\\s*:\\s*(\\S+).*$"
assets
.
open
(
"database/${name.replace("
.
sql
", "")}.sql"
).
reader
().
readLines
().
forEach
{
sql
->
if
(
sql
.
matches
(
importRegex
.
toRegex
()))
{
...
...
app/src/androidTest/java/fr/chenry/android/freshrss/store/database/FreshRSSDabatabaseMigrationsTest.kt
View file @
45146842
package
fr.chenry.android.freshrss.store.database
import
androidx.test.runner.AndroidJUnit4
import
androidx.test.ext.junit.runners.AndroidJUnit4
import
org.junit.Assert.assertArrayEquals
import
org.junit.Assert.assertEquals
import
org.junit.Test
import
org.junit.runner.RunWith
...
...
@@ -9,7 +10,7 @@ import org.junit.runner.RunWith
class
FreshRSSDabatabaseMigrationsTest
:
FreshRSSDabatabaseBaseTest
()
{
@Test
fun
allMigrations
()
{
createDatabaseFromScratch
(
FreshRSSDabatabase_Migrations
.
build
().
size
)
createDatabaseFromScratch
()
}
@Test
...
...
@@ -42,7 +43,7 @@ class FreshRSSDabatabaseMigrationsTest : FreshRSSDabatabaseBaseTest() {
val
query
=
database
.
rawQuery
(
"SELECT * FROM subscriptions"
,
arrayOf
())
assertEquals
(
5
,
query
.
count
)
assertEquals
(
arrayOf
(
"id"
,
"title"
,
"unreadCount"
,
"imageBitmap"
,
"iconUrl"
),
query
.
columnNames
)
assert
Array
Equals
(
arrayOf
(
"id"
,
"title"
,
"unreadCount"
,
"imageBitmap"
,
"iconUrl"
),
query
.
columnNames
)
assertEquals
(
true
,
query
.
moveToFirst
())
...
...
@@ -51,7 +52,6 @@ class FreshRSSDabatabaseMigrationsTest : FreshRSSDabatabaseBaseTest() {
val
bindArgs
=
arrayOf
(
"54f869cf-a764-4cb5-a77e-c46d8ca798e4"
)
database
.
execSQL
(
"UPDATE subscriptions SET iconUrl = 'https://example.com/icon' WHERE id = ?"
,
bindArgs
)
database
.
close
()
database
.
rawQuery
(
"SELECT * FROM subscriptions WHERE id = ?"
,
bindArgs
).
let
{
it
.
moveToFirst
()
assertEquals
(
"https://example.com/icon"
,
it
.
getString
(
4
))
...
...
app/src/androidTest/java/fr/chenry/android/freshrss/store/database/FreshRSSDabatabaseTest.kt
0 → 100644
View file @
45146842
package
fr.chenry.android.freshrss.store.database
import
androidx.room.Room
import
androidx.test.ext.junit.runners.AndroidJUnit4
import
fr.chenry.android.freshrss.store.database.models.Subscription
import
fr.chenry.android.freshrss.utils.SubscriptionsTestUtils
import
fr.chenry.android.freshrss.utils.TestUtils
import
kotlinx.coroutines.runBlocking
import
org.junit.*
import
org.junit.Assert.assertArrayEquals
import
org.junit.Assert.assertEquals
import
org.junit.runner.RunWith
@RunWith
(
AndroidJUnit4
::
class
)
class
FreshRSSDabatabaseTest
:
FreshRSSDabatabaseBaseTest
()
{
private
val
dbName
=
"${this::class.qualifiedName!!}.db"
private
lateinit
var
db
:
FreshRSSDabatabase
@Before
fun
setUp
()
{
db
=
Room
.
databaseBuilder
(
context
,
FreshRSSDabatabase
::
class
.
java
,
dbName
)
.
addMigrations
(*
FreshRSSDabatabase_Migrations
.
build
())
.
build
()
}
@After
fun
tearDown
()
{
context
.
deleteDatabase
(
dbName
)
}
@Test
fun
syncSubscriptionsFromScratch
()
{
runBlocking
{
val
subscriptions
=
SubscriptionsTestUtils
.
createSubscriptions
(
10
)
.
sortedBy
{
it
.
id
}.
map
{
it
.
id
to
it
}.
toMap
()
db
.
syncSubscriptions
(
subscriptions
)
val
result
=
db
.
getAllSubcriptionsIds
().
sorted
().
toTypedArray
()
assertArrayEquals
(
subscriptions
.
keys
.
toTypedArray
(),
result
)
}
}
@Test
fun
syncSubscriptionsWithUpdates
()
{
runBlocking
{
val
subscriptions
=
SubscriptionsTestUtils
.
createSubscriptions
(
10
)
val
subscriptionsMap
=
subscriptions
.
sortedBy
{
it
.
id
}.
map
{
it
.
id
to
it
}.
toMap
(
LinkedHashMap
())
db
.
syncSubscriptions
(
subscriptionsMap
)
val
oldSubscription
=
subscriptions
[
5
]
val
newSubscription
=
Subscription
(
oldSubscription
.
id
,
TestUtils
.
harryPotter
().
character
(),
"${oldSubscription.iconUrl}/icon"
,
oldSubscription
.
unreadCount
+
20
,
oldSubscription
.
subscriptionCategories
+
TestUtils
.
harryPotter
().
character
().
split
(
"\\s+"
.
toRegex
()),
oldSubscription
.
newestArticleDate
.
plusDays
(
3
)
)
subscriptionsMap
[
newSubscription
.
id
]
=
newSubscription
db
.
syncSubscriptions
(
subscriptionsMap
)
val
expected
=
oldSubscription
.
copy
(
title
=
newSubscription
.
title
,
iconUrl
=
newSubscription
.
iconUrl
,
subscriptionCategories
=
newSubscription
.
subscriptionCategories
)
val
actual
=
db
.
getSubcriptionsById
(
oldSubscription
.
id
).
blockingFirst
().
firstOrNull
()
assertEquals
(
expected
,
actual
)
}
}
@Test
fun
syncSubscriptionsWithDeletions
()
{
runBlocking
{
val
subscriptions
=
SubscriptionsTestUtils
.
createSubscriptions
(
10
)
val
subscriptionsMap
=
subscriptions
.
sortedBy
{
it
.
id
}.
map
{
it
.
id
to
it
}.
toMap
(
LinkedHashMap
())
db
.
syncSubscriptions
(
subscriptionsMap
)
val
subscriptionToRemove
=
subscriptions
[
5
]
subscriptionsMap
.
remove
(
subscriptionToRemove
.
id
)
assertEquals
(
9
,
subscriptionsMap
.
size
)
db
.
syncSubscriptions
(
subscriptionsMap
)
val
actual
=
db
.
getAllSubcriptionsIds
()
val
expected
=
subscriptions
.
filter
{
it
.
id
!=
subscriptionToRemove
.
id
}.
map
{
it
.
id
}.
sorted
()
assertEquals
(
expected
,
actual
)
}
}
}
app/src/androidTest/java/fr/chenry/android/freshrss/utils/SubscriptionsTestUtils.kt
0 → 100644
View file @
45146842
package
fr.chenry.android.freshrss.utils
import
fr.chenry.android.freshrss.store.database.models.Subscription
import
org.joda.time.LocalDateTime
import
java.util.concurrent.TimeUnit
object
SubscriptionsTestUtils
{
fun
createSubscription
(
id
:
String
=
TestUtils
.
idNumber
().
valid
(),
title
:
String
=
TestUtils
.
lebowski
().
character
(),
iconUrl
:
String
=
TestUtils
.
internet
().
url
(),
unreadCount
:
Int
=
TestUtils
.
number
().
numberBetween
(
0
,
100
),
subscriptionCategories
:
List
<
String
>
=
listOf
(),
newestArticleDate
:
LocalDateTime
=
LocalDateTime
(
TestUtils
.
jodaDate
().
past
(
15
,
TimeUnit
.
DAYS
).
millis
)
)
=
Subscription
(
id
,
title
,
iconUrl
,
unreadCount
,
subscriptionCategories
,
newestArticleDate
)
fun
createSubscriptions
(
number
:
Int
)
=
(
1
..
number
).
map
{
createSubscription
()}
}
app/src/androidTest/java/fr/chenry/android/freshrss/utils/TestUtils.kt
0 → 100644
View file @
45146842
package
fr.chenry.android.freshrss.utils
import
com.github.javafaker.DateAndTime
import
com.github.javafaker.Faker
import
org.joda.time.DateTime
import
java.util.Locale
import
java.util.concurrent.TimeUnit
class
JodaDateAndTime
internal
constructor
(
private
val
faker
:
Faker
){
/**
* Generates a future date from now. Note that there is a 1 second slack to avoid generating a past date.
*
* @param atMost
* at most this amount of time ahead from now exclusive.
* @param unit
* the time unit.
* @return a future date from now.
*/
fun
future
(
atMost
:
Int
,
unit
:
TimeUnit
):
DateTime
{
val
aBitLaterThanNow
=
DateTime
(
DateTime
.
now
().
plusSeconds
(
1
))
return
future
(
atMost
,
unit
,
aBitLaterThanNow
)
}
/**
* Generates a future date from now, with a minimum time.
*
* @param atMost
* at most this amount of time ahead from now exclusive.
* @param minimum
* the minimum amount of time in the future from now.
* @param unit
* the time unit.
* @return a future date from now.
*/
fun
future
(
atMost
:
Int
,
minimum
:
Int
,
unit
:
TimeUnit
):
DateTime
{
val
now
=
DateTime
()
val
minimumDateTime
=
DateTime
(
DateTime
.
now
().
millis
+
unit
.
toMillis
(
minimum
.
toLong
()))
return
future
(
atMost
-
minimum
,
unit
,
minimumDateTime
)
}
/**
* Generates a future date relative to the `referenceDateTime`.
*
* @param atMost
* at most this amount of time ahead to the `referenceDateTime` exclusive.
* @param unit
* the time unit.
* @param referenceDateTime
* the future date relative to this date.
* @return a future date relative to `referenceDateTime`.
*/
fun
future
(
atMost
:
Int
,
unit
:
TimeUnit
,
referenceDateTime
:
DateTime
):
DateTime
{
val
upperBound
=
unit
.
toMillis
(
atMost
.
toLong
())
var
futureMillis
=
referenceDateTime
.
millis
futureMillis
+=
1
+
faker
.
random
().
nextLong
(
upperBound
-
1
)
return
DateTime
(
futureMillis
)