@@ -1522,3 +1522,168 @@ func TestRun_OfflineMode_NoTokenRequired(t *testing.T) {
15221522 t .Errorf ("should not require GITHUB_TOKEN in offline mode, got: %s" , stderr .String ())
15231523 }
15241524}
1525+
1526+ func TestFilterResultBySinceDate (t * testing.T ) {
1527+ now := time .Date (2026 , 1 , 22 , 12 , 0 , 0 , 0 , time .UTC )
1528+ sinceDate := time .Date (2026 , 1 , 21 , 0 , 0 , 0 , 0 , time .UTC )
1529+ oldDate := time .Date (2026 , 1 , 5 , 0 , 0 , 0 , 0 , time .UTC ) // 3 weeks ago
1530+
1531+ result := & diff.Result {
1532+ OldCapturedAt : time .Date (2026 , 1 , 1 , 0 , 0 , 0 , 0 , time .UTC ),
1533+ NewCapturedAt : now ,
1534+ NewStars : []diff.RepoChange {
1535+ {
1536+ Username : "simonw" ,
1537+ Repo : diff.Repo {
1538+ Owner : "simonw" ,
1539+ Name : "old-repo" ,
1540+ CreatedAt : oldDate , // Should be filtered out
1541+ },
1542+ },
1543+ {
1544+ Username : "octocat" ,
1545+ Repo : diff.Repo {
1546+ Owner : "octocat" ,
1547+ Name : "new-repo" ,
1548+ CreatedAt : sinceDate .Add (time .Hour ), // Should be included
1549+ },
1550+ },
1551+ },
1552+ NewRepos : []diff.RepoChange {
1553+ {
1554+ Username : "user1" ,
1555+ Repo : diff.Repo {
1556+ Owner : "user1" ,
1557+ Name : "ancient-repo" ,
1558+ CreatedAt : oldDate , // Should be filtered out
1559+ },
1560+ },
1561+ {
1562+ Username : "user2" ,
1563+ Repo : diff.Repo {
1564+ Owner : "user2" ,
1565+ Name : "recent-repo" ,
1566+ CreatedAt : now , // Should be included
1567+ },
1568+ },
1569+ },
1570+ NewEvents : []diff.EventChange {
1571+ {
1572+ Username : "simonw" ,
1573+ Event : diff.Event {
1574+ Type : "PushEvent" ,
1575+ Actor : "simonw" ,
1576+ Repo : "simonw/old-project" ,
1577+ CreatedAt : oldDate , // Should be filtered out
1578+ },
1579+ },
1580+ {
1581+ Username : "octocat" ,
1582+ Event : diff.Event {
1583+ Type : "PushEvent" ,
1584+ Actor : "octocat" ,
1585+ Repo : "octocat/fresh-project" ,
1586+ CreatedAt : sinceDate , // Exactly on since date - should be included
1587+ },
1588+ },
1589+ },
1590+ NewUsers : []string {"newuser1" , "newuser2" },
1591+ GoneUsers : []string {"goneuser1" },
1592+ }
1593+
1594+ filtered := filterResultBySinceDate (result , sinceDate )
1595+
1596+ // Check that timestamps are preserved
1597+ if ! filtered .OldCapturedAt .Equal (result .OldCapturedAt ) {
1598+ t .Errorf ("OldCapturedAt mismatch: got %v, want %v" , filtered .OldCapturedAt , result .OldCapturedAt )
1599+ }
1600+ if ! filtered .NewCapturedAt .Equal (result .NewCapturedAt ) {
1601+ t .Errorf ("NewCapturedAt mismatch: got %v, want %v" , filtered .NewCapturedAt , result .NewCapturedAt )
1602+ }
1603+
1604+ // Check that user lists are preserved
1605+ if len (filtered .NewUsers ) != 2 || filtered .NewUsers [0 ] != "newuser1" {
1606+ t .Errorf ("NewUsers not preserved: got %v, want %v" , filtered .NewUsers , result .NewUsers )
1607+ }
1608+ if len (filtered .GoneUsers ) != 1 || filtered .GoneUsers [0 ] != "goneuser1" {
1609+ t .Errorf ("GoneUsers not preserved: got %v, want %v" , filtered .GoneUsers , result .GoneUsers )
1610+ }
1611+
1612+ // Check that old stars are filtered out
1613+ if len (filtered .NewStars ) != 1 {
1614+ t .Fatalf ("expected 1 new star, got %d" , len (filtered .NewStars ))
1615+ }
1616+ if filtered .NewStars [0 ].Username != "octocat" {
1617+ t .Errorf ("wrong star kept: got %s, want octocat" , filtered .NewStars [0 ].Username )
1618+ }
1619+
1620+ // Check that old repos are filtered out
1621+ if len (filtered .NewRepos ) != 1 {
1622+ t .Fatalf ("expected 1 new repo, got %d" , len (filtered .NewRepos ))
1623+ }
1624+ if filtered .NewRepos [0 ].Username != "user2" {
1625+ t .Errorf ("wrong repo kept: got %s, want user2" , filtered .NewRepos [0 ].Username )
1626+ }
1627+
1628+ // Check that old events are filtered out
1629+ if len (filtered .NewEvents ) != 1 {
1630+ t .Fatalf ("expected 1 new event, got %d" , len (filtered .NewEvents ))
1631+ }
1632+ if filtered .NewEvents [0 ].Username != "octocat" {
1633+ t .Errorf ("wrong event kept: got %s, want octocat" , filtered .NewEvents [0 ].Username )
1634+ }
1635+ }
1636+
1637+ func TestFilterResultBySinceDate_BoundaryConditions (t * testing.T ) {
1638+ sinceDate := time .Date (2026 , 1 , 15 , 0 , 0 , 0 , 0 , time .UTC )
1639+
1640+ tests := []struct {
1641+ createdAt time.Time
1642+ name string
1643+ shouldInclude bool
1644+ }{
1645+ {
1646+ name : "before since date" ,
1647+ createdAt : sinceDate .Add (- 24 * time .Hour ),
1648+ shouldInclude : false ,
1649+ },
1650+ {
1651+ name : "exactly on since date" ,
1652+ createdAt : sinceDate ,
1653+ shouldInclude : true ,
1654+ },
1655+ {
1656+ name : "after since date" ,
1657+ createdAt : sinceDate .Add (24 * time .Hour ),
1658+ shouldInclude : true ,
1659+ },
1660+ }
1661+
1662+ for _ , tt := range tests {
1663+ t .Run (tt .name , func (t * testing.T ) {
1664+ result := & diff.Result {
1665+ NewStars : []diff.RepoChange {
1666+ {
1667+ Username : "user" ,
1668+ Repo : diff.Repo {
1669+ Owner : "user" ,
1670+ Name : "repo" ,
1671+ CreatedAt : tt .createdAt ,
1672+ },
1673+ },
1674+ },
1675+ }
1676+
1677+ filtered := filterResultBySinceDate (result , sinceDate )
1678+
1679+ expectedCount := 0
1680+ if tt .shouldInclude {
1681+ expectedCount = 1
1682+ }
1683+
1684+ if len (filtered .NewStars ) != expectedCount {
1685+ t .Errorf ("expected %d stars, got %d" , expectedCount , len (filtered .NewStars ))
1686+ }
1687+ })
1688+ }
1689+ }
0 commit comments