Compare commits

..

No commits in common. 'main' and '13.4' have entirely different histories.
main ... 13.4

@ -19,12 +19,12 @@ jobs:
- name: Decode Keystore - name: Decode Keystore
run: | run: |
echo ${{ secrets.KEY_STORE }} | base64 -di > "${RUNNER_TEMP}"/keystore.jks echo ${{ secrets.KEY_STORE }} | base64 -di > "${RUNNER_TEMP}"/keystore.jks
- uses: actions/checkout@v4 - uses: actions/checkout@v3
- uses: ruby/setup-ruby@v1 - uses: ruby/setup-ruby@v1
with: with:
bundler-cache: true bundler-cache: true
- name: Set up JDK 17 - name: Set up JDK 17
uses: actions/setup-java@v4 uses: actions/setup-java@v3
with: with:
distribution: 'temurin' distribution: 'temurin'
java-version: '17' java-version: '17'
@ -41,7 +41,7 @@ jobs:
GOOGLE_KEY: ${{ secrets.GOOGLE_KEY }} GOOGLE_KEY: ${{ secrets.GOOGLE_KEY }}
run: bundle exec fastlane bundle run: bundle exec fastlane bundle
- name: Upload artifacts - name: Upload artifacts
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v3
with: with:
name: release name: release
path: app/build/outputs/** path: app/build/outputs/**

@ -11,12 +11,12 @@ jobs:
lint: lint:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v3
- uses: ruby/setup-ruby@v1 - uses: ruby/setup-ruby@v1
with: with:
bundler-cache: true bundler-cache: true
- name: Set up JDK 17 - name: Set up JDK 17
uses: actions/setup-java@v4 uses: actions/setup-java@v3
with: with:
distribution: 'temurin' distribution: 'temurin'
java-version: '17' java-version: '17'
@ -26,66 +26,31 @@ jobs:
- name: Lint checks - name: Lint checks
run: bundle exec fastlane lint run: bundle exec fastlane lint
- name: Archive lint reports - name: Archive lint reports
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v3
if: ${{ always() }} if: ${{ always() }}
with: with:
name: lint-reports name: lint-reports
path: app/build/reports/*.html path: app/build/reports/*.html
test: test:
runs-on: ubuntu-latest runs-on: macos-latest
strategy:
matrix:
flavor: [Googleplay, Generic]
api-level: [29]
steps: steps:
- name: checkout - name: checkout
uses: actions/checkout@v4 uses: actions/checkout@v3
- name: Set up JDK 17 - name: Set up JDK 17
uses: actions/setup-java@v4 uses: actions/setup-java@v3
with: with:
distribution: 'temurin' distribution: 'temurin'
java-version: '17' java-version: '17'
cache: 'gradle' cache: 'gradle'
- name: Enable KVM
run: |
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
sudo udevadm control --reload-rules
sudo udevadm trigger --name-match=kvm
# - name: AVD cache
# uses: actions/cache@v4
# id: avd-cache
# with:
# path: |
# ~/.android/avd/*
# ~/.android/adb*
# key: avd-${{ matrix.api-level }}
#
# - name: create AVD and generate snapshot for caching
# if: steps.avd-cache.outputs.cache-hit != 'true'
# uses: reactivecircus/android-emulator-runner@v2
# with:
# api-level: ${{ matrix.api-level }}
# force-avd-creation: false
# emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
# disable-animations: false
# script: echo "Generated AVD snapshot for caching."
- name: run tests - name: run tests
uses: reactivecircus/android-emulator-runner@v2 uses: reactivecircus/android-emulator-runner@v2
with: with:
api-level: ${{ matrix.api-level }} api-level: 29
force-avd-creation: false script: ./gradlew -Pcoverage app:testGoogleplayDebugUnitTest app:connectedGoogleplayDebugAndroidTest
emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
disable-animations: true
script: ./gradlew -Pcoverage app:test${{ matrix.flavor }}DebugUnitTest app:connected${{ matrix.flavor }}DebugAndroidTest
- name: Upload test reports - name: Upload test reports
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v3
if: ${{ always() }} if: ${{ always() }}
with: with:
name: test-reports-${{ matrix.flavor }} name: test-reports
path: app/build/reports/** path: app/build/reports/**

2
.gitignore vendored

@ -1,4 +1,3 @@
.kotlin
.idea .idea
*.iml *.iml
.gradle .gradle
@ -10,4 +9,3 @@ local.properties
Thumbs.db Thumbs.db
/captures/ /captures/
/fastlane/report.xml /fastlane/report.xml
/compose-metrics/

@ -1 +1 @@
3.3.3 3.2.2

@ -1,215 +1,3 @@
### 13.10 (2024-06-27)
* Add search bar to drawer
* Add search bar to list picker
* Move 'Manage drawer' to ⚙️ > Navigation drawer
* Android 13+ users must grant additional reminder permissions
* Fix completing task multiple times from notification
* Fix deleting new subtasks from edit screen
* Enable Managed DAVx5
* Update translations
* Arabic - @islam2hamy
* Brazilian Portuguese - Jose Delvani
* Chinese (Simplified) - 大王叫我来巡山
* Chinese (Traditional) - hugoalh
* Croatian - @milotype
* Finnish - Rami Lehtinen, @CSharpest
* German - min7-i
* Spanish - gallegonovato
* Turkish - @oersen
### 13.9.9 (2024-05-30)
* Fix import backup crashes
* Fix showing completed subtasks in edit screen
### 13.9.7 (2024-05-23)
* Add default reminders when adding start/due dates to existing tasks [#1846](https://github.com/tasks/tasks/issues/1846)
* Fix import backup crash
### 13.9.6 (2024-05-18)
* Fix widget crash [#2873](https://github.com/tasks/tasks/issues/2873)
* Fix recurrence unable to finish [#2874](https://github.com/tasks/tasks/issues/2874)
* Fix edit screen being cleared when reopening app [#2857](https://github.com/tasks/tasks/issues/2857)
* Fix performance regressions
* Simplified internal alarm scheduling logic
* Update translations
* Arabic - @islam2hamy
* Bulgarian - @StoyanDimitrov
### 13.9 (2024-05-01)
* @elmuffo: Add swipe-to-snooze [#2839](https://github.com/tasks/tasks/pull/2839)
* @IlyaBizyaev: Add option to use quick tile without unlocking device [#2847](https://github.com/tasks/tasks/pull/2847)
* @liz-desartiges: Add support for Z Flip 5 cover screen [#2843](https://github.com/tasks/tasks/pull/2843)
* @purushyb: Fix drawer not updating after editing items [#2855](https://github.com/tasks/tasks/pull/2855)
* @hady-exc: Migrate tag picker screen to Compose [#2849](https://github.com/tasks/tasks/pull/2849)
* @yurtpage: Add Russian app store description [#2848](https://github.com/tasks/tasks/pull/2848)
* Fix duplicate notifications [#2835](https://github.com/tasks/tasks/issues/2835)
* Fix adding '(Completed)' to calendar entries [#2832](https://github.com/tasks/tasks/issues/2832)
* Fix hiding empty items from drawer [#2831](https://github.com/tasks/tasks/issues/2831)
* Exclude old snoozed tasks from snoozed task filter
* Update translations
* Brazilian Portuguese - @mayhmemo, @gorgonun
* Chinese (Simplified) - 大王叫我来巡山
* Croatian - @milotype
* Esperanto - Don Zouras
* French - Lionel HANNEQUIN
* German - sorifukobexomajepasiricupuva33, min7-i
* Portuguese - @fparri, @laralem
* Spanish - gallegonovato
* Swedish - @JonatanWick
* Turkish - @emintufan, @oersen
### 13.8.1 (2024-03-24)
* Fix copy causing duplicate Google Tasks
* Fix navigation drawer crash
* Fix backup import dropping tasks
### 13.8 (2024-03-22)
* Dynamic widget theme (name-your-price subscription required)
* Replace 'until' with 'ends on' for repeating tasks [#2797](https://github.com/tasks/tasks/pull/2797) - @akwala
* Fix loading selected list on startup [#2777](https://github.com/tasks/tasks/issues/2777)
* Fix repeating tasks ending one day early
* Fix repeating task crash
* Fix backup import crash
* Fix Astrid manual ordering crash in widget
* Update translations
* Brazilian Portuguese - @mayhmemo
* Bulgarian - @StoyanDimitrov
* Catalan - @ferranpujolcamins
* Chinese (Simplified) - 大王叫我来巡山
* Croatian - @milotype
* Czech - Odweta
* German - @macpac59
* Italian - @ppasserini
* Spanish - gallegonovato
* Swedish - @bittin
* Ukrainian - @IhorHordiichuk
* Vietnamese - @ngocanhtve
### 13.7 (2024-02-07)
* Fix returning to previous filter after search [#2700](https://github.com/tasks/tasks/pull/2700)
* Fix wearable notifications on Android 14+
* Fix issue causing repeating tasks to not repeat
* Fix dragging a task into a subtask in another list
* Rewrote navigation drawer in Jetpack Compose
* Internal changes to navigation
* Enable multi-select when adding attachments
* Show count of tasks to be deleted when clearing completed
* Include hidden subtasks when clearing completed [#2724](https://github.com/tasks/tasks/issues/2724)
* Don't show hidden or completed tasks in snoozed filter
* Remove markdown from repeating task snackbar
* Update translations
* Azerbaijani - Shaban Mamedov
* Bulgarian - @StoyanDimitrov
* Catalan - raulmagdalena
* Chinese (Simplified) - 大王叫我来巡山
* Chinese (Traditional) - @abc0922001
* Croatian - @milotype
* Dutch - @mm4c
* Esperanto - Don Zouras
* Finnish - @millerii
* French - J. Lavoie
* German - @CennoxX
* Hebrew - @elig0n
* Interlingua - @softinterlingua
* Odia - @SubhamJena
* Persian - @Monirzadeh
* Spanish - gallegonovato
* Swedish - @bittin
* Turkish - @oersen
* Ukrainian - Сергій
* Vietnamese - @ngocanhtve
### 13.6.3 (2023-11-25)
* Revert "Preserve modification times on initial sync" [#2460](https://github.com/tasks/tasks/issues/2640)
* Fix unnecessary DecSync work
### 13.6.2 (2023-10-30)
* Fix updating modification timestamp on edits
### 13.6.1 (2023-10-27)
* Push pending changes when app is backgrounded
* Don't require internet connection for DAVx5/EteSync/DecSync sync
* Don't perform background sync for DAVx5/EteSync/DecSync
* Background sync is performed by the sync app
* Preserve modification times on initial sync [#2496](https://github.com/tasks/tasks/issues/2496)
* Replace deprecated method call [#2547](https://github.com/tasks/tasks/pull/2547) - @kmj-99
* Improve task list scrolling performance
* Fix hourly recurrence bug
* Update translations
* Chinese (Simplified) - Eric
* Croatian - @milotype
* Czech - @ceskyDJ
* Finnish - @millerii
* French - Lionel HANNEQUIN, Bruno Duyé
* Japanese - Kazushi Hayama
* Portuguese - @loucurapt
* Romanian - @ygorigor
* Swedish - @bittin
### 13.6 (2023-10-07)
* Change priority with multi-select [#2257](https://github.com/tasks/tasks/pull/2452) - @vulewuxe86
* Automatically select newly copied tasks [#2246](https://github.com/tasks/tasks/pull/2446) - @vulewuxe86
* Reduce minimum size for widgets [#2436](https://github.com/tasks/tasks/pull/2436) - @histefanhere
* Replace deprecated method call [#2526](https://github.com/tasks/tasks/pull/2526) - @kmj-99
* Improve handling text shared to Tasks [#2485](https://github.com/tasks/tasks/issues/2485)
* Use notification audio stream for completion sound
* Notification preference 'More settings' opens channel settings directly
* Respect 'New tasks on top' preference when creating subtasks
* Automatically add due dates for recurring tasks
* Fix crash on startup
* Update translations
* Brazilian Portuguese - @gorgonun
* Bulgarian - @StoyanDimitrov, @salif
* Catalan - Joan Montané
* Chinese (Simplified) - Poesty Li
* Chinese (Traditional) - @abc0922001
* Dutch - @fvbommel
* French - @FlorianLeChat
* German - @qwerty287, deep map, @franconian
* Hungarian - Kaci
* Italian - @ppasserini
* Japanese - Kazushi Hayama, Naga
* Spanish - @FlorianLeChat
* Swedish - @Anaemix, @bittin
* Turkish - @emintufan, @oersen
* Ukrainian - @IhorHordiichuk
### 13.5.1 (2023-08-02)
* Fix crash when importing Google Tasks from a backup file
* Added Burmese translations - @htetoh
* Update translations
* Chinese (Simplified) - Poesty Li
* Croatian - @milotype
* Japanese - Kazushi Hayama
* Polish - @alex-ter
* Russian - @alex-ter
* Ukrainian - @IhorHordiichuk
* Vietnamese - @unbiaseduser
### 13.5 (2023-07-28)
* New custom recurrence picker
* Update translations
* Bulgarian - @StoyanDimitrov
* Czech - @ceskyDJ
* Dutch - @fvbommel
* French - @FlorianLeChat
* Italian - @ppasserini
* Spanish - @FlorianLeChat
### 13.4 - (2023-07-16) ### 13.4 - (2023-07-16)
* Sorting improvements * Sorting improvements

@ -1,32 +1,29 @@
GEM GEM
remote: https://rubygems.org/ remote: https://rubygems.org/
specs: specs:
CFPropertyList (3.0.7) CFPropertyList (3.0.6)
base64
nkf
rexml rexml
addressable (2.8.6) addressable (2.8.4)
public_suffix (>= 2.0.2, < 6.0) public_suffix (>= 2.0.2, < 6.0)
artifactory (3.0.17) artifactory (3.0.15)
atomos (0.1.3) atomos (0.1.3)
aws-eventstream (1.3.0) aws-eventstream (1.2.0)
aws-partitions (1.944.0) aws-partitions (1.786.0)
aws-sdk-core (3.197.1) aws-sdk-core (3.178.0)
aws-eventstream (~> 1, >= 1.3.0) aws-eventstream (~> 1, >= 1.0.2)
aws-partitions (~> 1, >= 1.651.0) aws-partitions (~> 1, >= 1.651.0)
aws-sigv4 (~> 1.8) aws-sigv4 (~> 1.5)
jmespath (~> 1, >= 1.6.1) jmespath (~> 1, >= 1.6.1)
aws-sdk-kms (1.85.0) aws-sdk-kms (1.71.0)
aws-sdk-core (~> 3, >= 3.197.0) aws-sdk-core (~> 3, >= 3.177.0)
aws-sigv4 (~> 1.1) aws-sigv4 (~> 1.1)
aws-sdk-s3 (1.152.3) aws-sdk-s3 (1.130.0)
aws-sdk-core (~> 3, >= 3.197.0) aws-sdk-core (~> 3, >= 3.177.0)
aws-sdk-kms (~> 1) aws-sdk-kms (~> 1)
aws-sigv4 (~> 1.8) aws-sigv4 (~> 1.6)
aws-sigv4 (1.8.0) aws-sigv4 (1.6.0)
aws-eventstream (~> 1, >= 1.0.2) aws-eventstream (~> 1, >= 1.0.2)
babosa (1.0.4) babosa (1.0.4)
base64 (0.2.0)
claide (1.1.0) claide (1.1.0)
colored (1.2) colored (1.2)
colored2 (3.1.2) colored2 (3.1.2)
@ -35,10 +32,11 @@ GEM
declarative (0.0.20) declarative (0.0.20)
digest-crc (0.6.5) digest-crc (0.6.5)
rake (>= 12.0.0, < 14.0.0) rake (>= 12.0.0, < 14.0.0)
domain_name (0.6.20240107) domain_name (0.5.20190701)
unf (>= 0.0.5, < 1.0.0)
dotenv (2.8.1) dotenv (2.8.1)
emoji_regex (3.2.3) emoji_regex (3.2.3)
excon (0.110.0) excon (0.100.0)
faraday (1.10.3) faraday (1.10.3)
faraday-em_http (~> 1.0) faraday-em_http (~> 1.0)
faraday-em_synchrony (~> 1.0) faraday-em_synchrony (~> 1.0)
@ -67,15 +65,15 @@ GEM
faraday-retry (1.0.3) faraday-retry (1.0.3)
faraday_middleware (1.2.0) faraday_middleware (1.2.0)
faraday (~> 1.0) faraday (~> 1.0)
fastimage (2.3.1) fastimage (2.2.7)
fastlane (2.221.1) fastlane (2.214.0)
CFPropertyList (>= 2.3, < 4.0.0) CFPropertyList (>= 2.3, < 4.0.0)
addressable (>= 2.8, < 3.0.0) addressable (>= 2.8, < 3.0.0)
artifactory (~> 3.0) artifactory (~> 3.0)
aws-sdk-s3 (~> 1.0) aws-sdk-s3 (~> 1.0)
babosa (>= 1.0.3, < 2.0.0) babosa (>= 1.0.3, < 2.0.0)
bundler (>= 1.12.0, < 3.0.0) bundler (>= 1.12.0, < 3.0.0)
colored (~> 1.2) colored
commander (~> 4.6) commander (~> 4.6)
dotenv (>= 2.1.1, < 3.0.0) dotenv (>= 2.1.1, < 3.0.0)
emoji_regex (>= 0.1, < 4.0) emoji_regex (>= 0.1, < 4.0)
@ -87,32 +85,30 @@ GEM
gh_inspector (>= 1.1.2, < 2.0.0) gh_inspector (>= 1.1.2, < 2.0.0)
google-apis-androidpublisher_v3 (~> 0.3) google-apis-androidpublisher_v3 (~> 0.3)
google-apis-playcustomapp_v1 (~> 0.1) google-apis-playcustomapp_v1 (~> 0.1)
google-cloud-env (>= 1.6.0, < 2.0.0)
google-cloud-storage (~> 1.31) google-cloud-storage (~> 1.31)
highline (~> 2.0) highline (~> 2.0)
http-cookie (~> 1.0.5)
json (< 3.0.0) json (< 3.0.0)
jwt (>= 2.1.0, < 3) jwt (>= 2.1.0, < 3)
mini_magick (>= 4.9.4, < 5.0.0) mini_magick (>= 4.9.4, < 5.0.0)
multipart-post (>= 2.0.0, < 3.0.0) multipart-post (>= 2.0.0, < 3.0.0)
naturally (~> 2.2) naturally (~> 2.2)
optparse (>= 0.1.1, < 1.0.0) optparse (~> 0.1.1)
plist (>= 3.1.0, < 4.0.0) plist (>= 3.1.0, < 4.0.0)
rubyzip (>= 2.0.0, < 3.0.0) rubyzip (>= 2.0.0, < 3.0.0)
security (= 0.1.5) security (= 0.1.3)
simctl (~> 1.6.3) simctl (~> 1.6.3)
terminal-notifier (>= 2.0.0, < 3.0.0) terminal-notifier (>= 2.0.0, < 3.0.0)
terminal-table (~> 3) terminal-table (>= 1.4.5, < 2.0.0)
tty-screen (>= 0.6.3, < 1.0.0) tty-screen (>= 0.6.3, < 1.0.0)
tty-spinner (>= 0.8.0, < 1.0.0) tty-spinner (>= 0.8.0, < 1.0.0)
word_wrap (~> 1.0.0) word_wrap (~> 1.0.0)
xcodeproj (>= 1.13.0, < 2.0.0) xcodeproj (>= 1.13.0, < 2.0.0)
xcpretty (~> 0.3.0) xcpretty (~> 0.3.0)
xcpretty-travis-formatter (>= 0.0.3, < 2.0.0) xcpretty-travis-formatter (>= 0.0.3)
gh_inspector (1.1.3) gh_inspector (1.1.3)
google-apis-androidpublisher_v3 (0.54.0) google-apis-androidpublisher_v3 (0.45.0)
google-apis-core (>= 0.11.0, < 2.a) google-apis-core (>= 0.11.0, < 2.a)
google-apis-core (0.11.3) google-apis-core (0.11.0)
addressable (~> 2.5, >= 2.5.1) addressable (~> 2.5, >= 2.5.1)
googleauth (>= 0.16.2, < 2.a) googleauth (>= 0.16.2, < 2.a)
httpclient (>= 2.8.1, < 3.a) httpclient (>= 2.8.1, < 3.a)
@ -120,64 +116,64 @@ GEM
representable (~> 3.0) representable (~> 3.0)
retriable (>= 2.0, < 4.a) retriable (>= 2.0, < 4.a)
rexml rexml
webrick
google-apis-iamcredentials_v1 (0.17.0) google-apis-iamcredentials_v1 (0.17.0)
google-apis-core (>= 0.11.0, < 2.a) google-apis-core (>= 0.11.0, < 2.a)
google-apis-playcustomapp_v1 (0.13.0) google-apis-playcustomapp_v1 (0.13.0)
google-apis-core (>= 0.11.0, < 2.a) google-apis-core (>= 0.11.0, < 2.a)
google-apis-storage_v1 (0.31.0) google-apis-storage_v1 (0.19.0)
google-apis-core (>= 0.11.0, < 2.a) google-apis-core (>= 0.9.0, < 2.a)
google-cloud-core (1.7.0) google-cloud-core (1.6.0)
google-cloud-env (>= 1.0, < 3.a) google-cloud-env (~> 1.0)
google-cloud-errors (~> 1.0) google-cloud-errors (~> 1.0)
google-cloud-env (1.6.0) google-cloud-env (1.6.0)
faraday (>= 0.17.3, < 3.0) faraday (>= 0.17.3, < 3.0)
google-cloud-errors (1.4.0) google-cloud-errors (1.3.1)
google-cloud-storage (1.47.0) google-cloud-storage (1.44.0)
addressable (~> 2.8) addressable (~> 2.8)
digest-crc (~> 0.4) digest-crc (~> 0.4)
google-apis-iamcredentials_v1 (~> 0.1) google-apis-iamcredentials_v1 (~> 0.1)
google-apis-storage_v1 (~> 0.31.0) google-apis-storage_v1 (~> 0.19.0)
google-cloud-core (~> 1.6) google-cloud-core (~> 1.6)
googleauth (>= 0.16.2, < 2.a) googleauth (>= 0.16.2, < 2.a)
mini_mime (~> 1.0) mini_mime (~> 1.0)
googleauth (1.8.1) googleauth (1.6.0)
faraday (>= 0.17.3, < 3.a) faraday (>= 0.17.3, < 3.a)
jwt (>= 1.4, < 3.0) jwt (>= 1.4, < 3.0)
memoist (~> 0.16)
multi_json (~> 1.11) multi_json (~> 1.11)
os (>= 0.9, < 2.0) os (>= 0.9, < 2.0)
signet (>= 0.16, < 2.a) signet (>= 0.16, < 2.a)
highline (2.0.3) highline (2.0.3)
http-cookie (1.0.6) http-cookie (1.0.5)
domain_name (~> 0.5) domain_name (~> 0.5)
httpclient (2.8.3) httpclient (2.8.3)
jmespath (1.6.2) jmespath (1.6.2)
json (2.7.2) json (2.6.3)
jwt (2.8.2) jwt (2.7.1)
base64 memoist (0.16.2)
mini_magick (4.13.1) mini_magick (4.12.0)
mini_mime (1.1.5) mini_mime (1.1.2)
multi_json (1.15.0) multi_json (1.15.0)
multipart-post (2.4.1) multipart-post (2.3.0)
nanaimo (0.3.0) nanaimo (0.3.0)
naturally (2.2.1) naturally (2.2.1)
nkf (0.2.0) optparse (0.1.1)
optparse (0.5.0)
os (1.1.4) os (1.1.4)
plist (3.7.1) plist (3.7.0)
public_suffix (5.1.1) public_suffix (5.0.3)
rake (13.2.1) rake (13.0.6)
representable (3.2.0) representable (3.2.0)
declarative (< 0.1.0) declarative (< 0.1.0)
trailblazer-option (>= 0.1.1, < 0.2.0) trailblazer-option (>= 0.1.1, < 0.2.0)
uber (< 0.2.0) uber (< 0.2.0)
retriable (3.1.2) retriable (3.1.2)
rexml (3.2.9) rexml (3.2.5)
strscan
rouge (2.0.7) rouge (2.0.7)
ruby2_keywords (0.0.5) ruby2_keywords (0.0.5)
rubyzip (2.3.2) rubyzip (2.3.2)
security (0.1.5) security (0.1.3)
signet (0.19.0) signet (0.17.0)
addressable (~> 2.8) addressable (~> 2.8)
faraday (>= 0.17.5, < 3.a) faraday (>= 0.17.5, < 3.a)
jwt (>= 1.5, < 3.0) jwt (>= 1.5, < 3.0)
@ -185,19 +181,22 @@ GEM
simctl (1.6.10) simctl (1.6.10)
CFPropertyList CFPropertyList
naturally naturally
strscan (3.1.0)
terminal-notifier (2.0.0) terminal-notifier (2.0.0)
terminal-table (3.0.2) terminal-table (1.8.0)
unicode-display_width (>= 1.1.1, < 3) unicode-display_width (~> 1.1, >= 1.1.1)
trailblazer-option (0.1.2) trailblazer-option (0.1.2)
tty-cursor (0.7.1) tty-cursor (0.7.1)
tty-screen (0.8.2) tty-screen (0.8.1)
tty-spinner (0.9.3) tty-spinner (0.9.3)
tty-cursor (~> 0.7) tty-cursor (~> 0.7)
uber (0.1.0) uber (0.1.0)
unicode-display_width (2.5.0) unf (0.1.4)
unf_ext
unf_ext (0.0.8.2)
unicode-display_width (1.8.0)
webrick (1.8.1)
word_wrap (1.0.0) word_wrap (1.0.0)
xcodeproj (1.24.0) xcodeproj (1.22.0)
CFPropertyList (>= 2.3.3, < 4.0) CFPropertyList (>= 2.3.3, < 4.0)
atomos (~> 0.1.3) atomos (~> 0.1.3)
claide (>= 1.0.2, < 2.0) claide (>= 1.0.2, < 2.0)

@ -1,31 +1,36 @@
@file:Suppress("UnstableApiUsage") @file:Suppress("UnstableApiUsage")
import com.google.firebase.crashlytics.buildtools.gradle.CrashlyticsExtension import com.google.firebase.crashlytics.buildtools.gradle.CrashlyticsExtension
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
plugins { plugins {
alias(libs.plugins.android.application) id("com.android.application")
id("checkstyle")
id("com.google.gms.google-services") id("com.google.gms.google-services")
id("com.google.firebase.crashlytics") id("com.google.firebase.crashlytics")
kotlin("android") kotlin("android")
kotlin("kapt")
id("dagger.hilt.android.plugin") id("dagger.hilt.android.plugin")
id("com.google.android.gms.oss-licenses-plugin") id("com.google.android.gms.oss-licenses-plugin")
alias(libs.plugins.kotlin.parcelize) id("kotlin-parcelize")
alias(libs.plugins.ksp)
alias(libs.plugins.kotlin.serialization)
alias(libs.plugins.kotlin.compose.compiler)
} }
kotlin { repositories {
compilerOptions { mavenCentral()
jvmTarget.set(JvmTarget.JVM_17) google()
maven {
url = uri("https://jitpack.io")
content {
includeGroup("com.github.tasks")
includeModule("com.github.bitfireAT", "cert4android")
includeModule("com.github.bitfireAT", "dav4jvm")
includeModule("com.github.tasks.opentasks", "opentasks-provider")
includeModule("com.github.QuadFlask", "colorpicker")
includeModule("com.github.twofortyfouram", "android-plugin-api-for-locale")
includeModule("com.github.franmontiel", "PersistentCookieJar")
}
} }
} }
composeCompiler {
enableStrongSkippingMode = true
}
android { android {
bundle { bundle {
language { language {
@ -46,16 +51,23 @@ android {
textReport = true textReport = true
} }
compileSdk = libs.versions.android.compileSdk.get().toInt() compileSdk = 33
defaultConfig { defaultConfig {
testApplicationId = "org.tasks.test" testApplicationId = "org.tasks.test"
applicationId = "org.tasks" applicationId = "org.tasks"
versionCode = 131005 versionCode = 130400
versionName = "13.10" versionName = "13.4"
targetSdk = libs.versions.android.targetSdk.get().toInt() targetSdk = 33
minSdk = libs.versions.android.minSdk.get().toInt() minSdk = 24
testInstrumentationRunner = "org.tasks.TestRunner" testInstrumentationRunner = "org.tasks.TestRunner"
kapt {
arguments {
arg("room.schemaLocation", "$projectDir/schemas")
arg("room.incremental", "true")
}
}
} }
signingConfigs { signingConfigs {
@ -78,6 +90,13 @@ android {
targetCompatibility = JavaVersion.VERSION_17 targetCompatibility = JavaVersion.VERSION_17
} }
composeOptions {
kotlinCompilerExtensionVersion = libs.versions.compose.compiler.get()
}
kotlinOptions {
jvmTarget = "17"
}
flavorDimensions += listOf("store") flavorDimensions += listOf("store")
@Suppress("LocalVariableName") @Suppress("LocalVariableName")
@ -112,31 +131,23 @@ android {
dimension = "store" dimension = "store"
} }
create("googleplay") { create("googleplay") {
isDefault = true
dimension = "store" dimension = "store"
} }
} }
packaging { packagingOptions {
resources { resources {
excludes += setOf("META-INF/*.kotlin_module", "META-INF/INDEX.LIST") excludes += setOf("META-INF/*.kotlin_module")
}
}
testOptions {
managedDevices {
localDevices {
create("pixel2api30") {
device = "Pixel 2"
apiLevel = 30
systemImageSource = "aosp-atd"
}
}
} }
} }
namespace = "org.tasks" namespace = "org.tasks"
} }
configure<CheckstyleExtension> {
configFile = project.file("google_checks.xml")
toolVersion = "8.16"
}
configurations.all { configurations.all {
exclude(group = "org.apache.httpcomponents") exclude(group = "org.apache.httpcomponents")
exclude(group = "org.checkerframework") exclude(group = "org.checkerframework")
@ -151,8 +162,6 @@ val genericImplementation by configurations
val googleplayImplementation by configurations val googleplayImplementation by configurations
dependencies { dependencies {
implementation(projects.data)
implementation(projects.kmp)
coreLibraryDesugaring(libs.desugar.jdk.libs) coreLibraryDesugaring(libs.desugar.jdk.libs)
implementation(libs.bitfire.dav4jvm) { implementation(libs.bitfire.dav4jvm) {
exclude(group = "junit") exclude(group = "junit")
@ -173,37 +182,29 @@ dependencies {
implementation(libs.dmfs.jems) implementation(libs.dmfs.jems)
implementation(libs.dagger.hilt) implementation(libs.dagger.hilt)
ksp(libs.dagger.hilt.compiler) kapt(libs.dagger.hilt.compiler)
ksp(libs.androidx.hilt.compiler) kapt(libs.androidx.hilt.compiler)
implementation(libs.androidx.hilt.work) implementation(libs.androidx.hilt.work)
implementation(libs.androidx.fragment.ktx) implementation(libs.androidx.fragment.ktx)
implementation(libs.androidx.lifecycle.runtime) implementation(libs.androidx.lifecycle.runtime)
implementation(libs.androidx.lifecycle.runtime.compose)
implementation(libs.androidx.lifecycle.viewmodel) implementation(libs.androidx.lifecycle.viewmodel)
implementation(libs.androidx.room) implementation(libs.androidx.room)
kapt(libs.androidx.room.compiler)
implementation(libs.androidx.appcompat) implementation(libs.androidx.appcompat)
implementation(libs.markwon) implementation(libs.bundles.markwon)
implementation(libs.markwon.editor)
implementation(libs.markwon.linkify)
implementation(libs.markwon.strikethrough)
implementation(libs.markwon.tables)
implementation(libs.markwon.tasklist)
debugImplementation(libs.facebook.flipper) debugImplementation(libs.bundles.flipper)
debugImplementation(libs.facebook.flipper.network)
debugImplementation(libs.facebook.soloader)
debugImplementation(libs.leakcanary) debugImplementation(libs.leakcanary)
debugImplementation("androidx.compose.ui:ui-tooling") debugImplementation("androidx.compose.ui:ui-tooling")
debugImplementation(libs.kotlin.reflect) debugImplementation(libs.kotlin.reflect)
implementation(libs.kotlin.jdk8) implementation(libs.kotlin.jdk8)
implementation(libs.kotlinx.immutable)
implementation(libs.kotlinx.serialization)
implementation(libs.okhttp) implementation(libs.okhttp)
implementation(libs.persistent.cookiejar) implementation(libs.persistent.cookiejar)
implementation(libs.gson)
implementation(libs.material) implementation(libs.material)
implementation(libs.androidx.compose.material3) implementation(libs.material3)
implementation(libs.androidx.constraintlayout) implementation(libs.androidx.constraintlayout)
implementation(libs.androidx.swiperefreshlayout) implementation(libs.androidx.swiperefreshlayout)
implementation(libs.androidx.preference) implementation(libs.androidx.preference)
@ -224,8 +225,7 @@ dependencies {
implementation(libs.colorpicker) implementation(libs.colorpicker)
implementation(libs.appauth) implementation(libs.appauth)
implementation(libs.osmdroid) implementation(libs.osmdroid)
implementation(libs.retrofit) implementation(libs.bundles.retrofit)
implementation(libs.retrofit.moshi)
implementation(libs.androidx.recyclerview) implementation(libs.androidx.recyclerview)
implementation(platform(libs.androidx.compose)) implementation(platform(libs.androidx.compose))
@ -233,15 +233,13 @@ dependencies {
implementation("androidx.compose.foundation:foundation") implementation("androidx.compose.foundation:foundation")
implementation("androidx.compose.material:material") implementation("androidx.compose.material:material")
implementation("androidx.compose.runtime:runtime-livedata") implementation("androidx.compose.runtime:runtime-livedata")
implementation(libs.compose.theme.adapter)
implementation(libs.androidx.activity.compose) implementation(libs.androidx.activity.compose)
implementation("androidx.compose.material:material-icons-extended") implementation("androidx.compose.material:material-icons-extended")
implementation(libs.androidx.lifecycle.viewmodel.compose) implementation(libs.androidx.lifecycle.viewmodel.compose)
implementation("androidx.compose.ui:ui-viewbinding") implementation("androidx.compose.ui:ui-viewbinding")
implementation("androidx.compose.ui:ui-tooling-preview") implementation("androidx.compose.ui:ui-tooling-preview")
implementation(libs.coil.compose) implementation(libs.bundles.coil)
implementation(libs.coil.video)
implementation(libs.coil.svg)
implementation(libs.coil.gif)
implementation(libs.accompanist.flowlayout) implementation(libs.accompanist.flowlayout)
implementation(libs.accompanist.permissions) implementation(libs.accompanist.permissions)
@ -256,12 +254,13 @@ dependencies {
googleplayImplementation(libs.play.services.location) googleplayImplementation(libs.play.services.location)
googleplayImplementation(libs.play.services.maps) googleplayImplementation(libs.play.services.maps)
googleplayImplementation(libs.play.billing.ktx) googleplayImplementation(libs.play.billing.ktx)
googleplayImplementation(libs.play.review) googleplayImplementation(libs.play.core)
googleplayImplementation(libs.play.core.ktx)
googleplayImplementation(libs.play.services.oss.licenses) googleplayImplementation(libs.play.services.oss.licenses)
androidTestImplementation(libs.dagger.hilt.testing) androidTestImplementation(libs.dagger.hilt.testing)
kspAndroidTest(libs.dagger.hilt.compiler) kaptAndroidTest(libs.dagger.hilt.compiler)
kspAndroidTest(libs.androidx.hilt.compiler) kaptAndroidTest(libs.androidx.hilt.compiler)
androidTestImplementation(libs.mockito.android) androidTestImplementation(libs.mockito.android)
androidTestImplementation(libs.make.it.easy) androidTestImplementation(libs.make.it.easy)
androidTestImplementation(libs.androidx.test.runner) androidTestImplementation(libs.androidx.test.runner)

@ -0,0 +1,263 @@
<?xml version="1.0"?>
<!DOCTYPE module PUBLIC
"-//Checkstyle//DTD Checkstyle Configuration 1.3//EN"
"https://checkstyle.org/dtds/configuration_1_3.dtd">
<!-- https://raw.githubusercontent.com/checkstyle/checkstyle/checkstyle-8.16/src/main/resources/google_checks.xml -->
<!--
Checkstyle configuration that checks the Google coding conventions from Google Java Style
that can be found at https://google.github.io/styleguide/javaguide.html.
Checkstyle is very configurable. Be sure to read the documentation at
http://checkstyle.sf.net (or in your downloaded distribution).
To completely disable a check, just comment it out or delete it from the file.
Authors: Max Vetrenko, Ruslan Diachenko, Roman Ivanov.
-->
<module name = "Checker">
<property name="charset" value="UTF-8"/>
<property name="severity" value="warning"/>
<property name="fileExtensions" value="java, properties, xml"/>
<!-- Checks for whitespace -->
<!-- See http://checkstyle.sf.net/config_whitespace.html -->
<module name="FileTabCharacter">
<property name="eachLine" value="true"/>
</module>
<module name="TreeWalker">
<module name="OuterTypeFilename"/>
<module name="IllegalTokenText">
<property name="tokens" value="STRING_LITERAL, CHAR_LITERAL"/>
<property name="format"
value="\\u00(09|0(a|A)|0(c|C)|0(d|D)|22|27|5(C|c))|\\(0(10|11|12|14|15|42|47)|134)"/>
<property name="message"
value="Consider using special escape sequence instead of octal value or Unicode escaped value."/>
</module>
<module name="AvoidEscapedUnicodeCharacters">
<property name="allowEscapesForControlCharacters" value="true"/>
<property name="allowByTailComment" value="true"/>
<property name="allowNonPrintableEscapes" value="true"/>
</module>
<module name="LineLength">
<property name="max" value="100"/>
<property name="ignorePattern" value="^package.*|^import.*|a href|href|http://|https://|ftp://"/>
</module>
<module name="AvoidStarImport"/>
<module name="OneTopLevelClass"/>
<module name="NoLineWrap"/>
<module name="EmptyBlock">
<property name="option" value="TEXT"/>
<property name="tokens"
value="LITERAL_TRY, LITERAL_FINALLY, LITERAL_IF, LITERAL_ELSE, LITERAL_SWITCH"/>
</module>
<module name="NeedBraces"/>
<module name="LeftCurly"/>
<module name="RightCurly">
<property name="id" value="RightCurlySame"/>
<property name="tokens"
value="LITERAL_TRY, LITERAL_CATCH, LITERAL_FINALLY, LITERAL_IF, LITERAL_ELSE,
LITERAL_DO"/>
</module>
<module name="RightCurly">
<property name="id" value="RightCurlyAlone"/>
<property name="option" value="alone"/>
<property name="tokens"
value="CLASS_DEF, METHOD_DEF, CTOR_DEF, LITERAL_FOR, LITERAL_WHILE, STATIC_INIT,
INSTANCE_INIT"/>
</module>
<module name="WhitespaceAround">
<property name="allowEmptyConstructors" value="true"/>
<property name="allowEmptyMethods" value="true"/>
<property name="allowEmptyTypes" value="true"/>
<property name="allowEmptyLoops" value="true"/>
<message key="ws.notFollowed"
value="WhitespaceAround: ''{0}'' is not followed by whitespace. Empty blocks may only be represented as '{}' when not part of a multi-block statement (4.1.3)"/>
<message key="ws.notPreceded"
value="WhitespaceAround: ''{0}'' is not preceded with whitespace."/>
</module>
<module name="OneStatementPerLine"/>
<module name="MultipleVariableDeclarations"/>
<module name="ArrayTypeStyle"/>
<module name="MissingSwitchDefault"/>
<module name="FallThrough"/>
<module name="UpperEll"/>
<module name="ModifierOrder"/>
<module name="EmptyLineSeparator">
<property name="allowNoEmptyLineBetweenFields" value="true"/>
</module>
<module name="SeparatorWrap">
<property name="id" value="SeparatorWrapDot"/>
<property name="tokens" value="DOT"/>
<property name="option" value="nl"/>
</module>
<module name="SeparatorWrap">
<property name="id" value="SeparatorWrapComma"/>
<property name="tokens" value="COMMA"/>
<property name="option" value="EOL"/>
</module>
<module name="SeparatorWrap">
<!-- ELLIPSIS is EOL until https://github.com/google/styleguide/issues/258 -->
<property name="id" value="SeparatorWrapEllipsis"/>
<property name="tokens" value="ELLIPSIS"/>
<property name="option" value="EOL"/>
</module>
<module name="SeparatorWrap">
<!-- ARRAY_DECLARATOR is EOL until https://github.com/google/styleguide/issues/259 -->
<property name="id" value="SeparatorWrapArrayDeclarator"/>
<property name="tokens" value="ARRAY_DECLARATOR"/>
<property name="option" value="EOL"/>
</module>
<module name="SeparatorWrap">
<property name="id" value="SeparatorWrapMethodRef"/>
<property name="tokens" value="METHOD_REF"/>
<property name="option" value="nl"/>
</module>
<module name="PackageName">
<property name="format" value="^[a-z]+(\.[a-z][a-z0-9]*)*$"/>
<message key="name.invalidPattern"
value="Package name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="TypeName">
<message key="name.invalidPattern"
value="Type name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="MemberName">
<property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9]*$"/>
<message key="name.invalidPattern"
value="Member name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="ParameterName">
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
<message key="name.invalidPattern"
value="Parameter name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="LambdaParameterName">
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
<message key="name.invalidPattern"
value="Lambda parameter name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="CatchParameterName">
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
<message key="name.invalidPattern"
value="Catch parameter name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="LocalVariableName">
<property name="tokens" value="VARIABLE_DEF"/>
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
<message key="name.invalidPattern"
value="Local variable name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="ClassTypeParameterName">
<property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/>
<message key="name.invalidPattern"
value="Class type name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="MethodTypeParameterName">
<property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/>
<message key="name.invalidPattern"
value="Method type name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="InterfaceTypeParameterName">
<property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/>
<message key="name.invalidPattern"
value="Interface type name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="NoFinalizer"/>
<module name="GenericWhitespace">
<message key="ws.followed"
value="GenericWhitespace ''{0}'' is followed by whitespace."/>
<message key="ws.preceded"
value="GenericWhitespace ''{0}'' is preceded with whitespace."/>
<message key="ws.illegalFollow"
value="GenericWhitespace ''{0}'' should followed by whitespace."/>
<message key="ws.notPreceded"
value="GenericWhitespace ''{0}'' is not preceded with whitespace."/>
</module>
<module name="Indentation">
<property name="basicOffset" value="2"/>
<property name="braceAdjustment" value="0"/>
<property name="caseIndent" value="2"/>
<property name="throwsIndent" value="4"/>
<property name="lineWrappingIndentation" value="4"/>
<property name="arrayInitIndent" value="2"/>
</module>
<module name="AbbreviationAsWordInName">
<property name="ignoreFinal" value="false"/>
<property name="allowedAbbreviationLength" value="1"/>
</module>
<module name="OverloadMethodsDeclarationOrder"/>
<module name="VariableDeclarationUsageDistance"/>
<module name="CustomImportOrder">
<property name="sortImportsInGroupAlphabetically" value="true"/>
<property name="separateLineBetweenGroups" value="true"/>
<property name="customImportOrderRules" value="STATIC###THIRD_PARTY_PACKAGE"/>
</module>
<module name="MethodParamPad"/>
<module name="NoWhitespaceBefore">
<property name="tokens"
value="COMMA, SEMI, POST_INC, POST_DEC, DOT, ELLIPSIS, METHOD_REF"/>
<property name="allowLineBreaks" value="true"/>
</module>
<module name="ParenPad"/>
<module name="OperatorWrap">
<property name="option" value="NL"/>
<property name="tokens"
value="BAND, BOR, BSR, BXOR, DIV, EQUAL, GE, GT, LAND, LE, LITERAL_INSTANCEOF, LOR,
LT, MINUS, MOD, NOT_EQUAL, PLUS, QUESTION, SL, SR, STAR, METHOD_REF "/>
</module>
<module name="AnnotationLocation">
<property name="id" value="AnnotationLocationMostCases"/>
<property name="tokens"
value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, METHOD_DEF, CTOR_DEF"/>
</module>
<module name="AnnotationLocation">
<property name="id" value="AnnotationLocationVariables"/>
<property name="tokens" value="VARIABLE_DEF"/>
<property name="allowSamelineMultipleAnnotations" value="true"/>
</module>
<module name="NonEmptyAtclauseDescription"/>
<module name="JavadocTagContinuationIndentation">
<property name="severity" value="ignore" />
</module>
<module name="SummaryJavadoc">
<property name="severity" value="ignore" />
<property name="forbiddenSummaryFragments"
value="^@return the *|^This method returns |^A [{]@code [a-zA-Z0-9]+[}]( is a )"/>
</module>
<module name="JavadocParagraph">
<property name="severity" value="ignore" />
</module>
<module name="AtclauseOrder">
<property name="tagOrder" value="@param, @return, @throws, @deprecated"/>
<property name="target"
value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, METHOD_DEF, CTOR_DEF, VARIABLE_DEF"/>
</module>
<module name="JavadocMethod">
<property name="severity" value="ignore" />
<property name="scope" value="public"/>
<property name="allowMissingParamTags" value="true"/>
<property name="allowMissingThrowsTags" value="true"/>
<property name="allowMissingReturnTag" value="true"/>
<property name="minLineCount" value="2"/>
<property name="allowedAnnotations" value="Override, Test"/>
<property name="allowThrowsTagsForSubclasses" value="true"/>
</module>
<module name="MethodName">
<property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9_]*$"/>
<message key="name.invalidPattern"
value="Method name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="SingleLineJavadoc">
<property name="severity" value="ignore"/>
</module>
<module name="EmptyCatchBlock">
<property name="exceptionVariableName" value="expected"/>
</module>
<module name="CommentsIndentation"/>
</module>
</module>

@ -17,7 +17,7 @@ import org.tasks.Freeze.Companion.freezeAt
import org.tasks.date.DateTimeUtils import org.tasks.date.DateTimeUtils
import org.tasks.time.DateTime import org.tasks.time.DateTime
import java.time.format.FormatStyle import java.time.format.FormatStyle
import java.util.Locale import java.util.*
@RunWith(AndroidJUnit4::class) @RunWith(AndroidJUnit4::class)
class DateUtilitiesTest { class DateUtilitiesTest {
@ -29,21 +29,21 @@ class DateUtilitiesTest {
@Test @Test
fun testGet24HourTime() { fun testGet24HourTime() {
DateUtilities.is24HourOverride = true DateUtilities.is24HourOverride = true
assertEquals("09:05", DateUtilities.getTimeString(ApplicationProvider.getApplicationContext(), DateTime(2014, 1, 4, 9, 5, 36))) assertEquals("09:05", DateUtilities.getTimeString(null, DateTime(2014, 1, 4, 9, 5, 36)))
assertEquals("13:00", DateUtilities.getTimeString(ApplicationProvider.getApplicationContext(), DateTime(2014, 1, 4, 13, 0, 1))) assertEquals("13:00", DateUtilities.getTimeString(null, DateTime(2014, 1, 4, 13, 0, 1)))
} }
@Test @Test
fun testGetTime() { fun testGetTime() {
DateUtilities.is24HourOverride = false DateUtilities.is24HourOverride = false
assertEquals("9:05 AM", DateUtilities.getTimeString(ApplicationProvider.getApplicationContext(), DateTime(2014, 1, 4, 9, 5, 36))) assertEquals("9:05 AM", DateUtilities.getTimeString(null, DateTime(2014, 1, 4, 9, 5, 36)))
assertEquals("1:05 PM", DateUtilities.getTimeString(ApplicationProvider.getApplicationContext(), DateTime(2014, 1, 4, 13, 5, 36))) assertEquals("1:05 PM", DateUtilities.getTimeString(null, DateTime(2014, 1, 4, 13, 5, 36)))
} }
@Test @Test
fun testGetTimeWithNoMinutes() { fun testGetTimeWithNoMinutes() {
DateUtilities.is24HourOverride = false DateUtilities.is24HourOverride = false
assertEquals("1 PM", DateUtilities.getTimeString(ApplicationProvider.getApplicationContext(), DateTime(2014, 1, 4, 13, 0, 59))) // derp? assertEquals("1 PM", DateUtilities.getTimeString(null, DateTime(2014, 1, 4, 13, 0, 59))) // derp?
} }
@Test @Test

@ -2,9 +2,9 @@ package com.todoroo.astrid.adapter
import com.natpryce.makeiteasy.MakeItEasy.with import com.natpryce.makeiteasy.MakeItEasy.with
import com.natpryce.makeiteasy.PropertyValue import com.natpryce.makeiteasy.PropertyValue
import org.tasks.filters.CaldavFilter import com.todoroo.astrid.api.CaldavFilter
import com.todoroo.astrid.dao.TaskDao import com.todoroo.astrid.dao.TaskDao
import org.tasks.data.entity.Task import com.todoroo.astrid.data.Task
import com.todoroo.astrid.service.TaskMover import com.todoroo.astrid.service.TaskMover
import dagger.hilt.android.testing.HiltAndroidTest import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules import dagger.hilt.android.testing.UninstallModules
@ -15,9 +15,9 @@ import org.junit.Before
import org.junit.Test import org.junit.Test
import org.tasks.LocalBroadcastManager import org.tasks.LocalBroadcastManager
import org.tasks.R import org.tasks.R
import org.tasks.data.entity.CaldavCalendar import org.tasks.data.CaldavCalendar
import org.tasks.data.dao.CaldavDao import org.tasks.data.CaldavDao
import org.tasks.data.dao.GoogleTaskDao import org.tasks.data.GoogleTaskDao
import org.tasks.data.TaskContainer import org.tasks.data.TaskContainer
import org.tasks.data.TaskListQuery.getQuery import org.tasks.data.TaskListQuery.getQuery
import org.tasks.injection.InjectingTestCase import org.tasks.injection.InjectingTestCase

@ -12,9 +12,6 @@ import org.junit.Before
import org.junit.Test import org.junit.Test
import org.tasks.LocalBroadcastManager import org.tasks.LocalBroadcastManager
import org.tasks.data.* import org.tasks.data.*
import org.tasks.data.dao.CaldavDao
import org.tasks.data.dao.GoogleTaskDao
import org.tasks.data.entity.CaldavTask
import org.tasks.injection.InjectingTestCase import org.tasks.injection.InjectingTestCase
import org.tasks.injection.ProductionModule import org.tasks.injection.ProductionModule
import org.tasks.makers.TaskContainerMaker.PARENT import org.tasks.makers.TaskContainerMaker.PARENT

@ -2,8 +2,9 @@ package com.todoroo.astrid.adapter
import com.natpryce.makeiteasy.MakeItEasy.with import com.natpryce.makeiteasy.MakeItEasy.with
import com.natpryce.makeiteasy.PropertyValue import com.natpryce.makeiteasy.PropertyValue
import org.tasks.filters.GtasksFilter import com.todoroo.astrid.api.GtasksFilter
import com.todoroo.astrid.dao.TaskDao import com.todoroo.astrid.dao.TaskDao
import com.todoroo.astrid.data.Task
import com.todoroo.astrid.service.TaskMover import com.todoroo.astrid.service.TaskMover
import dagger.hilt.android.testing.HiltAndroidTest import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules import dagger.hilt.android.testing.UninstallModules
@ -13,14 +14,14 @@ import org.junit.Before
import org.junit.Test import org.junit.Test
import org.tasks.LocalBroadcastManager import org.tasks.LocalBroadcastManager
import org.tasks.R import org.tasks.R
import org.tasks.data.CaldavDao
import org.tasks.data.GoogleTaskDao
import org.tasks.data.TaskContainer import org.tasks.data.TaskContainer
import org.tasks.data.TaskListQuery.getQuery import org.tasks.data.TaskListQuery.getQuery
import org.tasks.data.dao.CaldavDao
import org.tasks.data.dao.GoogleTaskDao
import org.tasks.data.entity.CaldavCalendar
import org.tasks.data.entity.Task
import org.tasks.injection.InjectingTestCase import org.tasks.injection.InjectingTestCase
import org.tasks.injection.ProductionModule import org.tasks.injection.ProductionModule
import org.tasks.makers.CaldavCalendarMaker
import org.tasks.makers.CaldavCalendarMaker.newCaldavCalendar
import org.tasks.makers.CaldavTaskMaker.CALENDAR import org.tasks.makers.CaldavTaskMaker.CALENDAR
import org.tasks.makers.CaldavTaskMaker.TASK import org.tasks.makers.CaldavTaskMaker.TASK
import org.tasks.makers.CaldavTaskMaker.newCaldavTask import org.tasks.makers.CaldavTaskMaker.newCaldavTask
@ -41,7 +42,7 @@ class GoogleTaskManualSortAdapterTest : InjectingTestCase() {
private lateinit var adapter: GoogleTaskManualSortAdapter private lateinit var adapter: GoogleTaskManualSortAdapter
private val tasks = ArrayList<TaskContainer>() private val tasks = ArrayList<TaskContainer>()
private val filter = GtasksFilter(CaldavCalendar(uuid = "1234")) private val filter = GtasksFilter(newCaldavCalendar(with(CaldavCalendarMaker.UUID, "1234")))
private val dataSource = object : TaskAdapterDataSource { private val dataSource = object : TaskAdapterDataSource {
override fun getItem(position: Int) = tasks[position] override fun getItem(position: Int) = tasks[position]

@ -6,7 +6,7 @@ import com.natpryce.makeiteasy.MakeItEasy.with
import com.natpryce.makeiteasy.PropertyValue import com.natpryce.makeiteasy.PropertyValue
import com.todoroo.astrid.core.BuiltInFilterExposer import com.todoroo.astrid.core.BuiltInFilterExposer
import com.todoroo.astrid.dao.TaskDao import com.todoroo.astrid.dao.TaskDao
import org.tasks.data.entity.Task import com.todoroo.astrid.data.Task
import com.todoroo.astrid.service.TaskMover import com.todoroo.astrid.service.TaskMover
import dagger.hilt.android.testing.HiltAndroidTest import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules import dagger.hilt.android.testing.UninstallModules
@ -15,8 +15,8 @@ import org.junit.Assert.assertEquals
import org.junit.Before import org.junit.Before
import org.junit.Test import org.junit.Test
import org.tasks.LocalBroadcastManager import org.tasks.LocalBroadcastManager
import org.tasks.data.dao.CaldavDao import org.tasks.data.CaldavDao
import org.tasks.data.dao.GoogleTaskDao import org.tasks.data.GoogleTaskDao
import org.tasks.data.TaskContainer import org.tasks.data.TaskContainer
import org.tasks.data.TaskListQuery.getQuery import org.tasks.data.TaskListQuery.getQuery
import org.tasks.injection.InjectingTestCase import org.tasks.injection.InjectingTestCase

@ -4,7 +4,7 @@ import com.natpryce.makeiteasy.MakeItEasy.with
import com.natpryce.makeiteasy.PropertyValue import com.natpryce.makeiteasy.PropertyValue
import com.todoroo.astrid.core.BuiltInFilterExposer import com.todoroo.astrid.core.BuiltInFilterExposer
import com.todoroo.astrid.dao.TaskDao import com.todoroo.astrid.dao.TaskDao
import org.tasks.data.entity.Task import com.todoroo.astrid.data.Task
import dagger.hilt.android.testing.HiltAndroidTest import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules import dagger.hilt.android.testing.UninstallModules
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking

@ -1,290 +1,106 @@
package com.todoroo.astrid.alarms package com.todoroo.astrid.alarms
import com.natpryce.makeiteasy.MakeItEasy.with
import com.todoroo.andlib.utility.DateUtilities
import dagger.hilt.android.testing.HiltAndroidTest import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules import dagger.hilt.android.testing.UninstallModules
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertEquals import org.junit.Assert.assertEquals
import org.junit.Test import org.junit.Test
import org.tasks.SuspendFreeze.Companion.freezeAt import org.tasks.data.Alarm
import org.tasks.data.createDueDate import org.tasks.data.Alarm.Companion.TYPE_DATE_TIME
import org.tasks.data.dao.TaskDao import org.tasks.data.Alarm.Companion.TYPE_RANDOM
import org.tasks.data.entity.Alarm import org.tasks.data.Alarm.Companion.TYPE_SNOOZE
import org.tasks.data.entity.Notification import org.tasks.data.Alarm.Companion.whenDue
import org.tasks.data.entity.Task import org.tasks.data.Alarm.Companion.whenOverdue
import org.tasks.data.AlarmDao
import org.tasks.data.TaskDao
import org.tasks.date.DateTimeUtils.newDateTime
import org.tasks.injection.InjectingTestCase import org.tasks.injection.InjectingTestCase
import org.tasks.injection.ProductionModule import org.tasks.injection.ProductionModule
import org.tasks.jobs.AlarmEntry
import org.tasks.jobs.NotificationQueue
import org.tasks.makers.TaskMaker.COMPLETION_TIME
import org.tasks.makers.TaskMaker.DELETION_TIME
import org.tasks.makers.TaskMaker.DUE_DATE
import org.tasks.makers.TaskMaker.DUE_TIME
import org.tasks.makers.TaskMaker.REMINDER_LAST
import org.tasks.makers.TaskMaker.newTask
import org.tasks.time.DateTime import org.tasks.time.DateTime
import org.tasks.time.DateTimeUtils2
import java.util.concurrent.TimeUnit
import javax.inject.Inject import javax.inject.Inject
@UninstallModules(ProductionModule::class) @UninstallModules(ProductionModule::class)
@HiltAndroidTest @HiltAndroidTest
class AlarmJobServiceTest : InjectingTestCase() { class AlarmJobServiceTest : InjectingTestCase() {
@Inject lateinit var alarmDao: AlarmDao
@Inject lateinit var taskDao: TaskDao @Inject lateinit var taskDao: TaskDao
@Inject lateinit var jobs: NotificationQueue
@Inject lateinit var alarmService: AlarmService @Inject lateinit var alarmService: AlarmService
@Test @Test
fun testNoAlarms() = runBlocking { fun scheduleAlarm() = runBlocking {
testResults(emptyList(), 0) val task = taskDao.createNew(newTask())
} val alarm = insertAlarm(Alarm(task, DateTime(2017, 9, 24, 19, 57).millis, TYPE_DATE_TIME))
@Test
fun futureAlarmWithNoPastAlarm() = runBlocking {
freezeAt(DateTime(2024, 5, 17, 23, 20)) {
taskDao.insert(
Task(
dueDate = createDueDate(
Task.URGENCY_SPECIFIC_DAY,
DateTime(2024, 5, 18).millis
)
)
)
alarmService.synchronizeAlarms(1, mutableSetOf(Alarm(type = Alarm.TYPE_REL_END)))
testResults(emptyList(), DateTime(2024, 5, 18, 18, 0).millis) verify(AlarmEntry(alarm, task, DateTime(2017, 9, 24, 19, 57).millis, TYPE_DATE_TIME))
}
} }
@Test @Test
fun pastAlarmWithNoFutureAlarm() = runBlocking { fun ignoreStaleAlarm() = runBlocking {
freezeAt(DateTime(2024, 5, 17, 23, 20)) { val alarmTime = DateTime(2017, 9, 24, 19, 57)
taskDao.insert( val task = taskDao.createNew(newTask(with(REMINDER_LAST, alarmTime.endOfMinute())))
Task( alarmDao.insert(Alarm(task, alarmTime.millis, TYPE_DATE_TIME))
dueDate = createDueDate(
Task.URGENCY_SPECIFIC_DAY,
DateTime(2024, 5, 17).millis
)
)
)
alarmService.synchronizeAlarms(1, mutableSetOf(Alarm(type = Alarm.TYPE_REL_END)))
testResults( verify()
listOf(
Notification(
taskId = 1L,
timestamp = DateTimeUtils2.currentTimeMillis(),
type = Alarm.TYPE_REL_END
)
),
0
)
}
} }
@Test @Test
fun pastRecurringAlarmWithFutureRecurrence() = runBlocking { fun dontScheduleReminderForCompletedTask() = runBlocking {
freezeAt(DateTime(2024, 5, 17, 23, 20)) { val task = taskDao.insert(
taskDao.insert( newTask(
Task( with(DUE_DATE, newDateTime()),
dueDate = createDueDate( with(COMPLETION_TIME, newDateTime())
Task.URGENCY_SPECIFIC_DAY,
DateTime(2024, 5, 17).millis
)
)
)
alarmService.synchronizeAlarms(
1,
mutableSetOf(
Alarm(
type = Alarm.TYPE_REL_END,
repeat = 1,
interval = TimeUnit.HOURS.toMillis(6)
)
)
) )
)
alarmDao.insert(whenDue(task))
testResults( verify()
listOf(
Notification(
taskId = 1L,
timestamp = DateTimeUtils2.currentTimeMillis(),
type = Alarm.TYPE_REL_END
)
),
DateTime(2024, 5, 18, 0, 0).millis
)
}
} }
@Test @Test
fun pastAlarmsRemoveSnoozed() = runBlocking { fun dontScheduleReminderForDeletedTask() = runBlocking {
freezeAt(DateTime(2024, 5, 17, 23, 20)) { val task = taskDao.insert(
taskDao.insert( newTask(
Task( with(DUE_DATE, newDateTime()),
dueDate = createDueDate( with(DELETION_TIME, newDateTime())
Task.URGENCY_SPECIFIC_DAY,
DateTime(2024, 5, 17).millis
)
)
)
alarmService.synchronizeAlarms(
1,
mutableSetOf(
Alarm(type = Alarm.TYPE_REL_END),
Alarm(time = DateTimeUtils2.currentTimeMillis(), type = Alarm.TYPE_SNOOZE)
)
) )
)
alarmDao.insert(whenDue(task))
testResults( verify()
listOf(
Notification(
taskId = 1L,
timestamp = DateTimeUtils2.currentTimeMillis(),
type = Alarm.TYPE_REL_END
)
),
0
)
assertEquals(
listOf(Alarm(id = 1, task = 1, time = 0, type = Alarm.TYPE_REL_END)),
alarmService.getAlarms(1)
)
}
} }
@Test @Test
fun alarmsOneMinuteApart() = runBlocking { fun snoozeOverridesAll() = runBlocking {
freezeAt(DateTime(2024, 5, 17, 23, 20)) { val now = newDateTime()
taskDao.insert( val task = taskDao.insert(newTask(with(DUE_TIME, now)))
Task(
dueDate = createDueDate(
Task.URGENCY_SPECIFIC_DAY_TIME,
DateTime(2024, 5, 17, 23, 20).millis
)
)
)
alarmService.synchronizeAlarms(1, mutableSetOf(Alarm(type = Alarm.TYPE_REL_END)))
taskDao.insert(Task())
alarmService.synchronizeAlarms(
taskId = 2,
alarms = mutableSetOf(
Alarm(
type = Alarm.TYPE_SNOOZE,
time = DateTime(2024, 5, 17, 23, 21).millis)
)
)
testResults(
listOf(
Notification(
taskId = 1L,
timestamp = DateTimeUtils2.currentTimeMillis(),
type = Alarm.TYPE_REL_END
)
),
DateTime(2024, 5, 17, 23, 21).millis
)
}
}
@Test alarmDao.insert(whenDue(task))
fun futureSnoozeOverrideOverdue() = runBlocking { alarmDao.insert(whenOverdue(task))
freezeAt(DateTime(2024, 5, 17, 23, 20)) { alarmDao.insert(Alarm(task, DateUtilities.ONE_HOUR, TYPE_RANDOM))
taskDao.insert( val alarm = alarmDao.insert(Alarm(task, now.plusMonths(12).millis, TYPE_SNOOZE))
Task(
dueDate = createDueDate(
Task.URGENCY_SPECIFIC_DAY,
DateTime(2024, 5, 17).millis
)
)
)
alarmService.synchronizeAlarms(
1,
mutableSetOf(
Alarm(type = Alarm.TYPE_REL_END),
Alarm(
time = DateTimeUtils2.currentTimeMillis() + TimeUnit.MINUTES.toMillis(5),
type = Alarm.TYPE_SNOOZE
)
)
)
testResults( verify(AlarmEntry(alarm, task, now.plusMonths(12).millis, TYPE_SNOOZE))
emptyList(),
DateTimeUtils2.currentTimeMillis() + TimeUnit.MINUTES.toMillis(5)
)
}
}
@Test
fun ignoreStaleAlarm() = runBlocking {
freezeAt(DateTime(2024, 5, 17, 23, 20)) {
taskDao.insert(
Task(
dueDate = createDueDate(
Task.URGENCY_SPECIFIC_DAY,
DateTime(2024, 5, 17).millis
),
reminderLast = DateTime(2024, 5, 17, 18, 0).millis,
)
)
alarmService.synchronizeAlarms(
1,
mutableSetOf(Alarm(type = Alarm.TYPE_REL_END))
)
testResults(
emptyList(),
0
)
}
} }
@Test private suspend fun insertAlarm(alarm: Alarm): Long {
fun dontScheduleForCompletedTask() = runBlocking { alarm.id = alarmDao.insert(alarm)
freezeAt(DateTime(2024, 5, 17, 23, 20)) { return alarm.id
taskDao.insert(
Task(
dueDate = createDueDate(
Task.URGENCY_SPECIFIC_DAY,
DateTime(2024, 5, 17).millis
),
completionDate = DateTime(2024, 5, 17, 14, 0).millis,
)
)
alarmService.synchronizeAlarms(
1,
mutableSetOf(Alarm(type = Alarm.TYPE_REL_END))
)
testResults(
emptyList(),
0
)
}
} }
@Test private suspend fun verify(vararg alarms: AlarmEntry) {
fun dontScheduleForDeletedTask() = runBlocking { alarmService.scheduleAllAlarms()
freezeAt(DateTime(2024, 5, 17, 23, 20)) {
taskDao.insert(
Task(
dueDate = createDueDate(
Task.URGENCY_SPECIFIC_DAY,
DateTime(2024, 5, 17).millis
),
deletionDate = DateTime(2024, 5, 17, 14, 0).millis,
)
)
alarmService.synchronizeAlarms(
1,
mutableSetOf(Alarm(type = Alarm.TYPE_REL_END))
)
testResults(
emptyList(),
0
)
}
}
private suspend fun testResults(notifications: List<Notification>, nextAlarm: Long) { assertEquals(alarms.toList(), jobs.getJobs())
val actualNextAlarm = alarmService.triggerAlarms {
assertEquals(notifications, it)
it.forEach { taskDao.setLastNotified(it.taskId, DateTimeUtils2.currentTimeMillis()) }
}
assertEquals(nextAlarm, actualNextAlarm)
} }
} }

@ -5,7 +5,8 @@
*/ */
package com.todoroo.astrid.dao package com.todoroo.astrid.dao
import org.tasks.data.entity.Task import com.todoroo.andlib.utility.DateUtilities
import com.todoroo.astrid.data.Task
import com.todoroo.astrid.service.TaskDeleter import com.todoroo.astrid.service.TaskDeleter
import dagger.hilt.android.testing.HiltAndroidTest import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules import dagger.hilt.android.testing.UninstallModules
@ -14,7 +15,6 @@ import org.junit.Assert.*
import org.junit.Test import org.junit.Test
import org.tasks.injection.InjectingTestCase import org.tasks.injection.InjectingTestCase
import org.tasks.injection.ProductionModule import org.tasks.injection.ProductionModule
import org.tasks.time.DateTimeUtils2.currentTimeMillis
import javax.inject.Inject import javax.inject.Inject
@UninstallModules(ProductionModule::class) @UninstallModules(ProductionModule::class)
@ -75,23 +75,23 @@ class TaskDaoTests : InjectingTestCase() {
// create hidden task // create hidden task
task = Task() task = Task()
task.title = "hidden" task.title = "hidden"
task.hideUntil = currentTimeMillis() + 10000 task.hideUntil = DateUtilities.now() + 10000
taskDao.createNew(task) taskDao.createNew(task)
// create task with deadlines // create task with deadlines
task = Task() task = Task()
task.title = "deadlineInFuture" task.title = "deadlineInFuture"
task.dueDate = currentTimeMillis() + 10000 task.dueDate = DateUtilities.now() + 10000
taskDao.createNew(task) taskDao.createNew(task)
task = Task() task = Task()
task.title = "deadlineInPast" task.title = "deadlineInPast"
task.dueDate = currentTimeMillis() - 10000 task.dueDate = DateUtilities.now() - 10000
taskDao.createNew(task) taskDao.createNew(task)
// create completed task // create completed task
task = Task() task = Task()
task.title = "completed" task.title = "completed"
task.completionDate = currentTimeMillis() - 10000 task.completionDate = DateUtilities.now() - 10000
taskDao.createNew(task) taskDao.createNew(task)
// check is active // check is active

@ -11,12 +11,15 @@ import org.junit.Assert.assertNull
import org.junit.Before import org.junit.Before
import org.junit.Test import org.junit.Test
import org.tasks.LocalBroadcastManager import org.tasks.LocalBroadcastManager
import org.tasks.data.dao.CaldavDao import org.tasks.data.CaldavAccount
import org.tasks.data.dao.GoogleTaskListDao import org.tasks.data.CaldavDao
import org.tasks.data.entity.CaldavAccount import org.tasks.data.GoogleTaskListDao
import org.tasks.data.entity.CaldavCalendar
import org.tasks.injection.InjectingTestCase import org.tasks.injection.InjectingTestCase
import org.tasks.injection.ProductionModule import org.tasks.injection.ProductionModule
import org.tasks.makers.CaldavCalendarMaker.ID
import org.tasks.makers.CaldavCalendarMaker.NAME
import org.tasks.makers.CaldavCalendarMaker.UUID
import org.tasks.makers.CaldavCalendarMaker.newCaldavCalendar
import org.tasks.makers.RemoteGtaskListMaker import org.tasks.makers.RemoteGtaskListMaker
import org.tasks.makers.RemoteGtaskListMaker.newRemoteList import org.tasks.makers.RemoteGtaskListMaker.newRemoteList
import javax.inject.Inject import javax.inject.Inject
@ -43,14 +46,13 @@ class GtasksListServiceTest : InjectingTestCase() {
newRemoteList( newRemoteList(
with(RemoteGtaskListMaker.REMOTE_ID, "1"), with(RemoteGtaskListMaker.NAME, "Default"))) with(RemoteGtaskListMaker.REMOTE_ID, "1"), with(RemoteGtaskListMaker.NAME, "Default")))
assertEquals( assertEquals(
CaldavCalendar(id = 1, account = "account", uuid = "1", name = "Default"), newCaldavCalendar(with(ID, 1L), with(UUID, "1"), with(NAME, "Default")),
googleTaskListDao.getById(1L) googleTaskListDao.getById(1L))
)
} }
@Test @Test
fun testGetListByRemoteId() = runBlocking { fun testGetListByRemoteId() = runBlocking {
val list = CaldavCalendar(uuid = "1") val list = newCaldavCalendar(with(UUID, "1"))
list.id = googleTaskListDao.insertOrReplace(list) list.id = googleTaskListDao.insertOrReplace(list)
assertEquals(list, googleTaskListDao.getByRemoteId("1")) assertEquals(list, googleTaskListDao.getByRemoteId("1"))
} }
@ -62,19 +64,18 @@ class GtasksListServiceTest : InjectingTestCase() {
@Test @Test
fun testDeleteMissingList() = runBlocking { fun testDeleteMissingList() = runBlocking {
googleTaskListDao.insertOrReplace(CaldavCalendar(id = 1, account = "account", uuid = "1")) googleTaskListDao.insertOrReplace(newCaldavCalendar(with(ID, 1L), with(UUID, "1")))
val taskList = newRemoteList(with(RemoteGtaskListMaker.REMOTE_ID, "2")) val taskList = newRemoteList(with(RemoteGtaskListMaker.REMOTE_ID, "2"))
setLists(taskList) setLists(taskList)
assertEquals( assertEquals(
listOf(CaldavCalendar(id = 2, account = "account", uuid = "2", name = "Default")), listOf(newCaldavCalendar(with(ID, 2L), with(UUID, "2"), with(NAME, "Default"))),
googleTaskListDao.getLists("account") googleTaskListDao.getLists("account"))
)
} }
@Test @Test
fun testUpdateListName() = runBlocking { fun testUpdateListName() = runBlocking {
googleTaskListDao.insertOrReplace( googleTaskListDao.insertOrReplace(
CaldavCalendar(id = 1, uuid = "1", name = "oldName", account = "account") newCaldavCalendar(with(ID, 1L), with(UUID, "1"), with(NAME, "oldName"))
) )
setLists( setLists(
newRemoteList( newRemoteList(
@ -89,10 +90,10 @@ class GtasksListServiceTest : InjectingTestCase() {
} }
private suspend fun setLists(vararg list: TaskList) { private suspend fun setLists(vararg list: TaskList) {
val account = CaldavAccount( val account = CaldavAccount().apply {
username = "account", username = "account"
uuid = "account", uuid = "account"
) }
caldavDao.insert(account) caldavDao.insert(account)
gtasksListService.updateLists(account, listOf(*list)) gtasksListService.updateLists(account, listOf(*list))
} }

@ -1,7 +1,7 @@
package com.todoroo.astrid.model package com.todoroo.astrid.model
import com.todoroo.astrid.dao.TaskDao import com.todoroo.astrid.dao.TaskDao
import org.tasks.data.entity.Task import com.todoroo.astrid.data.Task
import dagger.hilt.android.testing.HiltAndroidTest import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules import dagger.hilt.android.testing.UninstallModules
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
@ -10,7 +10,7 @@ import org.junit.Test
import org.tasks.SuspendFreeze.Companion.freezeClock import org.tasks.SuspendFreeze.Companion.freezeClock
import org.tasks.injection.InjectingTestCase import org.tasks.injection.InjectingTestCase
import org.tasks.injection.ProductionModule import org.tasks.injection.ProductionModule
import org.tasks.time.DateTimeUtils2.currentTimeMillis import org.tasks.time.DateTimeUtils
import javax.inject.Inject import javax.inject.Inject
@UninstallModules(ProductionModule::class) @UninstallModules(ProductionModule::class)
@ -23,7 +23,7 @@ class TaskTest : InjectingTestCase() {
freezeClock { freezeClock {
val task = Task() val task = Task()
taskDao.createNew(task) taskDao.createNew(task)
assertEquals(currentTimeMillis(), task.creationDate) assertEquals(DateTimeUtils.currentTimeMillis(), task.creationDate)
} }
} }

@ -1,68 +1,50 @@
package com.todoroo.astrid.repeats package com.todoroo.astrid.repeats
import org.tasks.data.entity.Task import com.natpryce.makeiteasy.MakeItEasy.with
import com.todoroo.astrid.service.TaskCompleter
import dagger.hilt.android.testing.HiltAndroidTest import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules import dagger.hilt.android.testing.UninstallModules
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertFalse import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.junit.Test import org.junit.Test
import org.tasks.data.dao.TaskDao import org.tasks.data.TaskDao
import org.tasks.injection.InjectingTestCase import org.tasks.injection.InjectingTestCase
import org.tasks.injection.ProductionModule import org.tasks.injection.ProductionModule
import org.tasks.time.DateTimeUtils2.currentTimeMillis import org.tasks.makers.TaskMaker.COMPLETION_TIME
import org.tasks.makers.TaskMaker.PARENT
import org.tasks.makers.TaskMaker.RECUR
import org.tasks.makers.TaskMaker.newTask
import org.tasks.time.DateTime
import javax.inject.Inject import javax.inject.Inject
@UninstallModules(ProductionModule::class) @UninstallModules(ProductionModule::class)
@HiltAndroidTest @HiltAndroidTest
class RepeatWithSubtasksTests : InjectingTestCase() { class RepeatWithSubtasksTests : InjectingTestCase() {
@Inject lateinit var taskDao: TaskDao @Inject lateinit var taskDao: TaskDao
@Inject lateinit var taskCompleter: TaskCompleter @Inject lateinit var repeat: RepeatTaskHelper
@Test @Test
fun uncompleteGrandchildren() = runBlocking { fun uncompleteGrandchildren() = runBlocking {
val grandparent = taskDao.createNew( val grandparent = taskDao.createNew(newTask(with(RECUR, "RRULE:FREQ=DAILY")))
Task( val parent = taskDao.createNew(newTask(with(PARENT, grandparent)))
recurrence = "RRULE:FREQ=DAILY" val child = taskDao.createNew(newTask(
) with(PARENT, parent),
) with(COMPLETION_TIME, DateTime())
val parent = taskDao.createNew( ))
Task(
parent = grandparent
)
)
val child = taskDao.createNew(
Task(
parent = parent,
completionDate = currentTimeMillis(),
)
)
assertTrue(taskDao.fetch(child)!!.isCompleted) repeat.handleRepeat(taskDao.fetch(grandparent)!!)
taskCompleter.setComplete(grandparent)
assertFalse(taskDao.fetch(child)!!.isCompleted) assertFalse(taskDao.fetch(child)!!.isCompleted)
} }
@Test @Test
fun uncompleteGoogleTaskChildren() = runBlocking { fun uncompleteGoogleTaskChildren() = runBlocking {
val parent = taskDao.createNew( val parent = taskDao.createNew(newTask(with(RECUR, "RRULE:FREQ=DAILY")))
Task( val child = taskDao.createNew(newTask(
recurrence = "RRULE:FREQ=DAILY" with(PARENT, parent),
) with(COMPLETION_TIME, DateTime())
) ))
val child = taskDao.createNew(
Task(
parent = parent,
completionDate = currentTimeMillis(),
)
)
assertTrue(taskDao.fetch(child)!!.isCompleted)
taskCompleter.setComplete(parent) repeat.handleRepeat(taskDao.fetch(parent)!!)
assertFalse(taskDao.fetch(child)!!.isCompleted) assertFalse(taskDao.fetch(child)!!.isCompleted)
} }

@ -5,14 +5,14 @@
*/ */
package com.todoroo.astrid.service package com.todoroo.astrid.service
import org.tasks.data.entity.Task import com.todoroo.astrid.data.Task
import com.todoroo.astrid.utility.TitleParser import com.todoroo.astrid.utility.TitleParser
import dagger.hilt.android.testing.HiltAndroidTest import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules import dagger.hilt.android.testing.UninstallModules
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertEquals import org.junit.Assert.assertEquals
import org.junit.Test import org.junit.Test
import org.tasks.data.dao.TagDataDao import org.tasks.data.TagDataDao
import org.tasks.injection.InjectingTestCase import org.tasks.injection.InjectingTestCase
import org.tasks.injection.ProductionModule import org.tasks.injection.ProductionModule
import java.util.* import java.util.*

@ -1,12 +1,10 @@
package com.todoroo.astrid.service package com.todoroo.astrid.service
import com.todoroo.astrid.api.PermaSql.VALUE_EOD import com.todoroo.astrid.api.PermaSql.*
import com.todoroo.astrid.api.PermaSql.VALUE_EOD_NEXT_WEEK import com.todoroo.astrid.data.Task
import com.todoroo.astrid.api.PermaSql.VALUE_EOD_TOMORROW import com.todoroo.astrid.data.Task.Companion.DUE_DATE
import org.tasks.data.entity.Task import com.todoroo.astrid.data.Task.Companion.HIDE_UNTIL
import org.tasks.data.entity.Task.Companion.DUE_DATE import com.todoroo.astrid.data.Task.Companion.URGENCY_SPECIFIC_DAY
import org.tasks.data.entity.Task.Companion.HIDE_UNTIL
import org.tasks.data.entity.Task.Companion.URGENCY_SPECIFIC_DAY
import dagger.hilt.android.testing.HiltAndroidTest import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules import dagger.hilt.android.testing.UninstallModules
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
@ -14,7 +12,6 @@ import org.junit.Assert.assertEquals
import org.junit.Test import org.junit.Test
import org.tasks.R import org.tasks.R
import org.tasks.SuspendFreeze.Companion.freezeAt import org.tasks.SuspendFreeze.Companion.freezeAt
import org.tasks.data.createDueDate
import org.tasks.injection.InjectingTestCase import org.tasks.injection.InjectingTestCase
import org.tasks.injection.ProductionModule import org.tasks.injection.ProductionModule
import org.tasks.preferences.Preferences import org.tasks.preferences.Preferences
@ -38,7 +35,7 @@ class TaskCreatorTest : InjectingTestCase() {
assertEquals(DateTime(2021, 2, 4).millis, task.hideUntil) assertEquals(DateTime(2021, 2, 4).millis, task.hideUntil)
assertEquals( assertEquals(
createDueDate(URGENCY_SPECIFIC_DAY, DateTime(2021, 2, 5).millis), Task.createDueDate(URGENCY_SPECIFIC_DAY, DateTime(2021, 2, 5).millis),
task.dueDate task.dueDate
) )
} }
@ -66,7 +63,7 @@ class TaskCreatorTest : InjectingTestCase() {
assertEquals(DateTime(2021, 2, 4).millis, task.hideUntil) assertEquals(DateTime(2021, 2, 4).millis, task.hideUntil)
assertEquals( assertEquals(
createDueDate(URGENCY_SPECIFIC_DAY, DateTime(2021, 2, 4).millis), Task.createDueDate(URGENCY_SPECIFIC_DAY, DateTime(2021, 2, 4).millis),
task.dueDate task.dueDate
) )
} }
@ -96,7 +93,7 @@ class TaskCreatorTest : InjectingTestCase() {
} }
assertEquals( assertEquals(
createDueDate(URGENCY_SPECIFIC_DAY, DateTime(2021, 2, 5).millis), Task.createDueDate(URGENCY_SPECIFIC_DAY, DateTime(2021, 2, 5).millis),
task.dueDate task.dueDate
) )
} }

@ -1,15 +1,22 @@
package com.todoroo.astrid.service package com.todoroo.astrid.service
import org.tasks.data.entity.Task import com.natpryce.makeiteasy.MakeItEasy.with
import com.todoroo.astrid.core.BuiltInFilterExposer.Companion.getMyTasksFilter
import dagger.hilt.android.testing.HiltAndroidTest import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules import dagger.hilt.android.testing.UninstallModules
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertFalse import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue import org.junit.Assert.assertTrue
import org.junit.Test import org.junit.Test
import org.tasks.data.dao.TaskDao import org.tasks.data.GoogleTaskDao
import org.tasks.data.TaskDao
import org.tasks.injection.InjectingTestCase import org.tasks.injection.InjectingTestCase
import org.tasks.injection.ProductionModule import org.tasks.injection.ProductionModule
import org.tasks.makers.TaskMaker.COMPLETION_TIME
import org.tasks.makers.TaskMaker.PARENT
import org.tasks.makers.TaskMaker.RECUR
import org.tasks.makers.TaskMaker.newTask
import org.tasks.time.DateTime
import javax.inject.Inject import javax.inject.Inject
@UninstallModules(ProductionModule::class) @UninstallModules(ProductionModule::class)
@ -17,26 +24,75 @@ import javax.inject.Inject
class TaskDeleterTest : InjectingTestCase() { class TaskDeleterTest : InjectingTestCase() {
@Inject lateinit var taskDao: TaskDao @Inject lateinit var taskDao: TaskDao
@Inject lateinit var taskDeleter: TaskDeleter @Inject lateinit var taskDeleter: TaskDeleter
@Inject lateinit var googleTaskDao: GoogleTaskDao
@Test @Test
fun markTaskAsDeleted() = runBlocking { fun clearCompletedTask() = runBlocking {
val task = Task() val task = taskDao.createNew(newTask(with(COMPLETION_TIME, DateTime())))
taskDao.createNew(task)
taskDeleter.markDeleted(task) clearCompleted()
assertTrue(taskDao.fetch(task.id)!!.isDeleted) assertTrue(taskDao.fetch(task)!!.isDeleted)
} }
@Test @Test
fun dontDeleteReadOnlyTasks() = runBlocking { fun dontDeleteTaskWithRecurringParent() = runBlocking {
val task = Task( val parent = taskDao.createNew(newTask(with(RECUR, "RRULE:FREQ=DAILY;INTERVAL=1")))
readOnly = true val child = taskDao.createNew(newTask(
) with(PARENT, parent),
taskDao.createNew(task) with(COMPLETION_TIME, DateTime())
))
taskDeleter.markDeleted(task) clearCompleted()
assertFalse(taskDao.fetch(task.id)!!.isDeleted) assertFalse(taskDao.fetch(child)!!.isDeleted)
} }
}
@Test
fun dontDeleteTaskWithRecurringGrandparent() = runBlocking {
val grandparent = taskDao.createNew(newTask(with(RECUR, "RRULE:FREQ=DAILY;INTERVAL=1")))
val parent = taskDao.createNew(newTask(with(PARENT, grandparent)))
val child = taskDao.createNew(newTask(
with(PARENT, parent),
with(COMPLETION_TIME, DateTime())
))
clearCompleted()
assertFalse(taskDao.fetch(child)!!.isDeleted)
}
@Test
fun clearGrandchildWithNoRecurringAncestors() = runBlocking {
val grandparent = taskDao.createNew(newTask())
val parent = taskDao.createNew(newTask(with(PARENT, grandparent)))
val child = taskDao.createNew(newTask(
with(PARENT, parent),
with(COMPLETION_TIME, DateTime())
))
clearCompleted()
assertTrue(taskDao.fetch(child)!!.isDeleted)
}
@Test
fun clearGrandchildWithCompletedRecurringAncestor() = runBlocking {
val grandparent = taskDao.createNew(newTask(
with(RECUR, "RRULE:FREQ=DAILY;INTERVAL=1"),
with(COMPLETION_TIME, DateTime())
))
val parent = taskDao.createNew(newTask(with(PARENT, grandparent)))
val child = taskDao.createNew(newTask(
with(PARENT, parent),
with(COMPLETION_TIME, DateTime())
))
clearCompleted()
assertTrue(taskDao.fetch(child)!!.isDeleted)
}
private suspend fun clearCompleted() =
taskDeleter.clearCompleted(getMyTasksFilter(context.resources))
}

@ -1,8 +1,8 @@
package com.todoroo.astrid.service package com.todoroo.astrid.service
import com.natpryce.makeiteasy.MakeItEasy.with import com.natpryce.makeiteasy.MakeItEasy.with
import org.tasks.filters.CaldavFilter import com.todoroo.astrid.api.CaldavFilter
import org.tasks.filters.GtasksFilter import com.todoroo.astrid.api.GtasksFilter
import com.todoroo.astrid.dao.TaskDao import com.todoroo.astrid.dao.TaskDao
import dagger.hilt.android.testing.HiltAndroidTest import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules import dagger.hilt.android.testing.UninstallModules
@ -11,15 +11,20 @@ import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue import org.junit.Assert.assertTrue
import org.junit.Before import org.junit.Before
import org.junit.Test import org.junit.Test
import org.tasks.data.dao.CaldavDao import org.tasks.data.CaldavAccount.Companion.TYPE_CALDAV
import org.tasks.data.dao.GoogleTaskDao import org.tasks.data.CaldavAccount.Companion.TYPE_GOOGLE_TASKS
import org.tasks.data.entity.CaldavAccount import org.tasks.data.CaldavCalendar
import org.tasks.data.entity.CaldavAccount.Companion.TYPE_CALDAV import org.tasks.data.CaldavDao
import org.tasks.data.entity.CaldavAccount.Companion.TYPE_GOOGLE_TASKS import org.tasks.data.GoogleTaskDao
import org.tasks.data.entity.CaldavCalendar
import org.tasks.injection.InjectingTestCase import org.tasks.injection.InjectingTestCase
import org.tasks.injection.ProductionModule import org.tasks.injection.ProductionModule
import org.tasks.jobs.WorkManager import org.tasks.jobs.WorkManager
import org.tasks.makers.CaldavAccountMaker
import org.tasks.makers.CaldavAccountMaker.ACCOUNT_TYPE
import org.tasks.makers.CaldavAccountMaker.newCaldavAccount
import org.tasks.makers.CaldavCalendarMaker
import org.tasks.makers.CaldavCalendarMaker.ACCOUNT
import org.tasks.makers.CaldavCalendarMaker.newCaldavCalendar
import org.tasks.makers.CaldavTaskMaker.CALENDAR import org.tasks.makers.CaldavTaskMaker.CALENDAR
import org.tasks.makers.CaldavTaskMaker.REMOTE_ID import org.tasks.makers.CaldavTaskMaker.REMOTE_ID
import org.tasks.makers.CaldavTaskMaker.REMOTE_PARENT import org.tasks.makers.CaldavTaskMaker.REMOTE_PARENT
@ -43,8 +48,8 @@ class TaskMoverTest : InjectingTestCase() {
@Before @Before
fun setup() { fun setup() {
runBlocking { runBlocking {
caldavDao.insert(CaldavCalendar(uuid = "1", account = "account1")) caldavDao.insert(newCaldavCalendar(with(CaldavCalendarMaker.UUID, "1"), with(ACCOUNT, "account1")))
caldavDao.insert(CaldavCalendar(uuid = "2", account = "account2")) caldavDao.insert(newCaldavCalendar(with(CaldavCalendarMaker.UUID, "2"), with(ACCOUNT, "account2")))
} }
} }
@ -306,7 +311,7 @@ class TaskMoverTest : InjectingTestCase() {
} }
private suspend fun moveToGoogleTasks(list: String, vararg tasks: Long) { private suspend fun moveToGoogleTasks(list: String, vararg tasks: Long) {
taskMover.move(tasks.toList(), GtasksFilter(CaldavCalendar(uuid = list))) taskMover.move(tasks.toList(), GtasksFilter(newCaldavCalendar(with(CaldavCalendarMaker.UUID, list))))
} }
private suspend fun moveToCaldavList(calendar: String, vararg tasks: Long) { private suspend fun moveToCaldavList(calendar: String, vararg tasks: Long) {
@ -314,11 +319,6 @@ class TaskMoverTest : InjectingTestCase() {
} }
private suspend fun setAccountType(account: String, type: Int) { private suspend fun setAccountType(account: String, type: Int) {
caldavDao.insert( caldavDao.insert(newCaldavAccount(with(CaldavAccountMaker.UUID, account), with(ACCOUNT_TYPE, type)))
CaldavAccount(
uuid = account,
accountType = type,
)
)
} }
} }

@ -5,7 +5,7 @@
*/ */
package com.todoroo.astrid.service package com.todoroo.astrid.service
import org.tasks.data.entity.Task import com.todoroo.astrid.data.Task
import com.todoroo.astrid.utility.TitleParser import com.todoroo.astrid.utility.TitleParser
import dagger.hilt.android.testing.HiltAndroidTest import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules import dagger.hilt.android.testing.UninstallModules
@ -16,7 +16,7 @@ import org.junit.Before
import org.junit.Ignore import org.junit.Ignore
import org.junit.Test import org.junit.Test
import org.tasks.R import org.tasks.R
import org.tasks.data.dao.TagDataDao import org.tasks.data.TagDataDao
import org.tasks.date.DateTimeUtils import org.tasks.date.DateTimeUtils
import org.tasks.injection.InjectingTestCase import org.tasks.injection.InjectingTestCase
import org.tasks.injection.ProductionModule import org.tasks.injection.ProductionModule

@ -3,6 +3,7 @@
package com.todoroo.astrid.service package com.todoroo.astrid.service
import com.natpryce.makeiteasy.MakeItEasy.with import com.natpryce.makeiteasy.MakeItEasy.with
import com.todoroo.astrid.data.Task
import dagger.hilt.android.testing.HiltAndroidTest import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules import dagger.hilt.android.testing.UninstallModules
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
@ -11,12 +12,12 @@ import org.junit.Test
import org.tasks.SuspendFreeze.Companion.freezeAt import org.tasks.SuspendFreeze.Companion.freezeAt
import org.tasks.TestUtilities.assertEquals import org.tasks.TestUtilities.assertEquals
import org.tasks.caldav.VtodoCache import org.tasks.caldav.VtodoCache
import org.tasks.data.dao.CaldavDao import org.tasks.data.CaldavCalendar
import org.tasks.data.dao.TaskDao import org.tasks.data.CaldavDao
import org.tasks.data.entity.CaldavCalendar import org.tasks.data.TaskDao
import org.tasks.data.entity.Task
import org.tasks.injection.InjectingTestCase import org.tasks.injection.InjectingTestCase
import org.tasks.injection.ProductionModule import org.tasks.injection.ProductionModule
import org.tasks.makers.CaldavCalendarMaker.newCaldavCalendar
import org.tasks.makers.CaldavTaskMaker.CALENDAR import org.tasks.makers.CaldavTaskMaker.CALENDAR
import org.tasks.makers.CaldavTaskMaker.REMOTE_ID import org.tasks.makers.CaldavTaskMaker.REMOTE_ID
import org.tasks.makers.CaldavTaskMaker.TASK import org.tasks.makers.CaldavTaskMaker.TASK
@ -43,7 +44,7 @@ class Upgrade_11_3_Test : InjectingTestCase() {
@Before @Before
override fun setUp() { override fun setUp() {
super.setUp() super.setUp()
calendar = CaldavCalendar() calendar = newCaldavCalendar()
runBlocking { runBlocking {
caldavDao.insert(calendar) caldavDao.insert(calendar)
} }

@ -1,13 +1,13 @@
package com.todoroo.astrid.subtasks package com.todoroo.astrid.subtasks
import org.tasks.data.entity.Task import com.todoroo.astrid.data.Task
import dagger.hilt.android.testing.HiltAndroidTest import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules import dagger.hilt.android.testing.UninstallModules
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertEquals import org.junit.Assert.assertEquals
import org.junit.Before import org.junit.Before
import org.junit.Test import org.junit.Test
import org.tasks.data.entity.TaskListMetadata import org.tasks.data.TaskListMetadata
import org.tasks.injection.ProductionModule import org.tasks.injection.ProductionModule
@UninstallModules(ProductionModule::class) @UninstallModules(ProductionModule::class)

@ -1,12 +1,12 @@
package com.todoroo.astrid.subtasks package com.todoroo.astrid.subtasks
import org.tasks.data.entity.Task import com.todoroo.astrid.data.Task
import dagger.hilt.android.testing.HiltAndroidTest import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules import dagger.hilt.android.testing.UninstallModules
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import org.junit.Before import org.junit.Before
import org.junit.Test import org.junit.Test
import org.tasks.data.entity.TaskListMetadata import org.tasks.data.TaskListMetadata
import org.tasks.injection.ProductionModule import org.tasks.injection.ProductionModule
@UninstallModules(ProductionModule::class) @UninstallModules(ProductionModule::class)

@ -1,20 +1,20 @@
package com.todoroo.astrid.subtasks package com.todoroo.astrid.subtasks
import androidx.test.InstrumentationRegistry import androidx.test.InstrumentationRegistry
import com.todoroo.astrid.api.Filter
import com.todoroo.astrid.core.BuiltInFilterExposer import com.todoroo.astrid.core.BuiltInFilterExposer
import com.todoroo.astrid.dao.TaskDao import com.todoroo.astrid.dao.TaskDao
import com.todoroo.astrid.data.Task
import org.junit.Assert.assertEquals import org.junit.Assert.assertEquals
import org.junit.Assert.assertNotNull import org.junit.Assert.assertNotNull
import org.tasks.data.dao.TaskListMetadataDao import org.tasks.data.TaskListMetadataDao
import org.tasks.data.entity.Task
import org.tasks.filters.AstridOrderingFilter
import org.tasks.injection.InjectingTestCase import org.tasks.injection.InjectingTestCase
import org.tasks.preferences.Preferences import org.tasks.preferences.Preferences
import javax.inject.Inject import javax.inject.Inject
abstract class SubtasksTestCase : InjectingTestCase() { abstract class SubtasksTestCase : InjectingTestCase() {
lateinit var updater: SubtasksFilterUpdater lateinit var updater: SubtasksFilterUpdater
lateinit var filter: AstridOrderingFilter lateinit var filter: Filter
@Inject lateinit var taskListMetadataDao: TaskListMetadataDao @Inject lateinit var taskListMetadataDao: TaskListMetadataDao
@Inject lateinit var taskDao: TaskDao @Inject lateinit var taskDao: TaskDao
@Inject lateinit var preferences: Preferences @Inject lateinit var preferences: Preferences

@ -1,9 +1,9 @@
package com.todoroo.astrid.sync package com.todoroo.astrid.sync
import com.todoroo.astrid.dao.TaskDao import com.todoroo.astrid.dao.TaskDao
import org.tasks.data.dao.TagDataDao import com.todoroo.astrid.data.Task
import org.tasks.data.entity.TagData import org.tasks.data.TagData
import org.tasks.data.entity.Task import org.tasks.data.TagDataDao
import org.tasks.injection.InjectingTestCase import org.tasks.injection.InjectingTestCase
import javax.inject.Inject import javax.inject.Inject
@ -12,17 +12,17 @@ open class NewSyncTestCase : InjectingTestCase() {
@Inject lateinit var tagDataDao: TagDataDao @Inject lateinit var tagDataDao: TagDataDao
suspend fun createTask(): Task { suspend fun createTask(): Task {
val task = Task( val task = Task()
title = SYNC_TASK_TITLE, task.title = SYNC_TASK_TITLE
priority = SYNC_TASK_IMPORTANCE, task.priority = SYNC_TASK_IMPORTANCE
)
taskDao.createNew(task) taskDao.createNew(task)
return task return task
} }
suspend fun createTagData(): TagData { suspend fun createTagData(): TagData {
val tag = TagData(name = "new tag") val tag = TagData()
tagDataDao.insert(tag) tag.name = "new tag"
tagDataDao.createNew(tag)
return tag return tag
} }

@ -1,6 +1,6 @@
package com.todoroo.astrid.sync package com.todoroo.astrid.sync
import org.tasks.data.entity.Task import com.todoroo.astrid.data.Task
import dagger.hilt.android.testing.HiltAndroidTest import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules import dagger.hilt.android.testing.UninstallModules
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking

@ -1,15 +1,15 @@
package org.tasks.caldav package org.tasks.caldav
import com.natpryce.makeiteasy.MakeItEasy.with import com.natpryce.makeiteasy.MakeItEasy.with
import org.tasks.data.UUIDHelper import com.todoroo.astrid.helper.UUIDHelper
import dagger.hilt.android.testing.HiltAndroidTest import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules import dagger.hilt.android.testing.UninstallModules
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertEquals import org.junit.Assert.assertEquals
import org.junit.Before import org.junit.Before
import org.junit.Test import org.junit.Test
import org.tasks.data.entity.CaldavAccount import org.tasks.data.CaldavAccount
import org.tasks.data.entity.CaldavCalendar import org.tasks.data.CaldavCalendar
import org.tasks.injection.ProductionModule import org.tasks.injection.ProductionModule
import org.tasks.makers.CaldavTaskMaker.CALENDAR import org.tasks.makers.CaldavTaskMaker.CALENDAR
import org.tasks.makers.CaldavTaskMaker.ETAG import org.tasks.makers.CaldavTaskMaker.ETAG
@ -25,13 +25,12 @@ class CaldavSynchronizerTest : CaldavTest() {
@Before @Before
override fun setUp() = runBlocking { override fun setUp() = runBlocking {
super.setUp() super.setUp()
account = CaldavAccount( account = CaldavAccount().apply {
uuid = UUIDHelper.newUUID(), uuid = UUIDHelper.newUUID()
username = "username", username = "username"
password = encryption.encrypt("password"), password = encryption.encrypt("password")
url = server.url("/remote.php/dav/calendars/user1/").toString(), url = server.url("/remote.php/dav/calendars/user1/").toString()
).let { id = caldavDao.insert(this)
it.copy(id = caldavDao.insert(it))
} }
} }
@ -46,13 +45,11 @@ class CaldavSynchronizerTest : CaldavTest() {
@Test @Test
fun dontFetchCalendarIfCtagMatches() = runBlocking { fun dontFetchCalendarIfCtagMatches() = runBlocking {
caldavDao.insert( caldavDao.insert(CaldavCalendar(
CaldavCalendar( account = this@CaldavSynchronizerTest.account.uuid,
account = this@CaldavSynchronizerTest.account.uuid, ctag = "http://sabre.io/ns/sync/1",
ctag = "http://sabre.io/ns/sync/1", url = "${this@CaldavSynchronizerTest.account.url}test-shared/",
url = "${this@CaldavSynchronizerTest.account.url}test-shared/", ))
)
)
enqueue(OC_SHARE_PROPFIND) enqueue(OC_SHARE_PROPFIND)
sync() sync()

@ -9,8 +9,8 @@ import org.junit.Before
import org.junit.Rule import org.junit.Rule
import org.junit.rules.Timeout import org.junit.rules.Timeout
import org.tasks.R import org.tasks.R
import org.tasks.data.entity.CaldavAccount import org.tasks.data.CaldavAccount
import org.tasks.data.dao.CaldavDao import org.tasks.data.CaldavDao
import org.tasks.injection.InjectingTestCase import org.tasks.injection.InjectingTestCase
import org.tasks.preferences.Preferences import org.tasks.preferences.Preferences
import org.tasks.security.KeyStoreEncryption import org.tasks.security.KeyStoreEncryption

@ -1,19 +1,19 @@
package org.tasks.caldav package org.tasks.caldav
import org.tasks.data.UUIDHelper import com.todoroo.astrid.helper.UUIDHelper
import dagger.hilt.android.testing.HiltAndroidTest import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules import dagger.hilt.android.testing.UninstallModules
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertEquals import org.junit.Assert.assertEquals
import org.junit.Test import org.junit.Test
import org.tasks.data.entity.CaldavAccount import org.tasks.data.CaldavAccount
import org.tasks.data.entity.CaldavAccount.Companion.SERVER_OPEN_XCHANGE import org.tasks.data.CaldavAccount.Companion.SERVER_OPEN_XCHANGE
import org.tasks.data.entity.CaldavAccount.Companion.SERVER_OWNCLOUD import org.tasks.data.CaldavAccount.Companion.SERVER_OWNCLOUD
import org.tasks.data.entity.CaldavAccount.Companion.SERVER_SABREDAV import org.tasks.data.CaldavAccount.Companion.SERVER_SABREDAV
import org.tasks.data.entity.CaldavAccount.Companion.SERVER_TASKS import org.tasks.data.CaldavAccount.Companion.SERVER_TASKS
import org.tasks.data.entity.CaldavAccount.Companion.SERVER_UNKNOWN import org.tasks.data.CaldavAccount.Companion.SERVER_UNKNOWN
import org.tasks.data.entity.CaldavAccount.Companion.TYPE_CALDAV import org.tasks.data.CaldavAccount.Companion.TYPE_CALDAV
import org.tasks.data.entity.CaldavAccount.Companion.TYPE_TASKS import org.tasks.data.CaldavAccount.Companion.TYPE_TASKS
import org.tasks.injection.ProductionModule import org.tasks.injection.ProductionModule
@UninstallModules(ProductionModule::class) @UninstallModules(ProductionModule::class)
@ -79,14 +79,13 @@ class ServerDetectionTest : CaldavTest() {
vararg headers: Pair<String, String>, vararg headers: Pair<String, String>,
accountType: Int = TYPE_CALDAV accountType: Int = TYPE_CALDAV
) { ) {
account = CaldavAccount( account = CaldavAccount().apply {
uuid = UUIDHelper.newUUID(), uuid = UUIDHelper.newUUID()
username = "username", username = "username"
password = encryption.encrypt("password"), password = encryption.encrypt("password")
url = server.url("/remote.php/dav/calendars/user1/").toString(), url = server.url("/remote.php/dav/calendars/user1/").toString()
accountType = accountType, id = caldavDao.insert(this)
).let { this.accountType = accountType
it.copy(id = caldavDao.insert(it))
} }
this.headers.putAll(headers) this.headers.putAll(headers)
enqueue(NO_CALENDARS) enqueue(NO_CALENDARS)

@ -1,16 +1,16 @@
package org.tasks.caldav package org.tasks.caldav
import org.tasks.data.UUIDHelper import com.todoroo.astrid.helper.UUIDHelper
import dagger.hilt.android.testing.HiltAndroidTest import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules import dagger.hilt.android.testing.UninstallModules
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertEquals import org.junit.Assert.assertEquals
import org.junit.Assert.assertNull import org.junit.Assert.assertNull
import org.junit.Test import org.junit.Test
import org.tasks.data.entity.CaldavAccount import org.tasks.data.CaldavAccount
import org.tasks.data.entity.CaldavCalendar import org.tasks.data.CaldavCalendar
import org.tasks.data.entity.CaldavCalendar.Companion.ACCESS_READ_WRITE import org.tasks.data.CaldavCalendar.Companion.ACCESS_READ_WRITE
import org.tasks.data.dao.PrincipalDao import org.tasks.data.PrincipalDao
import org.tasks.injection.ProductionModule import org.tasks.injection.ProductionModule
import javax.inject.Inject import javax.inject.Inject
@ -22,13 +22,12 @@ class SharingMailboxDotOrgTest : CaldavTest() {
@Test @Test
fun ownerAccess() = runBlocking { fun ownerAccess() = runBlocking {
account = CaldavAccount( account = CaldavAccount().apply {
uuid = UUIDHelper.newUUID(), uuid = UUIDHelper.newUUID()
username = "3", username = "3"
password = encryption.encrypt("password"), password = encryption.encrypt("password")
url = server.url("/caldav/").toString(), url = server.url("/caldav/").toString()
).let { id = caldavDao.insert(this)
it.copy(id = caldavDao.insert(it))
} }
val calendar = CaldavCalendar( val calendar = CaldavCalendar(
account = this@SharingMailboxDotOrgTest.account.uuid, account = this@SharingMailboxDotOrgTest.account.uuid,
@ -46,13 +45,12 @@ class SharingMailboxDotOrgTest : CaldavTest() {
@Test @Test
fun principalForSharee() = runBlocking { fun principalForSharee() = runBlocking {
account = CaldavAccount( account = CaldavAccount().apply {
uuid = UUIDHelper.newUUID(), uuid = UUIDHelper.newUUID()
username = "3", username = "3"
password = encryption.encrypt("password"), password = encryption.encrypt("password")
url = server.url("/caldav/").toString(), url = server.url("/caldav/").toString()
).let { id = caldavDao.insert(this)
it.copy(id = caldavDao.insert(it))
} }
val calendar = CaldavCalendar( val calendar = CaldavCalendar(
account = this@SharingMailboxDotOrgTest.account.uuid, account = this@SharingMailboxDotOrgTest.account.uuid,

@ -1,16 +1,16 @@
package org.tasks.caldav package org.tasks.caldav
import org.tasks.data.UUIDHelper import com.todoroo.astrid.helper.UUIDHelper
import dagger.hilt.android.testing.HiltAndroidTest import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules import dagger.hilt.android.testing.UninstallModules
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import org.junit.Assert.* import org.junit.Assert.*
import org.junit.Test import org.junit.Test
import org.tasks.data.entity.CaldavAccount import org.tasks.data.CaldavAccount
import org.tasks.data.entity.CaldavCalendar import org.tasks.data.CaldavCalendar
import org.tasks.data.entity.CaldavCalendar.Companion.ACCESS_OWNER import org.tasks.data.CaldavCalendar.Companion.ACCESS_OWNER
import org.tasks.data.entity.CaldavCalendar.Companion.ACCESS_READ_ONLY import org.tasks.data.CaldavCalendar.Companion.ACCESS_READ_ONLY
import org.tasks.data.dao.PrincipalDao import org.tasks.data.PrincipalDao
import org.tasks.injection.ProductionModule import org.tasks.injection.ProductionModule
import javax.inject.Inject import javax.inject.Inject
@ -21,13 +21,12 @@ class SharingOwncloudTest : CaldavTest() {
@Inject lateinit var principalDao: PrincipalDao @Inject lateinit var principalDao: PrincipalDao
private suspend fun setupAccount(user: String) { private suspend fun setupAccount(user: String) {
account = CaldavAccount( account = CaldavAccount().apply {
uuid = UUIDHelper.newUUID(), uuid = UUIDHelper.newUUID()
username = user, username = user
password = encryption.encrypt("password"), password = encryption.encrypt("password")
url = server.url("/remote.php/dav/calendars/$user/").toString(), url = server.url("/remote.php/dav/calendars/$user/").toString()
).let { id = caldavDao.insert(this)
it.copy(id = caldavDao.insert(it))
} }
} }

@ -1,18 +1,18 @@
package org.tasks.caldav package org.tasks.caldav
import org.tasks.data.UUIDHelper import com.todoroo.astrid.helper.UUIDHelper
import dagger.hilt.android.testing.HiltAndroidTest import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules import dagger.hilt.android.testing.UninstallModules
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertEquals import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue import org.junit.Assert.assertTrue
import org.junit.Test import org.junit.Test
import org.tasks.data.entity.CaldavAccount import org.tasks.data.CaldavAccount
import org.tasks.data.entity.CaldavCalendar import org.tasks.data.CaldavCalendar
import org.tasks.data.entity.CaldavCalendar.Companion.ACCESS_OWNER import org.tasks.data.CaldavCalendar.Companion.ACCESS_OWNER
import org.tasks.data.entity.CaldavCalendar.Companion.ACCESS_READ_WRITE import org.tasks.data.CaldavCalendar.Companion.ACCESS_READ_WRITE
import org.tasks.data.entity.CaldavCalendar.Companion.INVITE_ACCEPTED import org.tasks.data.CaldavCalendar.Companion.INVITE_ACCEPTED
import org.tasks.data.dao.PrincipalDao import org.tasks.data.PrincipalDao
import org.tasks.injection.ProductionModule import org.tasks.injection.ProductionModule
import javax.inject.Inject import javax.inject.Inject
@ -23,13 +23,12 @@ class SharingSabredavTest : CaldavTest() {
@Inject lateinit var principalDao: PrincipalDao @Inject lateinit var principalDao: PrincipalDao
private suspend fun setupAccount(user: String) { private suspend fun setupAccount(user: String) {
account = CaldavAccount( account = CaldavAccount().apply {
uuid = UUIDHelper.newUUID(), uuid = UUIDHelper.newUUID()
username = user, username = user
password = encryption.encrypt("password"), password = encryption.encrypt("password")
url = server.url("/calendars/$user/").toString(), url = server.url("/calendars/$user/").toString()
).let { id = caldavDao.insert(this)
it.copy(id = caldavDao.insert(it))
} }
} }

@ -2,6 +2,7 @@ package org.tasks.data
import com.natpryce.makeiteasy.MakeItEasy.with import com.natpryce.makeiteasy.MakeItEasy.with
import com.natpryce.makeiteasy.PropertyValue import com.natpryce.makeiteasy.PropertyValue
import com.todoroo.andlib.utility.DateUtilities.now
import dagger.hilt.android.testing.HiltAndroidTest import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules import dagger.hilt.android.testing.UninstallModules
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
@ -9,15 +10,11 @@ import org.junit.Assert.assertEquals
import org.junit.Assert.assertNull import org.junit.Assert.assertNull
import org.junit.Test import org.junit.Test
import org.tasks.SuspendFreeze.Companion.freezeAt import org.tasks.SuspendFreeze.Companion.freezeAt
import org.tasks.data.dao.CaldavDao
import org.tasks.data.dao.TaskDao
import org.tasks.data.entity.CaldavTask
import org.tasks.injection.InjectingTestCase import org.tasks.injection.InjectingTestCase
import org.tasks.injection.ProductionModule import org.tasks.injection.ProductionModule
import org.tasks.makers.TaskContainerMaker import org.tasks.makers.TaskContainerMaker
import org.tasks.makers.TaskContainerMaker.CREATED import org.tasks.makers.TaskContainerMaker.CREATED
import org.tasks.time.DateTime import org.tasks.time.DateTime
import org.tasks.time.DateTimeUtils2.currentTimeMillis
import javax.inject.Inject import javax.inject.Inject
@UninstallModules(ProductionModule::class) @UninstallModules(ProductionModule::class)
@ -104,9 +101,7 @@ class CaldavDaoShiftTests : InjectingTestCase() {
fun ignoreMovedTasksWhenShiftingDown() = runBlocking { fun ignoreMovedTasksWhenShiftingDown() = runBlocking {
val created = DateTime(2020, 5, 17, 9, 53, 17) val created = DateTime(2020, 5, 17, 9, 53, 17)
addTask(with(CREATED, created)) addTask(with(CREATED, created))
caldavDao.update(caldavDao.getTask(tasks[0].id).apply { this?.deleted = caldavDao.update(caldavDao.getTask(tasks[0].id).apply { this?.deleted = now() }!!)
currentTimeMillis()
}!!)
caldavDao.shiftDown("calendar", 0, created.toAppleEpoch()) caldavDao.shiftDown("calendar", 0, created.toAppleEpoch())
@ -117,7 +112,7 @@ class CaldavDaoShiftTests : InjectingTestCase() {
fun ignoreDeletedTasksWhenShiftingDown() = runBlocking { fun ignoreDeletedTasksWhenShiftingDown() = runBlocking {
val created = DateTime(2020, 5, 17, 9, 53, 17) val created = DateTime(2020, 5, 17, 9, 53, 17)
addTask(with(CREATED, created)) addTask(with(CREATED, created))
taskDao.update(taskDao.fetch(tasks[0].id).apply { this?.deletionDate = currentTimeMillis() }!!) taskDao.update(taskDao.fetch(tasks[0].id).apply { this?.deletionDate = now() }!!)
caldavDao.shiftDown("calendar", 0, created.toAppleEpoch()) caldavDao.shiftDown("calendar", 0, created.toAppleEpoch())

@ -2,18 +2,12 @@ package org.tasks.data
import com.natpryce.makeiteasy.MakeItEasy.with import com.natpryce.makeiteasy.MakeItEasy.with
import com.todoroo.astrid.dao.TaskDao import com.todoroo.astrid.dao.TaskDao
import com.todoroo.astrid.helper.UUIDHelper
import dagger.hilt.android.testing.HiltAndroidTest import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules import dagger.hilt.android.testing.UninstallModules
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertEquals import org.junit.Assert.*
import org.junit.Assert.assertNull
import org.junit.Assert.assertTrue
import org.junit.Test import org.junit.Test
import org.tasks.data.dao.CaldavDao
import org.tasks.data.dao.TagDao
import org.tasks.data.dao.TagDataDao
import org.tasks.data.entity.CaldavAccount
import org.tasks.data.entity.CaldavTask
import org.tasks.injection.InjectingTestCase import org.tasks.injection.InjectingTestCase
import org.tasks.injection.ProductionModule import org.tasks.injection.ProductionModule
import org.tasks.makers.TaskMaker.CREATION_TIME import org.tasks.makers.TaskMaker.CREATION_TIME
@ -91,7 +85,8 @@ class CaldavDaoTests : InjectingTestCase() {
@Test @Test
fun noResultsForEmptyAccounts() = runBlocking { fun noResultsForEmptyAccounts() = runBlocking {
val caldavAccount = CaldavAccount(uuid = UUIDHelper.newUUID()) val caldavAccount = CaldavAccount()
caldavAccount.uuid = UUIDHelper.newUUID()
caldavDao.insert(caldavAccount) caldavDao.insert(caldavAccount)
assertTrue(caldavDao.getCaldavFilters(caldavAccount.uuid!!).isEmpty()) assertTrue(caldavDao.getCaldavFilters(caldavAccount.uuid!!).isEmpty())
} }

@ -2,18 +2,13 @@ package org.tasks.data
import com.natpryce.makeiteasy.MakeItEasy.with import com.natpryce.makeiteasy.MakeItEasy.with
import com.todoroo.astrid.dao.TaskDao import com.todoroo.astrid.dao.TaskDao
import com.todoroo.astrid.helper.UUIDHelper
import dagger.hilt.android.testing.HiltAndroidTest import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules import dagger.hilt.android.testing.UninstallModules
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertNotNull import org.junit.Assert.*
import org.junit.Assert.assertNull
import org.junit.Assert.assertTrue
import org.junit.Test import org.junit.Test
import org.tasks.data.dao.CaldavDao import org.tasks.data.CaldavDao.Companion.LOCAL
import org.tasks.data.dao.CaldavDao.Companion.LOCAL
import org.tasks.data.dao.DeletionDao
import org.tasks.data.entity.CaldavCalendar
import org.tasks.data.entity.CaldavTask
import org.tasks.date.DateTimeUtils.newDateTime import org.tasks.date.DateTimeUtils.newDateTime
import org.tasks.injection.InjectingTestCase import org.tasks.injection.InjectingTestCase
import org.tasks.injection.ProductionModule import org.tasks.injection.ProductionModule
@ -21,7 +16,7 @@ import org.tasks.makers.TaskMaker.CREATION_TIME
import org.tasks.makers.TaskMaker.DELETION_TIME import org.tasks.makers.TaskMaker.DELETION_TIME
import org.tasks.makers.TaskMaker.newTask import org.tasks.makers.TaskMaker.newTask
import org.tasks.time.DateTime import org.tasks.time.DateTime
import org.tasks.time.DateTimeUtils2.currentTimeMillis import org.tasks.time.DateTimeUtils
import javax.inject.Inject import javax.inject.Inject
@UninstallModules(ProductionModule::class) @UninstallModules(ProductionModule::class)
@ -48,7 +43,7 @@ class DeletionDaoTests : InjectingTestCase() {
deletionDao.markDeleted(listOf(task.id)) deletionDao.markDeleted(listOf(task.id))
task = taskDao.fetch(task.id)!! task = taskDao.fetch(task.id)!!
assertTrue(task.modificationDate > task.creationDate) assertTrue(task.modificationDate > task.creationDate)
assertTrue(task.modificationDate < currentTimeMillis()) assertTrue(task.modificationDate < DateTimeUtils.currentTimeMillis())
} }
@Test @Test
@ -58,7 +53,7 @@ class DeletionDaoTests : InjectingTestCase() {
deletionDao.markDeleted(listOf(task.id)) deletionDao.markDeleted(listOf(task.id))
task = taskDao.fetch(task.id)!! task = taskDao.fetch(task.id)!!
assertTrue(task.deletionDate > task.creationDate) assertTrue(task.deletionDate > task.creationDate)
assertTrue(task.deletionDate < currentTimeMillis()) assertTrue(task.deletionDate < DateTimeUtils.currentTimeMillis())
} }
@Test @Test

@ -9,15 +9,12 @@ import org.junit.Assert.assertEquals
import org.junit.Assert.assertNull import org.junit.Assert.assertNull
import org.junit.Before import org.junit.Before
import org.junit.Test import org.junit.Test
import org.tasks.data.dao.CaldavDao import org.tasks.data.CaldavAccount.Companion.TYPE_GOOGLE_TASKS
import org.tasks.data.dao.GoogleTaskDao
import org.tasks.data.dao.GoogleTaskListDao
import org.tasks.data.entity.CaldavAccount
import org.tasks.data.entity.CaldavAccount.Companion.TYPE_GOOGLE_TASKS
import org.tasks.data.entity.CaldavCalendar
import org.tasks.data.entity.CaldavTask
import org.tasks.injection.InjectingTestCase import org.tasks.injection.InjectingTestCase
import org.tasks.injection.ProductionModule import org.tasks.injection.ProductionModule
import org.tasks.makers.CaldavAccountMaker.ACCOUNT_TYPE
import org.tasks.makers.CaldavAccountMaker.newCaldavAccount
import org.tasks.makers.CaldavCalendarMaker.newCaldavCalendar
import org.tasks.makers.CaldavTaskMaker.CALENDAR import org.tasks.makers.CaldavTaskMaker.CALENDAR
import org.tasks.makers.CaldavTaskMaker.REMOTE_ID import org.tasks.makers.CaldavTaskMaker.REMOTE_ID
import org.tasks.makers.CaldavTaskMaker.REMOTE_PARENT import org.tasks.makers.CaldavTaskMaker.REMOTE_PARENT
@ -38,8 +35,8 @@ class GoogleTaskDaoTests : InjectingTestCase() {
override fun setUp() { override fun setUp() {
super.setUp() super.setUp()
runBlocking { runBlocking {
caldavDao.insert(CaldavAccount(uuid = "account", accountType = TYPE_GOOGLE_TASKS)) caldavDao.insert(newCaldavAccount(with(ACCOUNT_TYPE, TYPE_GOOGLE_TASKS)))
caldavDao.insert(CaldavCalendar(account = "account", uuid = "calendar")) caldavDao.insert(newCaldavCalendar())
} }
} }

@ -3,11 +3,8 @@ package org.tasks.data
import dagger.hilt.android.testing.HiltAndroidTest import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules import dagger.hilt.android.testing.UninstallModules
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertTrue import org.junit.Assert.*
import org.junit.Test import org.junit.Test
import org.tasks.data.dao.CaldavDao
import org.tasks.data.dao.GoogleTaskListDao
import org.tasks.data.entity.CaldavAccount
import org.tasks.injection.InjectingTestCase import org.tasks.injection.InjectingTestCase
import org.tasks.injection.ProductionModule import org.tasks.injection.ProductionModule
import javax.inject.Inject import javax.inject.Inject
@ -20,10 +17,10 @@ class GoogleTaskListDaoTest : InjectingTestCase() {
@Test @Test
fun noResultsForEmptyAccount() = runBlocking { fun noResultsForEmptyAccount() = runBlocking {
val account = CaldavAccount( val account = CaldavAccount().apply {
uuid = "user@gmail.com", uuid = "user@gmail.com"
username = "user@gmail.com", username = "user@gmail.com"
) }
caldavDao.insert(account) caldavDao.insert(account)
assertTrue(googleTaskListDao.getGoogleTaskFilters(account.username!!).isEmpty()) assertTrue(googleTaskListDao.getGoogleTaskFilters(account.username!!).isEmpty())

@ -1,24 +1,17 @@
package org.tasks.data package org.tasks.data
import com.natpryce.makeiteasy.MakeItEasy.with import com.natpryce.makeiteasy.MakeItEasy.with
import com.todoroo.andlib.utility.DateUtilities.now
import com.todoroo.astrid.dao.TaskDao import com.todoroo.astrid.dao.TaskDao
import com.todoroo.astrid.data.Task
import dagger.hilt.android.testing.HiltAndroidTest import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules import dagger.hilt.android.testing.UninstallModules
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertEquals import org.junit.Assert.*
import org.junit.Assert.assertFalse
import org.junit.Assert.assertNull
import org.junit.Assert.assertTrue
import org.junit.Test import org.junit.Test
import org.tasks.SuspendFreeze.Companion.freezeAt import org.tasks.SuspendFreeze.Companion.freezeAt
import org.tasks.caldav.GeoUtils.toLikeString import org.tasks.caldav.GeoUtils.toLikeString
import org.tasks.data.dao.AlarmDao import org.tasks.data.Alarm.Companion.TYPE_SNOOZE
import org.tasks.data.dao.LocationDao
import org.tasks.data.entity.Alarm
import org.tasks.data.entity.Alarm.Companion.TYPE_SNOOZE
import org.tasks.data.entity.Geofence
import org.tasks.data.entity.Place
import org.tasks.data.entity.Task
import org.tasks.date.DateTimeUtils.newDateTime import org.tasks.date.DateTimeUtils.newDateTime
import org.tasks.injection.InjectingTestCase import org.tasks.injection.InjectingTestCase
import org.tasks.injection.ProductionModule import org.tasks.injection.ProductionModule
@ -28,7 +21,6 @@ import org.tasks.makers.TaskMaker.DUE_TIME
import org.tasks.makers.TaskMaker.HIDE_TYPE import org.tasks.makers.TaskMaker.HIDE_TYPE
import org.tasks.makers.TaskMaker.ID import org.tasks.makers.TaskMaker.ID
import org.tasks.makers.TaskMaker.newTask import org.tasks.makers.TaskMaker.newTask
import org.tasks.time.DateTimeUtils2.currentTimeMillis
import javax.inject.Inject import javax.inject.Inject
@UninstallModules(ProductionModule::class) @UninstallModules(ProductionModule::class)
@ -121,89 +113,61 @@ class LocationDaoTest : InjectingTestCase() {
@Test @Test
fun ignoreArrivalForSnoozedTask() = runBlocking { fun ignoreArrivalForSnoozedTask() = runBlocking {
freezeAt(currentTimeMillis()).thawAfter { freezeAt(now()).thawAfter {
val place = Place() val place = Place()
locationDao.insert(place) locationDao.insert(place)
val task = taskDao.createNew(newTask()) val task = taskDao.createNew(newTask())
alarmDao.insert( alarmDao.insert(Alarm(task, newDateTime().plusMinutes(15).millis, TYPE_SNOOZE))
Alarm(
task = task,
time = newDateTime().plusMinutes(15).millis,
type = TYPE_SNOOZE
)
)
locationDao.insert(Geofence(task = task, place = place.uid, isArrival = true)) locationDao.insert(Geofence(task = task, place = place.uid, isArrival = true))
assertTrue(locationDao.getArrivalGeofences(place.uid!!, currentTimeMillis()).isEmpty()) assertTrue(locationDao.getArrivalGeofences(place.uid!!, now()).isEmpty())
} }
} }
@Test @Test
fun ignoreDepartureForSnoozedTask() = runBlocking { fun ignoreDepartureForSnoozedTask() = runBlocking {
freezeAt(currentTimeMillis()).thawAfter { freezeAt(now()).thawAfter {
val place = Place() val place = Place()
locationDao.insert(place) locationDao.insert(place)
val task = taskDao.createNew(newTask()) val task = taskDao.createNew(newTask())
alarmDao.insert( alarmDao.insert(Alarm(task, newDateTime().plusMinutes(15).millis, TYPE_SNOOZE))
Alarm(
task = task,
time = newDateTime().plusMinutes(15).millis,
type = TYPE_SNOOZE
)
)
locationDao.insert(Geofence(task = task, place = place.uid, isDeparture = true)) locationDao.insert(Geofence(task = task, place = place.uid, isDeparture = true))
assertTrue(locationDao.getDepartureGeofences(place.uid!!, currentTimeMillis()).isEmpty()) assertTrue(locationDao.getDepartureGeofences(place.uid!!, now()).isEmpty())
} }
} }
@Test @Test
fun getArrivalWithElapsedSnooze() = runBlocking { fun getArrivalWithElapsedSnooze() = runBlocking {
freezeAt(currentTimeMillis()).thawAfter { freezeAt(now()).thawAfter {
val place = Place() val place = Place()
locationDao.insert(place) locationDao.insert(place)
val task = taskDao.createNew(newTask()) val task = taskDao.createNew(newTask())
alarmDao.insert( alarmDao.insert(Alarm(task, newDateTime().minusMinutes(15).millis, TYPE_SNOOZE))
Alarm(
task = task,
time = newDateTime().minusMinutes(15).millis,
type = TYPE_SNOOZE
)
)
val geofence = Geofence(task = task, place = place.uid, isArrival = true) val geofence = Geofence(task = task, place = place.uid, isArrival = true)
.let { it.copy(id = locationDao.insert(it)) } .let { it.copy(id = locationDao.insert(it)) }
assertEquals(listOf(geofence), locationDao.getArrivalGeofences(place.uid!!, assertEquals(listOf(geofence), locationDao.getArrivalGeofences(place.uid!!, now()))
currentTimeMillis()
))
} }
} }
@Test @Test
fun getDepartureWithElapsedSnooze() = runBlocking { fun getDepartureWithElapsedSnooze() = runBlocking {
freezeAt(currentTimeMillis()).thawAfter { freezeAt(now()).thawAfter {
val place = Place() val place = Place()
locationDao.insert(place) locationDao.insert(place)
val task = taskDao.createNew(newTask()) val task = taskDao.createNew(newTask())
alarmDao.insert( alarmDao.insert(Alarm(task, newDateTime().minusMinutes(15).millis, TYPE_SNOOZE))
Alarm(
task = task,
time = newDateTime().minusMinutes(15).millis,
type = TYPE_SNOOZE
)
)
val geofence = Geofence(task = task, place = place.uid, isDeparture = true) val geofence = Geofence(task = task, place = place.uid, isDeparture = true)
.let { it.copy(id = locationDao.insert(it)) } .let { it.copy(id = locationDao.insert(it)) }
assertEquals(listOf(geofence), locationDao.getDepartureGeofences(place.uid!!, assertEquals(listOf(geofence), locationDao.getDepartureGeofences(place.uid!!, now()))
currentTimeMillis()
))
} }
} }
@Test @Test
fun ignoreArrivalForHiddenTask() = runBlocking { fun ignoreArrivalForHiddenTask() = runBlocking {
freezeAt(currentTimeMillis()).thawAfter { freezeAt(now()).thawAfter {
val place = Place() val place = Place()
locationDao.insert(place) locationDao.insert(place)
taskDao.createNew(newTask( taskDao.createNew(newTask(
@ -212,13 +176,13 @@ class LocationDaoTest : InjectingTestCase() {
with(HIDE_TYPE, Task.HIDE_UNTIL_DUE_TIME))) with(HIDE_TYPE, Task.HIDE_UNTIL_DUE_TIME)))
locationDao.insert(Geofence(task = 1, place = place.uid, isArrival = true)) locationDao.insert(Geofence(task = 1, place = place.uid, isArrival = true))
assertTrue(locationDao.getArrivalGeofences(place.uid!!, currentTimeMillis()).isEmpty()) assertTrue(locationDao.getArrivalGeofences(place.uid!!, now()).isEmpty())
} }
} }
@Test @Test
fun ignoreDepartureForHiddenTask() = runBlocking { fun ignoreDepartureForHiddenTask() = runBlocking {
freezeAt(currentTimeMillis()).thawAfter { freezeAt(now()).thawAfter {
val place = Place() val place = Place()
locationDao.insert(place) locationDao.insert(place)
taskDao.createNew(newTask( taskDao.createNew(newTask(
@ -227,13 +191,13 @@ class LocationDaoTest : InjectingTestCase() {
with(HIDE_TYPE, Task.HIDE_UNTIL_DUE_TIME))) with(HIDE_TYPE, Task.HIDE_UNTIL_DUE_TIME)))
locationDao.insert(Geofence(task = 1, place = place.uid, isDeparture = true)) locationDao.insert(Geofence(task = 1, place = place.uid, isDeparture = true))
assertTrue(locationDao.getDepartureGeofences(place.uid!!, currentTimeMillis()).isEmpty()) assertTrue(locationDao.getDepartureGeofences(place.uid!!, now()).isEmpty())
} }
} }
@Test @Test
fun getArrivalWithElapsedHideUntil() = runBlocking { fun getArrivalWithElapsedHideUntil() = runBlocking {
freezeAt(currentTimeMillis()).thawAfter { freezeAt(now()).thawAfter {
val place = Place() val place = Place()
locationDao.insert(place) locationDao.insert(place)
taskDao.createNew(newTask( taskDao.createNew(newTask(
@ -245,15 +209,13 @@ class LocationDaoTest : InjectingTestCase() {
it.copy(id = locationDao.insert(it)) it.copy(id = locationDao.insert(it))
} }
assertEquals(listOf(geofence), locationDao.getArrivalGeofences(place.uid!!, assertEquals(listOf(geofence), locationDao.getArrivalGeofences(place.uid!!, now()))
currentTimeMillis()
))
} }
} }
@Test @Test
fun getDepartureWithElapsedHideUntil() = runBlocking { fun getDepartureWithElapsedHideUntil() = runBlocking {
freezeAt(currentTimeMillis()).thawAfter { freezeAt(now()).thawAfter {
val place = Place() val place = Place()
locationDao.insert(place) locationDao.insert(place)
taskDao.createNew(newTask( taskDao.createNew(newTask(
@ -263,9 +225,7 @@ class LocationDaoTest : InjectingTestCase() {
val geofence = Geofence(task = 1, place = place.uid, isDeparture = true) val geofence = Geofence(task = 1, place = place.uid, isDeparture = true)
.let { it.copy(id = locationDao.insert(it)) } .let { it.copy(id = locationDao.insert(it)) }
assertEquals(listOf(geofence), locationDao.getDepartureGeofences(place.uid!!, assertEquals(listOf(geofence), locationDao.getDepartureGeofences(place.uid!!, now()))
currentTimeMillis()
))
} }
} }
} }

@ -1,8 +1,9 @@
package org.tasks.data package org.tasks.data
import com.natpryce.makeiteasy.MakeItEasy.with import com.natpryce.makeiteasy.MakeItEasy.with
import org.tasks.filters.GtasksFilter import com.todoroo.astrid.api.GtasksFilter
import com.todoroo.astrid.dao.TaskDao import com.todoroo.astrid.dao.TaskDao
import com.todoroo.astrid.helper.UUIDHelper
import dagger.hilt.android.testing.HiltAndroidTest import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules import dagger.hilt.android.testing.UninstallModules
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
@ -10,12 +11,11 @@ import org.junit.Assert.assertEquals
import org.junit.Before import org.junit.Before
import org.junit.Test import org.junit.Test
import org.tasks.R import org.tasks.R
import org.tasks.data.dao.CaldavDao
import org.tasks.data.dao.GoogleTaskDao
import org.tasks.data.entity.CaldavAccount
import org.tasks.data.entity.CaldavCalendar
import org.tasks.injection.InjectingTestCase import org.tasks.injection.InjectingTestCase
import org.tasks.injection.ProductionModule import org.tasks.injection.ProductionModule
import org.tasks.makers.CaldavAccountMaker.newCaldavAccount
import org.tasks.makers.CaldavCalendarMaker.UUID
import org.tasks.makers.CaldavCalendarMaker.newCaldavCalendar
import org.tasks.makers.CaldavTaskMaker.CALENDAR import org.tasks.makers.CaldavTaskMaker.CALENDAR
import org.tasks.makers.CaldavTaskMaker.TASK import org.tasks.makers.CaldavTaskMaker.TASK
import org.tasks.makers.CaldavTaskMaker.newCaldavTask import org.tasks.makers.CaldavTaskMaker.newCaldavTask
@ -40,9 +40,9 @@ class ManualGoogleTaskQueryTest : InjectingTestCase() {
super.setUp() super.setUp()
preferences.clear() preferences.clear()
preferences.setBoolean(R.string.p_manual_sort, true) preferences.setBoolean(R.string.p_manual_sort, true)
val calendar = CaldavCalendar(uuid = "1234") val calendar = newCaldavCalendar(with(UUID, "1234"))
runBlocking { runBlocking {
caldavDao.insert(CaldavAccount()) caldavDao.insert(newCaldavAccount())
caldavDao.insert(calendar) caldavDao.insert(calendar)
} }
filter = GtasksFilter(calendar) filter = GtasksFilter(calendar)

@ -8,12 +8,14 @@ import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertEquals import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue import org.junit.Assert.assertTrue
import org.junit.Test import org.junit.Test
import org.tasks.data.dao.TagDao
import org.tasks.data.dao.TagDataDao
import org.tasks.data.entity.Tag
import org.tasks.data.entity.TagData
import org.tasks.injection.InjectingTestCase import org.tasks.injection.InjectingTestCase
import org.tasks.injection.ProductionModule import org.tasks.injection.ProductionModule
import org.tasks.makers.TagDataMaker.NAME
import org.tasks.makers.TagDataMaker.newTagData
import org.tasks.makers.TagMaker.TAGDATA
import org.tasks.makers.TagMaker.TAGUID
import org.tasks.makers.TagMaker.TASK
import org.tasks.makers.TagMaker.newTag
import org.tasks.makers.TaskMaker.ID import org.tasks.makers.TaskMaker.ID
import org.tasks.makers.TaskMaker.newTask import org.tasks.makers.TaskMaker.newTask
import javax.inject.Inject import javax.inject.Inject
@ -27,13 +29,13 @@ class TagDataDaoTest : InjectingTestCase() {
@Test @Test
fun tagDataOrderedByNameIgnoresNullNames() = runBlocking { fun tagDataOrderedByNameIgnoresNullNames() = runBlocking {
tagDataDao.insert(TagData(name = null)) tagDataDao.createNew(newTagData(with(NAME, null as String?)))
assertTrue(tagDataDao.tagDataOrderedByName().isEmpty()) assertTrue(tagDataDao.tagDataOrderedByName().isEmpty())
} }
@Test @Test
fun tagDataOrderedByNameIgnoresEmptyNames() = runBlocking { fun tagDataOrderedByNameIgnoresEmptyNames() = runBlocking {
tagDataDao.insert(TagData(name = "")) tagDataDao.createNew(newTagData(with(NAME, "")))
assertTrue(tagDataDao.tagDataOrderedByName().isEmpty()) assertTrue(tagDataDao.tagDataOrderedByName().isEmpty())
} }
@ -44,19 +46,20 @@ class TagDataDaoTest : InjectingTestCase() {
@Test @Test
fun getTagWithCaseFixesCase() = runBlocking { fun getTagWithCaseFixesCase() = runBlocking {
tagDataDao.insert(TagData(name = "Derp")) tagDataDao.createNew(newTagData(with(NAME, "Derp")))
assertEquals("Derp", tagDataDao.getTagWithCase("derp")) assertEquals("Derp", tagDataDao.getTagWithCase("derp"))
} }
@Test @Test
fun getTagsByName() = runBlocking { fun getTagsByName() = runBlocking {
val tagData = TagData(name = "Derp").let { it.copy(id = tagDataDao.insert(it)) } val tagData = newTagData(with(NAME, "Derp"))
tagDataDao.createNew(tagData)
assertEquals(listOf(tagData), tagDataDao.getTags(listOf("Derp"))) assertEquals(listOf(tagData), tagDataDao.getTags(listOf("Derp")))
} }
@Test @Test
fun getTagsByNameCaseSensitive() = runBlocking { fun getTagsByNameCaseSensitive() = runBlocking {
tagDataDao.insert(TagData(name = "Derp")) tagDataDao.createNew(newTagData(with(NAME, "Derp")))
assertTrue(tagDataDao.getTags(listOf("derp")).isEmpty()) assertTrue(tagDataDao.getTags(listOf("derp")).isEmpty())
} }
@ -66,18 +69,20 @@ class TagDataDaoTest : InjectingTestCase() {
val taskTwo = newTask() val taskTwo = newTask()
taskDao.createNew(taskOne) taskDao.createNew(taskOne)
taskDao.createNew(taskTwo) taskDao.createNew(taskTwo)
val tagOne = TagData(name = "one").let { it.copy(id = tagDataDao.insert(it)) } val tagOne = newTagData(with(NAME, "one"))
val tagTwo = TagData(name = "two").let { it.copy(id = tagDataDao.insert(it)) } val tagTwo = newTagData(with(NAME, "two"))
tagDao.insert(Tag(task = taskOne.id, taskUid = taskOne.uuid, tagUid = tagOne.remoteId)) tagDataDao.createNew(tagOne)
tagDao.insert(Tag(task = taskTwo.id, taskUid = taskTwo.uuid, tagUid = tagTwo.remoteId)) tagDataDao.createNew(tagTwo)
tagDao.insert(newTag(with(TAGDATA, tagOne), with(TASK, taskOne)))
tagDao.insert(newTag(with(TAGDATA, tagTwo), with(TASK, taskTwo)))
assertEquals(listOf(tagOne), tagDataDao.getTagDataForTask(taskOne.id)) assertEquals(listOf(tagOne), tagDataDao.getTagDataForTask(taskOne.id))
} }
@Test @Test
fun getEmptyTagSelections() = runBlocking { fun getEmptyTagSelections() = runBlocking {
val selections = tagDataDao.getTagSelections(listOf(1L)) val selections = tagDataDao.getTagSelections(listOf(1L))
assertTrue(selections.first.isEmpty()) assertTrue(selections.first!!.isEmpty())
assertTrue(selections.second.isEmpty()) assertTrue(selections.second!!.isEmpty())
} }
@Test @Test
@ -92,7 +97,7 @@ class TagDataDaoTest : InjectingTestCase() {
fun getEmptyPartialSelections() = runBlocking { fun getEmptyPartialSelections() = runBlocking {
newTag(1, "tag1") newTag(1, "tag1")
newTag(2, "tag1") newTag(2, "tag1")
assertTrue(tagDataDao.getTagSelections(listOf(1L, 2L)).first.isEmpty()) assertTrue(tagDataDao.getTagSelections(listOf(1L, 2L)).first!!.isEmpty())
} }
@Test @Test
@ -106,15 +111,15 @@ class TagDataDaoTest : InjectingTestCase() {
fun getEmptyCommonSelections() = runBlocking { fun getEmptyCommonSelections() = runBlocking {
newTag(1, "tag1") newTag(1, "tag1")
newTag(2, "tag2") newTag(2, "tag2")
assertTrue(tagDataDao.getTagSelections(listOf(1L, 2L)).second.isEmpty()) assertTrue(tagDataDao.getTagSelections(listOf(1L, 2L)).second!!.isEmpty())
} }
@Test @Test
fun getSelectionsWithNoTags() = runBlocking { fun getSelectionsWithNoTags() = runBlocking {
newTag(1) newTag(1)
val selections = tagDataDao.getTagSelections(listOf(1L)) val selections = tagDataDao.getTagSelections(listOf(1L))
assertTrue(selections.first.isEmpty()) assertTrue(selections.first!!.isEmpty())
assertTrue(selections.second.isEmpty()) assertTrue(selections.second!!.isEmpty())
} }
@Test @Test
@ -123,14 +128,14 @@ class TagDataDaoTest : InjectingTestCase() {
newTag(2) newTag(2)
val selections = tagDataDao.getTagSelections(listOf(1L, 2L)) val selections = tagDataDao.getTagSelections(listOf(1L, 2L))
assertEquals(setOf("tag1"), selections.first) assertEquals(setOf("tag1"), selections.first)
assertTrue(selections.second.isEmpty()) assertTrue(selections.second!!.isEmpty())
} }
private suspend fun newTag(taskId: Long, vararg tags: String) { private suspend fun newTag(taskId: Long, vararg tags: String) {
val task = newTask(with(ID, taskId)) val task = newTask(with(ID, taskId))
taskDao.createNew(task) taskDao.createNew(task)
for (tag in tags) { for (tag in tags) {
tagDao.insert(Tag(task = task.id, taskUid = task.uuid, tagUid = tag)) tagDao.insert(newTag(with(TASK, task), with(TAGUID, tag)))
} }
} }
} }

@ -6,7 +6,8 @@
package org.tasks.data package org.tasks.data
import com.natpryce.makeiteasy.MakeItEasy.with import com.natpryce.makeiteasy.MakeItEasy.with
import org.tasks.data.entity.Task import com.todoroo.andlib.utility.DateUtilities
import com.todoroo.astrid.data.Task
import com.todoroo.astrid.service.TaskDeleter import com.todoroo.astrid.service.TaskDeleter
import dagger.hilt.android.testing.HiltAndroidTest import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules import dagger.hilt.android.testing.UninstallModules
@ -14,12 +15,10 @@ import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertEquals import org.junit.Assert.assertEquals
import org.junit.Assert.assertNull import org.junit.Assert.assertNull
import org.junit.Test import org.junit.Test
import org.tasks.data.dao.TaskDao
import org.tasks.injection.InjectingTestCase import org.tasks.injection.InjectingTestCase
import org.tasks.injection.ProductionModule import org.tasks.injection.ProductionModule
import org.tasks.makers.TaskMaker.PARENT import org.tasks.makers.TaskMaker.PARENT
import org.tasks.makers.TaskMaker.newTask import org.tasks.makers.TaskMaker.newTask
import org.tasks.time.DateTimeUtils2.currentTimeMillis
import javax.inject.Inject import javax.inject.Inject
@UninstallModules(ProductionModule::class) @UninstallModules(ProductionModule::class)
@ -45,23 +44,23 @@ class TaskDaoTests : InjectingTestCase() {
// create hidden task // create hidden task
task = Task() task = Task()
task.title = "hidden" task.title = "hidden"
task.hideUntil = currentTimeMillis() + 10000 task.hideUntil = DateUtilities.now() + 10000
taskDao.createNew(task) taskDao.createNew(task)
// create task with deadlines // create task with deadlines
task = Task() task = Task()
task.title = "deadlineInFuture" task.title = "deadlineInFuture"
task.dueDate = currentTimeMillis() + 10000 task.dueDate = DateUtilities.now() + 10000
taskDao.createNew(task) taskDao.createNew(task)
task = Task() task = Task()
task.title = "deadlineInPast" task.title = "deadlineInPast"
task.dueDate = currentTimeMillis() - 10000 task.dueDate = DateUtilities.now() - 10000
taskDao.createNew(task) taskDao.createNew(task)
// create completed task // create completed task
task = Task() task = Task()
task.title = "completed" task.title = "completed"
task.completionDate = currentTimeMillis() - 10000 task.completionDate = DateUtilities.now() - 10000
taskDao.createNew(task) taskDao.createNew(task)
// check is active // check is active

@ -8,15 +8,10 @@ import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertEquals import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue import org.junit.Assert.assertTrue
import org.junit.Test import org.junit.Test
import org.tasks.data.dao.CaldavDao
import org.tasks.data.dao.TagDao
import org.tasks.data.dao.TagDataDao
import org.tasks.data.dao.UpgraderDao
import org.tasks.data.entity.CaldavTask
import org.tasks.data.entity.Tag
import org.tasks.data.entity.TagData
import org.tasks.injection.InjectingTestCase import org.tasks.injection.InjectingTestCase
import org.tasks.injection.ProductionModule import org.tasks.injection.ProductionModule
import org.tasks.makers.TagDataMaker
import org.tasks.makers.TagMaker
import org.tasks.makers.TaskMaker import org.tasks.makers.TaskMaker
import javax.inject.Inject import javax.inject.Inject
@ -34,12 +29,12 @@ class UpgraderDaoTests : InjectingTestCase() {
fun getCaldavTasksWithTags() = runBlocking { fun getCaldavTasksWithTags() = runBlocking {
val task = TaskMaker.newTask(MakeItEasy.with(TaskMaker.ID, 1L)) val task = TaskMaker.newTask(MakeItEasy.with(TaskMaker.ID, 1L))
taskDao.createNew(task) taskDao.createNew(task)
val one = TagData() val one = TagDataMaker.newTagData()
val two = TagData() val two = TagDataMaker.newTagData()
tagDataDao.insert(one) tagDataDao.createNew(one)
tagDataDao.insert(two) tagDataDao.createNew(two)
tagDao.insert(Tag(task = task.id, taskUid = task.uuid, tagUid = one.remoteId)) tagDao.insert(TagMaker.newTag(MakeItEasy.with(TagMaker.TASK, task), MakeItEasy.with(TagMaker.TAGDATA, one)))
tagDao.insert(Tag(task = task.id, taskUid = task.uuid, tagUid = two.remoteId)) tagDao.insert(TagMaker.newTag(MakeItEasy.with(TagMaker.TASK, task), MakeItEasy.with(TagMaker.TAGDATA, two)))
caldavDao.insert(CaldavTask(task = task.id, calendar = "calendar")) caldavDao.insert(CaldavTask(task = task.id, calendar = "calendar"))
assertEquals(listOf(task.id), upgraderDao.tasksWithTags()) assertEquals(listOf(task.id), upgraderDao.tasksWithTags())
} }
@ -48,9 +43,9 @@ class UpgraderDaoTests : InjectingTestCase() {
fun ignoreNonCaldavTaskWithTags() = runBlocking { fun ignoreNonCaldavTaskWithTags() = runBlocking {
val task = TaskMaker.newTask(MakeItEasy.with(TaskMaker.ID, 1L)) val task = TaskMaker.newTask(MakeItEasy.with(TaskMaker.ID, 1L))
taskDao.createNew(task) taskDao.createNew(task)
val tag = TagData() val tag = TagDataMaker.newTagData()
tagDataDao.insert(tag) tagDataDao.createNew(tag)
tagDao.insert(Tag(task = task.id, taskUid = task.uuid, tagUid = tag.remoteId)) tagDao.insert(TagMaker.newTag(MakeItEasy.with(TagMaker.TASK, task), MakeItEasy.with(TagMaker.TAGDATA, tag)))
assertTrue(upgraderDao.tasksWithTags().isEmpty()) assertTrue(upgraderDao.tasksWithTags().isEmpty())
} }
@ -58,7 +53,7 @@ class UpgraderDaoTests : InjectingTestCase() {
fun ignoreCaldavTaskWithoutTags() = runBlocking { fun ignoreCaldavTaskWithoutTags() = runBlocking {
val task = TaskMaker.newTask(MakeItEasy.with(TaskMaker.ID, 1L)) val task = TaskMaker.newTask(MakeItEasy.with(TaskMaker.ID, 1L))
taskDao.createNew(task) taskDao.createNew(task)
tagDataDao.insert(TagData()) tagDataDao.createNew(TagDataMaker.newTagData())
caldavDao.insert(CaldavTask(task = task.id, calendar = "calendar")) caldavDao.insert(CaldavTask(task = task.id, calendar = "calendar"))
assertTrue(upgraderDao.tasksWithTags().isEmpty()) assertTrue(upgraderDao.tasksWithTags().isEmpty())
} }

@ -2,7 +2,7 @@ package org.tasks.gtasks
import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.ext.junit.runners.AndroidJUnit4
import com.natpryce.makeiteasy.MakeItEasy.with import com.natpryce.makeiteasy.MakeItEasy.with
import org.tasks.data.entity.Task import com.todoroo.astrid.data.Task
import org.junit.Assert.assertEquals import org.junit.Assert.assertEquals
import org.junit.Assert.assertNull import org.junit.Assert.assertNull
import org.junit.Test import org.junit.Test

@ -2,6 +2,7 @@ package org.tasks.injection
import android.content.Context import android.content.Context
import androidx.room.Room import androidx.room.Room
import com.todoroo.astrid.dao.Database
import dagger.Module import dagger.Module
import dagger.Provides import dagger.Provides
import dagger.hilt.InstallIn import dagger.hilt.InstallIn
@ -9,7 +10,6 @@ import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent import dagger.hilt.components.SingletonComponent
import org.mockito.Mockito.mock import org.mockito.Mockito.mock
import org.tasks.TestUtilities import org.tasks.TestUtilities
import org.tasks.data.db.Database
import org.tasks.jobs.WorkManager import org.tasks.jobs.WorkManager
import org.tasks.location.LocationManager import org.tasks.location.LocationManager
import org.tasks.location.MockLocationManager import org.tasks.location.MockLocationManager
@ -25,7 +25,7 @@ class TestModule {
@Singleton @Singleton
fun getDatabase(@ApplicationContext context: Context): Database { fun getDatabase(@ApplicationContext context: Context): Database {
return Room.inMemoryDatabaseBuilder(context, Database::class.java) return Room.inMemoryDatabaseBuilder(context, Database::class.java)
.fallbackToDestructiveMigration(dropAllTables = true) .fallbackToDestructiveMigration()
.build() .build()
} }

@ -8,7 +8,7 @@ package org.tasks.jobs
import android.net.Uri import android.net.Uri
import androidx.test.InstrumentationRegistry import androidx.test.InstrumentationRegistry
import com.todoroo.astrid.dao.TaskDao import com.todoroo.astrid.dao.TaskDao
import org.tasks.data.entity.Task import com.todoroo.astrid.data.Task
import dagger.hilt.android.testing.HiltAndroidTest import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules import dagger.hilt.android.testing.UninstallModules
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking

@ -1,7 +1,7 @@
package org.tasks.opentasks package org.tasks.opentasks
import com.natpryce.makeiteasy.MakeItEasy.with import com.natpryce.makeiteasy.MakeItEasy.with
import org.tasks.data.entity.Task import com.todoroo.astrid.data.Task
import dagger.hilt.android.testing.HiltAndroidTest import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules import dagger.hilt.android.testing.UninstallModules
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save