mirror of
https://github.com/bitwarden/android.git
synced 2025-03-15 18:58:59 +03:00
Replace remaining usages of TimeZone with Clock (#1119)
This commit is contained in:
parent
52b0410290
commit
0c64b7ad35
8 changed files with 62 additions and 56 deletions
|
@ -1,17 +1,16 @@
|
|||
package com.x8bit.bitwarden.ui.platform.base.util
|
||||
|
||||
import java.time.Clock
|
||||
import java.time.Duration
|
||||
import java.time.ZonedDateTime
|
||||
import java.util.TimeZone
|
||||
|
||||
/**
|
||||
* Returns a [Boolean] indicating whether this [ZonedDateTime] is five or more minutes old.
|
||||
*/
|
||||
@Suppress("MagicNumber")
|
||||
fun ZonedDateTime.isOverFiveMinutesOld(): Boolean =
|
||||
fun ZonedDateTime.isOverFiveMinutesOld(
|
||||
clock: Clock = Clock.systemDefaultZone(),
|
||||
): Boolean =
|
||||
Duration
|
||||
.between(
|
||||
this,
|
||||
ZonedDateTime.now(TimeZone.getDefault().toZoneId()),
|
||||
)
|
||||
.between(this.toInstant(), clock.instant())
|
||||
.toMinutes() > 5
|
||||
|
|
|
@ -129,7 +129,7 @@ class PendingRequestsViewModel @Inject constructor(
|
|||
is AuthRequestsUpdatesResult.Update -> {
|
||||
val requests = result
|
||||
.authRequests
|
||||
.filterRespondedAndExpired()
|
||||
.filterRespondedAndExpired(clock = clock)
|
||||
.sortedByDescending { request -> request.creationDate }
|
||||
.map { request ->
|
||||
PendingRequestsState.ViewState.Content.PendingLoginRequest(
|
||||
|
@ -342,9 +342,9 @@ sealed class PendingRequestsAction {
|
|||
* * The request has been declined (indicated by it not being approved & having a responseDate).
|
||||
* * The request has expired (it is at least 5 minutes old).
|
||||
*/
|
||||
private fun List<AuthRequest>.filterRespondedAndExpired() =
|
||||
private fun List<AuthRequest>.filterRespondedAndExpired(clock: Clock) =
|
||||
filterNot { request ->
|
||||
request.requestApproved ||
|
||||
request.responseDate != null ||
|
||||
request.creationDate.isOverFiveMinutesOld()
|
||||
request.creationDate.isOverFiveMinutesOld(clock)
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import com.bitwarden.core.SendView
|
|||
import com.x8bit.bitwarden.data.vault.repository.model.SendData
|
||||
import com.x8bit.bitwarden.ui.platform.util.toFormattedPattern
|
||||
import com.x8bit.bitwarden.ui.tools.feature.send.SendState
|
||||
import java.time.Clock
|
||||
|
||||
private const val DELETION_DATE_PATTERN: String = "MMM d, uuuu, hh:mm a"
|
||||
|
||||
|
@ -13,15 +14,17 @@ private const val DELETION_DATE_PATTERN: String = "MMM d, uuuu, hh:mm a"
|
|||
*/
|
||||
fun SendData.toViewState(
|
||||
baseWebSendUrl: String,
|
||||
clock: Clock = Clock.systemDefaultZone(),
|
||||
): SendState.ViewState =
|
||||
this
|
||||
.sendViewList
|
||||
.takeUnless { it.isEmpty() }
|
||||
?.toSendContent(baseWebSendUrl)
|
||||
?.toSendContent(baseWebSendUrl, clock)
|
||||
?: SendState.ViewState.Empty
|
||||
|
||||
private fun List<SendView>.toSendContent(
|
||||
baseWebSendUrl: String,
|
||||
clock: Clock,
|
||||
): SendState.ViewState.Content {
|
||||
return SendState.ViewState.Content(
|
||||
textTypeCount = this.count { it.type == SendType.TEXT },
|
||||
|
@ -31,7 +34,10 @@ private fun List<SendView>.toSendContent(
|
|||
SendState.ViewState.Content.SendItem(
|
||||
id = requireNotNull(sendView.id),
|
||||
name = sendView.name,
|
||||
deletionDate = sendView.deletionDate.toFormattedPattern(DELETION_DATE_PATTERN),
|
||||
deletionDate = sendView.deletionDate.toFormattedPattern(
|
||||
pattern = DELETION_DATE_PATTERN,
|
||||
clock = clock,
|
||||
),
|
||||
type = when (sendView.type) {
|
||||
SendType.TEXT -> SendState.ViewState.Content.SendItem.Type.TEXT
|
||||
SendType.FILE -> SendState.ViewState.Content.SendItem.Type.FILE
|
||||
|
|
|
@ -20,7 +20,7 @@ import com.x8bit.bitwarden.ui.vault.feature.vault.VaultState
|
|||
import com.x8bit.bitwarden.ui.vault.model.VaultCardBrand
|
||||
import com.x8bit.bitwarden.ui.vault.model.VaultLinkedFieldType
|
||||
import com.x8bit.bitwarden.ui.vault.model.findVaultCardBrandWithNameOrNull
|
||||
import java.util.TimeZone
|
||||
import java.time.Clock
|
||||
|
||||
private const val DATE_TIME_PATTERN: String = "M/d/yy hh:mm a"
|
||||
|
||||
|
@ -31,6 +31,7 @@ private const val DATE_TIME_PATTERN: String = "M/d/yy hh:mm a"
|
|||
fun CipherView.toViewState(
|
||||
isPremiumUser: Boolean,
|
||||
totpCodeItemData: TotpCodeItemData?,
|
||||
clock: Clock = Clock.systemDefaultZone(),
|
||||
): VaultItemState.ViewState =
|
||||
VaultItemState.ViewState.Content(
|
||||
common = VaultItemState.ViewState.Content.Common(
|
||||
|
@ -40,7 +41,7 @@ fun CipherView.toViewState(
|
|||
customFields = fields.orEmpty().map { it.toCustomField() },
|
||||
lastUpdated = revisionDate.toFormattedPattern(
|
||||
pattern = DATE_TIME_PATTERN,
|
||||
zone = TimeZone.getDefault().toZoneId(),
|
||||
clock = clock,
|
||||
),
|
||||
notes = notes,
|
||||
attachments = attachments
|
||||
|
@ -87,7 +88,7 @@ fun CipherView.toViewState(
|
|||
.passwordRevisionDate
|
||||
?.toFormattedPattern(
|
||||
pattern = DATE_TIME_PATTERN,
|
||||
zone = TimeZone.getDefault().toZoneId(),
|
||||
clock = clock,
|
||||
),
|
||||
passwordHistoryCount = passwordHistory?.count(),
|
||||
isPremiumUser = isPremiumUser,
|
||||
|
|
|
@ -1,46 +1,41 @@
|
|||
package com.x8bit.bitwarden.data.platform.base.util
|
||||
|
||||
import com.x8bit.bitwarden.ui.platform.base.util.isOverFiveMinutesOld
|
||||
import org.junit.jupiter.api.AfterEach
|
||||
import org.junit.jupiter.api.Assertions.assertFalse
|
||||
import org.junit.jupiter.api.Assertions.assertTrue
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Test
|
||||
import java.time.Clock
|
||||
import java.time.Instant
|
||||
import java.time.ZoneOffset
|
||||
import java.time.ZonedDateTime
|
||||
import java.util.TimeZone
|
||||
|
||||
class ZonedDateTimeExtensionsTest {
|
||||
@BeforeEach
|
||||
fun setup() {
|
||||
TimeZone.setDefault(TimeZone.getTimeZone("UTC"))
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
fun teardown() {
|
||||
TimeZone.setDefault(null)
|
||||
}
|
||||
private val fixedClock: Clock = Clock.fixed(
|
||||
Instant.parse("2023-10-27T12:00:00Z"),
|
||||
ZoneOffset.UTC,
|
||||
)
|
||||
|
||||
@Test
|
||||
fun `isOverFiveMinutesOld returns true when time is old`() {
|
||||
val time = ZonedDateTime.parse("2022-09-13T00:00Z")
|
||||
assertTrue(time.isOverFiveMinutesOld())
|
||||
assertTrue(time.isOverFiveMinutesOld(fixedClock))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `isOverFiveMinutesOld returns false when time is now`() {
|
||||
val time = ZonedDateTime.now()
|
||||
assertFalse(time.isOverFiveMinutesOld())
|
||||
val time = ZonedDateTime.parse("2023-10-27T11:55:00Z")
|
||||
assertFalse(time.isOverFiveMinutesOld(fixedClock))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `isOverFiveMinutesOld returns false when time is now minus 5 minutes`() {
|
||||
val time = ZonedDateTime.now().minusMinutes(5)
|
||||
assertFalse(time.isOverFiveMinutesOld())
|
||||
val time = ZonedDateTime.now(fixedClock).minusMinutes(5)
|
||||
assertFalse(time.isOverFiveMinutesOld(fixedClock))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `isOverFiveMinutesOld returns true when time is now minus 6 minutes`() {
|
||||
val time = ZonedDateTime.now().minusMinutes(6)
|
||||
assertTrue(time.isOverFiveMinutesOld())
|
||||
val time = ZonedDateTime.now(fixedClock).minusMinutes(6)
|
||||
assertTrue(time.isOverFiveMinutesOld(fixedClock))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -58,7 +58,7 @@ class PendingRequestsViewModelTest : BaseViewModelTest() {
|
|||
val dateTimeFormatter = DateTimeFormatter
|
||||
.ofPattern("M/d/yy hh:mm a")
|
||||
.withZone(fixedClock.zone)
|
||||
val nowZonedDateTime = ZonedDateTime.now()
|
||||
val nowZonedDateTime = ZonedDateTime.now(fixedClock)
|
||||
val requestList = listOf(
|
||||
AuthRequest(
|
||||
id = "1",
|
||||
|
@ -93,7 +93,7 @@ class PendingRequestsViewModelTest : BaseViewModelTest() {
|
|||
ipAddress = "192.168.0.2",
|
||||
key = "publicKey",
|
||||
masterPasswordHash = "verySecureHash",
|
||||
creationDate = ZonedDateTime.now().minusMinutes(10),
|
||||
creationDate = nowZonedDateTime.minusMinutes(10),
|
||||
responseDate = null,
|
||||
requestApproved = false,
|
||||
originUrl = "www.bitwarden.com",
|
||||
|
|
|
@ -14,14 +14,19 @@ import org.junit.jupiter.api.AfterEach
|
|||
import org.junit.jupiter.api.Assertions.assertEquals
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Test
|
||||
import java.util.TimeZone
|
||||
import java.time.Clock
|
||||
import java.time.Instant
|
||||
import java.time.ZoneOffset
|
||||
|
||||
class SendDataExtensionsTest {
|
||||
|
||||
private val fixedClock: Clock = Clock.fixed(
|
||||
Instant.parse("2023-10-27T12:00:00Z"),
|
||||
ZoneOffset.UTC,
|
||||
)
|
||||
|
||||
@BeforeEach
|
||||
fun setup() {
|
||||
// Setting the timezone so the tests pass consistently no matter the environment.
|
||||
TimeZone.setDefault(TimeZone.getTimeZone("UTC"))
|
||||
mockkStatic(
|
||||
SendView::toLabelIcons,
|
||||
SendView::toSendUrl,
|
||||
|
@ -30,8 +35,6 @@ class SendDataExtensionsTest {
|
|||
|
||||
@AfterEach
|
||||
fun tearDown() {
|
||||
// Clearing the timezone after the test.
|
||||
TimeZone.setDefault(null)
|
||||
unmockkStatic(
|
||||
SendView::toLabelIcons,
|
||||
SendView::toSendUrl,
|
||||
|
@ -42,7 +45,7 @@ class SendDataExtensionsTest {
|
|||
fun `toViewState should return Empty when SendData is empty`() {
|
||||
val sendData = SendData(emptyList())
|
||||
|
||||
val result = sendData.toViewState(DEFAULT_BASE_URL)
|
||||
val result = sendData.toViewState(DEFAULT_BASE_URL, fixedClock)
|
||||
|
||||
assertEquals(SendState.ViewState.Empty, result)
|
||||
}
|
||||
|
@ -63,7 +66,7 @@ class SendDataExtensionsTest {
|
|||
every { textSendView.toLabelIcons(any()) } returns DEFAULT_SEND_STATUS_ICONS
|
||||
every { fileSendView.toLabelIcons(any()) } returns DEFAULT_SEND_STATUS_ICONS
|
||||
|
||||
val result = sendData.toViewState(DEFAULT_BASE_URL)
|
||||
val result = sendData.toViewState(DEFAULT_BASE_URL, fixedClock)
|
||||
|
||||
assertEquals(
|
||||
SendState.ViewState.Content(
|
||||
|
|
|
@ -3,25 +3,18 @@ package com.x8bit.bitwarden.ui.vault.feature.item.util
|
|||
import com.bitwarden.core.CipherType
|
||||
import com.x8bit.bitwarden.ui.vault.feature.item.VaultItemState
|
||||
import com.x8bit.bitwarden.ui.vault.feature.item.model.TotpCodeItemData
|
||||
import org.junit.jupiter.api.AfterEach
|
||||
import org.junit.jupiter.api.Assertions.assertEquals
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Test
|
||||
import java.util.TimeZone
|
||||
import java.time.Clock
|
||||
import java.time.Instant
|
||||
import java.time.ZoneOffset
|
||||
|
||||
class CipherViewExtensionsTest {
|
||||
|
||||
@BeforeEach
|
||||
fun setup() {
|
||||
// Setting the timezone so the tests pass consistently no matter the environment.
|
||||
TimeZone.setDefault(TimeZone.getTimeZone("UTC"))
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
fun tearDown() {
|
||||
// Clearing the timezone after the test.
|
||||
TimeZone.setDefault(null)
|
||||
}
|
||||
private val fixedClock: Clock = Clock.fixed(
|
||||
Instant.parse("2023-10-27T12:00:00Z"),
|
||||
ZoneOffset.UTC,
|
||||
)
|
||||
|
||||
@Test
|
||||
fun `toViewState should transform full CipherView into ViewState Login Content with premium`() {
|
||||
|
@ -34,6 +27,7 @@ class CipherViewExtensionsTest {
|
|||
verificationCode = "123456",
|
||||
totpCode = "testCode",
|
||||
),
|
||||
clock = fixedClock,
|
||||
)
|
||||
|
||||
assertEquals(
|
||||
|
@ -59,6 +53,7 @@ class CipherViewExtensionsTest {
|
|||
verificationCode = "123456",
|
||||
totpCode = "testCode",
|
||||
),
|
||||
clock = fixedClock,
|
||||
)
|
||||
|
||||
assertEquals(
|
||||
|
@ -77,6 +72,7 @@ class CipherViewExtensionsTest {
|
|||
val viewState = cipherView.toViewState(
|
||||
isPremiumUser = true,
|
||||
totpCodeItemData = null,
|
||||
clock = fixedClock,
|
||||
)
|
||||
|
||||
assertEquals(
|
||||
|
@ -96,6 +92,7 @@ class CipherViewExtensionsTest {
|
|||
val viewState = cipherView.toViewState(
|
||||
isPremiumUser = true,
|
||||
totpCodeItemData = null,
|
||||
clock = fixedClock,
|
||||
)
|
||||
|
||||
assertEquals(
|
||||
|
@ -114,6 +111,7 @@ class CipherViewExtensionsTest {
|
|||
val viewState = cipherView.toViewState(
|
||||
isPremiumUser = true,
|
||||
totpCodeItemData = null,
|
||||
clock = fixedClock,
|
||||
)
|
||||
|
||||
assertEquals(
|
||||
|
@ -142,6 +140,7 @@ class CipherViewExtensionsTest {
|
|||
val viewState = cipherView.toViewState(
|
||||
isPremiumUser = true,
|
||||
totpCodeItemData = null,
|
||||
clock = fixedClock,
|
||||
)
|
||||
|
||||
assertEquals(
|
||||
|
@ -175,6 +174,7 @@ class CipherViewExtensionsTest {
|
|||
val result = cipherView.toViewState(
|
||||
isPremiumUser = true,
|
||||
totpCodeItemData = null,
|
||||
clock = fixedClock,
|
||||
)
|
||||
|
||||
assertEquals(
|
||||
|
@ -210,6 +210,7 @@ class CipherViewExtensionsTest {
|
|||
val viewState = cipherView.toViewState(
|
||||
isPremiumUser = true,
|
||||
totpCodeItemData = null,
|
||||
clock = fixedClock,
|
||||
)
|
||||
|
||||
assertEquals(
|
||||
|
@ -229,6 +230,7 @@ class CipherViewExtensionsTest {
|
|||
val viewState = cipherView.toViewState(
|
||||
isPremiumUser = true,
|
||||
totpCodeItemData = null,
|
||||
clock = fixedClock,
|
||||
)
|
||||
|
||||
val expectedState = VaultItemState.ViewState.Content(
|
||||
|
|
Loading…
Add table
Reference in a new issue