1 /*
<lambda>null2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.systemui.media.controls.ui.util
18 
19 import androidx.recyclerview.widget.DiffUtil
20 import androidx.test.ext.junit.runners.AndroidJUnit4
21 import androidx.test.filters.SmallTest
22 import com.android.internal.logging.InstanceId
23 import com.android.systemui.SysuiTestCase
24 import com.android.systemui.media.controls.ui.viewmodel.MediaCommonViewModel
25 import com.android.systemui.media.controls.ui.viewmodel.mediaControlViewModel
26 import com.android.systemui.media.controls.ui.viewmodel.mediaRecommendationsViewModel
27 import com.android.systemui.testKosmos
28 import com.google.common.truth.Truth.assertThat
29 import org.junit.Assert.fail
30 import org.junit.Test
31 import org.junit.runner.RunWith
32 
33 @SmallTest
34 @RunWith(AndroidJUnit4::class)
35 class MediaDiffUtilTest : SysuiTestCase() {
36 
37     private val kosmos = testKosmos()
38 
39     @Test
40     fun newMediaControlAdded() {
41         val mediaControl = createMediaControl(InstanceId.fakeInstanceId(123), true)
42         val oldList = listOf<MediaCommonViewModel>()
43         val newList = listOf(mediaControl)
44         val mediaLoadedCallback = MediaViewModelCallback(oldList, newList)
45         val mediaLoadedListUpdateCallback =
46             MediaViewModelListUpdateCallback(
47                 oldList,
48                 newList,
49                 { commonViewModel, _ -> assertThat(commonViewModel).isEqualTo(mediaControl) },
50                 { commonViewModel, _ -> fail("Unexpected to update $commonViewModel") },
51                 { fail("Unexpected to remove $it") },
52                 { commonViewModel, _, _ -> fail("Unexpected to move $commonViewModel ") },
53             )
54 
55         DiffUtil.calculateDiff(mediaLoadedCallback).dispatchUpdatesTo(mediaLoadedListUpdateCallback)
56     }
57 
58     @Test
59     fun newMediaRecommendationsAdded() {
60         val mediaRecs = createMediaRecommendations(KEY_MEDIA_SMARTSPACE, true)
61         val oldList = listOf<MediaCommonViewModel>()
62         val newList = listOf(mediaRecs)
63         val mediaLoadedCallback = MediaViewModelCallback(oldList, newList)
64         val mediaLoadedListUpdateCallback =
65             MediaViewModelListUpdateCallback(
66                 oldList,
67                 newList,
68                 { commonViewModel, _ -> assertThat(commonViewModel).isEqualTo(mediaRecs) },
69                 { commonViewModel, _ -> fail("Unexpected to update $commonViewModel") },
70                 { fail("Unexpected to remove $it") },
71                 { commonViewModel, _, _ -> fail("Unexpected to move $commonViewModel ") },
72             )
73 
74         DiffUtil.calculateDiff(mediaLoadedCallback).dispatchUpdatesTo(mediaLoadedListUpdateCallback)
75     }
76 
77     @Test
78     fun updateMediaControl_contentChanged() {
79         val mediaControl = createMediaControl(InstanceId.fakeInstanceId(123), true)
80         val oldList = listOf(mediaControl)
81         val newList = listOf(mediaControl.copy(immediatelyUpdateUi = false))
82         val mediaLoadedCallback = MediaViewModelCallback(oldList, newList)
83         val mediaLoadedListUpdateCallback =
84             MediaViewModelListUpdateCallback(
85                 oldList,
86                 newList,
87                 { commonViewModel, _ -> fail("Unexpected to add $commonViewModel") },
88                 { commonViewModel, _ -> assertThat(commonViewModel).isNotEqualTo(mediaControl) },
89                 { fail("Unexpected to remove $it") },
90                 { commonViewModel, _, _ -> fail("Unexpected to move $commonViewModel ") },
91             )
92 
93         DiffUtil.calculateDiff(mediaLoadedCallback).dispatchUpdatesTo(mediaLoadedListUpdateCallback)
94     }
95 
96     @Test
97     fun updateMediaRecommendations_contentChanged() {
98         val mediaRecs = createMediaRecommendations(KEY_MEDIA_SMARTSPACE, true)
99         val oldList = listOf(mediaRecs)
100         val newList = listOf(mediaRecs.copy(key = KEY_MEDIA_SMARTSPACE_2))
101         val mediaLoadedCallback = MediaViewModelCallback(oldList, newList)
102         val mediaLoadedListUpdateCallback =
103             MediaViewModelListUpdateCallback(
104                 oldList,
105                 newList,
106                 { commonViewModel, _ -> fail("Unexpected to add $commonViewModel") },
107                 { commonViewModel, _ -> assertThat(commonViewModel).isNotEqualTo(mediaRecs) },
108                 { fail("Unexpected to remove $it") },
109                 { commonViewModel, _, _ -> fail("Unexpected to move $commonViewModel ") },
110             )
111 
112         DiffUtil.calculateDiff(mediaLoadedCallback).dispatchUpdatesTo(mediaLoadedListUpdateCallback)
113     }
114 
115     @Test
116     fun mediaControlMoved() {
117         val mediaControl1 = createMediaControl(InstanceId.fakeInstanceId(123), true)
118         val mediaControl2 = createMediaControl(InstanceId.fakeInstanceId(456), false)
119         val oldList = listOf(mediaControl1, mediaControl2)
120         val newList = listOf(mediaControl2, mediaControl1)
121         val mediaLoadedCallback = MediaViewModelCallback(oldList, newList)
122         val mediaLoadedListUpdateCallback =
123             MediaViewModelListUpdateCallback(
124                 oldList,
125                 newList,
126                 { commonViewModel, _ -> fail("Unexpected to add $commonViewModel") },
127                 { commonViewModel, _ -> fail("Unexpected to update $commonViewModel") },
128                 { fail("Unexpected to remove $it") },
129                 { commonViewModel, _, _ -> assertThat(commonViewModel).isEqualTo(mediaControl1) },
130             )
131 
132         DiffUtil.calculateDiff(mediaLoadedCallback).dispatchUpdatesTo(mediaLoadedListUpdateCallback)
133     }
134 
135     @Test
136     fun mediaRecommendationsMoved() {
137         val mediaControl1 = createMediaControl(InstanceId.fakeInstanceId(123), true)
138         val mediaControl2 = createMediaControl(InstanceId.fakeInstanceId(456), false)
139         val mediaRecs = createMediaRecommendations(KEY_MEDIA_SMARTSPACE, true)
140         val oldList = listOf(mediaRecs, mediaControl1, mediaControl2)
141         val newList = listOf(mediaControl1, mediaControl2, mediaRecs)
142         val mediaLoadedCallback = MediaViewModelCallback(oldList, newList)
143         val mediaLoadedListUpdateCallback =
144             MediaViewModelListUpdateCallback(
145                 oldList,
146                 newList,
147                 { commonViewModel, _ -> fail("Unexpected to add $commonViewModel") },
148                 { commonViewModel, _ -> fail("Unexpected to update $commonViewModel") },
149                 { fail("Unexpected to remove $it") },
150                 { commonViewModel, _, _ -> assertThat(commonViewModel).isEqualTo(mediaRecs) },
151             )
152 
153         DiffUtil.calculateDiff(mediaLoadedCallback).dispatchUpdatesTo(mediaLoadedListUpdateCallback)
154     }
155 
156     @Test
157     fun mediaControlRemoved() {
158         val mediaControl = createMediaControl(InstanceId.fakeInstanceId(123), true)
159         val oldList = listOf(mediaControl)
160         val newList = listOf<MediaCommonViewModel>()
161         val mediaLoadedCallback = MediaViewModelCallback(oldList, newList)
162         val mediaLoadedListUpdateCallback =
163             MediaViewModelListUpdateCallback(
164                 oldList,
165                 newList,
166                 { commonViewModel, _ -> fail("Unexpected to add $commonViewModel") },
167                 { commonViewModel, _ -> fail("Unexpected to update $commonViewModel") },
168                 { commonViewModel -> assertThat(commonViewModel).isEqualTo(mediaControl) },
169                 { commonViewModel, _, _ -> fail("Unexpected to move $commonViewModel ") },
170             )
171 
172         DiffUtil.calculateDiff(mediaLoadedCallback).dispatchUpdatesTo(mediaLoadedListUpdateCallback)
173     }
174 
175     @Test
176     fun mediaRecommendationsRemoved() {
177         val mediaRecs = createMediaRecommendations(KEY_MEDIA_SMARTSPACE_2, false)
178         val oldList = listOf(mediaRecs)
179         val newList = listOf<MediaCommonViewModel>()
180         val mediaLoadedCallback = MediaViewModelCallback(oldList, newList)
181         val mediaLoadedListUpdateCallback =
182             MediaViewModelListUpdateCallback(
183                 oldList,
184                 newList,
185                 { commonViewModel, _ -> fail("Unexpected to add $commonViewModel") },
186                 { commonViewModel, _ -> fail("Unexpected to update $commonViewModel") },
187                 { commonViewModel -> assertThat(commonViewModel).isEqualTo(mediaRecs) },
188                 { commonViewModel, _, _ -> fail("Unexpected to move $commonViewModel ") },
189             )
190 
191         DiffUtil.calculateDiff(mediaLoadedCallback).dispatchUpdatesTo(mediaLoadedListUpdateCallback)
192     }
193 
194     private fun createMediaControl(
195         instanceId: InstanceId,
196         immediatelyUpdateUi: Boolean,
197     ): MediaCommonViewModel.MediaControl {
198         return MediaCommonViewModel.MediaControl(
199             instanceId = instanceId,
200             immediatelyUpdateUi = immediatelyUpdateUi,
201             controlViewModel = kosmos.mediaControlViewModel,
202             onAdded = {},
203             onRemoved = {},
204             onUpdated = {}
205         )
206     }
207 
208     private fun createMediaRecommendations(
209         key: String,
210         loadingEnabled: Boolean,
211     ): MediaCommonViewModel.MediaRecommendations {
212         return MediaCommonViewModel.MediaRecommendations(
213             key = key,
214             loadingEnabled = loadingEnabled,
215             recsViewModel = kosmos.mediaRecommendationsViewModel,
216             onAdded = {},
217             onRemoved = {},
218             onUpdated = {}
219         )
220     }
221 
222     companion object {
223         private const val KEY_MEDIA_SMARTSPACE = "MEDIA_SMARTSPACE_ID"
224         private const val KEY_MEDIA_SMARTSPACE_2 = "MEDIA_SMARTSPACE_ID_2"
225     }
226 }
227