From 941e9a36fbc1e2a7bc410fae03fba4c57f4d165e Mon Sep 17 00:00:00 2001 From: dylan Date: Wed, 1 Jan 2025 19:47:55 +0100 Subject: [PATCH] Add more test cases and add UniqueValues check --- cmd/web/handlers.go | 5 ++++ cmd/web/handlers_test.go | 41 ++++++++++++++++++++++++++++++++- internal/validator/validator.go | 13 +++++++++++ 3 files changed, 58 insertions(+), 1 deletion(-) diff --git a/cmd/web/handlers.go b/cmd/web/handlers.go index 7b7f777..4e15e4b 100644 --- a/cmd/web/handlers.go +++ b/cmd/web/handlers.go @@ -69,6 +69,11 @@ func isRequestValid(r *createElectionRequestWithValidator) bool { r.CheckField(validator.GreaterThan(r.Tokens, 0), "tokens", "must be greater than 0") r.CheckField(validator.After(r.ExpiresAt, time.Now()), "expiresAt", "must expire in a future date") r.CheckField(validator.GreaterThan(len(r.Choices), 1), "choices", "there must be more than 1 choice") + r.CheckField(validator.UniqueValues(r.Choices), "choices", "must not contain duplicate values") + + for _, choice := range r.Choices { + r.CheckField(validator.NotBlank(choice), "choice", "must not be blank") + } if r.AreVotersKnown { r.CheckField( diff --git a/cmd/web/handlers_test.go b/cmd/web/handlers_test.go index b12c51e..0bc7883 100644 --- a/cmd/web/handlers_test.go +++ b/cmd/web/handlers_test.go @@ -2,7 +2,7 @@ package main import ( "bytes" - api "code.dlmw.ch/dlmw/qv/internal" + "code.dlmw.ch/dlmw/qv/internal" "encoding/json" "github.com/stretchr/testify/assert" "net/http" @@ -47,6 +47,19 @@ func TestCreateElection(t *testing.T) { }, expectedCode: http.StatusOK, }, + { + name: "Valid request (with 3 choices)", + urlPath: "/election", + body: api.CreateElectionRequest{ + Choices: []string{"Gandhi", "Buddha", "You"}, + ExpiresAt: time.Now().Add(24 * time.Hour), + AreVotersKnown: false, + MaxVoters: 0, + Name: "Guy of the year", + Tokens: 100, + }, + expectedCode: http.StatusOK, + }, { name: "Valid request (voters unknown with max voters)", urlPath: "/election", @@ -125,6 +138,32 @@ func TestCreateElection(t *testing.T) { }, expectedCode: http.StatusUnprocessableEntity, }, + { + name: "Invalid request (choices are not unique)", + urlPath: "/election", + body: api.CreateElectionRequest{ + Choices: []string{"Gandhi", "Gandhi"}, + ExpiresAt: time.Now().Add(24 * time.Hour), + AreVotersKnown: false, + MaxVoters: 0, + Name: "Guy of the year", + Tokens: 100, + }, + expectedCode: http.StatusUnprocessableEntity, + }, + { + name: "Invalid request (choices contain blank entries)", + urlPath: "/election", + body: api.CreateElectionRequest{ + Choices: []string{"Gandhi", "Buddha", ""}, + ExpiresAt: time.Now().Add(24 * time.Hour), + AreVotersKnown: false, + MaxVoters: 0, + Name: "Guy of the year", + Tokens: 100, + }, + expectedCode: http.StatusUnprocessableEntity, + }, } for _, tt := range tests { diff --git a/internal/validator/validator.go b/internal/validator/validator.go index d91f2d3..e609409 100644 --- a/internal/validator/validator.go +++ b/internal/validator/validator.go @@ -67,3 +67,16 @@ func GreaterThanOrEquals(value int, n int) bool { func After(value time.Time, n time.Time) bool { return value.After(n) } + +func UniqueValues[T comparable](values []T) bool { + seen := make(map[T]bool) + + for _, value := range values { + if seen[value] { + return false + } + seen[value] = true + } + + return true +}