diff options
author | 2024-03-28 13:45:29 -0400 | |
---|---|---|
committer | 2024-03-28 15:42:30 -0400 | |
commit | 9c6a03ac16a40a75cf57b175e622c98c27c7d08e (patch) | |
tree | 1b9de791eb22e6d9350346fee684473728d46cdd | |
parent | 38a6a7637ed22bed196ede400ff72fea5407b17b (diff) |
Introduce Kosmos DI for unit testing
Bug: 302691505
Flag: ACONFIG android.service.chooser.chooser_payload_toggling DEVELOPMENT
Test: atest IntentResolver-tests-unit
Change-Id: I47bd50ceb8aa39fdd4c37de0032e6b925ce88145
26 files changed, 1046 insertions, 822 deletions
diff --git a/tests/shared/Android.bp b/tests/shared/Android.bp index 249bf38f..7f5d605a 100644 --- a/tests/shared/Android.bp +++ b/tests/shared/Android.bp @@ -31,6 +31,7 @@ java_library { static_libs: [ "hamcrest", "IntentResolver-core", + "kosmos", "mockito-kotlin2", "mockito-target-minus-junit4", "truth", diff --git a/tests/shared/src/com/android/intentresolver/CoroutinesKosmos.kt b/tests/shared/src/com/android/intentresolver/CoroutinesKosmos.kt new file mode 100644 index 00000000..eacefdc0 --- /dev/null +++ b/tests/shared/src/com/android/intentresolver/CoroutinesKosmos.kt @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.intentresolver + +import com.android.systemui.kosmos.Kosmos +import kotlinx.coroutines.CoroutineDispatcher + +var Kosmos.backgroundDispatcher: CoroutineDispatcher by Kosmos.Fixture() diff --git a/tests/shared/src/com/android/intentresolver/FrameworkMocksKosmos.kt b/tests/shared/src/com/android/intentresolver/FrameworkMocksKosmos.kt new file mode 100644 index 00000000..d578fb66 --- /dev/null +++ b/tests/shared/src/com/android/intentresolver/FrameworkMocksKosmos.kt @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.intentresolver + +import android.content.ContentResolver +import android.content.pm.PackageManager +import com.android.systemui.kosmos.Kosmos + +var Kosmos.contentResolver by Kosmos.Fixture { mock<ContentResolver> {} } +var Kosmos.contentInterface by Kosmos.Fixture { contentResolver } +var Kosmos.packageManager by Kosmos.Fixture { mock<PackageManager> {} } diff --git a/tests/shared/src/com/android/intentresolver/contentpreview/MimetypeClassifierKosmos.kt b/tests/shared/src/com/android/intentresolver/contentpreview/MimetypeClassifierKosmos.kt new file mode 100644 index 00000000..4f979f54 --- /dev/null +++ b/tests/shared/src/com/android/intentresolver/contentpreview/MimetypeClassifierKosmos.kt @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.intentresolver.contentpreview + +import com.android.systemui.kosmos.Kosmos + +var Kosmos.mimetypeClassifier: MimeTypeClassifier by Kosmos.Fixture { DefaultMimeTypeClassifier } diff --git a/tests/shared/src/com/android/intentresolver/contentpreview/UriMetadataReaderKosmos.kt b/tests/shared/src/com/android/intentresolver/contentpreview/UriMetadataReaderKosmos.kt new file mode 100644 index 00000000..bdee477d --- /dev/null +++ b/tests/shared/src/com/android/intentresolver/contentpreview/UriMetadataReaderKosmos.kt @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.intentresolver.contentpreview + +import com.android.intentresolver.contentInterface +import com.android.systemui.kosmos.Kosmos + +var Kosmos.uriMetadataReader: UriMetadataReader by Kosmos.Fixture { uriMetadataReaderImpl } +val Kosmos.uriMetadataReaderImpl + get() = + UriMetadataReaderImpl( + contentInterface, + mimetypeClassifier, + ) diff --git a/tests/shared/src/com/android/intentresolver/contentpreview/payloadtoggle/data/repository/PayloadToggleRepoKosmos.kt b/tests/shared/src/com/android/intentresolver/contentpreview/payloadtoggle/data/repository/PayloadToggleRepoKosmos.kt new file mode 100644 index 00000000..894ef163 --- /dev/null +++ b/tests/shared/src/com/android/intentresolver/contentpreview/payloadtoggle/data/repository/PayloadToggleRepoKosmos.kt @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.intentresolver.contentpreview.payloadtoggle.data.repository + +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.kosmos.Kosmos.Fixture + +val Kosmos.activityResultRepository by Fixture { ActivityResultRepository() } +val Kosmos.cursorPreviewsRepository by Fixture { CursorPreviewsRepository() } +val Kosmos.pendingSelectionCallbackRepository by Fixture { PendingSelectionCallbackRepository() } +val Kosmos.previewSelectionsRepository by Fixture { PreviewSelectionsRepository() } diff --git a/tests/shared/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/cursor/CursorResolverKosmos.kt b/tests/shared/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/cursor/CursorResolverKosmos.kt new file mode 100644 index 00000000..10b89c71 --- /dev/null +++ b/tests/shared/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/cursor/CursorResolverKosmos.kt @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.intentresolver.contentpreview.payloadtoggle.domain.cursor + +import android.net.Uri +import com.android.intentresolver.contentResolver +import com.android.intentresolver.inject.additionalContentUri +import com.android.intentresolver.inject.chooserIntent +import com.android.systemui.kosmos.Kosmos + +var Kosmos.payloadToggleCursorResolver: CursorResolver<Uri?> by + Kosmos.Fixture { payloadToggleCursorResolverImpl } +val Kosmos.payloadToggleCursorResolverImpl + get() = + PayloadToggleCursorResolver( + contentResolver, + additionalContentUri, + chooserIntent, + ) diff --git a/tests/shared/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/intent/PendingIntentSenderKosmos.kt b/tests/shared/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/intent/PendingIntentSenderKosmos.kt new file mode 100644 index 00000000..f022373d --- /dev/null +++ b/tests/shared/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/intent/PendingIntentSenderKosmos.kt @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.intentresolver.contentpreview.payloadtoggle.domain.intent + +import com.android.intentresolver.mock +import com.android.systemui.kosmos.Kosmos + +var Kosmos.pendingIntentSender by Kosmos.Fixture { mock<PendingIntentSender> {} } diff --git a/tests/shared/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/intent/TargetIntentModifierKosmos.kt b/tests/shared/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/intent/TargetIntentModifierKosmos.kt new file mode 100644 index 00000000..29e11a15 --- /dev/null +++ b/tests/shared/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/intent/TargetIntentModifierKosmos.kt @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.intentresolver.contentpreview.payloadtoggle.domain.intent + +import com.android.intentresolver.contentpreview.payloadtoggle.shared.model.PreviewModel +import com.android.systemui.kosmos.Kosmos + +var Kosmos.targetIntentModifier: TargetIntentModifier<PreviewModel> by Kosmos.Fixture() diff --git a/tests/shared/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/interactor/PayloadToggleInteractorKosmos.kt b/tests/shared/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/interactor/PayloadToggleInteractorKosmos.kt new file mode 100644 index 00000000..9e34acff --- /dev/null +++ b/tests/shared/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/interactor/PayloadToggleInteractorKosmos.kt @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.intentresolver.contentpreview.payloadtoggle.domain.interactor + +import com.android.intentresolver.backgroundDispatcher +import com.android.intentresolver.contentResolver +import com.android.intentresolver.contentpreview.HeadlineGenerator +import com.android.intentresolver.contentpreview.ImageLoader +import com.android.intentresolver.contentpreview.payloadtoggle.data.repository.activityResultRepository +import com.android.intentresolver.contentpreview.payloadtoggle.data.repository.cursorPreviewsRepository +import com.android.intentresolver.contentpreview.payloadtoggle.data.repository.pendingSelectionCallbackRepository +import com.android.intentresolver.contentpreview.payloadtoggle.data.repository.previewSelectionsRepository +import com.android.intentresolver.contentpreview.payloadtoggle.domain.cursor.payloadToggleCursorResolver +import com.android.intentresolver.contentpreview.payloadtoggle.domain.intent.pendingIntentSender +import com.android.intentresolver.contentpreview.payloadtoggle.domain.intent.targetIntentModifier +import com.android.intentresolver.contentpreview.payloadtoggle.domain.update.selectionChangeCallback +import com.android.intentresolver.contentpreview.uriMetadataReader +import com.android.intentresolver.inject.contentUris +import com.android.intentresolver.logging.eventLog +import com.android.intentresolver.packageManager +import com.android.intentresolver.v2.data.repository.chooserRequestRepository +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.kosmos.Kosmos.Fixture + +var Kosmos.focusedItemIndex: Int by Fixture { 0 } +var Kosmos.pageSize: Int by Fixture { 16 } +var Kosmos.maxLoadedPages: Int by Fixture { 3 } + +val Kosmos.chooserRequestInteractor + get() = ChooserRequestInteractor(chooserRequestRepository) + +val Kosmos.cursorPreviewsInteractor + get() = + CursorPreviewsInteractor( + interactor = setCursorPreviewsInteractor, + focusedItemIdx = focusedItemIndex, + uriMetadataReader = uriMetadataReader, + pageSize = pageSize, + maxLoadedPages = maxLoadedPages, + ) + +val Kosmos.customActionsInteractor + get() = + CustomActionsInteractor( + activityResultRepo = activityResultRepository, + bgDispatcher = backgroundDispatcher, + contentResolver = contentResolver, + eventLog = eventLog, + packageManager = packageManager, + chooserRequestInteractor = chooserRequestInteractor, + ) + +val Kosmos.fetchPreviewsInteractor + get() = + FetchPreviewsInteractor( + setCursorPreviews = setCursorPreviewsInteractor, + selectionRepository = previewSelectionsRepository, + cursorInteractor = cursorPreviewsInteractor, + focusedItemIdx = focusedItemIndex, + selectedItems = contentUris, + uriMetadataReader = uriMetadataReader, + cursorResolver = payloadToggleCursorResolver, + ) + +val Kosmos.processTargetIntentUpdatesInteractor + get() = + ProcessTargetIntentUpdatesInteractor( + selectionCallback = selectionChangeCallback, + repository = pendingSelectionCallbackRepository, + chooserRequestInteractor = updateChooserRequestInteractor, + ) + +val Kosmos.selectablePreviewsInteractor + get() = + SelectablePreviewsInteractor( + previewsRepo = cursorPreviewsRepository, + selectionInteractor = selectionInteractor, + ) + +val Kosmos.selectionInteractor + get() = + SelectionInteractor( + selectionsRepo = previewSelectionsRepository, + targetIntentModifier = targetIntentModifier, + updateTargetIntentInteractor = updateTargetIntentInteractor, + ) + +val Kosmos.setCursorPreviewsInteractor + get() = SetCursorPreviewsInteractor(previewsRepo = cursorPreviewsRepository) + +val Kosmos.updateChooserRequestInteractor + get() = + UpdateChooserRequestInteractor( + chooserRequestRepository, + pendingIntentSender, + ) + +val Kosmos.updateTargetIntentInteractor + get() = + UpdateTargetIntentInteractor( + repository = pendingSelectionCallbackRepository, + chooserRequestInteractor = updateChooserRequestInteractor, + ) + +var Kosmos.payloadToggleImageLoader: ImageLoader by Fixture() +var Kosmos.headlineGenerator: HeadlineGenerator by Fixture() diff --git a/tests/shared/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/update/SelectionChangeCallbackKosmos.kt b/tests/shared/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/update/SelectionChangeCallbackKosmos.kt new file mode 100644 index 00000000..548b1f37 --- /dev/null +++ b/tests/shared/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/update/SelectionChangeCallbackKosmos.kt @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.intentresolver.contentpreview.payloadtoggle.domain.update + +import com.android.intentresolver.contentInterface +import com.android.intentresolver.inject.additionalContentUri +import com.android.intentresolver.inject.chooserIntent +import com.android.intentresolver.inject.chooserServiceFlags +import com.android.systemui.kosmos.Kosmos + +val Kosmos.selectionChangeCallbackImpl by + Kosmos.Fixture { + SelectionChangeCallbackImpl( + additionalContentUri, + chooserIntent, + contentInterface, + chooserServiceFlags, + ) + } +var Kosmos.selectionChangeCallback: SelectionChangeCallback by + Kosmos.Fixture { selectionChangeCallbackImpl } diff --git a/tests/shared/src/com/android/intentresolver/inject/ActivityModelKosmos.kt b/tests/shared/src/com/android/intentresolver/inject/ActivityModelKosmos.kt new file mode 100644 index 00000000..9944163b --- /dev/null +++ b/tests/shared/src/com/android/intentresolver/inject/ActivityModelKosmos.kt @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.intentresolver.inject + +import android.content.Intent +import android.net.Uri +import com.android.systemui.kosmos.Kosmos + +var Kosmos.contentUris: List<Uri> by Kosmos.Fixture { emptyList() } +var Kosmos.additionalContentUri: Uri by + Kosmos.Fixture { Uri.fromParts("scheme", "ssp", "fragment") } +var Kosmos.chooserIntent: Intent by Kosmos.Fixture { Intent() } diff --git a/tests/shared/src/com/android/intentresolver/inject/ChooserServiceFlagsKosmos.kt b/tests/shared/src/com/android/intentresolver/inject/ChooserServiceFlagsKosmos.kt new file mode 100644 index 00000000..51dad82a --- /dev/null +++ b/tests/shared/src/com/android/intentresolver/inject/ChooserServiceFlagsKosmos.kt @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.intentresolver.inject + +import android.service.chooser.FeatureFlagsImpl +import com.android.systemui.kosmos.Kosmos + +var Kosmos.chooserServiceFlags: ChooserServiceFlags by Kosmos.Fixture { chooserServiceFlagsImpl } +val chooserServiceFlagsImpl: FeatureFlagsImpl + get() = FeatureFlagsImpl() diff --git a/tests/shared/src/com/android/intentresolver/logging/EventLogKosmos.kt b/tests/shared/src/com/android/intentresolver/logging/EventLogKosmos.kt new file mode 100644 index 00000000..5bf3ddee --- /dev/null +++ b/tests/shared/src/com/android/intentresolver/logging/EventLogKosmos.kt @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.intentresolver.logging + +import com.android.internal.logging.InstanceId +import com.android.systemui.kosmos.Kosmos + +var Kosmos.eventLog by Kosmos.Fixture { fakeEventLog } +var Kosmos.fakeEventLog by Kosmos.Fixture { FakeEventLog(InstanceId.fakeInstanceId(0)) } diff --git a/tests/unit/src/com/android/intentresolver/v2/data/model/FakeChooserRequest.kt b/tests/shared/src/com/android/intentresolver/v2/data/model/FakeChooserRequest.kt index 559e3b77..e697a13d 100644 --- a/tests/unit/src/com/android/intentresolver/v2/data/model/FakeChooserRequest.kt +++ b/tests/shared/src/com/android/intentresolver/v2/data/model/FakeChooserRequest.kt @@ -23,4 +23,4 @@ fun fakeChooserRequest( intent: Intent = Intent(), packageName: String = "pkg", referrer: Uri? = null, -) = ChooserRequest(intent, packageName, null) +) = ChooserRequest(intent, packageName, referrer) diff --git a/tests/shared/src/com/android/intentresolver/v2/data/repository/V2RepositoryKosmos.kt b/tests/shared/src/com/android/intentresolver/v2/data/repository/V2RepositoryKosmos.kt new file mode 100644 index 00000000..ec6b2dec --- /dev/null +++ b/tests/shared/src/com/android/intentresolver/v2/data/repository/V2RepositoryKosmos.kt @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.intentresolver.v2.data.repository + +import com.android.intentresolver.v2.data.model.fakeChooserRequest +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.kosmos.Kosmos.Fixture + +var Kosmos.chooserRequestRepository by Fixture { + ChooserRequestRepository(fakeChooserRequest(), emptyList()) +} diff --git a/tests/unit/Android.bp b/tests/unit/Android.bp index 78d32ae7..2c3c7910 100644 --- a/tests/unit/Android.bp +++ b/tests/unit/Android.bp @@ -51,6 +51,7 @@ android_test { "IntentResolver-core", "IntentResolver-tests-shared", "junit", + "kosmos", "kotlinx_coroutines_test", "mockito-target-minus-junit4", "mockito-kotlin2", diff --git a/tests/unit/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/interactor/CursorPreviewsInteractorTest.kt b/tests/unit/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/interactor/CursorPreviewsInteractorTest.kt index b2d9be94..af6de833 100644 --- a/tests/unit/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/interactor/CursorPreviewsInteractorTest.kt +++ b/tests/unit/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/interactor/CursorPreviewsInteractorTest.kt @@ -22,15 +22,17 @@ import android.database.MatrixCursor import android.net.Uri import androidx.core.os.bundleOf import com.android.intentresolver.contentpreview.FileInfo -import com.android.intentresolver.contentpreview.payloadtoggle.data.repository.CursorPreviewsRepository +import com.android.intentresolver.contentpreview.UriMetadataReader +import com.android.intentresolver.contentpreview.payloadtoggle.data.repository.cursorPreviewsRepository import com.android.intentresolver.contentpreview.payloadtoggle.shared.model.PreviewModel +import com.android.intentresolver.contentpreview.uriMetadataReader +import com.android.intentresolver.util.KosmosTestScope import com.android.intentresolver.util.cursor.viewBy +import com.android.intentresolver.util.runTest +import com.android.systemui.kosmos.Kosmos import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.launch -import kotlinx.coroutines.test.TestScope -import kotlinx.coroutines.test.runCurrent -import kotlinx.coroutines.test.runTest import org.junit.Test class CursorPreviewsInteractorTest { @@ -42,27 +44,31 @@ class CursorPreviewsInteractorTest { cursorStartPosition: Int = cursor.count() / 2, pageSize: Int = 16, maxLoadedPages: Int = 3, - block: TestScope.(TestDeps) -> Unit, - ): Unit = runTest { - block( - TestDeps( - initialSelection, - focusedItemIndex, - cursor, - cursorStartPosition, - pageSize, - maxLoadedPages, - ) - ) + block: KosmosTestScope.(TestDeps) -> Unit, + ) { + with(Kosmos()) { + this.focusedItemIndex = focusedItemIndex + this.pageSize = pageSize + this.maxLoadedPages = maxLoadedPages + uriMetadataReader = UriMetadataReader { + FileInfo.Builder(it).withMimeType("image/bitmap").build() + } + runTest { + block( + TestDeps( + initialSelection, + cursor, + cursorStartPosition, + ) + ) + } + } } private class TestDeps( initialSelectionRange: Iterable<Int>, - focusedItemIndex: Int, private val cursorRange: Iterable<Int>, private val cursorStartPosition: Int, - pageSize: Int, - maxLoadedPages: Int, ) { val cursor = MatrixCursor(arrayOf("uri")) @@ -73,15 +79,6 @@ class CursorPreviewsInteractorTest { } } .viewBy { getString(0)?.let(Uri::parse) } - val previewsRepo = CursorPreviewsRepository() - val underTest = - CursorPreviewsInteractor( - interactor = SetCursorPreviewsInteractor(previewsRepo = previewsRepo), - focusedItemIdx = focusedItemIndex, - uriMetadataReader = { FileInfo.Builder(it).withMimeType("image/bitmap").build() }, - pageSize = pageSize, - maxLoadedPages = maxLoadedPages, - ) val initialPreviews: List<PreviewModel> = initialSelectionRange.map { i -> PreviewModel(uri = uri(i), mimeType = "image/bitmap") } @@ -90,14 +87,16 @@ class CursorPreviewsInteractorTest { @Test fun initialCursorLoad() = runTestWithDeps { deps -> - backgroundScope.launch { deps.underTest.launch(deps.cursor, deps.initialPreviews) } + backgroundScope.launch { + cursorPreviewsInteractor.launch(deps.cursor, deps.initialPreviews) + } runCurrent() - assertThat(deps.previewsRepo.previewsModel.value).isNotNull() - assertThat(deps.previewsRepo.previewsModel.value!!.startIdx).isEqualTo(0) - assertThat(deps.previewsRepo.previewsModel.value!!.loadMoreLeft).isNull() - assertThat(deps.previewsRepo.previewsModel.value!!.loadMoreRight).isNull() - assertThat(deps.previewsRepo.previewsModel.value!!.previewModels) + assertThat(cursorPreviewsRepository.previewsModel.value).isNotNull() + assertThat(cursorPreviewsRepository.previewsModel.value!!.startIdx).isEqualTo(0) + assertThat(cursorPreviewsRepository.previewsModel.value!!.loadMoreLeft).isNull() + assertThat(cursorPreviewsRepository.previewsModel.value!!.loadMoreRight).isNull() + assertThat(cursorPreviewsRepository.previewsModel.value!!.previewModels) .containsExactly( PreviewModel(Uri.fromParts("scheme0", "ssp0", "fragment0"), "image/bitmap"), PreviewModel(Uri.fromParts("scheme1", "ssp1", "fragment1"), "image/bitmap"), @@ -115,27 +114,29 @@ class CursorPreviewsInteractorTest { pageSize = 16, maxLoadedPages = 1, ) { deps -> - backgroundScope.launch { deps.underTest.launch(deps.cursor, deps.initialPreviews) } + backgroundScope.launch { + cursorPreviewsInteractor.launch(deps.cursor, deps.initialPreviews) + } runCurrent() - assertThat(deps.previewsRepo.previewsModel.value).isNotNull() - assertThat(deps.previewsRepo.previewsModel.value!!.previewModels).hasSize(16) - assertThat(deps.previewsRepo.previewsModel.value!!.previewModels.first().uri) + assertThat(cursorPreviewsRepository.previewsModel.value).isNotNull() + assertThat(cursorPreviewsRepository.previewsModel.value!!.previewModels).hasSize(16) + assertThat(cursorPreviewsRepository.previewsModel.value!!.previewModels.first().uri) .isEqualTo(Uri.fromParts("scheme16", "ssp16", "fragment16")) - assertThat(deps.previewsRepo.previewsModel.value!!.previewModels.last().uri) + assertThat(cursorPreviewsRepository.previewsModel.value!!.previewModels.last().uri) .isEqualTo(Uri.fromParts("scheme31", "ssp31", "fragment31")) - assertThat(deps.previewsRepo.previewsModel.value!!.loadMoreLeft).isNotNull() + assertThat(cursorPreviewsRepository.previewsModel.value!!.loadMoreLeft).isNotNull() - deps.previewsRepo.previewsModel.value!!.loadMoreLeft!!.invoke() + cursorPreviewsRepository.previewsModel.value!!.loadMoreLeft!!.invoke() runCurrent() - assertThat(deps.previewsRepo.previewsModel.value).isNotNull() - assertThat(deps.previewsRepo.previewsModel.value!!.previewModels).hasSize(16) - assertThat(deps.previewsRepo.previewsModel.value!!.previewModels.first().uri) + assertThat(cursorPreviewsRepository.previewsModel.value).isNotNull() + assertThat(cursorPreviewsRepository.previewsModel.value!!.previewModels).hasSize(16) + assertThat(cursorPreviewsRepository.previewsModel.value!!.previewModels.first().uri) .isEqualTo(Uri.fromParts("scheme0", "ssp0", "fragment0")) - assertThat(deps.previewsRepo.previewsModel.value!!.previewModels.last().uri) + assertThat(cursorPreviewsRepository.previewsModel.value!!.previewModels.last().uri) .isEqualTo(Uri.fromParts("scheme15", "ssp15", "fragment15")) - assertThat(deps.previewsRepo.previewsModel.value!!.loadMoreLeft).isNull() + assertThat(cursorPreviewsRepository.previewsModel.value!!.loadMoreLeft).isNull() } @Test @@ -146,27 +147,29 @@ class CursorPreviewsInteractorTest { pageSize = 16, maxLoadedPages = 2, ) { deps -> - backgroundScope.launch { deps.underTest.launch(deps.cursor, deps.initialPreviews) } + backgroundScope.launch { + cursorPreviewsInteractor.launch(deps.cursor, deps.initialPreviews) + } runCurrent() - assertThat(deps.previewsRepo.previewsModel.value).isNotNull() - assertThat(deps.previewsRepo.previewsModel.value!!.previewModels).hasSize(16) - assertThat(deps.previewsRepo.previewsModel.value!!.previewModels.first().uri) + assertThat(cursorPreviewsRepository.previewsModel.value).isNotNull() + assertThat(cursorPreviewsRepository.previewsModel.value!!.previewModels).hasSize(16) + assertThat(cursorPreviewsRepository.previewsModel.value!!.previewModels.first().uri) .isEqualTo(Uri.fromParts("scheme16", "ssp16", "fragment16")) - assertThat(deps.previewsRepo.previewsModel.value!!.previewModels.last().uri) + assertThat(cursorPreviewsRepository.previewsModel.value!!.previewModels.last().uri) .isEqualTo(Uri.fromParts("scheme31", "ssp31", "fragment31")) - assertThat(deps.previewsRepo.previewsModel.value!!.loadMoreLeft).isNotNull() + assertThat(cursorPreviewsRepository.previewsModel.value!!.loadMoreLeft).isNotNull() - deps.previewsRepo.previewsModel.value!!.loadMoreLeft!!.invoke() + cursorPreviewsRepository.previewsModel.value!!.loadMoreLeft!!.invoke() runCurrent() - assertThat(deps.previewsRepo.previewsModel.value).isNotNull() - assertThat(deps.previewsRepo.previewsModel.value!!.previewModels).hasSize(32) - assertThat(deps.previewsRepo.previewsModel.value!!.previewModels.first().uri) + assertThat(cursorPreviewsRepository.previewsModel.value).isNotNull() + assertThat(cursorPreviewsRepository.previewsModel.value!!.previewModels).hasSize(32) + assertThat(cursorPreviewsRepository.previewsModel.value!!.previewModels.first().uri) .isEqualTo(Uri.fromParts("scheme0", "ssp0", "fragment0")) - assertThat(deps.previewsRepo.previewsModel.value!!.previewModels.last().uri) + assertThat(cursorPreviewsRepository.previewsModel.value!!.previewModels.last().uri) .isEqualTo(Uri.fromParts("scheme31", "ssp31", "fragment31")) - assertThat(deps.previewsRepo.previewsModel.value!!.loadMoreLeft).isNull() + assertThat(cursorPreviewsRepository.previewsModel.value!!.loadMoreLeft).isNull() } @Test @@ -177,25 +180,27 @@ class CursorPreviewsInteractorTest { pageSize = 16, maxLoadedPages = 1, ) { deps -> - backgroundScope.launch { deps.underTest.launch(deps.cursor, deps.initialPreviews) } + backgroundScope.launch { + cursorPreviewsInteractor.launch(deps.cursor, deps.initialPreviews) + } runCurrent() - assertThat(deps.previewsRepo.previewsModel.value).isNotNull() - assertThat(deps.previewsRepo.previewsModel.value!!.previewModels).hasSize(16) - assertThat(deps.previewsRepo.previewsModel.value!!.previewModels.first().uri) + assertThat(cursorPreviewsRepository.previewsModel.value).isNotNull() + assertThat(cursorPreviewsRepository.previewsModel.value!!.previewModels).hasSize(16) + assertThat(cursorPreviewsRepository.previewsModel.value!!.previewModels.first().uri) .isEqualTo(Uri.fromParts("scheme16", "ssp16", "fragment16")) - assertThat(deps.previewsRepo.previewsModel.value!!.previewModels.last().uri) + assertThat(cursorPreviewsRepository.previewsModel.value!!.previewModels.last().uri) .isEqualTo(Uri.fromParts("scheme31", "ssp31", "fragment31")) - assertThat(deps.previewsRepo.previewsModel.value!!.loadMoreRight).isNotNull() + assertThat(cursorPreviewsRepository.previewsModel.value!!.loadMoreRight).isNotNull() - deps.previewsRepo.previewsModel.value!!.loadMoreRight!!.invoke() + cursorPreviewsRepository.previewsModel.value!!.loadMoreRight!!.invoke() runCurrent() - assertThat(deps.previewsRepo.previewsModel.value).isNotNull() - assertThat(deps.previewsRepo.previewsModel.value!!.previewModels).hasSize(16) - assertThat(deps.previewsRepo.previewsModel.value!!.previewModels.first().uri) + assertThat(cursorPreviewsRepository.previewsModel.value).isNotNull() + assertThat(cursorPreviewsRepository.previewsModel.value!!.previewModels).hasSize(16) + assertThat(cursorPreviewsRepository.previewsModel.value!!.previewModels.first().uri) .isEqualTo(Uri.fromParts("scheme32", "ssp32", "fragment32")) - assertThat(deps.previewsRepo.previewsModel.value!!.previewModels.last().uri) + assertThat(cursorPreviewsRepository.previewsModel.value!!.previewModels.last().uri) .isEqualTo(Uri.fromParts("scheme47", "ssp47", "fragment47")) } @@ -207,25 +212,27 @@ class CursorPreviewsInteractorTest { pageSize = 16, maxLoadedPages = 2, ) { deps -> - backgroundScope.launch { deps.underTest.launch(deps.cursor, deps.initialPreviews) } + backgroundScope.launch { + cursorPreviewsInteractor.launch(deps.cursor, deps.initialPreviews) + } runCurrent() - assertThat(deps.previewsRepo.previewsModel.value).isNotNull() - assertThat(deps.previewsRepo.previewsModel.value!!.previewModels).hasSize(16) - assertThat(deps.previewsRepo.previewsModel.value!!.previewModels.first().uri) + assertThat(cursorPreviewsRepository.previewsModel.value).isNotNull() + assertThat(cursorPreviewsRepository.previewsModel.value!!.previewModels).hasSize(16) + assertThat(cursorPreviewsRepository.previewsModel.value!!.previewModels.first().uri) .isEqualTo(Uri.fromParts("scheme16", "ssp16", "fragment16")) - assertThat(deps.previewsRepo.previewsModel.value!!.previewModels.last().uri) + assertThat(cursorPreviewsRepository.previewsModel.value!!.previewModels.last().uri) .isEqualTo(Uri.fromParts("scheme31", "ssp31", "fragment31")) - assertThat(deps.previewsRepo.previewsModel.value!!.loadMoreRight).isNotNull() + assertThat(cursorPreviewsRepository.previewsModel.value!!.loadMoreRight).isNotNull() - deps.previewsRepo.previewsModel.value!!.loadMoreRight!!.invoke() + cursorPreviewsRepository.previewsModel.value!!.loadMoreRight!!.invoke() runCurrent() - assertThat(deps.previewsRepo.previewsModel.value).isNotNull() - assertThat(deps.previewsRepo.previewsModel.value!!.previewModels).hasSize(32) - assertThat(deps.previewsRepo.previewsModel.value!!.previewModels.first().uri) + assertThat(cursorPreviewsRepository.previewsModel.value).isNotNull() + assertThat(cursorPreviewsRepository.previewsModel.value!!.previewModels).hasSize(32) + assertThat(cursorPreviewsRepository.previewsModel.value!!.previewModels.first().uri) .isEqualTo(Uri.fromParts("scheme16", "ssp16", "fragment16")) - assertThat(deps.previewsRepo.previewsModel.value!!.previewModels.last().uri) + assertThat(cursorPreviewsRepository.previewsModel.value!!.previewModels.last().uri) .isEqualTo(Uri.fromParts("scheme47", "ssp47", "fragment47")) } @@ -237,16 +244,18 @@ class CursorPreviewsInteractorTest { pageSize = 16, maxLoadedPages = 2, ) { deps -> - backgroundScope.launch { deps.underTest.launch(deps.cursor, deps.initialPreviews) } + backgroundScope.launch { + cursorPreviewsInteractor.launch(deps.cursor, deps.initialPreviews) + } runCurrent() - assertThat(deps.previewsRepo.previewsModel.value).isNotNull() - assertThat(deps.previewsRepo.previewsModel.value!!.previewModels).hasSize(2) - assertThat(deps.previewsRepo.previewsModel.value!!.previewModels.first().uri) + assertThat(cursorPreviewsRepository.previewsModel.value).isNotNull() + assertThat(cursorPreviewsRepository.previewsModel.value!!.previewModels).hasSize(2) + assertThat(cursorPreviewsRepository.previewsModel.value!!.previewModels.first().uri) .isEqualTo(Uri.fromParts("scheme24", "ssp24", "fragment24")) - assertThat(deps.previewsRepo.previewsModel.value!!.previewModels.last().uri) + assertThat(cursorPreviewsRepository.previewsModel.value!!.previewModels.last().uri) .isEqualTo(Uri.fromParts("scheme50", "ssp50", "fragment50")) - assertThat(deps.previewsRepo.previewsModel.value!!.loadMoreRight).isNull() + assertThat(cursorPreviewsRepository.previewsModel.value!!.loadMoreRight).isNull() } @Test @@ -257,15 +266,17 @@ class CursorPreviewsInteractorTest { pageSize = 16, maxLoadedPages = 2, ) { deps -> - backgroundScope.launch { deps.underTest.launch(deps.cursor, deps.initialPreviews) } + backgroundScope.launch { + cursorPreviewsInteractor.launch(deps.cursor, deps.initialPreviews) + } runCurrent() - assertThat(deps.previewsRepo.previewsModel.value).isNotNull() - assertThat(deps.previewsRepo.previewsModel.value!!.previewModels).hasSize(2) - assertThat(deps.previewsRepo.previewsModel.value!!.previewModels.first().uri) + assertThat(cursorPreviewsRepository.previewsModel.value).isNotNull() + assertThat(cursorPreviewsRepository.previewsModel.value!!.previewModels).hasSize(2) + assertThat(cursorPreviewsRepository.previewsModel.value!!.previewModels.first().uri) .isEqualTo(Uri.fromParts("scheme0", "ssp0", "fragment0")) - assertThat(deps.previewsRepo.previewsModel.value!!.previewModels.last().uri) + assertThat(cursorPreviewsRepository.previewsModel.value!!.previewModels.last().uri) .isEqualTo(Uri.fromParts("scheme24", "ssp24", "fragment24")) - assertThat(deps.previewsRepo.previewsModel.value!!.loadMoreLeft).isNull() + assertThat(cursorPreviewsRepository.previewsModel.value!!.loadMoreLeft).isNull() } } diff --git a/tests/unit/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/interactor/CustomActionsInteractorTest.kt b/tests/unit/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/interactor/CustomActionsInteractorTest.kt index ceb20dab..feda8133 100644 --- a/tests/unit/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/interactor/CustomActionsInteractorTest.kt +++ b/tests/unit/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/interactor/CustomActionsInteractorTest.kt @@ -22,145 +22,96 @@ import android.app.Activity import android.graphics.Bitmap import android.graphics.drawable.Icon import com.android.intentresolver.contentpreview.payloadtoggle.data.model.CustomActionModel -import com.android.intentresolver.contentpreview.payloadtoggle.data.repository.ActivityResultRepository +import com.android.intentresolver.contentpreview.payloadtoggle.data.repository.activityResultRepository import com.android.intentresolver.contentpreview.payloadtoggle.domain.model.ActionModel import com.android.intentresolver.icon.BitmapIcon -import com.android.intentresolver.mock import com.android.intentresolver.util.comparingElementsUsingTransform +import com.android.intentresolver.util.runKosmosTest import com.android.intentresolver.v2.data.model.fakeChooserRequest import com.android.intentresolver.v2.data.repository.ChooserRequestRepository +import com.android.intentresolver.v2.data.repository.chooserRequestRepository import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.stateIn -import kotlinx.coroutines.test.StandardTestDispatcher -import kotlinx.coroutines.test.runCurrent -import kotlinx.coroutines.test.runTest import org.junit.Test class CustomActionsInteractorTest { - private val testDispatcher = StandardTestDispatcher() - @Test - fun customActions_initialRepoValue() = - runTest(testDispatcher) { - val bitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ALPHA_8) - val icon = Icon.createWithBitmap(bitmap) - val chooserRequestRepository = - ChooserRequestRepository( - initialRequest = fakeChooserRequest(), - initialActions = - listOf( - CustomActionModel(label = "label1", icon = icon, performAction = {}), - ), - ) - val underTest = - CustomActionsInteractor( - activityResultRepo = ActivityResultRepository(), - bgDispatcher = testDispatcher, - contentResolver = mock {}, - eventLog = mock {}, - packageManager = mock {}, - chooserRequestInteractor = - ChooserRequestInteractor(repository = chooserRequestRepository), - ) - val customActions: StateFlow<List<ActionModel>> = - underTest.customActions.stateIn(backgroundScope) - assertThat(customActions.value) - .comparingElementsUsingTransform("has a label of") { model: ActionModel -> - model.label - } - .containsExactly("label1") - .inOrder() - assertThat(customActions.value) - .comparingElementsUsingTransform("has an icon of") { model: ActionModel -> - model.icon - } - .containsExactly(BitmapIcon(icon.bitmap)) - .inOrder() - } + fun customActions_initialRepoValue() = runKosmosTest { + val bitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ALPHA_8) + val icon = Icon.createWithBitmap(bitmap) + chooserRequestRepository = + ChooserRequestRepository( + initialRequest = fakeChooserRequest(), + initialActions = + listOf( + CustomActionModel(label = "label1", icon = icon, performAction = {}), + ), + ) + val underTest = customActionsInteractor + val customActions: StateFlow<List<ActionModel>> = + underTest.customActions.stateIn(backgroundScope) + assertThat(customActions.value) + .comparingElementsUsingTransform("has a label of") { model: ActionModel -> model.label } + .containsExactly("label1") + .inOrder() + assertThat(customActions.value) + .comparingElementsUsingTransform("has an icon of") { model: ActionModel -> model.icon } + .containsExactly(BitmapIcon(icon.bitmap)) + .inOrder() + } @Test - fun customActions_tracksRepoUpdates() = - runTest(testDispatcher) { - val chooserRequestRepository = - ChooserRequestRepository( - initialRequest = fakeChooserRequest(), - initialActions = emptyList(), - ) - val underTest = - CustomActionsInteractor( - activityResultRepo = ActivityResultRepository(), - bgDispatcher = testDispatcher, - contentResolver = mock {}, - eventLog = mock {}, - packageManager = mock {}, - chooserRequestInteractor = - ChooserRequestInteractor(repository = chooserRequestRepository), - ) + fun customActions_tracksRepoUpdates() = runKosmosTest { + val underTest = customActionsInteractor - val customActions: StateFlow<List<ActionModel>> = - underTest.customActions.stateIn(backgroundScope) - val bitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ALPHA_8) - val icon = Icon.createWithBitmap(bitmap) - val chooserActions = listOf(CustomActionModel("label1", icon) {}) - chooserRequestRepository.customActions.value = chooserActions - runCurrent() + val customActions: StateFlow<List<ActionModel>> = + underTest.customActions.stateIn(backgroundScope) + val bitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ALPHA_8) + val icon = Icon.createWithBitmap(bitmap) + val chooserActions = listOf(CustomActionModel("label1", icon) {}) + chooserRequestRepository.customActions.value = chooserActions + runCurrent() - assertThat(customActions.value) - .comparingElementsUsingTransform("has a label of") { model: ActionModel -> - model.label - } - .containsExactly("label1") - .inOrder() - assertThat(customActions.value) - .comparingElementsUsingTransform("has an icon of") { model: ActionModel -> - model.icon - } - .containsExactly(BitmapIcon(icon.bitmap)) - .inOrder() - } + assertThat(customActions.value) + .comparingElementsUsingTransform("has a label of") { model: ActionModel -> model.label } + .containsExactly("label1") + .inOrder() + assertThat(customActions.value) + .comparingElementsUsingTransform("has an icon of") { model: ActionModel -> model.icon } + .containsExactly(BitmapIcon(icon.bitmap)) + .inOrder() + } @Test - fun customActions_performAction_sendsPendingIntent() = - runTest(testDispatcher) { - val bitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ALPHA_8) - val icon = Icon.createWithBitmap(bitmap) - var actionSent = false - val activityResultRepository = ActivityResultRepository() - val chooserRequestRepository = - ChooserRequestRepository( - initialRequest = fakeChooserRequest(), - initialActions = - listOf( - CustomActionModel( - label = "label1", - icon = icon, - performAction = { actionSent = true }, - ) - ), - ) - val underTest = - CustomActionsInteractor( - activityResultRepo = activityResultRepository, - bgDispatcher = testDispatcher, - contentResolver = mock {}, - eventLog = mock {}, - packageManager = mock {}, - chooserRequestInteractor = - ChooserRequestInteractor( - repository = chooserRequestRepository, - ), - ) - val customActions: StateFlow<List<ActionModel>> = - underTest.customActions.stateIn(backgroundScope) + fun customActions_performAction_sendsPendingIntent() = runKosmosTest { + val bitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ALPHA_8) + val icon = Icon.createWithBitmap(bitmap) + var actionSent = false + chooserRequestRepository = + ChooserRequestRepository( + initialRequest = fakeChooserRequest(), + initialActions = + listOf( + CustomActionModel( + label = "label1", + icon = icon, + performAction = { actionSent = true }, + ) + ), + ) + val underTest = customActionsInteractor + + val customActions: StateFlow<List<ActionModel>> = + underTest.customActions.stateIn(backgroundScope) - assertThat(customActions.value).hasSize(1) + assertThat(customActions.value).hasSize(1) - customActions.value[0].performAction(123) + customActions.value[0].performAction(123) - assertThat(actionSent).isTrue() - assertThat(activityResultRepository.activityResult.value).isEqualTo(Activity.RESULT_OK) - } + assertThat(actionSent).isTrue() + assertThat(activityResultRepository.activityResult.value).isEqualTo(Activity.RESULT_OK) + } } diff --git a/tests/unit/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/interactor/FetchPreviewsInteractorTest.kt b/tests/unit/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/interactor/FetchPreviewsInteractorTest.kt index 08a667b9..f012fcc6 100644 --- a/tests/unit/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/interactor/FetchPreviewsInteractorTest.kt +++ b/tests/unit/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/interactor/FetchPreviewsInteractorTest.kt @@ -23,108 +23,81 @@ import android.net.Uri import androidx.core.os.bundleOf import com.android.intentresolver.contentpreview.FileInfo import com.android.intentresolver.contentpreview.UriMetadataReader -import com.android.intentresolver.contentpreview.payloadtoggle.data.repository.CursorPreviewsRepository -import com.android.intentresolver.contentpreview.payloadtoggle.data.repository.PreviewSelectionsRepository +import com.android.intentresolver.contentpreview.payloadtoggle.data.repository.cursorPreviewsRepository import com.android.intentresolver.contentpreview.payloadtoggle.domain.cursor.CursorResolver +import com.android.intentresolver.contentpreview.payloadtoggle.domain.cursor.payloadToggleCursorResolver import com.android.intentresolver.contentpreview.payloadtoggle.shared.model.PreviewModel import com.android.intentresolver.contentpreview.payloadtoggle.shared.model.PreviewsModel +import com.android.intentresolver.contentpreview.uriMetadataReader +import com.android.intentresolver.inject.contentUris +import com.android.intentresolver.util.KosmosTestScope import com.android.intentresolver.util.cursor.CursorView import com.android.intentresolver.util.cursor.viewBy +import com.android.intentresolver.util.runTest as runKosmosTest +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.kosmos.Kosmos.Fixture import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.launch import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock -import kotlinx.coroutines.test.TestScope -import kotlinx.coroutines.test.runCurrent -import kotlinx.coroutines.test.runTest import org.junit.Test class FetchPreviewsInteractorTest { - private fun runTestWithDeps( + private fun runTest( initialSelection: Iterable<Int> = (1..2), focusedItemIndex: Int = initialSelection.count() / 2, cursor: Iterable<Int> = (0 until 4), cursorStartPosition: Int = cursor.count() / 2, pageSize: Int = 16, maxLoadedPages: Int = 3, - block: TestScope.(TestDeps) -> Unit, - ): Unit = runTest { - block( - TestDeps( - initialSelection, - focusedItemIndex, - cursor, - cursorStartPosition, - pageSize, - maxLoadedPages, - ) - ) - } - - private class TestDeps( - initialSelectionRange: Iterable<Int>, - focusedItemIndex: Int, - private val cursorRange: Iterable<Int>, - private val cursorStartPosition: Int, - pageSize: Int, - maxLoadedPages: Int, + block: KosmosTestScope.() -> Unit, ) { - - private fun uri(index: Int) = Uri.fromParts("scheme$index", "ssp$index", "fragment$index") - - val previewsRepo = CursorPreviewsRepository() - - val cursorResolver = FakeCursorResolver() - - private val uriMetadataReader = UriMetadataReader { - FileInfo.Builder(it).withMimeType("image/bitmap").build() + with(Kosmos()) { + fakeCursorResolver = + FakeCursorResolver(cursorRange = cursor, cursorStartPosition = cursorStartPosition) + payloadToggleCursorResolver = fakeCursorResolver + contentUris = initialSelection.map { uri(it) } + this.focusedItemIndex = focusedItemIndex + uriMetadataReader = UriMetadataReader { + FileInfo.Builder(it).withMimeType("image/bitmap").build() + } + this.pageSize = pageSize + this.maxLoadedPages = maxLoadedPages + runKosmosTest { block() } } + } - val underTest = - FetchPreviewsInteractor( - setCursorPreviews = SetCursorPreviewsInteractor(previewsRepo), - selectionRepository = PreviewSelectionsRepository(), - cursorInteractor = - CursorPreviewsInteractor( - interactor = SetCursorPreviewsInteractor(previewsRepo = previewsRepo), - focusedItemIdx = focusedItemIndex, - uriMetadataReader = uriMetadataReader, - pageSize = pageSize, - maxLoadedPages = maxLoadedPages, - ), - focusedItemIdx = focusedItemIndex, - selectedItems = initialSelectionRange.map { idx -> uri(idx) }, - uriMetadataReader = uriMetadataReader, - cursorResolver = cursorResolver, - ) - - inner class FakeCursorResolver : CursorResolver<Uri?> { - private val mutex = Mutex(locked = true) - - fun complete() = mutex.unlock() + private var Kosmos.fakeCursorResolver: FakeCursorResolver by Fixture() - override suspend fun getCursor(): CursorView<Uri?> = - mutex.withLock { - MatrixCursor(arrayOf("uri")) - .apply { - extras = bundleOf("position" to cursorStartPosition) - for (i in cursorRange) { - newRow().add("uri", uri(i).toString()) - } + private class FakeCursorResolver( + private val cursorRange: Iterable<Int>, + private val cursorStartPosition: Int, + ) : CursorResolver<Uri?> { + private val mutex = Mutex(locked = true) + + fun complete() = mutex.unlock() + + override suspend fun getCursor(): CursorView<Uri?> = + mutex.withLock { + MatrixCursor(arrayOf("uri")) + .apply { + extras = bundleOf("position" to cursorStartPosition) + for (i in cursorRange) { + newRow().add("uri", uri(i).toString()) } - .viewBy { getString(0)?.let(Uri::parse) } - } - } + } + .viewBy { getString(0)?.let(Uri::parse) } + } } @Test - fun setsInitialPreviews() = runTestWithDeps { deps -> - backgroundScope.launch { deps.underTest.activate() } + fun setsInitialPreviews() = runTest { + backgroundScope.launch { fetchPreviewsInteractor.activate() } runCurrent() - assertThat(deps.previewsRepo.previewsModel.value) + assertThat(cursorPreviewsRepository.previewsModel.value) .isEqualTo( PreviewsModel( previewModels = @@ -146,190 +119,198 @@ class FetchPreviewsInteractorTest { } @Test - fun lookupCursorFromContentResolver() = runTestWithDeps { deps -> - backgroundScope.launch { deps.underTest.activate() } - deps.cursorResolver.complete() + fun lookupCursorFromContentResolver() = runTest { + backgroundScope.launch { fetchPreviewsInteractor.activate() } + fakeCursorResolver.complete() runCurrent() - assertThat(deps.previewsRepo.previewsModel.value).isNotNull() - assertThat(deps.previewsRepo.previewsModel.value!!.startIdx).isEqualTo(0) - assertThat(deps.previewsRepo.previewsModel.value!!.loadMoreLeft).isNull() - assertThat(deps.previewsRepo.previewsModel.value!!.loadMoreRight).isNull() - assertThat(deps.previewsRepo.previewsModel.value!!.previewModels) - .containsExactly( - PreviewModel(Uri.fromParts("scheme0", "ssp0", "fragment0"), "image/bitmap"), - PreviewModel(Uri.fromParts("scheme1", "ssp1", "fragment1"), "image/bitmap"), - PreviewModel(Uri.fromParts("scheme2", "ssp2", "fragment2"), "image/bitmap"), - PreviewModel(Uri.fromParts("scheme3", "ssp3", "fragment3"), "image/bitmap"), - ) - .inOrder() + with(cursorPreviewsRepository) { + assertThat(previewsModel.value).isNotNull() + assertThat(previewsModel.value!!.startIdx).isEqualTo(0) + assertThat(previewsModel.value!!.loadMoreLeft).isNull() + assertThat(previewsModel.value!!.loadMoreRight).isNull() + assertThat(previewsModel.value!!.previewModels) + .containsExactly( + PreviewModel(Uri.fromParts("scheme0", "ssp0", "fragment0"), "image/bitmap"), + PreviewModel(Uri.fromParts("scheme1", "ssp1", "fragment1"), "image/bitmap"), + PreviewModel(Uri.fromParts("scheme2", "ssp2", "fragment2"), "image/bitmap"), + PreviewModel(Uri.fromParts("scheme3", "ssp3", "fragment3"), "image/bitmap"), + ) + .inOrder() + } } @Test fun loadMoreLeft_evictRight() = - runTestWithDeps( + runTest( initialSelection = listOf(24), cursor = (0 until 48), pageSize = 16, maxLoadedPages = 1, - ) { deps -> - backgroundScope.launch { deps.underTest.activate() } - deps.cursorResolver.complete() + ) { + backgroundScope.launch { fetchPreviewsInteractor.activate() } + fakeCursorResolver.complete() runCurrent() - assertThat(deps.previewsRepo.previewsModel.value).isNotNull() - assertThat(deps.previewsRepo.previewsModel.value!!.previewModels).hasSize(16) - assertThat(deps.previewsRepo.previewsModel.value!!.previewModels.first().uri) - .isEqualTo(Uri.fromParts("scheme16", "ssp16", "fragment16")) - assertThat(deps.previewsRepo.previewsModel.value!!.previewModels.last().uri) - .isEqualTo(Uri.fromParts("scheme31", "ssp31", "fragment31")) - assertThat(deps.previewsRepo.previewsModel.value!!.loadMoreLeft).isNotNull() - - deps.previewsRepo.previewsModel.value!!.loadMoreLeft!!.invoke() + with(cursorPreviewsRepository) { + assertThat(previewsModel.value).isNotNull() + assertThat(previewsModel.value!!.previewModels).hasSize(16) + assertThat(previewsModel.value!!.previewModels.first().uri) + .isEqualTo(Uri.fromParts("scheme16", "ssp16", "fragment16")) + assertThat(previewsModel.value!!.previewModels.last().uri) + .isEqualTo(Uri.fromParts("scheme31", "ssp31", "fragment31")) + assertThat(previewsModel.value!!.loadMoreLeft).isNotNull() + } + + cursorPreviewsRepository.previewsModel.value!!.loadMoreLeft!!.invoke() runCurrent() - assertThat(deps.previewsRepo.previewsModel.value).isNotNull() - assertThat(deps.previewsRepo.previewsModel.value!!.previewModels).hasSize(16) - assertThat(deps.previewsRepo.previewsModel.value!!.previewModels.first().uri) - .isEqualTo(Uri.fromParts("scheme0", "ssp0", "fragment0")) - assertThat(deps.previewsRepo.previewsModel.value!!.previewModels.last().uri) - .isEqualTo(Uri.fromParts("scheme15", "ssp15", "fragment15")) - assertThat(deps.previewsRepo.previewsModel.value!!.loadMoreLeft).isNull() + with(cursorPreviewsRepository) { + assertThat(previewsModel.value).isNotNull() + assertThat(previewsModel.value!!.previewModels).hasSize(16) + assertThat(previewsModel.value!!.previewModels.first().uri) + .isEqualTo(Uri.fromParts("scheme0", "ssp0", "fragment0")) + assertThat(previewsModel.value!!.previewModels.last().uri) + .isEqualTo(Uri.fromParts("scheme15", "ssp15", "fragment15")) + assertThat(previewsModel.value!!.loadMoreLeft).isNull() + } } @Test fun loadMoreLeft_keepRight() = - runTestWithDeps( + runTest( initialSelection = listOf(24), cursor = (0 until 48), pageSize = 16, maxLoadedPages = 2, - ) { deps -> - backgroundScope.launch { deps.underTest.activate() } - deps.cursorResolver.complete() + ) { + backgroundScope.launch { fetchPreviewsInteractor.activate() } + fakeCursorResolver.complete() runCurrent() - assertThat(deps.previewsRepo.previewsModel.value).isNotNull() - assertThat(deps.previewsRepo.previewsModel.value!!.previewModels).hasSize(16) - assertThat(deps.previewsRepo.previewsModel.value!!.previewModels.first().uri) + assertThat(cursorPreviewsRepository.previewsModel.value).isNotNull() + assertThat(cursorPreviewsRepository.previewsModel.value!!.previewModels).hasSize(16) + assertThat(cursorPreviewsRepository.previewsModel.value!!.previewModels.first().uri) .isEqualTo(Uri.fromParts("scheme16", "ssp16", "fragment16")) - assertThat(deps.previewsRepo.previewsModel.value!!.previewModels.last().uri) + assertThat(cursorPreviewsRepository.previewsModel.value!!.previewModels.last().uri) .isEqualTo(Uri.fromParts("scheme31", "ssp31", "fragment31")) - assertThat(deps.previewsRepo.previewsModel.value!!.loadMoreLeft).isNotNull() + assertThat(cursorPreviewsRepository.previewsModel.value!!.loadMoreLeft).isNotNull() - deps.previewsRepo.previewsModel.value!!.loadMoreLeft!!.invoke() + cursorPreviewsRepository.previewsModel.value!!.loadMoreLeft!!.invoke() runCurrent() - assertThat(deps.previewsRepo.previewsModel.value).isNotNull() - assertThat(deps.previewsRepo.previewsModel.value!!.previewModels).hasSize(32) - assertThat(deps.previewsRepo.previewsModel.value!!.previewModels.first().uri) + assertThat(cursorPreviewsRepository.previewsModel.value).isNotNull() + assertThat(cursorPreviewsRepository.previewsModel.value!!.previewModels).hasSize(32) + assertThat(cursorPreviewsRepository.previewsModel.value!!.previewModels.first().uri) .isEqualTo(Uri.fromParts("scheme0", "ssp0", "fragment0")) - assertThat(deps.previewsRepo.previewsModel.value!!.previewModels.last().uri) + assertThat(cursorPreviewsRepository.previewsModel.value!!.previewModels.last().uri) .isEqualTo(Uri.fromParts("scheme31", "ssp31", "fragment31")) - assertThat(deps.previewsRepo.previewsModel.value!!.loadMoreLeft).isNull() + assertThat(cursorPreviewsRepository.previewsModel.value!!.loadMoreLeft).isNull() } @Test fun loadMoreRight_evictLeft() = - runTestWithDeps( + runTest( initialSelection = listOf(24), cursor = (0 until 48), pageSize = 16, maxLoadedPages = 1, - ) { deps -> - backgroundScope.launch { deps.underTest.activate() } - deps.cursorResolver.complete() + ) { + backgroundScope.launch { fetchPreviewsInteractor.activate() } + fakeCursorResolver.complete() runCurrent() - assertThat(deps.previewsRepo.previewsModel.value).isNotNull() - assertThat(deps.previewsRepo.previewsModel.value!!.previewModels).hasSize(16) - assertThat(deps.previewsRepo.previewsModel.value!!.previewModels.first().uri) + assertThat(cursorPreviewsRepository.previewsModel.value).isNotNull() + assertThat(cursorPreviewsRepository.previewsModel.value!!.previewModels).hasSize(16) + assertThat(cursorPreviewsRepository.previewsModel.value!!.previewModels.first().uri) .isEqualTo(Uri.fromParts("scheme16", "ssp16", "fragment16")) - assertThat(deps.previewsRepo.previewsModel.value!!.previewModels.last().uri) + assertThat(cursorPreviewsRepository.previewsModel.value!!.previewModels.last().uri) .isEqualTo(Uri.fromParts("scheme31", "ssp31", "fragment31")) - assertThat(deps.previewsRepo.previewsModel.value!!.loadMoreRight).isNotNull() + assertThat(cursorPreviewsRepository.previewsModel.value!!.loadMoreRight).isNotNull() - deps.previewsRepo.previewsModel.value!!.loadMoreRight!!.invoke() + cursorPreviewsRepository.previewsModel.value!!.loadMoreRight!!.invoke() runCurrent() - assertThat(deps.previewsRepo.previewsModel.value).isNotNull() - assertThat(deps.previewsRepo.previewsModel.value!!.previewModels).hasSize(16) - assertThat(deps.previewsRepo.previewsModel.value!!.previewModels.first().uri) + assertThat(cursorPreviewsRepository.previewsModel.value).isNotNull() + assertThat(cursorPreviewsRepository.previewsModel.value!!.previewModels).hasSize(16) + assertThat(cursorPreviewsRepository.previewsModel.value!!.previewModels.first().uri) .isEqualTo(Uri.fromParts("scheme32", "ssp32", "fragment32")) - assertThat(deps.previewsRepo.previewsModel.value!!.previewModels.last().uri) + assertThat(cursorPreviewsRepository.previewsModel.value!!.previewModels.last().uri) .isEqualTo(Uri.fromParts("scheme47", "ssp47", "fragment47")) } @Test fun loadMoreRight_keepLeft() = - runTestWithDeps( + runTest( initialSelection = listOf(24), cursor = (0 until 48), pageSize = 16, maxLoadedPages = 2, - ) { deps -> - backgroundScope.launch { deps.underTest.activate() } - deps.cursorResolver.complete() + ) { + backgroundScope.launch { fetchPreviewsInteractor.activate() } + fakeCursorResolver.complete() runCurrent() - assertThat(deps.previewsRepo.previewsModel.value).isNotNull() - assertThat(deps.previewsRepo.previewsModel.value!!.previewModels).hasSize(16) - assertThat(deps.previewsRepo.previewsModel.value!!.previewModels.first().uri) + assertThat(cursorPreviewsRepository.previewsModel.value).isNotNull() + assertThat(cursorPreviewsRepository.previewsModel.value!!.previewModels).hasSize(16) + assertThat(cursorPreviewsRepository.previewsModel.value!!.previewModels.first().uri) .isEqualTo(Uri.fromParts("scheme16", "ssp16", "fragment16")) - assertThat(deps.previewsRepo.previewsModel.value!!.previewModels.last().uri) + assertThat(cursorPreviewsRepository.previewsModel.value!!.previewModels.last().uri) .isEqualTo(Uri.fromParts("scheme31", "ssp31", "fragment31")) - assertThat(deps.previewsRepo.previewsModel.value!!.loadMoreRight).isNotNull() + assertThat(cursorPreviewsRepository.previewsModel.value!!.loadMoreRight).isNotNull() - deps.previewsRepo.previewsModel.value!!.loadMoreRight!!.invoke() + cursorPreviewsRepository.previewsModel.value!!.loadMoreRight!!.invoke() runCurrent() - assertThat(deps.previewsRepo.previewsModel.value).isNotNull() - assertThat(deps.previewsRepo.previewsModel.value!!.previewModels).hasSize(32) - assertThat(deps.previewsRepo.previewsModel.value!!.previewModels.first().uri) + assertThat(cursorPreviewsRepository.previewsModel.value).isNotNull() + assertThat(cursorPreviewsRepository.previewsModel.value!!.previewModels).hasSize(32) + assertThat(cursorPreviewsRepository.previewsModel.value!!.previewModels.first().uri) .isEqualTo(Uri.fromParts("scheme16", "ssp16", "fragment16")) - assertThat(deps.previewsRepo.previewsModel.value!!.previewModels.last().uri) + assertThat(cursorPreviewsRepository.previewsModel.value!!.previewModels.last().uri) .isEqualTo(Uri.fromParts("scheme47", "ssp47", "fragment47")) } @Test fun noMoreRight_appendUnclaimedFromInitialSelection() = - runTestWithDeps( + runTest( initialSelection = listOf(24, 50), cursor = listOf(24), pageSize = 16, maxLoadedPages = 2, - ) { deps -> - backgroundScope.launch { deps.underTest.activate() } - deps.cursorResolver.complete() + ) { + backgroundScope.launch { fetchPreviewsInteractor.activate() } + fakeCursorResolver.complete() runCurrent() - assertThat(deps.previewsRepo.previewsModel.value).isNotNull() - assertThat(deps.previewsRepo.previewsModel.value!!.previewModels).hasSize(2) - assertThat(deps.previewsRepo.previewsModel.value!!.previewModels.first().uri) + assertThat(cursorPreviewsRepository.previewsModel.value).isNotNull() + assertThat(cursorPreviewsRepository.previewsModel.value!!.previewModels).hasSize(2) + assertThat(cursorPreviewsRepository.previewsModel.value!!.previewModels.first().uri) .isEqualTo(Uri.fromParts("scheme24", "ssp24", "fragment24")) - assertThat(deps.previewsRepo.previewsModel.value!!.previewModels.last().uri) + assertThat(cursorPreviewsRepository.previewsModel.value!!.previewModels.last().uri) .isEqualTo(Uri.fromParts("scheme50", "ssp50", "fragment50")) - assertThat(deps.previewsRepo.previewsModel.value!!.loadMoreRight).isNull() + assertThat(cursorPreviewsRepository.previewsModel.value!!.loadMoreRight).isNull() } @Test fun noMoreLeft_appendUnclaimedFromInitialSelection() = - runTestWithDeps( + runTest( initialSelection = listOf(0, 24), cursor = listOf(24), pageSize = 16, maxLoadedPages = 2, - ) { deps -> - backgroundScope.launch { deps.underTest.activate() } - deps.cursorResolver.complete() + ) { + backgroundScope.launch { fetchPreviewsInteractor.activate() } + fakeCursorResolver.complete() runCurrent() - assertThat(deps.previewsRepo.previewsModel.value).isNotNull() - assertThat(deps.previewsRepo.previewsModel.value!!.previewModels).hasSize(2) - assertThat(deps.previewsRepo.previewsModel.value!!.previewModels.first().uri) + assertThat(cursorPreviewsRepository.previewsModel.value).isNotNull() + assertThat(cursorPreviewsRepository.previewsModel.value!!.previewModels).hasSize(2) + assertThat(cursorPreviewsRepository.previewsModel.value!!.previewModels.first().uri) .isEqualTo(Uri.fromParts("scheme0", "ssp0", "fragment0")) - assertThat(deps.previewsRepo.previewsModel.value!!.previewModels.last().uri) + assertThat(cursorPreviewsRepository.previewsModel.value!!.previewModels.last().uri) .isEqualTo(Uri.fromParts("scheme24", "ssp24", "fragment24")) - assertThat(deps.previewsRepo.previewsModel.value!!.loadMoreLeft).isNull() + assertThat(cursorPreviewsRepository.previewsModel.value!!.loadMoreLeft).isNull() } } + +private fun uri(index: Int) = Uri.fromParts("scheme$index", "ssp$index", "fragment$index") diff --git a/tests/unit/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/interactor/SelectablePreviewInteractorTest.kt b/tests/unit/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/interactor/SelectablePreviewInteractorTest.kt index ff22f37b..c56d8026 100644 --- a/tests/unit/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/interactor/SelectablePreviewInteractorTest.kt +++ b/tests/unit/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/interactor/SelectablePreviewInteractorTest.kt @@ -20,46 +20,27 @@ package com.android.intentresolver.contentpreview.payloadtoggle.domain.interacto import android.content.Intent import android.net.Uri -import com.android.intentresolver.contentpreview.payloadtoggle.data.repository.PendingSelectionCallbackRepository -import com.android.intentresolver.contentpreview.payloadtoggle.data.repository.PreviewSelectionsRepository +import com.android.intentresolver.contentpreview.payloadtoggle.data.repository.pendingSelectionCallbackRepository +import com.android.intentresolver.contentpreview.payloadtoggle.data.repository.previewSelectionsRepository +import com.android.intentresolver.contentpreview.payloadtoggle.domain.intent.TargetIntentModifier +import com.android.intentresolver.contentpreview.payloadtoggle.domain.intent.targetIntentModifier import com.android.intentresolver.contentpreview.payloadtoggle.shared.model.PreviewModel -import com.android.intentresolver.v2.data.model.fakeChooserRequest -import com.android.intentresolver.v2.data.repository.ChooserRequestRepository +import com.android.intentresolver.util.runKosmosTest +import com.android.intentresolver.v2.data.repository.chooserRequestRepository import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.first -import kotlinx.coroutines.test.runCurrent -import kotlinx.coroutines.test.runTest import org.junit.Test class SelectablePreviewInteractorTest { @Test - fun reflectPreviewRepo_initState() = runTest { - val selectionRepo = PreviewSelectionsRepository() - val chooserRequestRepo = - ChooserRequestRepository( - initialRequest = fakeChooserRequest(), - initialActions = emptyList(), - ) - val pendingSelectionCallbackRepo = PendingSelectionCallbackRepository() + fun reflectPreviewRepo_initState() = runKosmosTest { + targetIntentModifier = TargetIntentModifier { error("unexpected invocation") } val underTest = SelectablePreviewInteractor( key = PreviewModel(Uri.fromParts("scheme", "ssp", "fragment"), null), - selectionInteractor = - SelectionInteractor( - selectionsRepo = selectionRepo, - targetIntentModifier = { error("unexpected invocation") }, - updateTargetIntentInteractor = - UpdateTargetIntentInteractor( - repository = pendingSelectionCallbackRepo, - chooserRequestInteractor = - UpdateChooserRequestInteractor( - repository = chooserRequestRepo, - pendingIntentSender = { error("unexpected invocation") }, - ) - ) - ), + selectionInteractor = selectionInteractor, ) runCurrent() @@ -67,36 +48,17 @@ class SelectablePreviewInteractorTest { } @Test - fun reflectPreviewRepo_updatedState() = runTest { - val selectionRepo = PreviewSelectionsRepository() - val chooserRequestRepo = - ChooserRequestRepository( - initialRequest = fakeChooserRequest(), - initialActions = emptyList(), - ) - val pendingSelectionCallbackRepo = PendingSelectionCallbackRepository() + fun reflectPreviewRepo_updatedState() = runKosmosTest { + targetIntentModifier = TargetIntentModifier { error("unexpected invocation") } val underTest = SelectablePreviewInteractor( key = PreviewModel(Uri.fromParts("scheme", "ssp", "fragment"), "image/bitmap"), - selectionInteractor = - SelectionInteractor( - selectionsRepo = selectionRepo, - targetIntentModifier = { error("unexpected invocation") }, - updateTargetIntentInteractor = - UpdateTargetIntentInteractor( - repository = pendingSelectionCallbackRepo, - chooserRequestInteractor = - UpdateChooserRequestInteractor( - repository = chooserRequestRepo, - pendingIntentSender = { error("unexpected invocation") }, - ) - ) - ), + selectionInteractor = selectionInteractor, ) assertThat(underTest.isSelected.first()).isFalse() - selectionRepo.selections.value = + previewSelectionsRepository.selections.value = setOf(PreviewModel(Uri.fromParts("scheme", "ssp", "fragment"), "image/bitmap")) runCurrent() @@ -104,45 +66,26 @@ class SelectablePreviewInteractorTest { } @Test - fun setSelected_updatesChooserRequestRepo() = runTest { + fun setSelected_updatesChooserRequestRepo() = runKosmosTest { val modifiedIntent = Intent() - val selectionRepo = PreviewSelectionsRepository() - val chooserRequestRepo = - ChooserRequestRepository( - initialRequest = fakeChooserRequest(), - initialActions = emptyList(), - ) - val pendingSelectionCallbackRepo = PendingSelectionCallbackRepository() + targetIntentModifier = TargetIntentModifier { modifiedIntent } val underTest = SelectablePreviewInteractor( key = PreviewModel(Uri.fromParts("scheme", "ssp", "fragment"), "image/bitmap"), - selectionInteractor = - SelectionInteractor( - selectionsRepo = selectionRepo, - targetIntentModifier = { modifiedIntent }, - updateTargetIntentInteractor = - UpdateTargetIntentInteractor( - repository = pendingSelectionCallbackRepo, - chooserRequestInteractor = - UpdateChooserRequestInteractor( - repository = chooserRequestRepo, - pendingIntentSender = { error("unexpected invocation") }, - ) - ) - ), + selectionInteractor = selectionInteractor, ) underTest.setSelected(true) runCurrent() - assertThat(selectionRepo.selections.value) + assertThat(previewSelectionsRepository.selections.value) .containsExactly( PreviewModel(Uri.fromParts("scheme", "ssp", "fragment"), "image/bitmap") ) - assertThat(chooserRequestRepo.chooserRequest.value.targetIntent) + assertThat(chooserRequestRepository.chooserRequest.value.targetIntent) .isSameInstanceAs(modifiedIntent) - assertThat(pendingSelectionCallbackRepo.pendingTargetIntent.value) + assertThat(pendingSelectionCallbackRepository.pendingTargetIntent.value) .isSameInstanceAs(modifiedIntent) } } diff --git a/tests/unit/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/interactor/SelectablePreviewsInteractorTest.kt b/tests/unit/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/interactor/SelectablePreviewsInteractorTest.kt index 3f02c0cd..5fa5cab4 100644 --- a/tests/unit/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/interactor/SelectablePreviewsInteractorTest.kt +++ b/tests/unit/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/interactor/SelectablePreviewsInteractorTest.kt @@ -19,75 +19,46 @@ package com.android.intentresolver.contentpreview.payloadtoggle.domain.interactor import android.net.Uri -import com.android.intentresolver.contentpreview.payloadtoggle.data.repository.CursorPreviewsRepository -import com.android.intentresolver.contentpreview.payloadtoggle.data.repository.PendingSelectionCallbackRepository -import com.android.intentresolver.contentpreview.payloadtoggle.data.repository.PreviewSelectionsRepository +import com.android.intentresolver.contentpreview.payloadtoggle.data.repository.cursorPreviewsRepository +import com.android.intentresolver.contentpreview.payloadtoggle.data.repository.previewSelectionsRepository +import com.android.intentresolver.contentpreview.payloadtoggle.domain.intent.TargetIntentModifier +import com.android.intentresolver.contentpreview.payloadtoggle.domain.intent.targetIntentModifier import com.android.intentresolver.contentpreview.payloadtoggle.shared.model.PreviewModel import com.android.intentresolver.contentpreview.payloadtoggle.shared.model.PreviewsModel -import com.android.intentresolver.v2.data.model.fakeChooserRequest -import com.android.intentresolver.v2.data.repository.ChooserRequestRepository +import com.android.intentresolver.util.runKosmosTest import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.stateIn -import kotlinx.coroutines.test.runCurrent -import kotlinx.coroutines.test.runTest import org.junit.Test class SelectablePreviewsInteractorTest { @Test - fun keySet_reflectsRepositoryInit() = runTest { - val repo = - CursorPreviewsRepository().apply { - previewsModel.value = - PreviewsModel( - previewModels = - setOf( - PreviewModel( - Uri.fromParts("scheme", "ssp", "fragment"), - "image/bitmap", - ), - PreviewModel( - Uri.fromParts("scheme2", "ssp2", "fragment2"), - "image/bitmap", - ), - ), - startIdx = 0, - loadMoreLeft = null, - loadMoreRight = null, - ) - } - val selectionRepo = - PreviewSelectionsRepository().apply { - selections.value = + fun keySet_reflectsRepositoryInit() = runKosmosTest { + cursorPreviewsRepository.previewsModel.value = + PreviewsModel( + previewModels = setOf( - PreviewModel(Uri.fromParts("scheme", "ssp", "fragment"), null), - ) - } - val chooserRequestRepo = - ChooserRequestRepository( - initialRequest = fakeChooserRequest(), - initialActions = emptyList(), - ) - val underTest = - SelectablePreviewsInteractor( - previewsRepo = repo, - selectionInteractor = - SelectionInteractor( - selectionRepo, - targetIntentModifier = { error("unexpected invocation") }, - updateTargetIntentInteractor = - UpdateTargetIntentInteractor( - repository = PendingSelectionCallbackRepository(), - chooserRequestInteractor = - UpdateChooserRequestInteractor( - repository = chooserRequestRepo, - pendingIntentSender = { error("unexpected invocation") }, - ) - ) + PreviewModel( + Uri.fromParts("scheme", "ssp", "fragment"), + "image/bitmap", + ), + PreviewModel( + Uri.fromParts("scheme2", "ssp2", "fragment2"), + "image/bitmap", + ), ), + startIdx = 0, + loadMoreLeft = null, + loadMoreRight = null, ) + previewSelectionsRepository.selections.value = + setOf( + PreviewModel(Uri.fromParts("scheme", "ssp", "fragment"), null), + ) + targetIntentModifier = TargetIntentModifier { error("unexpected invocation") } + val underTest = selectablePreviewsInteractor val keySet = underTest.previews.stateIn(backgroundScope) assertThat(keySet.value).isNotNull() @@ -111,38 +82,13 @@ class SelectablePreviewsInteractorTest { } @Test - fun keySet_reflectsRepositoryUpdate() = runTest { - val previewsRepo = CursorPreviewsRepository() - val selectionRepo = - PreviewSelectionsRepository().apply { - selections.value = - setOf( - PreviewModel(Uri.fromParts("scheme", "ssp", "fragment"), null), - ) - } - val chooserRequestRepo = - ChooserRequestRepository( - initialRequest = fakeChooserRequest(), - initialActions = emptyList(), - ) - val underTest = - SelectablePreviewsInteractor( - previewsRepo = previewsRepo, - selectionInteractor = - SelectionInteractor( - selectionRepo, - targetIntentModifier = { error("unexpected invocation") }, - updateTargetIntentInteractor = - UpdateTargetIntentInteractor( - repository = PendingSelectionCallbackRepository(), - chooserRequestInteractor = - UpdateChooserRequestInteractor( - repository = chooserRequestRepo, - pendingIntentSender = { error("unexpected invocation") }, - ) - ) - ), + fun keySet_reflectsRepositoryUpdate() = runKosmosTest { + previewSelectionsRepository.selections.value = + setOf( + PreviewModel(Uri.fromParts("scheme", "ssp", "fragment"), null), ) + targetIntentModifier = TargetIntentModifier { error("unexpected invocation") } + val underTest = selectablePreviewsInteractor val previews = underTest.previews.stateIn(backgroundScope) val firstModel = @@ -153,7 +99,7 @@ class SelectablePreviewsInteractorTest { var loadRequested = false - previewsRepo.previewsModel.value = + cursorPreviewsRepository.previewsModel.value = PreviewsModel( previewModels = setOf( @@ -170,7 +116,7 @@ class SelectablePreviewsInteractorTest { loadMoreLeft = null, loadMoreRight = { loadRequested = true }, ) - selectionRepo.selections.value = emptySet() + previewSelectionsRepository.selections.value = emptySet() runCurrent() assertThat(previews.value).isNotNull() diff --git a/tests/unit/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/interactor/SetCursorPreviewsInteractorTest.kt b/tests/unit/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/interactor/SetCursorPreviewsInteractorTest.kt index 9683d01f..5aac7b55 100644 --- a/tests/unit/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/interactor/SetCursorPreviewsInteractorTest.kt +++ b/tests/unit/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/interactor/SetCursorPreviewsInteractorTest.kt @@ -19,25 +19,21 @@ package com.android.intentresolver.contentpreview.payloadtoggle.domain.interactor import android.net.Uri -import com.android.intentresolver.contentpreview.payloadtoggle.data.repository.CursorPreviewsRepository +import com.android.intentresolver.contentpreview.payloadtoggle.data.repository.cursorPreviewsRepository import com.android.intentresolver.contentpreview.payloadtoggle.domain.model.LoadDirection import com.android.intentresolver.contentpreview.payloadtoggle.shared.model.PreviewModel +import com.android.intentresolver.util.runKosmosTest import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.stateIn -import kotlinx.coroutines.test.runCurrent -import kotlinx.coroutines.test.runTest import org.junit.Test class SetCursorPreviewsInteractorTest { @Test - fun setPreviews_noAdditionalData() = runTest { - val repo = CursorPreviewsRepository() - val underTest = SetCursorPreviewsInteractor(repo) - + fun setPreviews_noAdditionalData() = runKosmosTest { val loadState = - underTest.setPreviews( + setCursorPreviewsInteractor.setPreviews( previewsByKey = setOf( PreviewModel( @@ -51,7 +47,7 @@ class SetCursorPreviewsInteractorTest { ) assertThat(loadState.first()).isNull() - repo.previewsModel.value.let { + cursorPreviewsRepository.previewsModel.value.let { assertThat(it).isNotNull() it!! assertThat(it.loadMoreRight).isNull() @@ -69,12 +65,9 @@ class SetCursorPreviewsInteractorTest { } @Test - fun setPreviews_additionalData() = runTest { - val repo = CursorPreviewsRepository() - val underTest = SetCursorPreviewsInteractor(repo) - + fun setPreviews_additionalData() = runKosmosTest { val loadState = - underTest + setCursorPreviewsInteractor .setPreviews( previewsByKey = setOf( @@ -90,7 +83,7 @@ class SetCursorPreviewsInteractorTest { .stateIn(backgroundScope) assertThat(loadState.value).isNull() - repo.previewsModel.value.let { + cursorPreviewsRepository.previewsModel.value.let { assertThat(it).isNotNull() it!! assertThat(it.loadMoreRight).isNotNull() diff --git a/tests/unit/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/interactor/UpdateChooserRequestInteractorTest.kt b/tests/unit/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/interactor/UpdateChooserRequestInteractorTest.kt index 05c7646a..7a4f4754 100644 --- a/tests/unit/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/interactor/UpdateChooserRequestInteractorTest.kt +++ b/tests/unit/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/interactor/UpdateChooserRequestInteractorTest.kt @@ -19,49 +19,23 @@ package com.android.intentresolver.contentpreview.payloadtoggle.domain.interactor import android.content.Intent -import com.android.intentresolver.contentpreview.payloadtoggle.data.repository.PendingSelectionCallbackRepository -import com.android.intentresolver.contentpreview.payloadtoggle.domain.intent.PendingIntentSender +import com.android.intentresolver.contentpreview.payloadtoggle.data.repository.pendingSelectionCallbackRepository import com.android.intentresolver.contentpreview.payloadtoggle.domain.model.ShareouselUpdate import com.android.intentresolver.contentpreview.payloadtoggle.domain.model.ValueUpdate -import com.android.intentresolver.v2.data.model.fakeChooserRequest -import com.android.intentresolver.v2.data.repository.ChooserRequestRepository +import com.android.intentresolver.contentpreview.payloadtoggle.domain.update.SelectionChangeCallback +import com.android.intentresolver.contentpreview.payloadtoggle.domain.update.selectionChangeCallback +import com.android.intentresolver.util.runKosmosTest +import com.android.intentresolver.v2.data.repository.chooserRequestRepository import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.launch -import kotlinx.coroutines.test.runCurrent -import kotlinx.coroutines.test.runTest import org.junit.Test class UpdateChooserRequestInteractorTest { @Test - fun updateTargetIntentWithSelection() = runTest { - val pendingIntentSender = PendingIntentSender {} - val chooserRequestRepository = - ChooserRequestRepository( - initialRequest = fakeChooserRequest(), - initialActions = emptyList(), - ) + fun updateTargetIntentWithSelection() = runKosmosTest { val selectionCallbackResult = ShareouselUpdate(metadataText = ValueUpdate.Value("update")) - val pendingSelectionCallbackRepository = PendingSelectionCallbackRepository() - val updateTargetIntentInteractor = - UpdateTargetIntentInteractor( - repository = pendingSelectionCallbackRepository, - chooserRequestInteractor = - UpdateChooserRequestInteractor( - repository = chooserRequestRepository, - pendingIntentSender = pendingIntentSender, - ) - ) - val processTargetIntentUpdatesInteractor = - ProcessTargetIntentUpdatesInteractor( - selectionCallback = { selectionCallbackResult }, - repository = pendingSelectionCallbackRepository, - chooserRequestInteractor = - UpdateChooserRequestInteractor( - repository = chooserRequestRepository, - pendingIntentSender = pendingIntentSender, - ) - ) + selectionChangeCallback = SelectionChangeCallback { selectionCallbackResult } backgroundScope.launch { processTargetIntentUpdatesInteractor.activate() } diff --git a/tests/unit/src/com/android/intentresolver/contentpreview/payloadtoggle/ui/viewmodel/ShareouselViewModelTest.kt b/tests/unit/src/com/android/intentresolver/contentpreview/payloadtoggle/ui/viewmodel/ShareouselViewModelTest.kt index 5d95df04..58804456 100644 --- a/tests/unit/src/com/android/intentresolver/contentpreview/payloadtoggle/ui/viewmodel/ShareouselViewModelTest.kt +++ b/tests/unit/src/com/android/intentresolver/contentpreview/payloadtoggle/ui/viewmodel/ShareouselViewModelTest.kt @@ -19,287 +19,208 @@ package com.android.intentresolver.contentpreview.payloadtoggle.ui.viewmodel import android.app.Activity -import android.content.ContentResolver import android.content.Intent -import android.content.pm.PackageManager import android.graphics.Bitmap import android.graphics.drawable.Icon import android.net.Uri import com.android.intentresolver.FakeImageLoader import com.android.intentresolver.contentpreview.HeadlineGenerator import com.android.intentresolver.contentpreview.payloadtoggle.data.model.CustomActionModel -import com.android.intentresolver.contentpreview.payloadtoggle.data.repository.ActivityResultRepository -import com.android.intentresolver.contentpreview.payloadtoggle.data.repository.CursorPreviewsRepository -import com.android.intentresolver.contentpreview.payloadtoggle.data.repository.PendingSelectionCallbackRepository -import com.android.intentresolver.contentpreview.payloadtoggle.data.repository.PreviewSelectionsRepository +import com.android.intentresolver.contentpreview.payloadtoggle.data.repository.activityResultRepository +import com.android.intentresolver.contentpreview.payloadtoggle.data.repository.cursorPreviewsRepository +import com.android.intentresolver.contentpreview.payloadtoggle.data.repository.previewSelectionsRepository import com.android.intentresolver.contentpreview.payloadtoggle.domain.intent.PendingIntentSender import com.android.intentresolver.contentpreview.payloadtoggle.domain.intent.TargetIntentModifier -import com.android.intentresolver.contentpreview.payloadtoggle.domain.interactor.ChooserRequestInteractor -import com.android.intentresolver.contentpreview.payloadtoggle.domain.interactor.CustomActionsInteractor -import com.android.intentresolver.contentpreview.payloadtoggle.domain.interactor.SelectablePreviewsInteractor -import com.android.intentresolver.contentpreview.payloadtoggle.domain.interactor.SelectionInteractor -import com.android.intentresolver.contentpreview.payloadtoggle.domain.interactor.UpdateChooserRequestInteractor -import com.android.intentresolver.contentpreview.payloadtoggle.domain.interactor.UpdateTargetIntentInteractor +import com.android.intentresolver.contentpreview.payloadtoggle.domain.intent.pendingIntentSender +import com.android.intentresolver.contentpreview.payloadtoggle.domain.intent.targetIntentModifier +import com.android.intentresolver.contentpreview.payloadtoggle.domain.interactor.customActionsInteractor +import com.android.intentresolver.contentpreview.payloadtoggle.domain.interactor.headlineGenerator +import com.android.intentresolver.contentpreview.payloadtoggle.domain.interactor.payloadToggleImageLoader +import com.android.intentresolver.contentpreview.payloadtoggle.domain.interactor.selectablePreviewsInteractor +import com.android.intentresolver.contentpreview.payloadtoggle.domain.interactor.selectionInteractor import com.android.intentresolver.contentpreview.payloadtoggle.shared.model.PreviewModel import com.android.intentresolver.contentpreview.payloadtoggle.shared.model.PreviewsModel import com.android.intentresolver.icon.BitmapIcon import com.android.intentresolver.logging.FakeEventLog -import com.android.intentresolver.mock +import com.android.intentresolver.logging.eventLog +import com.android.intentresolver.util.KosmosTestScope import com.android.intentresolver.util.comparingElementsUsingTransform -import com.android.intentresolver.v2.data.model.fakeChooserRequest -import com.android.intentresolver.v2.data.repository.ChooserRequestRepository -import com.android.internal.logging.InstanceId +import com.android.intentresolver.util.runKosmosTest +import com.android.intentresolver.v2.data.repository.chooserRequestRepository +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.kosmos.Kosmos.Fixture import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertWithMessage +import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.first -import kotlinx.coroutines.test.StandardTestDispatcher -import kotlinx.coroutines.test.TestScope -import kotlinx.coroutines.test.runCurrent -import kotlinx.coroutines.test.runTest import org.junit.Test class ShareouselViewModelTest { - class Dependencies( - val pendingIntentSender: PendingIntentSender, - val targetIntentModifier: TargetIntentModifier<PreviewModel>, - ) { - val testDispatcher = StandardTestDispatcher() - val testScope = TestScope(testDispatcher) - val previewsRepository = CursorPreviewsRepository() - val selectionRepository = - PreviewSelectionsRepository().apply { - selections.value = - setOf(PreviewModel(Uri.fromParts("scheme", "ssp", "fragment"), null)) - } - val activityResultRepository = ActivityResultRepository() - val contentResolver = mock<ContentResolver> {} - val packageManager = mock<PackageManager> {} - val eventLog = FakeEventLog(instanceId = InstanceId.fakeInstanceId(1)) - val chooserRequestRepo = - ChooserRequestRepository( - initialRequest = fakeChooserRequest(), - initialActions = emptyList(), - ) - val pendingSelectionCallbackRepo = PendingSelectionCallbackRepository() + private var Kosmos.viewModelScope: CoroutineScope by Fixture() + private val Kosmos.shareouselViewModel: ShareouselViewModel by Fixture { + ShareouselViewModelModule.create( + interactor = selectablePreviewsInteractor, + imageLoader = payloadToggleImageLoader, + actionsInteractor = customActionsInteractor, + headlineGenerator = headlineGenerator, + selectionInteractor = selectionInteractor, + scope = viewModelScope, + ) + } - val actionsInteractor - get() = - CustomActionsInteractor( - activityResultRepo = activityResultRepository, - bgDispatcher = testDispatcher, - contentResolver = contentResolver, - eventLog = eventLog, - packageManager = packageManager, - chooserRequestInteractor = chooserRequestInteractor, + @Test + fun headline() = runTest { + assertThat(shareouselViewModel.headline.first()).isEqualTo("IMAGES: 1") + previewSelectionsRepository.selections.value = + setOf( + PreviewModel( + Uri.fromParts("scheme", "ssp", "fragment"), + null, + ), + PreviewModel( + Uri.fromParts("scheme1", "ssp1", "fragment1"), + null, ) + ) + runCurrent() + assertThat(shareouselViewModel.headline.first()).isEqualTo("IMAGES: 2") + } - val selectionInteractor - get() = - SelectionInteractor( - selectionsRepo = selectionRepository, - targetIntentModifier = targetIntentModifier, - updateTargetIntentInteractor = updateTargetIntentInteractor, + @Test + fun previews() = + runTest(targetIntentModifier = { Intent() }) { + cursorPreviewsRepository.previewsModel.value = + PreviewsModel( + previewModels = + setOf( + PreviewModel( + Uri.fromParts("scheme", "ssp", "fragment"), + null, + ), + PreviewModel( + Uri.fromParts("scheme1", "ssp1", "fragment1"), + null, + ) + ), + startIdx = 1, + loadMoreLeft = null, + loadMoreRight = null, ) + runCurrent() - val updateTargetIntentInteractor - get() = - UpdateTargetIntentInteractor( - repository = pendingSelectionCallbackRepo, - chooserRequestInteractor = updateChooserRequestInteractor, + assertWithMessage("previewsKeys is null") + .that(shareouselViewModel.previews.first()) + .isNotNull() + assertThat(shareouselViewModel.previews.first()!!.previewModels) + .comparingElementsUsingTransform("has uri of") { it: PreviewModel -> it.uri } + .containsExactly( + Uri.fromParts("scheme", "ssp", "fragment"), + Uri.fromParts("scheme1", "ssp1", "fragment1"), ) + .inOrder() - val updateChooserRequestInteractor - get() = - UpdateChooserRequestInteractor( - repository = chooserRequestRepo, - pendingIntentSender = pendingIntentSender, + val previewVm = + shareouselViewModel.preview( + PreviewModel(Uri.fromParts("scheme1", "ssp1", "fragment1"), null) ) - val chooserRequestInteractor - get() = ChooserRequestInteractor(repository = chooserRequestRepo) + assertWithMessage("preview bitmap is null").that(previewVm.bitmap.first()).isNotNull() + assertThat(previewVm.isSelected.first()).isFalse() - val previewsInteractor - get() = - SelectablePreviewsInteractor( - previewsRepo = previewsRepository, - selectionInteractor = selectionInteractor, - ) + previewVm.setSelected(true) - val underTest = - ShareouselViewModelModule.create( - interactor = previewsInteractor, - imageLoader = - FakeImageLoader( - initialBitmaps = - mapOf( - Uri.fromParts("scheme1", "ssp1", "fragment1") to - Bitmap.createBitmap(100, 100, Bitmap.Config.ALPHA_8) - ) - ), - actionsInteractor = actionsInteractor, - headlineGenerator = - object : HeadlineGenerator { - override fun getImagesHeadline(count: Int): String = "IMAGES: $count" - - override fun getTextHeadline(text: CharSequence): String = - error("not supported") - - override fun getAlbumHeadline(): String = error("not supported") - - override fun getImagesWithTextHeadline( - text: CharSequence, - count: Int - ): String = error("not supported") - - override fun getVideosWithTextHeadline( - text: CharSequence, - count: Int - ): String = error("not supported") - - override fun getFilesWithTextHeadline( - text: CharSequence, - count: Int - ): String = error("not supported") - - override fun getVideosHeadline(count: Int): String = error("not supported") - - override fun getFilesHeadline(count: Int): String = error("not supported") - }, - selectionInteractor = selectionInteractor, - scope = testScope.backgroundScope, - ) - } - - private inline fun runTestWithDeps( - pendingIntentSender: PendingIntentSender = PendingIntentSender {}, - targetIntentModifier: TargetIntentModifier<PreviewModel> = TargetIntentModifier { - error("unexpected invocation") - }, - crossinline block: suspend TestScope.(Dependencies) -> Unit, - ): Unit = - Dependencies(pendingIntentSender, targetIntentModifier).run { - testScope.runTest { - runCurrent() - block(this@run) - } + assertThat(previewSelectionsRepository.selections.value) + .comparingElementsUsingTransform("has uri of") { model: PreviewModel -> model.uri } + .contains(Uri.fromParts("scheme1", "ssp1", "fragment1")) } @Test - fun headline() = runTestWithDeps { deps -> - with(deps) { - assertThat(underTest.headline.first()).isEqualTo("IMAGES: 1") - selectionRepository.selections.value = - setOf( - PreviewModel( - Uri.fromParts("scheme", "ssp", "fragment"), - null, - ), - PreviewModel( - Uri.fromParts("scheme1", "ssp1", "fragment1"), - null, + fun actions() { + runTest { + assertThat(shareouselViewModel.actions.first()).isEmpty() + + val bitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ALPHA_8) + val icon = Icon.createWithBitmap(bitmap) + var actionSent = false + chooserRequestRepository.customActions.value = + listOf( + CustomActionModel( + label = "label1", + icon = icon, + performAction = { actionSent = true }, ) ) runCurrent() - assertThat(underTest.headline.first()).isEqualTo("IMAGES: 2") + + assertThat(shareouselViewModel.actions.first()) + .comparingElementsUsingTransform("has a label of") { vm: ActionChipViewModel -> + vm.label + } + .containsExactly("label1") + .inOrder() + assertThat(shareouselViewModel.actions.first()) + .comparingElementsUsingTransform("has an icon of") { vm: ActionChipViewModel -> + vm.icon + } + .containsExactly(BitmapIcon(icon.bitmap)) + .inOrder() + + shareouselViewModel.actions.first()[0].onClicked() + + assertThat(actionSent).isTrue() + assertThat(eventLog.customActionSelected) + .isEqualTo(FakeEventLog.CustomActionSelected(0)) + assertThat(activityResultRepository.activityResult.value).isEqualTo(Activity.RESULT_OK) } } - @Test - fun previews() = - runTestWithDeps(targetIntentModifier = { Intent() }) { deps -> - with(deps) { - previewsRepository.previewsModel.value = - PreviewsModel( - previewModels = - setOf( - PreviewModel( - Uri.fromParts("scheme", "ssp", "fragment"), - null, - ), - PreviewModel( - Uri.fromParts("scheme1", "ssp1", "fragment1"), - null, - ) - ), - startIdx = 1, - loadMoreLeft = null, - loadMoreRight = null, - ) - runCurrent() - - assertWithMessage("previewsKeys is null") - .that(underTest.previews.first()) - .isNotNull() - assertThat(underTest.previews.first()!!.previewModels) - .comparingElementsUsingTransform("has uri of") { it: PreviewModel -> it.uri } - .containsExactly( - Uri.fromParts("scheme", "ssp", "fragment"), - Uri.fromParts("scheme1", "ssp1", "fragment1"), - ) - .inOrder() - - val previewVm = - underTest.preview( - PreviewModel(Uri.fromParts("scheme1", "ssp1", "fragment1"), null) + private fun runTest( + pendingIntentSender: PendingIntentSender = PendingIntentSender {}, + targetIntentModifier: TargetIntentModifier<PreviewModel> = TargetIntentModifier { + error("unexpected invocation") + }, + block: suspend KosmosTestScope.() -> Unit, + ): Unit = runKosmosTest { + viewModelScope = backgroundScope + this.pendingIntentSender = pendingIntentSender + this.targetIntentModifier = targetIntentModifier + previewSelectionsRepository.selections.value = + setOf(PreviewModel(Uri.fromParts("scheme", "ssp", "fragment"), null)) + payloadToggleImageLoader = + FakeImageLoader( + initialBitmaps = + mapOf( + Uri.fromParts("scheme1", "ssp1", "fragment1") to + Bitmap.createBitmap(100, 100, Bitmap.Config.ALPHA_8) ) + ) + headlineGenerator = + object : HeadlineGenerator { + override fun getImagesHeadline(count: Int): String = "IMAGES: $count" - assertWithMessage("preview bitmap is null") - .that(previewVm.bitmap.first()) - .isNotNull() - assertThat(previewVm.isSelected.first()).isFalse() - - previewVm.setSelected(true) + override fun getTextHeadline(text: CharSequence): String = error("not supported") - assertThat(selectionRepository.selections.value) - .comparingElementsUsingTransform("has uri of") { model: PreviewModel -> - model.uri - } - .contains(Uri.fromParts("scheme1", "ssp1", "fragment1")) - } - } + override fun getAlbumHeadline(): String = error("not supported") - @Test - fun actions() { - runTestWithDeps { deps -> - with(deps) { - assertThat(underTest.actions.first()).isEmpty() + override fun getImagesWithTextHeadline(text: CharSequence, count: Int): String = + error("not supported") - val bitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ALPHA_8) - val icon = Icon.createWithBitmap(bitmap) - var actionSent = false - chooserRequestRepo.customActions.value = - listOf( - CustomActionModel( - label = "label1", - icon = icon, - performAction = { actionSent = true }, - ) - ) - runCurrent() + override fun getVideosWithTextHeadline(text: CharSequence, count: Int): String = + error("not supported") - assertThat(underTest.actions.first()) - .comparingElementsUsingTransform("has a label of") { vm: ActionChipViewModel -> - vm.label - } - .containsExactly("label1") - .inOrder() - assertThat(underTest.actions.first()) - .comparingElementsUsingTransform("has an icon of") { vm: ActionChipViewModel -> - vm.icon - } - .containsExactly(BitmapIcon(icon.bitmap)) - .inOrder() + override fun getFilesWithTextHeadline(text: CharSequence, count: Int): String = + error("not supported") - underTest.actions.first()[0].onClicked() + override fun getVideosHeadline(count: Int): String = error("not supported") - assertThat(actionSent).isTrue() - assertThat(eventLog.customActionSelected) - .isEqualTo(FakeEventLog.CustomActionSelected(0)) - assertThat(activityResultRepository.activityResult.value) - .isEqualTo(Activity.RESULT_OK) + override fun getFilesHeadline(count: Int): String = error("not supported") } - } + // instantiate the view model, and then runCurrent() so that it is fully hydrated before + // starting the test + shareouselViewModel + runCurrent() + block() } } diff --git a/tests/unit/src/com/android/intentresolver/util/TestKosmos.kt b/tests/unit/src/com/android/intentresolver/util/TestKosmos.kt new file mode 100644 index 00000000..473d9b72 --- /dev/null +++ b/tests/unit/src/com/android/intentresolver/util/TestKosmos.kt @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.intentresolver.util + +import com.android.intentresolver.backgroundDispatcher +import com.android.systemui.kosmos.Kosmos +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.StandardTestDispatcher +import kotlinx.coroutines.test.TestDispatcher +import kotlinx.coroutines.test.TestScope +import kotlinx.coroutines.test.runCurrent + +fun Kosmos.runTest( + dispatcher: TestDispatcher = StandardTestDispatcher(), + block: suspend KosmosTestScope.() -> Unit, +) { + val kosmos = this + backgroundDispatcher = dispatcher + kotlinx.coroutines.test.runTest(dispatcher) { KosmosTestScope(kosmos, this).block() } +} + +fun runKosmosTest( + dispatcher: TestDispatcher = StandardTestDispatcher(), + block: suspend KosmosTestScope.() -> Unit, +) { + Kosmos().runTest(dispatcher, block) +} + +class KosmosTestScope( + kosmos: Kosmos, + private val testScope: TestScope, +) : Kosmos by kosmos { + val backgroundScope + get() = testScope.backgroundScope + + @ExperimentalCoroutinesApi fun runCurrent() = testScope.runCurrent() +} |