Skip to content

Commit 84cbf55

Browse files
committed
feat: allow renaming profiles
- test: unit test for renaming method
1 parent 8d2e785 commit 84cbf55

2 files changed

Lines changed: 93 additions & 0 deletions

File tree

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

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,40 @@ class ProfileManager private constructor(
215215
return ProfileRestrictedDirectory(directoryFile)
216216
}
217217

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

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

Lines changed: 59 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
@@ -172,4 +173,62 @@ class ProfileManagerTest {
172173

173174
assertEquals("Serialization round-trip failed!", original, reconstructed)
174175
}
176+
177+
@Test
178+
fun `renameProfile updates displayName in registry`() {
179+
val manager = ProfileManager.create(context)
180+
val profileId = manager.createNewProfile("Original Name")
181+
val newName = "Updated Name"
182+
183+
manager.renameProfile(profileId, newName)
184+
185+
val json = prefs.getString(profileId.value, null)
186+
val metadata = ProfileManager.ProfileMetadata.fromJson(json!!)
187+
188+
assertEquals(newName, metadata.displayName)
189+
}
190+
191+
@Test
192+
fun `renameProfile preserves version and createdTimestamp`() {
193+
val manager = ProfileManager.create(context)
194+
val profileId = manager.createNewProfile("Original Name")
195+
196+
val originalJson = prefs.getString(profileId.value, null)
197+
val originalMetadata = ProfileManager.ProfileMetadata.fromJson(originalJson!!)
198+
199+
manager.renameProfile(profileId, "New Name")
200+
201+
val updatedJson = prefs.getString(profileId.value, null)
202+
val updatedMetadata = ProfileManager.ProfileMetadata.fromJson(updatedJson!!)
203+
204+
assertEquals("Version must be preserved", originalMetadata.version, updatedMetadata.version)
205+
assertEquals("Timestamp must be preserved", originalMetadata.createdTimestamp, updatedMetadata.createdTimestamp)
206+
}
207+
208+
@Test
209+
fun `renameProfile does not write to disk if name is identical`() {
210+
val manager = ProfileManager.create(context)
211+
val name = "No Change"
212+
val profileId = manager.createNewProfile(name)
213+
214+
val originalJson = prefs.getString(profileId.value, null)
215+
216+
manager.renameProfile(profileId, name)
217+
218+
val currentJson = prefs.getString(profileId.value, null)
219+
assertEquals("No disk write should occur for identical names", originalJson, currentJson)
220+
}
221+
222+
@Test
223+
fun `renameProfile throws IllegalArgumentException for missing profile`() {
224+
val manager = ProfileManager.create(context)
225+
val fakeId = ProfileId("p_ghost")
226+
227+
val exception =
228+
assertThrows(IllegalArgumentException::class.java) {
229+
manager.renameProfile(fakeId, "New Name")
230+
}
231+
232+
assertTrue(exception.message!!.contains("not found"))
233+
}
175234
}

0 commit comments

Comments
 (0)