• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2025 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 package com.android.documentsui.ui
17 
18 import android.content.Context
19 import android.content.res.Resources
20 import android.net.Uri
21 import android.provider.DocumentsContract.Document.MIME_TYPE_DIR
22 import androidx.test.filters.SmallTest
23 import com.android.documentsui.OperationDialogFragment.DIALOG_TYPE_CONVERTED
24 import com.android.documentsui.OperationDialogFragment.DIALOG_TYPE_FAILURE
25 import com.android.documentsui.R
26 import com.android.documentsui.base.DocumentInfo
27 import com.android.documentsui.services.FileOperationService.OPERATION_COMPRESS
28 import com.android.documentsui.services.FileOperationService.OPERATION_COPY
29 import com.android.documentsui.services.FileOperationService.OPERATION_DELETE
30 import com.android.documentsui.services.FileOperationService.OPERATION_EXTRACT
31 import com.android.documentsui.services.FileOperationService.OPERATION_MOVE
32 import com.android.documentsui.services.FileOperationService.OPERATION_UNKNOWN
33 import org.junit.Assert.assertEquals
34 import org.junit.Before
35 import org.junit.Test
36 import org.junit.runner.RunWith
37 import org.junit.runners.Parameterized
38 import org.junit.runners.Suite
39 import org.junit.runners.Suite.SuiteClasses
40 import org.mockito.ArgumentMatchers.anyString
41 import org.mockito.Mock
42 import org.mockito.Mockito.eq
43 import org.mockito.Mockito.`when` as whenever
44 import org.mockito.MockitoAnnotations
45 
46 @SmallTest
47 @RunWith(Suite::class)
48 @SuiteClasses(
49     MessageBuilderTest.GenerateDeleteMessage::class,
50     MessageBuilderTest.GenerateListMessage::class
51 )
52 open class MessageBuilderTest() {
53     companion object {
54         const val EXPECTED_MESSAGE = "Delete message"
55     }
56 
57     class GenerateDeleteMessage() {
58         private lateinit var messageBuilder: MessageBuilder
59 
60         @Mock
61         private lateinit var resources: Resources
62 
63         @Mock
64         private lateinit var context: Context
65 
66         @Before
setUpnull67         fun setUp() {
68             MockitoAnnotations.openMocks(this)
69             whenever(context.resources).thenReturn(resources)
70             messageBuilder = MessageBuilder(context)
71         }
72 
assertDeleteMessagenull73         private fun assertDeleteMessage(docInfo: DocumentInfo, resId: Int) {
74             whenever(
75                 resources.getString(
76                     eq(resId),
77                     eq(docInfo.displayName)
78                 )
79             ).thenReturn(EXPECTED_MESSAGE)
80             assertEquals(messageBuilder.generateDeleteMessage(listOf(docInfo)), EXPECTED_MESSAGE)
81         }
82 
assertQuantityDeleteMessagenull83         private fun assertQuantityDeleteMessage(docInfos: List<DocumentInfo>, resId: Int) {
84             whenever(
85                 resources.getQuantityString(
86                     eq(resId),
87                     eq(docInfos.size),
88                     eq(docInfos.size)
89                 )
90             ).thenReturn(EXPECTED_MESSAGE)
91             assertEquals(messageBuilder.generateDeleteMessage(docInfos), EXPECTED_MESSAGE)
92         }
93 
94         @Test
testGenerateDeleteMessage_singleFilenull95         fun testGenerateDeleteMessage_singleFile() {
96             assertDeleteMessage(
97                 createFile("Test doc"),
98                 R.string.delete_filename_confirmation_message
99             )
100         }
101 
102         @Test
testGenerateDeleteMessage_singleDirectorynull103         fun testGenerateDeleteMessage_singleDirectory() {
104             assertDeleteMessage(
105                 createDirectory("Test doc"),
106                 R.string.delete_foldername_confirmation_message
107             )
108         }
109 
110         @Test
testGenerateDeleteMessage_multipleFilesnull111         fun testGenerateDeleteMessage_multipleFiles() {
112             assertQuantityDeleteMessage(
113                 listOf(createFile("File 1"), createFile("File 2")),
114                 R.plurals.delete_files_confirmation_message
115             )
116         }
117 
118         @Test
testGenerateDeleteMessage_multipleDirectoriesnull119         fun testGenerateDeleteMessage_multipleDirectories() {
120             assertQuantityDeleteMessage(
121                 listOf(
122                     createDirectory("Directory 1"),
123                     createDirectory("Directory 2")
124                 ),
125                 R.plurals.delete_folders_confirmation_message
126             )
127         }
128 
129         @Test
testGenerateDeleteMessage_mixedFilesAndDirectoriesnull130         fun testGenerateDeleteMessage_mixedFilesAndDirectories() {
131             assertQuantityDeleteMessage(
132                 listOf(createFile("File 1"), createDirectory("Directory 1")),
133                 R.plurals.delete_items_confirmation_message
134             )
135         }
136     }
137 
138     @RunWith(Parameterized::class)
139     class GenerateListMessage() {
140         private lateinit var messageBuilder: MessageBuilder
141 
142         @Mock
143         private lateinit var resources: Resources
144 
145         @Mock
146         private lateinit var context: Context
147 
148         @Before
setUpnull149         fun setUp() {
150             MockitoAnnotations.openMocks(this)
151             whenever(context.resources).thenReturn(resources)
152             messageBuilder = MessageBuilder(context)
153         }
154 
155         data class ListMessageData(
156             val dialogType: Int,
157             val opType: Int = OPERATION_UNKNOWN,
158             val resId: Int
159         )
160 
161         companion object {
162             @Parameterized.Parameters(name = "{0}")
163             @JvmStatic
parametersnull164             fun parameters() =
165                 listOf(
166                     ListMessageData(
167                         dialogType = DIALOG_TYPE_CONVERTED,
168                         resId = R.plurals.copy_converted_warning_content,
169                     ),
170                     ListMessageData(
171                         dialogType = DIALOG_TYPE_FAILURE,
172                         opType = OPERATION_COPY,
173                         resId = R.plurals.copy_failure_alert_content,
174                     ),
175                     ListMessageData(
176                         dialogType = DIALOG_TYPE_FAILURE,
177                         opType = OPERATION_COMPRESS,
178                         resId = R.plurals.compress_failure_alert_content,
179                     ),
180                     ListMessageData(
181                         dialogType = DIALOG_TYPE_FAILURE,
182                         opType = OPERATION_EXTRACT,
183                         resId = R.plurals.extract_failure_alert_content,
184                     ),
185                     ListMessageData(
186                         dialogType = DIALOG_TYPE_FAILURE,
187                         opType = OPERATION_DELETE,
188                         resId = R.plurals.delete_failure_alert_content,
189                     ),
190                     ListMessageData(
191                         dialogType = DIALOG_TYPE_FAILURE,
192                         opType = OPERATION_MOVE,
193                         resId = R.plurals.move_failure_alert_content,
194                     ),
195                 )
196         }
197 
198         @Parameterized.Parameter(0)
199         lateinit var testData: ListMessageData
200 
201         @Test
202         fun testGenerateListMessage() {
203             whenever(
204                 resources.getQuantityString(
205                     eq(testData.resId),
206                     eq(2),
207                     anyString(),
208                 )
209             ).thenReturn(EXPECTED_MESSAGE)
210             assertEquals(
211                 messageBuilder.generateListMessage(
212                     testData.dialogType,
213                     testData.opType,
214                     listOf(createFile("File 1")),
215                     listOf(Uri.parse("content://random-uri")),
216                 ),
217                 EXPECTED_MESSAGE
218             )
219         }
220     }
221 }
222 
createFilenull223 fun createFile(displayName: String): DocumentInfo {
224     val doc = DocumentInfo()
225     doc.displayName = displayName
226     return doc
227 }
228 
createDirectorynull229 fun createDirectory(displayName: String): DocumentInfo {
230     val doc = DocumentInfo()
231     doc.displayName = displayName
232     doc.mimeType = MIME_TYPE_DIR
233     return doc
234 }
235