Add initial instrumentation testing for V2 ConversationItem shapes.
This commit is contained in:
parent
47b97aafc6
commit
3040b70100
5 changed files with 409 additions and 9 deletions
|
@ -0,0 +1,325 @@
|
|||
/*
|
||||
* Copyright 2023 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.thoughtcrime.securesms.conversation.v2.items
|
||||
|
||||
import android.net.Uri
|
||||
import android.view.View
|
||||
import androidx.lifecycle.Observer
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.signal.ringrtc.CallLinkRootKey
|
||||
import org.thoughtcrime.securesms.components.voice.VoiceNotePlaybackState
|
||||
import org.thoughtcrime.securesms.contactshare.Contact
|
||||
import org.thoughtcrime.securesms.conversation.ConversationAdapter
|
||||
import org.thoughtcrime.securesms.conversation.ConversationItem
|
||||
import org.thoughtcrime.securesms.conversation.ConversationItemDisplayMode
|
||||
import org.thoughtcrime.securesms.conversation.ConversationMessage
|
||||
import org.thoughtcrime.securesms.conversation.colors.Colorizer
|
||||
import org.thoughtcrime.securesms.conversation.mutiselect.MultiselectPart
|
||||
import org.thoughtcrime.securesms.database.FakeMessageRecords
|
||||
import org.thoughtcrime.securesms.database.model.InMemoryMessageRecord
|
||||
import org.thoughtcrime.securesms.database.model.MessageRecord
|
||||
import org.thoughtcrime.securesms.database.model.MmsMessageRecord
|
||||
import org.thoughtcrime.securesms.groups.GroupId
|
||||
import org.thoughtcrime.securesms.groups.GroupMigrationMembershipChange
|
||||
import org.thoughtcrime.securesms.linkpreview.LinkPreview
|
||||
import org.thoughtcrime.securesms.mediapreview.MediaIntentFactory
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
import org.thoughtcrime.securesms.stickers.StickerLocator
|
||||
import org.thoughtcrime.securesms.testing.SignalActivityRule
|
||||
import kotlin.time.Duration.Companion.minutes
|
||||
|
||||
class V2ConversationItemShapeTest {
|
||||
|
||||
@get:Rule
|
||||
val harness = SignalActivityRule(othersCount = 10)
|
||||
|
||||
@Test
|
||||
fun givenNextAndPreviousMessageDoNotExist_whenISetMessageShape_thenIExpectSingle() {
|
||||
val testSubject = V2ConversationItemShape(FakeConversationContext())
|
||||
|
||||
val expected = V2ConversationItemShape.MessageShape.SINGLE
|
||||
val actual = testSubject.setMessageShape(
|
||||
isLtr = true,
|
||||
currentMessage = getMessageRecord(),
|
||||
isGroupThread = false,
|
||||
adapterPosition = 5
|
||||
)
|
||||
|
||||
assertEquals(expected, actual)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenPreviousWithinTimeoutAndNoNext_whenISetMessageShape_thenIExpectEnd() {
|
||||
val now = System.currentTimeMillis()
|
||||
val prev = now - 2.minutes.inWholeMilliseconds
|
||||
|
||||
val testSubject = V2ConversationItemShape(
|
||||
FakeConversationContext(
|
||||
previousMessage = getMessageRecord(prev)
|
||||
)
|
||||
)
|
||||
|
||||
val expected = V2ConversationItemShape.MessageShape.END
|
||||
val actual = testSubject.setMessageShape(
|
||||
isLtr = true,
|
||||
currentMessage = getMessageRecord(now),
|
||||
isGroupThread = false,
|
||||
adapterPosition = 5
|
||||
)
|
||||
|
||||
assertEquals(expected, actual)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenNextWithinTimeoutAndNoPrevious_whenISetMessageShape_thenIExpectStart() {
|
||||
val now = System.currentTimeMillis()
|
||||
val prev = now - 2.minutes.inWholeMilliseconds
|
||||
|
||||
val testSubject = V2ConversationItemShape(
|
||||
FakeConversationContext(
|
||||
nextMessage = getMessageRecord(now)
|
||||
)
|
||||
)
|
||||
|
||||
val expected = V2ConversationItemShape.MessageShape.START
|
||||
val actual = testSubject.setMessageShape(
|
||||
isLtr = true,
|
||||
currentMessage = getMessageRecord(prev),
|
||||
isGroupThread = false,
|
||||
adapterPosition = 5
|
||||
)
|
||||
|
||||
assertEquals(expected, actual)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenPreviousAndNextWithinTimeout_whenISetMessageShape_thenIExpectMiddle() {
|
||||
val now = System.currentTimeMillis()
|
||||
val prev = now - 2.minutes.inWholeMilliseconds
|
||||
val next = now + 2.minutes.inWholeMilliseconds
|
||||
|
||||
val testSubject = V2ConversationItemShape(
|
||||
FakeConversationContext(
|
||||
previousMessage = getMessageRecord(prev),
|
||||
nextMessage = getMessageRecord(next)
|
||||
)
|
||||
)
|
||||
|
||||
val expected = V2ConversationItemShape.MessageShape.MIDDLE
|
||||
val actual = testSubject.setMessageShape(
|
||||
isLtr = true,
|
||||
currentMessage = getMessageRecord(now),
|
||||
isGroupThread = false,
|
||||
adapterPosition = 5
|
||||
)
|
||||
|
||||
assertEquals(expected, actual)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenPreviousOutsideTimeoutAndNoNext_whenISetMessageShape_thenIExpectSingle() {
|
||||
val now = System.currentTimeMillis()
|
||||
val prev = now - 4.minutes.inWholeMilliseconds
|
||||
|
||||
val testSubject = V2ConversationItemShape(
|
||||
FakeConversationContext(
|
||||
previousMessage = getMessageRecord(prev)
|
||||
)
|
||||
)
|
||||
|
||||
val expected = V2ConversationItemShape.MessageShape.SINGLE
|
||||
val actual = testSubject.setMessageShape(
|
||||
isLtr = true,
|
||||
currentMessage = getMessageRecord(now),
|
||||
isGroupThread = false,
|
||||
adapterPosition = 5
|
||||
)
|
||||
|
||||
assertEquals(expected, actual)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenNextOutsideTimeoutAndNoPrevious_whenISetMessageShape_thenIExpectSingle() {
|
||||
val now = System.currentTimeMillis()
|
||||
val prev = now - 4.minutes.inWholeMilliseconds
|
||||
|
||||
val testSubject = V2ConversationItemShape(
|
||||
FakeConversationContext(
|
||||
nextMessage = getMessageRecord(now)
|
||||
)
|
||||
)
|
||||
|
||||
val expected = V2ConversationItemShape.MessageShape.SINGLE
|
||||
val actual = testSubject.setMessageShape(
|
||||
isLtr = true,
|
||||
currentMessage = getMessageRecord(prev),
|
||||
isGroupThread = false,
|
||||
adapterPosition = 5
|
||||
)
|
||||
|
||||
assertEquals(expected, actual)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenPreviousAndNextOutsideTimeout_whenISetMessageShape_thenIExpectSingle() {
|
||||
val now = System.currentTimeMillis()
|
||||
val prev = now - 4.minutes.inWholeMilliseconds
|
||||
val next = now + 4.minutes.inWholeMilliseconds
|
||||
|
||||
val testSubject = V2ConversationItemShape(
|
||||
FakeConversationContext(
|
||||
previousMessage = getMessageRecord(prev),
|
||||
nextMessage = getMessageRecord(next)
|
||||
)
|
||||
)
|
||||
|
||||
val expected = V2ConversationItemShape.MessageShape.SINGLE
|
||||
val actual = testSubject.setMessageShape(
|
||||
isLtr = true,
|
||||
currentMessage = getMessageRecord(now),
|
||||
isGroupThread = false,
|
||||
adapterPosition = 5
|
||||
)
|
||||
|
||||
assertEquals(expected, actual)
|
||||
}
|
||||
|
||||
private fun getMessageRecord(
|
||||
timestamp: Long = System.currentTimeMillis()
|
||||
): MessageRecord {
|
||||
return FakeMessageRecords.buildMediaMmsMessageRecord(
|
||||
dateReceived = timestamp,
|
||||
dateSent = timestamp,
|
||||
dateServer = timestamp
|
||||
)
|
||||
}
|
||||
|
||||
private class FakeConversationContext(
|
||||
private val hasWallpaper: Boolean = false,
|
||||
private val previousMessage: MessageRecord? = null,
|
||||
private val nextMessage: MessageRecord? = null
|
||||
) : V2ConversationContext {
|
||||
|
||||
private val colorizer = Colorizer()
|
||||
|
||||
override val displayMode: ConversationItemDisplayMode = ConversationItemDisplayMode.STANDARD
|
||||
|
||||
override val clickListener: ConversationAdapter.ItemClickListener = FakeConversationItemClickListener
|
||||
|
||||
override fun onStartExpirationTimeout(messageRecord: MessageRecord) = Unit
|
||||
|
||||
override fun hasWallpaper(): Boolean = hasWallpaper
|
||||
|
||||
override fun getColorizer(): Colorizer = colorizer
|
||||
|
||||
override fun getNextMessage(adapterPosition: Int): MessageRecord? = nextMessage
|
||||
|
||||
override fun getPreviousMessage(adapterPosition: Int): MessageRecord? = previousMessage
|
||||
}
|
||||
|
||||
private object FakeConversationItemClickListener : ConversationAdapter.ItemClickListener {
|
||||
override fun onQuoteClicked(messageRecord: MmsMessageRecord?) = Unit
|
||||
|
||||
override fun onLinkPreviewClicked(linkPreview: LinkPreview) = Unit
|
||||
|
||||
override fun onQuotedIndicatorClicked(messageRecord: MessageRecord) = Unit
|
||||
|
||||
override fun onMoreTextClicked(conversationRecipientId: RecipientId, messageId: Long, isMms: Boolean) = Unit
|
||||
|
||||
override fun onStickerClicked(stickerLocator: StickerLocator) = Unit
|
||||
|
||||
override fun onViewOnceMessageClicked(messageRecord: MmsMessageRecord) = Unit
|
||||
|
||||
override fun onSharedContactDetailsClicked(contact: Contact, avatarTransitionView: View) = Unit
|
||||
|
||||
override fun onAddToContactsClicked(contact: Contact) = Unit
|
||||
|
||||
override fun onMessageSharedContactClicked(choices: MutableList<Recipient>) = Unit
|
||||
|
||||
override fun onInviteSharedContactClicked(choices: MutableList<Recipient>) = Unit
|
||||
|
||||
override fun onReactionClicked(multiselectPart: MultiselectPart, messageId: Long, isMms: Boolean) = Unit
|
||||
|
||||
override fun onGroupMemberClicked(recipientId: RecipientId, groupId: GroupId) = Unit
|
||||
|
||||
override fun onMessageWithErrorClicked(messageRecord: MessageRecord) = Unit
|
||||
|
||||
override fun onMessageWithRecaptchaNeededClicked(messageRecord: MessageRecord) = Unit
|
||||
|
||||
override fun onIncomingIdentityMismatchClicked(recipientId: RecipientId) = Unit
|
||||
|
||||
override fun onRegisterVoiceNoteCallbacks(onPlaybackStartObserver: Observer<VoiceNotePlaybackState>) = Unit
|
||||
|
||||
override fun onUnregisterVoiceNoteCallbacks(onPlaybackStartObserver: Observer<VoiceNotePlaybackState>) = Unit
|
||||
|
||||
override fun onVoiceNotePause(uri: Uri) = Unit
|
||||
|
||||
override fun onVoiceNotePlay(uri: Uri, messageId: Long, position: Double) = Unit
|
||||
|
||||
override fun onVoiceNoteSeekTo(uri: Uri, position: Double) = Unit
|
||||
|
||||
override fun onVoiceNotePlaybackSpeedChanged(uri: Uri, speed: Float) = Unit
|
||||
|
||||
override fun onGroupMigrationLearnMoreClicked(membershipChange: GroupMigrationMembershipChange) = Unit
|
||||
|
||||
override fun onChatSessionRefreshLearnMoreClicked() = Unit
|
||||
|
||||
override fun onBadDecryptLearnMoreClicked(author: RecipientId) = Unit
|
||||
|
||||
override fun onSafetyNumberLearnMoreClicked(recipient: Recipient) = Unit
|
||||
|
||||
override fun onJoinGroupCallClicked() = Unit
|
||||
|
||||
override fun onInviteFriendsToGroupClicked(groupId: GroupId.V2) = Unit
|
||||
|
||||
override fun onEnableCallNotificationsClicked() = Unit
|
||||
|
||||
override fun onPlayInlineContent(conversationMessage: ConversationMessage?) = Unit
|
||||
|
||||
override fun onInMemoryMessageClicked(messageRecord: InMemoryMessageRecord) = Unit
|
||||
|
||||
override fun onViewGroupDescriptionChange(groupId: GroupId?, description: String, isMessageRequestAccepted: Boolean) = Unit
|
||||
|
||||
override fun onChangeNumberUpdateContact(recipient: Recipient) = Unit
|
||||
|
||||
override fun onCallToAction(action: String) = Unit
|
||||
|
||||
override fun onDonateClicked() = Unit
|
||||
|
||||
override fun onBlockJoinRequest(recipient: Recipient) = Unit
|
||||
|
||||
override fun onRecipientNameClicked(target: RecipientId) = Unit
|
||||
|
||||
override fun onInviteToSignalClicked() = Unit
|
||||
|
||||
override fun onActivatePaymentsClicked() = Unit
|
||||
|
||||
override fun onSendPaymentClicked(recipientId: RecipientId) = Unit
|
||||
|
||||
override fun onScheduledIndicatorClicked(view: View, conversationMessage: ConversationMessage) = Unit
|
||||
|
||||
override fun onUrlClicked(url: String): Boolean = false
|
||||
|
||||
override fun onViewGiftBadgeClicked(messageRecord: MessageRecord) = Unit
|
||||
|
||||
override fun onGiftBadgeRevealed(messageRecord: MessageRecord) = Unit
|
||||
|
||||
override fun goToMediaPreview(parent: ConversationItem?, sharedElement: View?, args: MediaIntentFactory.MediaPreviewArgs?) = Unit
|
||||
|
||||
override fun onEditedIndicatorClicked(messageRecord: MessageRecord) = Unit
|
||||
|
||||
override fun onShowGroupDescriptionClicked(groupName: String, description: String, shouldLinkifyWebLinks: Boolean) = Unit
|
||||
|
||||
override fun onJoinCallLink(callLinkRootKey: CallLinkRootKey) = Unit
|
||||
|
||||
override fun onItemClick(item: MultiselectPart?) = Unit
|
||||
|
||||
override fun onItemLongClick(itemView: View?, item: MultiselectPart?) = Unit
|
||||
}
|
||||
}
|
|
@ -8,13 +8,12 @@ package org.thoughtcrime.securesms.conversation.v2.items
|
|||
import com.google.android.material.shape.MaterialShapeDrawable
|
||||
import com.google.android.material.shape.ShapeAppearanceModel
|
||||
import org.signal.core.util.dp
|
||||
import org.thoughtcrime.securesms.conversation.ConversationMessage
|
||||
import org.thoughtcrime.securesms.database.model.MessageRecord
|
||||
import org.thoughtcrime.securesms.util.DateUtils
|
||||
import org.thoughtcrime.securesms.util.Projection
|
||||
import org.thoughtcrime.securesms.util.isScheduled
|
||||
import java.util.concurrent.TimeUnit
|
||||
import kotlin.math.abs
|
||||
import kotlin.time.Duration.Companion.minutes
|
||||
|
||||
/**
|
||||
* Determines the shape for a conversation item based off of the appearance context
|
||||
|
@ -30,6 +29,8 @@ class V2ConversationItemShape(
|
|||
|
||||
private var collapsedSpacing: Float = 1f.dp
|
||||
private var defaultSpacing: Float = 8f.dp
|
||||
|
||||
private val clusterTimeout = 3.minutes
|
||||
}
|
||||
|
||||
var corners: Projection.Corners = Projection.Corners(bigRadius)
|
||||
|
@ -49,13 +50,12 @@ class V2ConversationItemShape(
|
|||
*/
|
||||
fun setMessageShape(
|
||||
isLtr: Boolean,
|
||||
conversationMessage: ConversationMessage,
|
||||
currentMessage: MessageRecord,
|
||||
isGroupThread: Boolean,
|
||||
adapterPosition: Int
|
||||
): MessageShape {
|
||||
val currentMessage: MessageRecord = conversationMessage.messageRecord
|
||||
val nextMessage: MessageRecord? = conversationContext.getNextMessage(adapterPosition)
|
||||
val previousMessage: MessageRecord? = conversationContext.getPreviousMessage(adapterPosition)
|
||||
val isGroupThread: Boolean = conversationMessage.threadRecipient.isGroup
|
||||
|
||||
if (isSingularMessage(currentMessage, previousMessage, nextMessage, isGroupThread)) {
|
||||
setBodyBubbleCorners(isLtr, bigRadius, bigRadius, bigRadius, bigRadius)
|
||||
|
@ -153,7 +153,7 @@ class V2ConversationItemShape(
|
|||
}
|
||||
|
||||
private fun isWithinClusteringTime(currentMessage: MessageRecord, previousMessage: MessageRecord): Boolean {
|
||||
return abs(currentMessage.dateSent - previousMessage.dateSent) <= TimeUnit.MINUTES.toMillis(3)
|
||||
return abs(currentMessage.dateSent - previousMessage.dateSent) <= clusterTimeout.inWholeMilliseconds
|
||||
}
|
||||
|
||||
enum class MessageShape {
|
||||
|
|
|
@ -97,9 +97,10 @@ class V2TextOnlyViewHolder<Model : MappingModel<Model>>(
|
|||
}
|
||||
|
||||
val shape = shapeDelegate.setMessageShape(
|
||||
itemView.layoutDirection == View.LAYOUT_DIRECTION_LTR,
|
||||
conversationMessage,
|
||||
bindingAdapterPosition
|
||||
isLtr = itemView.layoutDirection == View.LAYOUT_DIRECTION_LTR,
|
||||
currentMessage = conversationMessage.messageRecord,
|
||||
isGroupThread = conversationMessage.threadRecipient.isGroup,
|
||||
adapterPosition = bindingAdapterPosition
|
||||
)
|
||||
|
||||
binding.conversationItemBody.setTextColor(themeDelegate.getBodyTextColor(conversationMessage))
|
||||
|
|
|
@ -1843,6 +1843,11 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
|
|||
<sha256 value="66de3038ddc4f240a2b3331bc9863b379c3999a1a8b0923dc731f11a9a295034" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="com.android.tools.emulator" name="proto" version="31.0.2">
|
||||
<artifact name="proto-31.0.2.jar">
|
||||
<sha256 value="03c9f2a9eb08ebad38da2352e82e5ab08fa4fac7083fe771942aa29f60ab5bab" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="com.android.tools.external.com-intellij" name="intellij-core" version="30.2.2">
|
||||
<artifact name="intellij-core-30.2.2.jar">
|
||||
<sha256 value="cdec995f5c1a8839b996188fa8e0212b303021a48d4eed9659fcb5a7df92a364" origin="Generated by Gradle"/>
|
||||
|
@ -1961,6 +1966,14 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
|
|||
<sha256 value="e8aace773417569f1e0989d62b943891ff6e6eaf09f10ec7a5ef4fe91775bc0c" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="com.android.tools.utp" name="android-device-provider-ddmlib" version="31.0.2">
|
||||
<artifact name="android-device-provider-ddmlib-31.0.2.jar">
|
||||
<sha256 value="9972f7f0be3b9999feb88a4a20928aa7c8305d715b0aa71155669c9afc48511b" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="android-device-provider-ddmlib-31.0.2.module">
|
||||
<sha256 value="10cd2df76d221953915c89afa9f2a05378b14c5bd94de17ad3005cf309d21e81" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="com.android.tools.utp" name="android-device-provider-ddmlib-proto" version="31.0.2">
|
||||
<artifact name="android-device-provider-ddmlib-proto-31.0.2.jar">
|
||||
<sha256 value="332794db1e7702c9689c8075532f235cccbf57d70aba29cbd7d378e781bad37f" origin="Generated by Gradle"/>
|
||||
|
@ -1974,6 +1987,14 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
|
|||
<sha256 value="93aa2a29181c4f7404d0c49f6bb7c392713f9018e2cecc0a23f846e86c3f360b" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="com.android.tools.utp" name="android-device-provider-gradle" version="31.0.2">
|
||||
<artifact name="android-device-provider-gradle-31.0.2.jar">
|
||||
<sha256 value="55e574b7f1c1196e61718cdc0419b7fa0e7baef07e5df4b92e3cdd7b3aa0f297" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="android-device-provider-gradle-31.0.2.module">
|
||||
<sha256 value="37b0f23856e6206a74ac1891c455115c88e16d4d89ec3cc62e9902dc1c116a91" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="com.android.tools.utp" name="android-device-provider-gradle-proto" version="31.0.2">
|
||||
<artifact name="android-device-provider-gradle-proto-31.0.2.jar">
|
||||
<sha256 value="48f8b288d3b3195199ded91cbaa67a28be2fb9d317da187b88a7d4ffb505a578" origin="Generated by Gradle"/>
|
||||
|
@ -1987,6 +2008,14 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
|
|||
<sha256 value="cf36bcd4e8af5b240f8f7d80f231ffaf14a442cfe87dea16c5fc4fe8a16c05bb" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="com.android.tools.utp" name="android-test-plugin-host-additional-test-output" version="31.0.2">
|
||||
<artifact name="android-test-plugin-host-additional-test-output-31.0.2.jar">
|
||||
<sha256 value="957d41b43c848272f43e2aee91fb21a65710f6d963639ea4bf210546d3102f6c" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="android-test-plugin-host-additional-test-output-31.0.2.module">
|
||||
<sha256 value="6ae9f8b15d5679d838b538f09b2972f5f4de20cd8fc7824f7695a984b004a92f" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="com.android.tools.utp" name="android-test-plugin-host-additional-test-output-proto" version="31.0.2">
|
||||
<artifact name="android-test-plugin-host-additional-test-output-proto-31.0.2.jar">
|
||||
<sha256 value="6c4d0907badf886cbea14e56e8d08ce232ee775403ad811c27a280520d7efa1a" origin="Generated by Gradle"/>
|
||||
|
@ -2000,6 +2029,14 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
|
|||
<sha256 value="f2e069b05d3b1d2ccffe9a30818ea67182f5376dc7b3ca802301ef3b75f8c69d" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="com.android.tools.utp" name="android-test-plugin-host-coverage" version="31.0.2">
|
||||
<artifact name="android-test-plugin-host-coverage-31.0.2.jar">
|
||||
<sha256 value="4753f96f79e26c02dc41367ff1ae9db018558f58702599f372d178ed4bae9016" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="android-test-plugin-host-coverage-31.0.2.module">
|
||||
<sha256 value="1c6d141394fab54d47c25d11dfdff681ccee0dc958e61999b4fd2cbdb5bafe12" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="com.android.tools.utp" name="android-test-plugin-host-coverage-proto" version="31.0.2">
|
||||
<artifact name="android-test-plugin-host-coverage-proto-31.0.2.jar">
|
||||
<sha256 value="22686a7d1775171e76534ab8f40f9c9677cabc77321088e3268cb9cb74d0e5c6" origin="Generated by Gradle"/>
|
||||
|
@ -2013,11 +2050,24 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
|
|||
<sha256 value="5832d310d2215a9ceb730d0d82519938e43115477d72cc6105835a505dd988d9" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="com.android.tools.utp" name="android-test-plugin-host-device-info" version="31.0.2">
|
||||
<artifact name="android-test-plugin-host-device-info-31.0.2.jar">
|
||||
<sha256 value="8e09d5b0c69a76ff1f4561f2f1ecbc5a0bbc325d0b4d6c65bd03dd5146561f72" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="android-test-plugin-host-device-info-31.0.2.module">
|
||||
<sha256 value="2e7b95eda2cb48b2461df0270f7665f801e15b4f7c0fe1c1190d933334bf5f88" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="com.android.tools.utp" name="android-test-plugin-host-device-info-proto" version="31.0.0">
|
||||
<artifact name="android-test-plugin-host-device-info-proto-31.0.0.jar">
|
||||
<sha256 value="2981a0892b14f189b27c068020b858d91f02c3951bab9b15d49c30d2d356baea" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="com.android.tools.utp" name="android-test-plugin-host-device-info-proto" version="31.0.2">
|
||||
<artifact name="android-test-plugin-host-device-info-proto-31.0.2.jar">
|
||||
<sha256 value="2981a0892b14f189b27c068020b858d91f02c3951bab9b15d49c30d2d356baea" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="com.android.tools.utp" name="android-test-plugin-host-logcat" version="31.0.0">
|
||||
<artifact name="android-test-plugin-host-logcat-31.0.0.jar">
|
||||
<sha256 value="8e0ca774310c4b6abb769ba466a4cb13f1d7c47395fc19b4834402209e8c322d" origin="Generated by Gradle"/>
|
||||
|
@ -2026,6 +2076,14 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
|
|||
<sha256 value="f4b034d37463a18df4fff04c3fb0155b65eeff8e58b9fb407035352b2cc8d517" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="com.android.tools.utp" name="android-test-plugin-host-logcat" version="31.0.2">
|
||||
<artifact name="android-test-plugin-host-logcat-31.0.2.jar">
|
||||
<sha256 value="8ab98d66d6e47f57c71c082dd4e832ff6dbc1488843cc1b9c8d483887a6de452" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="android-test-plugin-host-logcat-31.0.2.module">
|
||||
<sha256 value="5c66828e36a4796b2d1828ef3856399deb9fc8c9e3f62cdbc4385544439eb79d" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="com.android.tools.utp" name="android-test-plugin-host-logcat-proto" version="31.0.2">
|
||||
<artifact name="android-test-plugin-host-logcat-proto-31.0.2.jar">
|
||||
<sha256 value="62234086f76d3dc1d1acbf9def72fcd7741ce2a10de587b4608ab45da62e9bc1" origin="Generated by Gradle"/>
|
||||
|
@ -2039,6 +2097,14 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
|
|||
<sha256 value="2f887040b34faf247889a3e668289d919f4f71d8e93e23c0b89e3a429b3de061" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="com.android.tools.utp" name="android-test-plugin-host-retention" version="31.0.2">
|
||||
<artifact name="android-test-plugin-host-retention-31.0.2.jar">
|
||||
<sha256 value="1b15643fc225427eb12a3c630b4e5a49e3cfc0c4ba65507de965f40505f0a235" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="android-test-plugin-host-retention-31.0.2.module">
|
||||
<sha256 value="5147f2a7070bf474a18f8cc44e1d34aaf77ec9fa694091cd17341212a8675ae5" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="com.android.tools.utp" name="android-test-plugin-host-retention-proto" version="31.0.2">
|
||||
<artifact name="android-test-plugin-host-retention-proto-31.0.2.jar">
|
||||
<sha256 value="031c4c933c5e53ddb863b960074ba36ec040a2464f208d4f5d390d2b227f6505" origin="Generated by Gradle"/>
|
||||
|
@ -2052,6 +2118,14 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
|
|||
<sha256 value="9544d215345b1ac132bc77d421816e8a503af74dc596eac472824b0327f20e57" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="com.android.tools.utp" name="android-test-plugin-result-listener-gradle" version="31.0.2">
|
||||
<artifact name="android-test-plugin-result-listener-gradle-31.0.2.jar">
|
||||
<sha256 value="04273a4018de59cc8e52b48e29954074c99fbc33617f3323641e960a9ac36354" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="android-test-plugin-result-listener-gradle-31.0.2.module">
|
||||
<sha256 value="4e94cac776ee83ec1729c040c002a646bfab20f518baac182214ac893492b8ea" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="com.android.tools.utp" name="android-test-plugin-result-listener-gradle-proto" version="31.0.2">
|
||||
<artifact name="android-test-plugin-result-listener-gradle-proto-31.0.2.jar">
|
||||
<sha256 value="38c664b016fc380676ab80fb9da0c42f13b049cfd98d16467a2049fe85072e70" origin="Generated by Gradle"/>
|
||||
|
|
Loading…
Add table
Reference in a new issue