1515 * - deleteIdentityFromConfig: deletion and validation tests
1616 * - addIdentityToConfig: security validation and business logic tests
1717 * - updateIdentityInConfig: security validation and business logic tests
18+ * - moveIdentityInConfig: reorder, boundary, single-element, and persistence tests
1819 *
19- * Test Count: 48 tests covering identity.ts related functionality
20+ * Test Count: 57 tests covering identity.ts related functionality
2021 *
2122 * Note: These tests use the real VS Code API (no mocks) to ensure actual behavior.
2223 * Each test restores original configuration values after execution.
@@ -28,6 +29,7 @@ import {
2829 deleteIdentityFromConfig ,
2930 addIdentityToConfig ,
3031 updateIdentityInConfig ,
32+ moveIdentityInConfig ,
3133} from '../../identity/identity' ;
3234
3335const EXTENSION_ID = 'nullvariant.git-id-switcher' ;
@@ -1231,4 +1233,262 @@ describe('Identity E2E Test Suite', function () {
12311233 } ) ;
12321234 } ) ;
12331235 } ) ;
1236+
1237+ // ===========================================================================
1238+ // 5.7.14-18 moveIdentityInConfig() Tests
1239+ // ===========================================================================
1240+
1241+ describe ( 'moveIdentityInConfig' , ( ) => {
1242+ it ( 'should move identity down successfully' , async ( ) => {
1243+ const config = vscode . workspace . getConfiguration ( CONFIG_SECTION ) ;
1244+ const currentIdentities = config . get < TestIdentity [ ] > ( 'identities' , [ ] ) ;
1245+
1246+ // Set up three identities
1247+ const testIdentities : TestIdentity [ ] = [
1248+ { id : 'move-a' , name : 'User A' , email : 'a@example.com' } ,
1249+ { id : 'move-b' , name : 'User B' , email : 'b@example.com' } ,
1250+ { id : 'move-c' , name : 'User C' , email : 'c@example.com' } ,
1251+ ] ;
1252+ await config . update ( 'identities' , testIdentities , vscode . ConfigurationTarget . Global ) ;
1253+
1254+ // Move first identity down
1255+ const result = await moveIdentityInConfig ( 'move-a' , 'down' ) ;
1256+
1257+ assert . strictEqual ( result , true , 'Should return true for successful move' ) ;
1258+
1259+ // Verify new order: B, A, C
1260+ const freshConfig = vscode . workspace . getConfiguration ( CONFIG_SECTION ) ;
1261+ const afterMove = freshConfig . get < TestIdentity [ ] > ( 'identities' , [ ] ) ;
1262+ assert . strictEqual ( afterMove [ 0 ] . id , 'move-b' , 'First should be B' ) ;
1263+ assert . strictEqual ( afterMove [ 1 ] . id , 'move-a' , 'Second should be A' ) ;
1264+ assert . strictEqual ( afterMove [ 2 ] . id , 'move-c' , 'Third should be C' ) ;
1265+
1266+ // Restore original state
1267+ await config . update ( 'identities' , currentIdentities , vscode . ConfigurationTarget . Global ) ;
1268+ } ) ;
1269+
1270+ it ( 'should move identity up successfully' , async ( ) => {
1271+ const config = vscode . workspace . getConfiguration ( CONFIG_SECTION ) ;
1272+ const currentIdentities = config . get < TestIdentity [ ] > ( 'identities' , [ ] ) ;
1273+
1274+ // Set up three identities
1275+ const testIdentities : TestIdentity [ ] = [
1276+ { id : 'move-a' , name : 'User A' , email : 'a@example.com' } ,
1277+ { id : 'move-b' , name : 'User B' , email : 'b@example.com' } ,
1278+ { id : 'move-c' , name : 'User C' , email : 'c@example.com' } ,
1279+ ] ;
1280+ await config . update ( 'identities' , testIdentities , vscode . ConfigurationTarget . Global ) ;
1281+
1282+ // Move last identity up
1283+ const result = await moveIdentityInConfig ( 'move-c' , 'up' ) ;
1284+
1285+ assert . strictEqual ( result , true , 'Should return true for successful move' ) ;
1286+
1287+ // Verify new order: A, C, B
1288+ const freshConfig = vscode . workspace . getConfiguration ( CONFIG_SECTION ) ;
1289+ const afterMove = freshConfig . get < TestIdentity [ ] > ( 'identities' , [ ] ) ;
1290+ assert . strictEqual ( afterMove [ 0 ] . id , 'move-a' , 'First should be A' ) ;
1291+ assert . strictEqual ( afterMove [ 1 ] . id , 'move-c' , 'Second should be C' ) ;
1292+ assert . strictEqual ( afterMove [ 2 ] . id , 'move-b' , 'Third should be B' ) ;
1293+
1294+ // Restore original state
1295+ await config . update ( 'identities' , currentIdentities , vscode . ConfigurationTarget . Global ) ;
1296+ } ) ;
1297+
1298+ it ( 'should return false when moving first item up (boundary)' , async ( ) => {
1299+ const config = vscode . workspace . getConfiguration ( CONFIG_SECTION ) ;
1300+ const currentIdentities = config . get < TestIdentity [ ] > ( 'identities' , [ ] ) ;
1301+
1302+ // Set up two identities
1303+ const testIdentities : TestIdentity [ ] = [
1304+ { id : 'first-item' , name : 'First User' , email : 'first@example.com' } ,
1305+ { id : 'second-item' , name : 'Second User' , email : 'second@example.com' } ,
1306+ ] ;
1307+ await config . update ( 'identities' , testIdentities , vscode . ConfigurationTarget . Global ) ;
1308+
1309+ // Try to move first item up
1310+ const result = await moveIdentityInConfig ( 'first-item' , 'up' ) ;
1311+
1312+ assert . strictEqual ( result , false , 'Should return false for boundary move' ) ;
1313+
1314+ // Verify order unchanged
1315+ const freshConfig = vscode . workspace . getConfiguration ( CONFIG_SECTION ) ;
1316+ const afterMove = freshConfig . get < TestIdentity [ ] > ( 'identities' , [ ] ) ;
1317+ assert . strictEqual ( afterMove [ 0 ] . id , 'first-item' , 'First should remain first' ) ;
1318+ assert . strictEqual ( afterMove [ 1 ] . id , 'second-item' , 'Second should remain second' ) ;
1319+
1320+ // Restore original state
1321+ await config . update ( 'identities' , currentIdentities , vscode . ConfigurationTarget . Global ) ;
1322+ } ) ;
1323+
1324+ it ( 'should return false when moving last item down (boundary)' , async ( ) => {
1325+ const config = vscode . workspace . getConfiguration ( CONFIG_SECTION ) ;
1326+ const currentIdentities = config . get < TestIdentity [ ] > ( 'identities' , [ ] ) ;
1327+
1328+ // Set up two identities
1329+ const testIdentities : TestIdentity [ ] = [
1330+ { id : 'first-item' , name : 'First User' , email : 'first@example.com' } ,
1331+ { id : 'last-item' , name : 'Last User' , email : 'last@example.com' } ,
1332+ ] ;
1333+ await config . update ( 'identities' , testIdentities , vscode . ConfigurationTarget . Global ) ;
1334+
1335+ // Try to move last item down
1336+ const result = await moveIdentityInConfig ( 'last-item' , 'down' ) ;
1337+
1338+ assert . strictEqual ( result , false , 'Should return false for boundary move' ) ;
1339+
1340+ // Verify order unchanged
1341+ const freshConfig = vscode . workspace . getConfiguration ( CONFIG_SECTION ) ;
1342+ const afterMove = freshConfig . get < TestIdentity [ ] > ( 'identities' , [ ] ) ;
1343+ assert . strictEqual ( afterMove [ 0 ] . id , 'first-item' , 'First should remain first' ) ;
1344+ assert . strictEqual ( afterMove [ 1 ] . id , 'last-item' , 'Last should remain last' ) ;
1345+
1346+ // Restore original state
1347+ await config . update ( 'identities' , currentIdentities , vscode . ConfigurationTarget . Global ) ;
1348+ } ) ;
1349+
1350+ it ( 'should return false when array has single element (move up)' , async ( ) => {
1351+ const config = vscode . workspace . getConfiguration ( CONFIG_SECTION ) ;
1352+ const currentIdentities = config . get < TestIdentity [ ] > ( 'identities' , [ ] ) ;
1353+
1354+ // Set up single identity
1355+ const testIdentities : TestIdentity [ ] = [
1356+ { id : 'only-item' , name : 'Only User' , email : 'only@example.com' } ,
1357+ ] ;
1358+ await config . update ( 'identities' , testIdentities , vscode . ConfigurationTarget . Global ) ;
1359+
1360+ // Try to move single item up
1361+ const result = await moveIdentityInConfig ( 'only-item' , 'up' ) ;
1362+
1363+ assert . strictEqual ( result , false , 'Should return false for single element move up' ) ;
1364+
1365+ // Verify unchanged
1366+ const freshConfig = vscode . workspace . getConfiguration ( CONFIG_SECTION ) ;
1367+ const afterMove = freshConfig . get < TestIdentity [ ] > ( 'identities' , [ ] ) ;
1368+ assert . strictEqual ( afterMove . length , 1 , 'Should still have 1 identity' ) ;
1369+ assert . strictEqual ( afterMove [ 0 ] . id , 'only-item' , 'Identity should be unchanged' ) ;
1370+
1371+ // Restore original state
1372+ await config . update ( 'identities' , currentIdentities , vscode . ConfigurationTarget . Global ) ;
1373+ } ) ;
1374+
1375+ it ( 'should return false when array has single element (move down)' , async ( ) => {
1376+ const config = vscode . workspace . getConfiguration ( CONFIG_SECTION ) ;
1377+ const currentIdentities = config . get < TestIdentity [ ] > ( 'identities' , [ ] ) ;
1378+
1379+ // Set up single identity
1380+ const testIdentities : TestIdentity [ ] = [
1381+ { id : 'only-item' , name : 'Only User' , email : 'only@example.com' } ,
1382+ ] ;
1383+ await config . update ( 'identities' , testIdentities , vscode . ConfigurationTarget . Global ) ;
1384+
1385+ // Try to move single item down
1386+ const result = await moveIdentityInConfig ( 'only-item' , 'down' ) ;
1387+
1388+ assert . strictEqual ( result , false , 'Should return false for single element move down' ) ;
1389+
1390+ // Restore original state
1391+ await config . update ( 'identities' , currentIdentities , vscode . ConfigurationTarget . Global ) ;
1392+ } ) ;
1393+
1394+ it ( 'should throw error for non-existent identity ID' , async ( ) => {
1395+ const config = vscode . workspace . getConfiguration ( CONFIG_SECTION ) ;
1396+ const currentIdentities = config . get < TestIdentity [ ] > ( 'identities' , [ ] ) ;
1397+
1398+ // Set up known state
1399+ const testIdentities : TestIdentity [ ] = [
1400+ { id : 'existing-move' , name : 'Existing User' , email : 'existing@example.com' } ,
1401+ ] ;
1402+ await config . update ( 'identities' , testIdentities , vscode . ConfigurationTarget . Global ) ;
1403+
1404+ try {
1405+ await moveIdentityInConfig ( 'non-existent-id' , 'up' ) ;
1406+ assert . fail ( 'Should have thrown an error' ) ;
1407+ } catch ( error ) {
1408+ assert . ok ( error instanceof Error , 'Should throw an Error' ) ;
1409+ assert . ok (
1410+ error . message . includes ( 'not found' ) ,
1411+ `Error message should indicate identity not found, got: ${ error . message } `
1412+ ) ;
1413+ }
1414+
1415+ // Restore original state
1416+ await config . update ( 'identities' , currentIdentities , vscode . ConfigurationTarget . Global ) ;
1417+ } ) ;
1418+
1419+ it ( 'should throw error for invalid ID format' , async ( ) => {
1420+ const invalidIds = [
1421+ '' ,
1422+ 'id with spaces' ,
1423+ 'id@with@symbols' ,
1424+ 'id/with/slashes' ,
1425+ ] ;
1426+
1427+ for ( const invalidId of invalidIds ) {
1428+ try {
1429+ await moveIdentityInConfig ( invalidId , 'up' ) ;
1430+ assert . fail ( `Should have thrown an error for invalid ID: ${ invalidId } ` ) ;
1431+ } catch ( error ) {
1432+ assert . ok ( error instanceof Error , 'Should throw an Error' ) ;
1433+ assert . ok (
1434+ error . message . includes ( 'Invalid' ) ,
1435+ `Error message should indicate invalid ID format for "${ invalidId } ", got: ${ error . message } `
1436+ ) ;
1437+ }
1438+ }
1439+ } ) ;
1440+
1441+ it ( 'should persist reorder to VS Code configuration (E2E)' , async ( ) => {
1442+ const config = vscode . workspace . getConfiguration ( CONFIG_SECTION ) ;
1443+ const currentIdentities = config . get < TestIdentity [ ] > ( 'identities' , [ ] ) ;
1444+
1445+ // Set up identities with all fields to verify full data preservation
1446+ const testIdentities : TestIdentity [ ] = [
1447+ {
1448+ id : 'persist-a' ,
1449+ name : 'User A' ,
1450+ email : 'a@example.com' ,
1451+ icon : '🅰️' ,
1452+ service : 'GitHub' ,
1453+ } ,
1454+ {
1455+ id : 'persist-b' ,
1456+ name : 'User B' ,
1457+ email : 'b@example.com' ,
1458+ icon : '🅱️' ,
1459+ service : 'GitLab' ,
1460+ } ,
1461+ {
1462+ id : 'persist-c' ,
1463+ name : 'User C' ,
1464+ email : 'c@example.com' ,
1465+ } ,
1466+ ] ;
1467+ await config . update ( 'identities' , testIdentities , vscode . ConfigurationTarget . Global ) ;
1468+
1469+ // Move B up (swap A and B)
1470+ await moveIdentityInConfig ( 'persist-b' , 'up' ) ;
1471+
1472+ // Re-read configuration fresh to verify persistence
1473+ const freshConfig = vscode . workspace . getConfiguration ( CONFIG_SECTION ) ;
1474+ const persisted = freshConfig . get < TestIdentity [ ] > ( 'identities' , [ ] ) ;
1475+
1476+ // Verify order: B, A, C
1477+ assert . strictEqual ( persisted . length , 3 , 'Should still have 3 identities' ) ;
1478+ assert . strictEqual ( persisted [ 0 ] . id , 'persist-b' , 'First should be B' ) ;
1479+ assert . strictEqual ( persisted [ 1 ] . id , 'persist-a' , 'Second should be A' ) ;
1480+ assert . strictEqual ( persisted [ 2 ] . id , 'persist-c' , 'Third should be C' ) ;
1481+
1482+ // Verify all data preserved after move
1483+ assert . strictEqual ( persisted [ 0 ] . name , 'User B' , 'B name should be preserved' ) ;
1484+ assert . strictEqual ( persisted [ 0 ] . email , 'b@example.com' , 'B email should be preserved' ) ;
1485+ assert . strictEqual ( persisted [ 0 ] . icon , '🅱️' , 'B icon should be preserved' ) ;
1486+ assert . strictEqual ( persisted [ 0 ] . service , 'GitLab' , 'B service should be preserved' ) ;
1487+ assert . strictEqual ( persisted [ 1 ] . name , 'User A' , 'A name should be preserved' ) ;
1488+ assert . strictEqual ( persisted [ 1 ] . icon , '🅰️' , 'A icon should be preserved' ) ;
1489+
1490+ // Restore original state
1491+ await config . update ( 'identities' , currentIdentities , vscode . ConfigurationTarget . Global ) ;
1492+ } ) ;
1493+ } ) ;
12341494} ) ;
0 commit comments