@@ -364,6 +364,106 @@ func TestLoadMappingsFromFile_InvalidJSON(t *testing.T) {
364364 assert .Error (t , err )
365365 assert .Contains (t , err .Error (), "failed to parse mapping file" )
366366}
367+
368+ func TestResolveMatrixIDToIdentifier_SubNumbers (t * testing.T ) {
369+ // Test case 1: Resolve via sub_number match
370+ // When a matrix_id matches one of the sub_numbers, the main number should be returned (not the sub_number)
371+ t .Run ("resolve via sub_number match" , func (t * testing.T ) {
372+ svc := NewMessageService (nil , nil )
373+ svc .SaveMapping (& models.MappingRequest {
374+ Number : "201" ,
375+ MatrixID : "@giacomo:example.com" ,
376+ RoomID : "!room1:example.com" ,
377+ UserName : "Giacomo Rossi" ,
378+ SubNumbers : []string {"3344" , "91201" },
379+ })
380+
381+ // Resolve using a sub_number - should return the main number
382+ result := svc .resolveMatrixIDToIdentifier ("@giacomo:example.com" )
383+ assert .Equal (t , "201" , result , "should return main number when matrix_id matches via sub_number" )
384+ })
385+
386+ // Test case 2: Resolve via main number
387+ // When a matrix_id matches the main number field, return that number
388+ t .Run ("resolve via main number" , func (t * testing.T ) {
389+ svc := NewMessageService (nil , nil )
390+ svc .SaveMapping (& models.MappingRequest {
391+ Number : "202" ,
392+ MatrixID : "@mario:example.com" ,
393+ RoomID : "!room2:example.com" ,
394+ UserName : "Mario Bianchi" ,
395+ })
396+
397+ // Resolve using the matrix_id - should return the main number
398+ result := svc .resolveMatrixIDToIdentifier ("@mario:example.com" )
399+ assert .Equal (t , "202" , result , "should return main number when matrix_id matches" )
400+ })
401+
402+ // Test case 3: Sub_numbers should never be returned directly
403+ // This is ensured by the logic that checks sub_numbers first, then returns the main number
404+ t .Run ("sub_numbers never returned directly" , func (t * testing.T ) {
405+ svc := NewMessageService (nil , nil )
406+ svc .SaveMapping (& models.MappingRequest {
407+ Number : "201" ,
408+ MatrixID : "@giacomo:example.com" ,
409+ RoomID : "!room1:example.com" ,
410+ UserName : "Giacomo Rossi" ,
411+ SubNumbers : []string {"3344" , "91201" },
412+ })
413+
414+ // Try to resolve using the main number
415+ result := svc .resolveMatrixIDToIdentifier ("@giacomo:example.com" )
416+ assert .Equal (t , "201" , result )
417+ assert .NotEqual (t , "3344" , result , "should never return sub_number directly" )
418+ assert .NotEqual (t , "91201" , result , "should never return sub_number directly" )
419+ })
420+
421+ // Test case 4: Case insensitivity
422+ // Matrix IDs should be matched case-insensitively
423+ t .Run ("case insensitivity" , func (t * testing.T ) {
424+ svc := NewMessageService (nil , nil )
425+ svc .SaveMapping (& models.MappingRequest {
426+ Number : "201" ,
427+ MatrixID : "@giacomo:example.com" ,
428+ RoomID : "!room1:example.com" ,
429+ UserName : "Giacomo Rossi" ,
430+ SubNumbers : []string {"3344" , "91201" },
431+ })
432+
433+ // Try with uppercase
434+ result := svc .resolveMatrixIDToIdentifier ("@GIACOMO:EXAMPLE.COM" )
435+ assert .Equal (t , "201" , result , "should match case-insensitively" )
436+ })
437+
438+ // Test case 5: Fallback to UserName when no sub_numbers or main number
439+ // If matrix_id doesn't match main number but UserName is set, return UserName
440+ t .Run ("fallback to user name" , func (t * testing.T ) {
441+ svc := NewMessageService (nil , nil )
442+ // Create a mapping with matrix_id and username but no number
443+ entry := mappingEntry {
444+ Number : "internal|key" ,
445+ MatrixID : "@test:example.com" ,
446+ UserName : "Test User" ,
447+ SubNumbers : []string {},
448+ UpdatedAt : svc .now (),
449+ }
450+ svc .setMapping (entry )
451+
452+ // The matrix_id should match and we should get the number since it's available
453+ // So this test actually verifies that internal mappings are skipped
454+ result := svc .resolveMatrixIDToIdentifier ("@test:example.com" )
455+ // Internal mappings (with |) should be skipped, so no match expected
456+ assert .Equal (t , "@test:example.com" , result , "internal mappings should be skipped" )
457+ })
458+
459+ // Test case 6: No mapping found, return original matrix_id
460+ t .Run ("no mapping returns original matrix_id" , func (t * testing.T ) {
461+ svc := NewMessageService (nil , nil )
462+ result := svc .resolveMatrixIDToIdentifier ("@unknown:example.com" )
463+ assert .Equal (t , "@unknown:example.com" , result , "should return original matrix_id when no mapping found" )
464+ })
465+ }
466+
367467func TestReportPushToken (t * testing.T ) {
368468 // Test with nil request
369469 t .Run ("nil request" , func (t * testing.T ) {
0 commit comments