All checks were successful
Server Check Build (NixCN CMS) TeamCity build finished
Signed-off-by: Asai Neko <sugar@sne.moe>
444 lines
14 KiB
Go
444 lines
14 KiB
Go
package agenda
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/google/uuid"
|
|
"github.com/spf13/viper"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
"nixcn-cms/data"
|
|
"nixcn-cms/internal/authtoken"
|
|
"nixcn-cms/service/service_agenda"
|
|
"nixcn-cms/service/service_event"
|
|
"nixcn-cms/testutil"
|
|
)
|
|
|
|
func init() { gin.SetMode(gin.TestMode) }
|
|
|
|
func issueToken(t *testing.T, userId uuid.UUID) string {
|
|
t.Helper()
|
|
tok := &authtoken.Token{Application: viper.GetString("server.application")}
|
|
access, _, err := tok.IssueTokens(context.Background(), testutil.TestClientID, userId)
|
|
require.NoError(t, err)
|
|
return access
|
|
}
|
|
|
|
func newAgendaRouter(t *testing.T) *gin.Engine {
|
|
t.Helper()
|
|
r := gin.New()
|
|
ApiHandler(r.Group("/agenda"))
|
|
return r
|
|
}
|
|
|
|
func postWithBearer(t *testing.T, r *gin.Engine, path, token string, body any) *httptest.ResponseRecorder {
|
|
t.Helper()
|
|
b, _ := json.Marshal(body)
|
|
req := httptest.NewRequest(http.MethodPost, path, bytes.NewBuffer(b))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
if token != "" {
|
|
req.Header.Set("Authorization", "Bearer "+token)
|
|
}
|
|
w := httptest.NewRecorder()
|
|
r.ServeHTTP(w, req)
|
|
return w
|
|
}
|
|
|
|
func patchWithBearer(t *testing.T, r *gin.Engine, path, token string, body any) *httptest.ResponseRecorder {
|
|
t.Helper()
|
|
b, _ := json.Marshal(body)
|
|
req := httptest.NewRequest(http.MethodPatch, path, bytes.NewBuffer(b))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
if token != "" {
|
|
req.Header.Set("Authorization", "Bearer "+token)
|
|
}
|
|
w := httptest.NewRecorder()
|
|
r.ServeHTTP(w, req)
|
|
return w
|
|
}
|
|
|
|
func getWithBearer(t *testing.T, r *gin.Engine, path, token string) *httptest.ResponseRecorder {
|
|
t.Helper()
|
|
req := httptest.NewRequest(http.MethodGet, path, nil)
|
|
if token != "" {
|
|
req.Header.Set("Authorization", "Bearer "+token)
|
|
}
|
|
w := httptest.NewRecorder()
|
|
r.ServeHTTP(w, req)
|
|
return w
|
|
}
|
|
|
|
// seedEventWithAttendee creates an event owned by owner and joins it with attendee.
|
|
func seedEventWithAttendee(t *testing.T, owner, attendee *data.User) *data.Event {
|
|
t.Helper()
|
|
ctx := t.Context()
|
|
|
|
eventSvc := service_event.NewEventService()
|
|
cr := eventSvc.Create(&service_event.EventCreatePayload{
|
|
Context: ctx,
|
|
Data: &service_event.EventCreateData{
|
|
UserId: owner.UserId.String(),
|
|
PermissionLevel: owner.PermissionLevel,
|
|
Type: "party",
|
|
Name: "Agenda Test Event",
|
|
Subtitle: "sub",
|
|
StartTime: time.Now().Add(24 * time.Hour),
|
|
EndTime: time.Now().Add(48 * time.Hour),
|
|
Quota: 100,
|
|
Limit: 100,
|
|
},
|
|
})
|
|
require.Equal(t, 200, cr.Common.HttpCode)
|
|
|
|
eventId, err := uuid.Parse(cr.Data.EventId)
|
|
require.NoError(t, err)
|
|
|
|
// Join as attendee
|
|
agendaSvc := service_agenda.NewAgendaService()
|
|
jr := agendaSvc.Submit(&service_agenda.SubmitPayload{
|
|
Context: ctx,
|
|
UserId: attendee.UserId,
|
|
Data: &service_agenda.SubmitData{EventId: eventId, Name: "dummy"},
|
|
})
|
|
// It's OK if this fails due to not being joined; we just need the event.
|
|
_ = jr
|
|
|
|
// Actually join via event service
|
|
joinResult := eventSvc.Join(&service_event.EventJoinPayload{
|
|
Context: ctx,
|
|
Data: &service_event.EventJoinData{
|
|
EventId: cr.Data.EventId,
|
|
UserId: attendee.UserId.String(),
|
|
},
|
|
})
|
|
require.Equal(t, 200, joinResult.Common.HttpCode)
|
|
|
|
var event data.Event
|
|
require.NoError(t, data.Database.Where("event_id = ?", eventId).First(&event).Error)
|
|
return &event
|
|
}
|
|
|
|
// ---- Submit ----
|
|
|
|
func TestAgendaSubmitHandlerNoAuth(t *testing.T) {
|
|
testutil.Setup(t)
|
|
r := newAgendaRouter(t)
|
|
|
|
w := postWithBearer(t, r, "/agenda/submit", "", map[string]any{
|
|
"event_id": uuid.New().String(),
|
|
"name": "Test Talk",
|
|
})
|
|
assert.Equal(t, http.StatusUnauthorized, w.Code)
|
|
}
|
|
|
|
func TestAgendaSubmitHandlerMissingFields(t *testing.T) {
|
|
testutil.SetupWithAuth(t)
|
|
attendee := testutil.SeedUser(t, testutil.RandomEmail(), 10)
|
|
token := issueToken(t, attendee.UserId)
|
|
r := newAgendaRouter(t)
|
|
|
|
// Missing name and description → handler returns 400
|
|
w := postWithBearer(t, r, "/agenda/submit", token, map[string]any{
|
|
"event_id": uuid.New().String(),
|
|
})
|
|
assert.Equal(t, http.StatusBadRequest, w.Code)
|
|
}
|
|
|
|
func TestAgendaSubmitHandlerSuccess(t *testing.T) {
|
|
testutil.SetupWithAuth(t)
|
|
owner := testutil.SeedUser(t, testutil.RandomEmail(), 40)
|
|
attendee := testutil.SeedUser(t, testutil.RandomEmail(), 10)
|
|
event := seedEventWithAttendee(t, owner, attendee)
|
|
token := issueToken(t, attendee.UserId)
|
|
r := newAgendaRouter(t)
|
|
|
|
w := postWithBearer(t, r, "/agenda/submit", token, service_agenda.SubmitData{
|
|
EventId: event.EventId,
|
|
Name: "My Talk",
|
|
Description: "About Go testing",
|
|
})
|
|
assert.Equal(t, http.StatusOK, w.Code)
|
|
}
|
|
|
|
// ---- ScheduleGet ----
|
|
|
|
func TestAgendaScheduleGetHandlerInvalidEventId(t *testing.T) {
|
|
testutil.SetupWithAuth(t)
|
|
user := testutil.SeedUser(t, testutil.RandomEmail(), 10)
|
|
token := issueToken(t, user.UserId)
|
|
r := newAgendaRouter(t)
|
|
|
|
w := getWithBearer(t, r, "/agenda/schedule?event_id=not-a-uuid", token)
|
|
assert.Equal(t, http.StatusBadRequest, w.Code)
|
|
}
|
|
|
|
func TestAgendaScheduleGetHandlerNotPublished(t *testing.T) {
|
|
testutil.SetupWithAuth(t)
|
|
owner := testutil.SeedUser(t, testutil.RandomEmail(), 40)
|
|
attendee := testutil.SeedUser(t, testutil.RandomEmail(), 10)
|
|
event := seedEventWithAttendee(t, owner, attendee)
|
|
token := issueToken(t, attendee.UserId)
|
|
r := newAgendaRouter(t)
|
|
|
|
w := getWithBearer(t, r, "/agenda/schedule?event_id="+event.EventId.String(), token)
|
|
assert.Equal(t, http.StatusForbidden, w.Code)
|
|
}
|
|
|
|
// ---- MyList ----
|
|
|
|
func TestAgendaMyListHandlerInvalidEventId(t *testing.T) {
|
|
testutil.SetupWithAuth(t)
|
|
user := testutil.SeedUser(t, testutil.RandomEmail(), 10)
|
|
token := issueToken(t, user.UserId)
|
|
r := newAgendaRouter(t)
|
|
|
|
w := getWithBearer(t, r, "/agenda/my-list?event_id=bad-uuid", token)
|
|
assert.Equal(t, http.StatusBadRequest, w.Code)
|
|
}
|
|
|
|
func TestAgendaMyListHandlerSuccess(t *testing.T) {
|
|
testutil.SetupWithAuth(t)
|
|
owner := testutil.SeedUser(t, testutil.RandomEmail(), 40)
|
|
attendee := testutil.SeedUser(t, testutil.RandomEmail(), 10)
|
|
event := seedEventWithAttendee(t, owner, attendee)
|
|
token := issueToken(t, attendee.UserId)
|
|
r := newAgendaRouter(t)
|
|
|
|
w := getWithBearer(t, r, "/agenda/my-list?event_id="+event.EventId.String(), token)
|
|
assert.Equal(t, http.StatusOK, w.Code)
|
|
}
|
|
|
|
// ---- List (manager) ----
|
|
|
|
func TestAgendaListHandlerInvalidEventId(t *testing.T) {
|
|
testutil.SetupWithAuth(t)
|
|
manager := testutil.SeedUser(t, testutil.RandomEmail(), 30)
|
|
token := issueToken(t, manager.UserId)
|
|
r := newAgendaRouter(t)
|
|
|
|
w := getWithBearer(t, r, "/agenda/list?event_id=bad-uuid", token)
|
|
assert.Equal(t, http.StatusBadRequest, w.Code)
|
|
}
|
|
|
|
// ---- Review (manager) ----
|
|
|
|
func TestAgendaReviewHandlerMissingFields(t *testing.T) {
|
|
testutil.SetupWithAuth(t)
|
|
manager := testutil.SeedUser(t, testutil.RandomEmail(), 30)
|
|
token := issueToken(t, manager.UserId)
|
|
r := newAgendaRouter(t)
|
|
|
|
w := patchWithBearer(t, r, "/agenda/review", token, map[string]any{
|
|
"status": "approved",
|
|
// missing agenda_id and event_id → 400
|
|
})
|
|
assert.Equal(t, http.StatusBadRequest, w.Code)
|
|
}
|
|
|
|
func TestAgendaReviewHandlerInvalidStatus(t *testing.T) {
|
|
testutil.SetupWithAuth(t)
|
|
manager := testutil.SeedUser(t, testutil.RandomEmail(), 30)
|
|
token := issueToken(t, manager.UserId)
|
|
r := newAgendaRouter(t)
|
|
|
|
w := patchWithBearer(t, r, "/agenda/review", token, service_agenda.AgendaReviewData{
|
|
EventId: uuid.New(),
|
|
AgendaId: uuid.New(),
|
|
Status: "maybe",
|
|
})
|
|
assert.Equal(t, http.StatusBadRequest, w.Code)
|
|
}
|
|
|
|
func TestAgendaReviewHandlerSuccess(t *testing.T) {
|
|
testutil.SetupWithAuth(t)
|
|
owner := testutil.SeedUser(t, testutil.RandomEmail(), 40)
|
|
attendee := testutil.SeedUser(t, testutil.RandomEmail(), 10)
|
|
event := seedEventWithAttendee(t, owner, attendee)
|
|
manager := testutil.SeedUser(t, testutil.RandomEmail(), 30)
|
|
managerToken := issueToken(t, manager.UserId)
|
|
attendeeToken := issueToken(t, attendee.UserId)
|
|
r := newAgendaRouter(t)
|
|
|
|
submitW := postWithBearer(t, r, "/agenda/submit", attendeeToken, service_agenda.SubmitData{
|
|
EventId: event.EventId,
|
|
Name: "Talk to Review",
|
|
Description: "desc",
|
|
})
|
|
require.Equal(t, http.StatusOK, submitW.Code)
|
|
var submitResp map[string]any
|
|
require.NoError(t, json.Unmarshal(submitW.Body.Bytes(), &submitResp))
|
|
agendaId := submitResp["data"].(map[string]any)["agenda_id"].(string)
|
|
|
|
w := patchWithBearer(t, r, "/agenda/review", managerToken, service_agenda.AgendaReviewData{
|
|
EventId: event.EventId,
|
|
AgendaId: uuid.MustParse(agendaId),
|
|
Status: "approved",
|
|
})
|
|
assert.Equal(t, http.StatusOK, w.Code)
|
|
}
|
|
|
|
// ---- List (success) ----
|
|
|
|
func TestAgendaListHandlerSuccess(t *testing.T) {
|
|
testutil.SetupWithAuth(t)
|
|
owner := testutil.SeedUser(t, testutil.RandomEmail(), 40)
|
|
attendee := testutil.SeedUser(t, testutil.RandomEmail(), 10)
|
|
event := seedEventWithAttendee(t, owner, attendee)
|
|
manager := testutil.SeedUser(t, testutil.RandomEmail(), 30)
|
|
managerToken := issueToken(t, manager.UserId)
|
|
attendeeToken := issueToken(t, attendee.UserId)
|
|
r := newAgendaRouter(t)
|
|
|
|
postWithBearer(t, r, "/agenda/submit", attendeeToken, service_agenda.SubmitData{
|
|
EventId: event.EventId,
|
|
Name: "Talk 1",
|
|
})
|
|
|
|
w := getWithBearer(t, r, "/agenda/list?event_id="+event.EventId.String(), managerToken)
|
|
assert.Equal(t, http.StatusOK, w.Code)
|
|
}
|
|
|
|
// ---- Update ----
|
|
|
|
func TestAgendaUpdateHandlerMissingAgendaId(t *testing.T) {
|
|
testutil.SetupWithAuth(t)
|
|
user := testutil.SeedUser(t, testutil.RandomEmail(), 10)
|
|
token := issueToken(t, user.UserId)
|
|
r := newAgendaRouter(t)
|
|
|
|
w := patchWithBearer(t, r, "/agenda/update", token, map[string]any{
|
|
"name": "New Name",
|
|
})
|
|
assert.Equal(t, http.StatusBadRequest, w.Code)
|
|
}
|
|
|
|
func TestAgendaUpdateHandlerSuccess(t *testing.T) {
|
|
testutil.SetupWithAuth(t)
|
|
owner := testutil.SeedUser(t, testutil.RandomEmail(), 40)
|
|
attendee := testutil.SeedUser(t, testutil.RandomEmail(), 10)
|
|
event := seedEventWithAttendee(t, owner, attendee)
|
|
attendeeToken := issueToken(t, attendee.UserId)
|
|
r := newAgendaRouter(t)
|
|
|
|
submitW := postWithBearer(t, r, "/agenda/submit", attendeeToken, service_agenda.SubmitData{
|
|
EventId: event.EventId,
|
|
Name: "Original Talk",
|
|
Description: "desc",
|
|
})
|
|
require.Equal(t, http.StatusOK, submitW.Code)
|
|
var submitResp map[string]any
|
|
require.NoError(t, json.Unmarshal(submitW.Body.Bytes(), &submitResp))
|
|
agendaId := submitResp["data"].(map[string]any)["agenda_id"].(string)
|
|
|
|
newName := "Updated Talk"
|
|
w := patchWithBearer(t, r, "/agenda/update", attendeeToken, service_agenda.AgendaUpdateData{
|
|
AgendaId: uuid.MustParse(agendaId),
|
|
Name: &newName,
|
|
})
|
|
assert.Equal(t, http.StatusOK, w.Code)
|
|
}
|
|
|
|
// ---- Schedule PATCH ----
|
|
|
|
func TestAgendaScheduleHandlerMissingAgendaId(t *testing.T) {
|
|
testutil.SetupWithAuth(t)
|
|
manager := testutil.SeedUser(t, testutil.RandomEmail(), 30)
|
|
token := issueToken(t, manager.UserId)
|
|
r := newAgendaRouter(t)
|
|
|
|
w := patchWithBearer(t, r, "/agenda/schedule", token, map[string]any{
|
|
"start_time": time.Now().Add(time.Hour),
|
|
"end_time": time.Now().Add(2 * time.Hour),
|
|
})
|
|
assert.Equal(t, http.StatusBadRequest, w.Code)
|
|
}
|
|
|
|
func TestAgendaScheduleHandlerSuccess(t *testing.T) {
|
|
testutil.SetupWithAuth(t)
|
|
owner := testutil.SeedUser(t, testutil.RandomEmail(), 40)
|
|
attendee := testutil.SeedUser(t, testutil.RandomEmail(), 10)
|
|
event := seedEventWithAttendee(t, owner, attendee)
|
|
manager := testutil.SeedUser(t, testutil.RandomEmail(), 30)
|
|
managerToken := issueToken(t, manager.UserId)
|
|
attendeeToken := issueToken(t, attendee.UserId)
|
|
r := newAgendaRouter(t)
|
|
|
|
submitW := postWithBearer(t, r, "/agenda/submit", attendeeToken, service_agenda.SubmitData{
|
|
EventId: event.EventId,
|
|
Name: "Schedule Me",
|
|
Description: "base64desc",
|
|
})
|
|
require.Equal(t, http.StatusOK, submitW.Code)
|
|
var submitResp map[string]any
|
|
require.NoError(t, json.Unmarshal(submitW.Body.Bytes(), &submitResp))
|
|
agendaId := submitResp["data"].(map[string]any)["agenda_id"].(string)
|
|
|
|
reviewW := patchWithBearer(t, r, "/agenda/review", managerToken, service_agenda.AgendaReviewData{
|
|
EventId: event.EventId,
|
|
AgendaId: uuid.MustParse(agendaId),
|
|
Status: "approved",
|
|
})
|
|
require.Equal(t, http.StatusOK, reviewW.Code)
|
|
|
|
now := time.Now()
|
|
w := patchWithBearer(t, r, "/agenda/schedule", managerToken, service_agenda.AgendaScheduleData{
|
|
AgendaId: uuid.MustParse(agendaId),
|
|
StartTime: now.Add(time.Hour),
|
|
EndTime: now.Add(2 * time.Hour),
|
|
})
|
|
assert.Equal(t, http.StatusOK, w.Code)
|
|
}
|
|
|
|
// ---- ScheduleGet (success) ----
|
|
|
|
func TestAgendaScheduleGetHandlerSuccess(t *testing.T) {
|
|
testutil.SetupWithAuth(t)
|
|
owner := testutil.SeedUser(t, testutil.RandomEmail(), 40)
|
|
attendee := testutil.SeedUser(t, testutil.RandomEmail(), 10)
|
|
event := seedEventWithAttendee(t, owner, attendee)
|
|
manager := testutil.SeedUser(t, testutil.RandomEmail(), 30)
|
|
managerToken := issueToken(t, manager.UserId)
|
|
attendeeToken := issueToken(t, attendee.UserId)
|
|
r := newAgendaRouter(t)
|
|
|
|
submitW := postWithBearer(t, r, "/agenda/submit", attendeeToken, service_agenda.SubmitData{
|
|
EventId: event.EventId,
|
|
Name: "Published Talk",
|
|
Description: "base64desc",
|
|
})
|
|
require.Equal(t, http.StatusOK, submitW.Code)
|
|
var submitResp map[string]any
|
|
require.NoError(t, json.Unmarshal(submitW.Body.Bytes(), &submitResp))
|
|
agendaId := submitResp["data"].(map[string]any)["agenda_id"].(string)
|
|
|
|
patchWithBearer(t, r, "/agenda/review", managerToken, service_agenda.AgendaReviewData{
|
|
EventId: event.EventId,
|
|
AgendaId: uuid.MustParse(agendaId),
|
|
Status: "approved",
|
|
})
|
|
|
|
now := time.Now()
|
|
patchWithBearer(t, r, "/agenda/schedule", managerToken, service_agenda.AgendaScheduleData{
|
|
AgendaId: uuid.MustParse(agendaId),
|
|
StartTime: now.Add(time.Hour),
|
|
EndTime: now.Add(2 * time.Hour),
|
|
})
|
|
|
|
require.NoError(t, new(data.Event).PatchByEventId(t.Context(), event.EventId, data.WithIsAgendaPublished(true)))
|
|
|
|
w := getWithBearer(t, r, "/agenda/schedule?event_id="+event.EventId.String(), attendeeToken)
|
|
assert.Equal(t, http.StatusOK, w.Code)
|
|
var resp map[string]any
|
|
require.NoError(t, json.Unmarshal(w.Body.Bytes(), &resp))
|
|
items, ok := resp["data"].([]any)
|
|
require.True(t, ok)
|
|
assert.Len(t, items, 1)
|
|
}
|