test(project): pin archived propagation aggregation in ReadAll CTE
Regression test for #2589. Locks the contract that getAllProjectsForUser exposes inherited is_archived for child projects of archived parents and filters them out when getArchived=false, exercising both the MAX(...) column expression and the HAVING MAX(...) = 0 filter.
This commit is contained in:
parent
c9809f1385
commit
3b7996feef
|
|
@ -629,6 +629,52 @@ func TestProject_ReadAll(t *testing.T) {
|
||||||
assert.Equal(t, int64(-1), ls[0].ID)
|
assert.Equal(t, int64(-1), ls[0].ID)
|
||||||
assert.Equal(t, int64(-2), ls[1].ID)
|
assert.Equal(t, int64(-2), ls[1].ID)
|
||||||
})
|
})
|
||||||
|
t.Run("archived propagation aggregation", func(t *testing.T) {
|
||||||
|
// Regression test for #2589. getAllProjectsForUser must:
|
||||||
|
// 1. Expose inherited is_archived for child projects whose parent is archived
|
||||||
|
// (exercises the MAX(...) AS is_archived column expression).
|
||||||
|
// 2. Hide those inherited-archived rows when getArchived=false
|
||||||
|
// (exercises the HAVING MAX(...) = 0 filter).
|
||||||
|
// The CTE must use dialect-agnostic SQL — no CAST(... AS int), which MySQL 8 rejects.
|
||||||
|
|
||||||
|
db.LoadAndAssertFixtures(t)
|
||||||
|
s := db.NewSession()
|
||||||
|
defer s.Close()
|
||||||
|
|
||||||
|
findByID := func(ps []*Project, id int64) *Project {
|
||||||
|
for _, p := range ps {
|
||||||
|
if p.ID == id {
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// getArchived=true: project 21 (child of archived 22) must appear and carry is_archived=true.
|
||||||
|
withArchived, _, err := getAllProjectsForUser(s, 1, &projectOptions{getArchived: true})
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
parent := findByID(withArchived, 22)
|
||||||
|
require.NotNil(t, parent, "archived parent project 22 must be returned when getArchived=true")
|
||||||
|
assert.True(t, parent.IsArchived, "project 22 is archived in fixtures")
|
||||||
|
|
||||||
|
child := findByID(withArchived, 21)
|
||||||
|
require.NotNil(t, child, "child project 21 must be returned when getArchived=true")
|
||||||
|
assert.True(t, child.IsArchived, "project 21 must inherit is_archived from its archived parent (22)")
|
||||||
|
|
||||||
|
// getArchived=false: both rows must be filtered out by the HAVING clause.
|
||||||
|
withoutArchived, _, err := getAllProjectsForUser(s, 1, &projectOptions{getArchived: false})
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
assert.Nil(t, findByID(withoutArchived, 22),
|
||||||
|
"archived project 22 must be filtered when getArchived=false")
|
||||||
|
assert.Nil(t, findByID(withoutArchived, 21),
|
||||||
|
"child of archived project (21) must be filtered when getArchived=false (inherited archived state)")
|
||||||
|
|
||||||
|
// Sanity: a non-archived project owned by user 1 is still present in the filtered list.
|
||||||
|
assert.NotNil(t, findByID(withoutArchived, 1),
|
||||||
|
"non-archived project 1 must still be present when getArchived=false")
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestProject_ReadOne(t *testing.T) {
|
func TestProject_ReadOne(t *testing.T) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue