Skip to content

Commit 59f6869

Browse files
Merge pull request #16380 from nextcloud/test/add-upload-utils-unit-tests
test: add unit tests for DisplayUtils and UploadEntity conversions
2 parents 78fdd76 + aaeb3bd commit 59f6869

1 file changed

Lines changed: 155 additions & 0 deletions

File tree

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
/*
2+
* Nextcloud - Android Client
3+
*
4+
* SPDX-FileCopyrightText: 2026 Alper Ozturk <alper.ozturk@nextcloud.com>
5+
* SPDX-License-Identifier: AGPL-3.0-or-later
6+
*/
7+
8+
package com.nextcloud.utils
9+
10+
import android.content.Context
11+
import android.text.format.DateUtils
12+
import androidx.test.platform.app.InstrumentationRegistry
13+
import com.nextcloud.client.database.entity.UploadEntity
14+
import com.nextcloud.client.database.entity.toOCUpload
15+
import com.nextcloud.client.database.entity.toUploadEntity
16+
import com.owncloud.android.R
17+
import com.owncloud.android.utils.DisplayUtils
18+
import io.mockk.MockKAnnotations
19+
import io.mockk.every
20+
import io.mockk.mockkStatic
21+
import org.junit.Assert.assertEquals
22+
import org.junit.Assert.assertNotNull
23+
import org.junit.Assert.assertTrue
24+
import org.junit.Before
25+
import org.junit.Test
26+
import java.text.SimpleDateFormat
27+
import java.util.Date
28+
import java.util.Locale
29+
30+
class UploadDateTests {
31+
32+
companion object {
33+
private const val JANUARY_27_2026 = 1769505718000
34+
private const val ONE_YEAR = 365L * 24 * 60 * 60 * 1000
35+
private const val ONE_MONTH = 30L * 24 * 60 * 60 * 1000
36+
private const val ONE_WEEK = 7 * 24 * 60 * 60 * 1000
37+
private const val TWO_HOURS = 2 * 60 * 60 * 1000
38+
private const val ONE_MINUTE = 60_000
39+
private const val THIRTY_SECONDS = 30_000
40+
41+
private const val DATE_FORMATTER_PATTERN = "MMM dd, yyyy, hh:mm:ss a"
42+
}
43+
44+
private lateinit var context: Context
45+
46+
@Before
47+
fun setup() {
48+
context = InstrumentationRegistry.getInstrumentation().context
49+
MockKAnnotations.init(this, relaxed = true)
50+
mockkStatic(System::class)
51+
every { System.currentTimeMillis() } returns JANUARY_27_2026
52+
}
53+
54+
@Test
55+
fun uploadEntityConvertsToOCUploadAndBackCorrectly() {
56+
val entity = UploadEntity(
57+
id = 123,
58+
localPath = "/local/file.txt",
59+
remotePath = "/remote/file.txt",
60+
accountName = "test@example.com",
61+
fileSize = 1024L,
62+
status = 2,
63+
localBehaviour = 1,
64+
uploadTime = null,
65+
nameCollisionPolicy = 0,
66+
isCreateRemoteFolder = 1,
67+
uploadEndTimestamp = 0,
68+
uploadEndTimestampLong = 1_650_000_000_000,
69+
lastResult = 0,
70+
isWhileChargingOnly = 1,
71+
isWifiOnly = 1,
72+
createdBy = 5,
73+
folderUnlockToken = "token123"
74+
)
75+
76+
val upload = entity.toOCUpload()
77+
assertNotNull(upload)
78+
assertEquals(entity.localPath, upload?.localPath)
79+
assertEquals(entity.remotePath, upload?.remotePath)
80+
assertEquals(entity.uploadEndTimestampLong, upload?.uploadEndTimestamp)
81+
82+
val convertedEntity = upload!!.toUploadEntity()
83+
assertEquals(entity.localPath, convertedEntity.localPath)
84+
assertEquals(entity.remotePath, convertedEntity.remotePath)
85+
assertEquals(entity.uploadEndTimestampLong, convertedEntity.uploadEndTimestampLong)
86+
assertEquals(entity.isCreateRemoteFolder, convertedEntity.isCreateRemoteFolder)
87+
assertEquals(entity.isWifiOnly, convertedEntity.isWifiOnly)
88+
assertEquals(entity.isWhileChargingOnly, convertedEntity.isWhileChargingOnly)
89+
}
90+
91+
@Test
92+
fun getRelativeDateTimeStringReturnsSecondsAgoForRecentPast() {
93+
val result = DisplayUtils.getRelativeDateTimeString(
94+
context,
95+
JANUARY_27_2026 - THIRTY_SECONDS,
96+
DateUtils.SECOND_IN_MILLIS,
97+
DateUtils.WEEK_IN_MILLIS,
98+
0
99+
)
100+
assertTrue(result.toString() == context.getString(R.string.file_list_seconds_ago))
101+
}
102+
103+
@Test
104+
fun getRelativeDateTimeStringReturnsFutureAsHumanReadableWhenShowFutureIsFalse() {
105+
val formatter = SimpleDateFormat(DATE_FORMATTER_PATTERN, Locale.US)
106+
val time = JANUARY_27_2026 + ONE_MINUTE
107+
val expected = formatter.format(Date(time))
108+
109+
assertRelativeDateTimeString(time, expected, DateUtils.SECOND_IN_MILLIS)
110+
}
111+
112+
@Test
113+
fun getRelativeDateTimeStringReturnsProperRelativeStringForHoursAgo() {
114+
val expected = "2 hours ago"
115+
val time = JANUARY_27_2026 - TWO_HOURS
116+
117+
assertRelativeDateTimeString(time, expected, DateUtils.MINUTE_IN_MILLIS)
118+
}
119+
120+
@Test
121+
fun getRelativeDateTimeStringReturnsRelativeStringForOneWeekAgo() {
122+
val expected = "Jan 20"
123+
val time = JANUARY_27_2026 - ONE_WEEK
124+
125+
assertRelativeDateTimeString(time, expected)
126+
}
127+
128+
@Test
129+
fun getRelativeDateTimeStringReturnsRelativeStringForOneMonthAgo() {
130+
val expected = "12/28/2025"
131+
val time = JANUARY_27_2026 - ONE_MONTH
132+
133+
assertRelativeDateTimeString(time, expected, DateUtils.DAY_IN_MILLIS)
134+
}
135+
136+
@Test
137+
fun getRelativeDateTimeStringReturnsRelativeStringForOneYearAgo() {
138+
val expected = "1/27/2025"
139+
val time = JANUARY_27_2026 - ONE_YEAR
140+
141+
assertRelativeDateTimeString(time, expected, DateUtils.DAY_IN_MILLIS)
142+
}
143+
144+
private fun assertRelativeDateTimeString(
145+
time: Long,
146+
expected: String,
147+
minResolution: Long = DateUtils.MINUTE_IN_MILLIS,
148+
transitionResolution: Long = DateUtils.WEEK_IN_MILLIS
149+
) {
150+
val result = DisplayUtils.getRelativeDateTimeString(context, time, minResolution, transitionResolution, 0)
151+
assertEquals(expected.normalizeResult(), result.toString().normalizeResult())
152+
}
153+
154+
private fun String.normalizeResult(): String = replace('\u202F', ' ').replace('\u00A0', ' ')
155+
}

0 commit comments

Comments
 (0)