Skip to content

Commit cb2e7c4

Browse files
committed
feat: allow renaming profiles
- test: unit test for renaming method
1 parent b9ab20d commit cb2e7c4

File tree

2 files changed

+96
-0
lines changed

2 files changed

+96
-0
lines changed

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

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,40 @@ class ProfileManager private constructor(
224224
return ProfileRestrictedDirectory(directoryFile)
225225
}
226226

227+
/**
228+
* Renames an existing profile by updating its display name in
229+
* the registry.
230+
*
231+
* All other metadata fields (version, creation timestamp) are
232+
* preserved. The change is persisted immediately.
233+
*
234+
* @param profileId The [ProfileId] of the profile to rename.
235+
* @param newDisplayName The new user-facing name.
236+
*
237+
* @throws IllegalArgumentException if [profileId] does not
238+
* exist in the registry.
239+
*/
240+
fun renameProfile(
241+
profileId: ProfileId,
242+
newDisplayName: String,
243+
) {
244+
Timber.d("ProfileManager::renameProfile called for $profileId")
245+
246+
val existing =
247+
profileRegistry.getProfileMetadata(profileId)
248+
?: throw IllegalArgumentException("Profile $profileId not found")
249+
250+
if (existing.displayName == newDisplayName) {
251+
Timber.d("Rename skipped: New name matches existing name for $profileId")
252+
return
253+
}
254+
255+
val updated = existing.copy(displayName = newDisplayName)
256+
profileRegistry.saveProfile(profileId, updated)
257+
258+
Timber.d("Renamed profile $profileId to '$newDisplayName'")
259+
}
260+
227261
private fun triggerAppRestart() {
228262
Timber.w("Restarting app to apply profile switch")
229263
// TODO: Implement process restart logic (e.g. ProcessPhoenix)

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+
206+
fun `renameProfile updates displayName in registry`() {
207+
val manager = ProfileManager.create(context)
208+
val profileId = manager.createNewProfile("Original Name")
209+
val newName = "Updated Name"
210+
211+
manager.renameProfile(profileId, newName)
212+
213+
val json = prefs.getString(profileId.value, null)
214+
val metadata = ProfileManager.ProfileMetadata.fromJson(json!!)
215+
216+
assertEquals(newName, metadata.displayName)
217+
}
218+
219+
@Test
220+
fun `renameProfile preserves version and createdTimestamp`() {
221+
val manager = ProfileManager.create(context)
222+
val profileId = manager.createNewProfile("Original Name")
223+
224+
val originalJson = prefs.getString(profileId.value, null)
225+
val originalMetadata = ProfileManager.ProfileMetadata.fromJson(originalJson!!)
226+
227+
manager.renameProfile(profileId, "New Name")
228+
229+
val updatedJson = prefs.getString(profileId.value, null)
230+
val updatedMetadata = ProfileManager.ProfileMetadata.fromJson(updatedJson!!)
231+
232+
assertEquals("Version must be preserved", originalMetadata.version, updatedMetadata.version)
233+
assertEquals(
234+
"Timestamp must be preserved",
235+
originalMetadata.createdTimestamp,
236+
updatedMetadata.createdTimestamp
237+
)
238+
}
239+
240+
@Test
241+
fun `renameProfile does not write to disk if name is identical`() {
242+
val manager = ProfileManager.create(context)
243+
val name = "No Change"
244+
val profileId = manager.createNewProfile(name)
245+
246+
val originalJson = prefs.getString(profileId.value, null)
247+
248+
manager.renameProfile(profileId, name)
249+
250+
val currentJson = prefs.getString(profileId.value, null)
251+
assertEquals("No disk write should occur for identical names", originalJson, currentJson)
252+
}
253+
254+
@Test
255+
fun `renameProfile throws IllegalArgumentException for missing profile`() {
256+
val manager = ProfileManager.create(context)
257+
val fakeId = ProfileId("p_ghost")
258+
259+
val exception = 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)