Skip to content

Commit 5c375ec

Browse files
criticalAYmikehardy
authored andcommitted
feat: allow renaming profiles
- test: unit test for renaming method
1 parent 570c05a commit 5c375ec

2 files changed

Lines changed: 100 additions & 0 deletions

File tree

AnkiDroid/src/main/java/com/ichi2/anki/multiprofile/ProfileManager.kt

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,44 @@ class ProfileManager private constructor(
232232
return ProfileRestrictedDirectory(directoryFile)
233233
}
234234

235+
/**
236+
* Renames an existing profile by updating its display name in
237+
* the registry.
238+
*
239+
* All other metadata fields (version, creation timestamp) are
240+
* preserved. The change is persisted immediately.
241+
*
242+
* @param profileId The [ProfileId] of the profile to rename.
243+
* @param newDisplayName The new user-facing name.
244+
*
245+
* @throws IllegalArgumentException if [profileId] does not
246+
* exist in the registry.
247+
*/
248+
fun renameProfile(
249+
profileId: ProfileId,
250+
newDisplayName: String,
251+
) {
252+
Timber.d("ProfileManager::renameProfile called for $profileId")
253+
254+
require(newDisplayName.isNotBlank()) {
255+
"Profile display name must not be blank"
256+
}
257+
258+
val existing =
259+
profileRegistry.getProfileMetadata(profileId)
260+
?: throw IllegalArgumentException("Profile $profileId not found")
261+
262+
if (existing.displayName == newDisplayName) {
263+
Timber.d("Rename skipped: New name matches existing name for $profileId")
264+
return
265+
}
266+
267+
val updated = existing.copy(displayName = newDisplayName)
268+
profileRegistry.saveProfile(profileId, updated)
269+
270+
Timber.d("Renamed profile $profileId to '$newDisplayName'")
271+
}
272+
235273
/**
236274
* Holds the meta-data for a profile.
237275
* Converted to JSON for storage to allow future extensibility (e.g. avatars, themes).

AnkiDroid/src/test/java/com/ichi2/anki/multiprofile/ProfileManagerTest.kt

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ import org.junit.Assert.assertEquals
3939
import org.junit.Assert.assertTrue
4040
import org.junit.Before
4141
import org.junit.Test
42+
import org.junit.jupiter.api.Assertions.assertThrows
4243
import org.junit.runner.RunWith
4344
import org.robolectric.annotation.Config
4445
import java.io.File
@@ -200,4 +201,65 @@ class ProfileManagerTest {
200201
assertEquals(1, allProfiles.size)
201202
assertTrue(allProfiles.containsKey(ProfileId.DEFAULT))
202203
}
204+
205+
fun `renameProfile updates displayName in registry`() {
206+
val manager = ProfileManager.create(context)
207+
val profileId = manager.createNewProfile("Original Name")
208+
val newName = "Updated Name"
209+
210+
manager.renameProfile(profileId, newName)
211+
212+
val json = prefs.getString(profileId.value, null)
213+
val metadata = ProfileManager.ProfileMetadata.fromJson(json!!)
214+
215+
assertEquals(newName, metadata.displayName)
216+
}
217+
218+
@Test
219+
fun `renameProfile preserves version and createdTimestamp`() {
220+
val manager = ProfileManager.create(context)
221+
val profileId = manager.createNewProfile("Original Name")
222+
223+
val originalJson = prefs.getString(profileId.value, null)
224+
val originalMetadata = ProfileManager.ProfileMetadata.fromJson(originalJson!!)
225+
226+
manager.renameProfile(profileId, "New Name")
227+
228+
val updatedJson = prefs.getString(profileId.value, null)
229+
val updatedMetadata = ProfileManager.ProfileMetadata.fromJson(updatedJson!!)
230+
231+
assertEquals("Version must be preserved", originalMetadata.version, updatedMetadata.version)
232+
assertEquals(
233+
"Timestamp must be preserved",
234+
originalMetadata.createdTimestamp,
235+
updatedMetadata.createdTimestamp,
236+
)
237+
}
238+
239+
@Test
240+
fun `renameProfile does not write to disk if name is identical`() {
241+
val manager = ProfileManager.create(context)
242+
val name = "No Change"
243+
val profileId = manager.createNewProfile(name)
244+
245+
val originalJson = prefs.getString(profileId.value, null)
246+
247+
manager.renameProfile(profileId, name)
248+
249+
val currentJson = prefs.getString(profileId.value, null)
250+
assertEquals("No disk write should occur for identical names", originalJson, currentJson)
251+
}
252+
253+
@Test
254+
fun `renameProfile throws IllegalArgumentException for missing profile`() {
255+
val manager = ProfileManager.create(context)
256+
val fakeId = ProfileId("p_ghost")
257+
258+
val exception =
259+
assertThrows(IllegalArgumentException::class.java) {
260+
manager.renameProfile(fakeId, "New Name")
261+
}
262+
263+
assertTrue(exception.message!!.contains("not found"))
264+
}
203265
}

0 commit comments

Comments
 (0)