Replace remaining usages of TimeZone with Clock (#1119)

This commit is contained in:
David Perez 2024-03-11 10:35:59 -05:00 committed by Álison Fernandes
parent 52b0410290
commit 0c64b7ad35
8 changed files with 62 additions and 56 deletions

View file

@ -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

View file

@ -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)
}

View file

@ -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

View 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,

View file

@ -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))
}
}

View file

@ -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",

View file

@ -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(

View file

@ -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(