test(09-03): add task etape assignment tests
This commit is contained in:
parent
3ce7c8ea4f
commit
9f6c7eb044
1 changed files with 313 additions and 0 deletions
|
|
@ -302,6 +302,319 @@ func TestTaskUpdate(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestTaskEditRendersEtapeSelector(t *testing.T) {
|
||||
pool, cleanup := setupTestDB(t)
|
||||
defer cleanup()
|
||||
|
||||
ctx := context.Background()
|
||||
q := sqlc.New(pool)
|
||||
store := auth.NewStore(q)
|
||||
router := newTaskTestRouter(q, store)
|
||||
|
||||
user := preInsertUser(t, ctx, q, "taskeditetape@example.com", "correct-horse-12")
|
||||
tablo, err := q.InsertTablo(ctx, sqlc.InsertTabloParams{
|
||||
UserID: user.ID,
|
||||
Title: "Task Edit Etape Tablo",
|
||||
Description: pgtype.Text{Valid: false},
|
||||
Color: pgtype.Text{Valid: false},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("InsertTablo: %v", err)
|
||||
}
|
||||
etape, err := q.InsertEtape(ctx, sqlc.InsertEtapeParams{
|
||||
TabloID: tablo.ID,
|
||||
Title: "Design",
|
||||
Description: pgtype.Text{Valid: false},
|
||||
Position: 100,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("InsertEtape: %v", err)
|
||||
}
|
||||
task, err := q.InsertTask(ctx, sqlc.InsertTaskParams{
|
||||
TabloID: tablo.ID,
|
||||
Title: "Editable",
|
||||
Description: pgtype.Text{Valid: false},
|
||||
Status: sqlc.TaskStatusTodo,
|
||||
Position: 100,
|
||||
EtapeID: pgtype.UUID{Bytes: etape.ID, Valid: true},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("InsertTask: %v", err)
|
||||
}
|
||||
|
||||
cookieVal, _, err := store.Create(ctx, user.ID)
|
||||
if err != nil {
|
||||
t.Fatalf("store.Create: %v", err)
|
||||
}
|
||||
sessionCookie := &http.Cookie{Name: auth.SessionCookieName, Value: cookieVal}
|
||||
|
||||
req := httptest.NewRequest(http.MethodGet, "/tablos/"+tablo.ID.String()+"/tasks/"+task.ID.String()+"/edit", nil)
|
||||
req.Header.Set("HX-Request", "true")
|
||||
req.AddCookie(sessionCookie)
|
||||
rec := httptest.NewRecorder()
|
||||
router.ServeHTTP(rec, req)
|
||||
|
||||
if rec.Code != http.StatusOK {
|
||||
t.Fatalf("GET task edit status = %d; want 200", rec.Code)
|
||||
}
|
||||
body := rec.Body.String()
|
||||
for _, want := range []string{"Etape", "No etape", "Design"} {
|
||||
if !strings.Contains(body, want) {
|
||||
t.Errorf("edit form missing %q; body: %.500s", want, body)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestTaskUpdateAssignsAndUnassignsEtape(t *testing.T) {
|
||||
pool, cleanup := setupTestDB(t)
|
||||
defer cleanup()
|
||||
|
||||
ctx := context.Background()
|
||||
q := sqlc.New(pool)
|
||||
store := auth.NewStore(q)
|
||||
router := newTaskTestRouter(q, store)
|
||||
|
||||
user := preInsertUser(t, ctx, q, "taskupdateetape@example.com", "correct-horse-12")
|
||||
tablo, err := q.InsertTablo(ctx, sqlc.InsertTabloParams{
|
||||
UserID: user.ID,
|
||||
Title: "Task Update Etape Tablo",
|
||||
Description: pgtype.Text{Valid: false},
|
||||
Color: pgtype.Text{Valid: false},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("InsertTablo: %v", err)
|
||||
}
|
||||
etape, err := q.InsertEtape(ctx, sqlc.InsertEtapeParams{
|
||||
TabloID: tablo.ID,
|
||||
Title: "Design",
|
||||
Description: pgtype.Text{Valid: false},
|
||||
Position: 100,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("InsertEtape: %v", err)
|
||||
}
|
||||
task, err := q.InsertTask(ctx, sqlc.InsertTaskParams{
|
||||
TabloID: tablo.ID,
|
||||
Title: "Assignable",
|
||||
Description: pgtype.Text{Valid: false},
|
||||
Status: sqlc.TaskStatusInReview,
|
||||
Position: 300,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("InsertTask: %v", err)
|
||||
}
|
||||
|
||||
cookieVal, _, err := store.Create(ctx, user.ID)
|
||||
if err != nil {
|
||||
t.Fatalf("store.Create: %v", err)
|
||||
}
|
||||
sessionCookie := &http.Cookie{Name: auth.SessionCookieName, Value: cookieVal}
|
||||
csrfToken, csrfCookies := getCSRFToken(t, router, "/tablos/"+tablo.ID.String(), []*http.Cookie{sessionCookie})
|
||||
|
||||
postUpdate := func(etapeID string) {
|
||||
t.Helper()
|
||||
form := url.Values{
|
||||
"title": {"Assignable"},
|
||||
"description": {"Updated"},
|
||||
"etape_id": {etapeID},
|
||||
"_csrf": {csrfToken},
|
||||
}
|
||||
req := httptest.NewRequest(http.MethodPost, "/tablos/"+tablo.ID.String()+"/tasks/"+task.ID.String(), strings.NewReader(form.Encode()))
|
||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||
req.Header.Set("HX-Request", "true")
|
||||
for _, c := range csrfCookies {
|
||||
req.AddCookie(c)
|
||||
}
|
||||
rec := httptest.NewRecorder()
|
||||
router.ServeHTTP(rec, req)
|
||||
if rec.Code != http.StatusOK {
|
||||
t.Fatalf("POST task update status = %d; want 200; body: %.500s", rec.Code, rec.Body.String())
|
||||
}
|
||||
}
|
||||
|
||||
postUpdate(etape.ID.String())
|
||||
assigned, err := q.GetTaskByID(ctx, sqlc.GetTaskByIDParams{ID: task.ID, TabloID: tablo.ID})
|
||||
if err != nil {
|
||||
t.Fatalf("GetTaskByID assigned: %v", err)
|
||||
}
|
||||
if !assigned.EtapeID.Valid || assigned.EtapeID.Bytes != etape.ID {
|
||||
t.Fatalf("assigned etape_id = %+v; want %s", assigned.EtapeID, etape.ID)
|
||||
}
|
||||
if assigned.Status != sqlc.TaskStatusInReview || assigned.Position != 300 {
|
||||
t.Fatalf("status/position changed after assignment: %+v", assigned)
|
||||
}
|
||||
|
||||
postUpdate("")
|
||||
unassigned, err := q.GetTaskByID(ctx, sqlc.GetTaskByIDParams{ID: task.ID, TabloID: tablo.ID})
|
||||
if err != nil {
|
||||
t.Fatalf("GetTaskByID unassigned: %v", err)
|
||||
}
|
||||
if unassigned.EtapeID.Valid {
|
||||
t.Fatalf("etape_id valid after unassign; want null")
|
||||
}
|
||||
}
|
||||
|
||||
func TestTaskAssignmentRejectsForeignEtape(t *testing.T) {
|
||||
pool, cleanup := setupTestDB(t)
|
||||
defer cleanup()
|
||||
|
||||
ctx := context.Background()
|
||||
q := sqlc.New(pool)
|
||||
store := auth.NewStore(q)
|
||||
router := newTaskTestRouter(q, store)
|
||||
|
||||
user := preInsertUser(t, ctx, q, "taskforeignetape@example.com", "correct-horse-12")
|
||||
firstTablo, err := q.InsertTablo(ctx, sqlc.InsertTabloParams{
|
||||
UserID: user.ID,
|
||||
Title: "First",
|
||||
Description: pgtype.Text{Valid: false},
|
||||
Color: pgtype.Text{Valid: false},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("InsertTablo first: %v", err)
|
||||
}
|
||||
secondTablo, err := q.InsertTablo(ctx, sqlc.InsertTabloParams{
|
||||
UserID: user.ID,
|
||||
Title: "Second",
|
||||
Description: pgtype.Text{Valid: false},
|
||||
Color: pgtype.Text{Valid: false},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("InsertTablo second: %v", err)
|
||||
}
|
||||
foreignEtape, err := q.InsertEtape(ctx, sqlc.InsertEtapeParams{
|
||||
TabloID: secondTablo.ID,
|
||||
Title: "Foreign",
|
||||
Description: pgtype.Text{Valid: false},
|
||||
Position: 100,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("InsertEtape: %v", err)
|
||||
}
|
||||
task, err := q.InsertTask(ctx, sqlc.InsertTaskParams{
|
||||
TabloID: firstTablo.ID,
|
||||
Title: "Protected",
|
||||
Description: pgtype.Text{Valid: false},
|
||||
Status: sqlc.TaskStatusTodo,
|
||||
Position: 100,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("InsertTask: %v", err)
|
||||
}
|
||||
|
||||
cookieVal, _, err := store.Create(ctx, user.ID)
|
||||
if err != nil {
|
||||
t.Fatalf("store.Create: %v", err)
|
||||
}
|
||||
sessionCookie := &http.Cookie{Name: auth.SessionCookieName, Value: cookieVal}
|
||||
csrfToken, csrfCookies := getCSRFToken(t, router, "/tablos/"+firstTablo.ID.String(), []*http.Cookie{sessionCookie})
|
||||
|
||||
form := url.Values{
|
||||
"title": {"Protected"},
|
||||
"description": {""},
|
||||
"etape_id": {foreignEtape.ID.String()},
|
||||
"_csrf": {csrfToken},
|
||||
}
|
||||
req := httptest.NewRequest(http.MethodPost, "/tablos/"+firstTablo.ID.String()+"/tasks/"+task.ID.String(), strings.NewReader(form.Encode()))
|
||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||
req.Header.Set("HX-Request", "true")
|
||||
for _, c := range csrfCookies {
|
||||
req.AddCookie(c)
|
||||
}
|
||||
rec := httptest.NewRecorder()
|
||||
router.ServeHTTP(rec, req)
|
||||
|
||||
if rec.Code == http.StatusOK {
|
||||
t.Fatalf("foreign etape assignment status = 200; want failure")
|
||||
}
|
||||
unchanged, err := q.GetTaskByID(ctx, sqlc.GetTaskByIDParams{ID: task.ID, TabloID: firstTablo.ID})
|
||||
if err != nil {
|
||||
t.Fatalf("GetTaskByID: %v", err)
|
||||
}
|
||||
if unchanged.EtapeID.Valid {
|
||||
t.Fatalf("foreign assignment updated task etape_id: %+v", unchanged.EtapeID)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTasksTabUnassignedFilter(t *testing.T) {
|
||||
pool, cleanup := setupTestDB(t)
|
||||
defer cleanup()
|
||||
|
||||
ctx := context.Background()
|
||||
q := sqlc.New(pool)
|
||||
store := auth.NewStore(q)
|
||||
router := newTaskTestRouter(q, store)
|
||||
|
||||
user := preInsertUser(t, ctx, q, "tasksunassignedfilter@example.com", "correct-horse-12")
|
||||
tablo, err := q.InsertTablo(ctx, sqlc.InsertTabloParams{
|
||||
UserID: user.ID,
|
||||
Title: "Unassigned Filter",
|
||||
Description: pgtype.Text{Valid: false},
|
||||
Color: pgtype.Text{Valid: false},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("InsertTablo: %v", err)
|
||||
}
|
||||
etape, err := q.InsertEtape(ctx, sqlc.InsertEtapeParams{
|
||||
TabloID: tablo.ID,
|
||||
Title: "Design",
|
||||
Description: pgtype.Text{Valid: false},
|
||||
Position: 100,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("InsertEtape: %v", err)
|
||||
}
|
||||
_, err = q.InsertTask(ctx, sqlc.InsertTaskParams{
|
||||
TabloID: tablo.ID,
|
||||
Title: "Assigned Hidden",
|
||||
Description: pgtype.Text{Valid: false},
|
||||
Status: sqlc.TaskStatusTodo,
|
||||
Position: 100,
|
||||
EtapeID: pgtype.UUID{Bytes: etape.ID, Valid: true},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("InsertTask assigned: %v", err)
|
||||
}
|
||||
_, err = q.InsertTask(ctx, sqlc.InsertTaskParams{
|
||||
TabloID: tablo.ID,
|
||||
Title: "Unassigned Visible",
|
||||
Description: pgtype.Text{Valid: false},
|
||||
Status: sqlc.TaskStatusDone,
|
||||
Position: 100,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("InsertTask unassigned: %v", err)
|
||||
}
|
||||
|
||||
cookieVal, _, err := store.Create(ctx, user.ID)
|
||||
if err != nil {
|
||||
t.Fatalf("store.Create: %v", err)
|
||||
}
|
||||
sessionCookie := &http.Cookie{Name: auth.SessionCookieName, Value: cookieVal}
|
||||
|
||||
req := httptest.NewRequest(http.MethodGet, "/tablos/"+tablo.ID.String()+"/tasks?etape=unassigned", nil)
|
||||
req.Header.Set("HX-Request", "true")
|
||||
req.AddCookie(sessionCookie)
|
||||
rec := httptest.NewRecorder()
|
||||
router.ServeHTTP(rec, req)
|
||||
|
||||
if rec.Code != http.StatusOK {
|
||||
t.Fatalf("GET unassigned filter status = %d; want 200", rec.Code)
|
||||
}
|
||||
body := rec.Body.String()
|
||||
for _, col := range []string{"To do", "In progress", "In review", "Done"} {
|
||||
if !strings.Contains(body, col) {
|
||||
t.Errorf("unassigned filter missing column %q", col)
|
||||
}
|
||||
}
|
||||
if !strings.Contains(body, "Unassigned Visible") {
|
||||
t.Errorf("unassigned filter missing unassigned task; body: %.500s", body)
|
||||
}
|
||||
if strings.Contains(body, "Assigned Hidden") {
|
||||
t.Errorf("unassigned filter includes assigned task; body: %.500s", body)
|
||||
}
|
||||
}
|
||||
|
||||
// ---- TestTaskReorderCrossColumn (TASK-04) ----
|
||||
|
||||
// TestTaskReorderCrossColumn verifies that POST /tablos/{id}/tasks/reorder
|
||||
|
|
|
|||
Loading…
Reference in a new issue