Write some tests for createVotes before refactoring
This commit is contained in:
@ -184,6 +184,16 @@ func (app *application) createVotes(w http.ResponseWriter, r *http.Request) {
|
|||||||
app.unprocessableEntityErrorSingle(w, fmt.Errorf("you already voted"))
|
app.unprocessableEntityErrorSingle(w, fmt.Errorf("you already voted"))
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
voterExists, err := app.voters.Exists(voterIdentity, election.ID)
|
||||||
|
if err != nil {
|
||||||
|
app.serverError(w, r, err)
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
if !voterExists {
|
||||||
|
app.unprocessableEntityErrorSingle(w, fmt.Errorf("invalid voter identity"))
|
||||||
|
return ""
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
voterIdentity = r.RemoteAddr
|
voterIdentity = r.RemoteAddr
|
||||||
|
|
||||||
|
@ -3,6 +3,8 @@ package main
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"code.dlmw.ch/dlmw/qv/internal"
|
"code.dlmw.ch/dlmw/qv/internal"
|
||||||
|
"code.dlmw.ch/dlmw/qv/internal/models"
|
||||||
|
"database/sql"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
@ -216,3 +218,265 @@ func TestCreateElection_ServerError(t *testing.T) {
|
|||||||
|
|
||||||
assert.Equal(t, 500, code)
|
assert.Equal(t, 500, code)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCreateVotesUnknownVotersElection(t *testing.T) {
|
||||||
|
app := newTestApplication(t)
|
||||||
|
server := newTestServer(t, app.routes())
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
mockElections := app.elections.(*mockElectionModel)
|
||||||
|
mockElections.
|
||||||
|
On("GetById", mock.Anything).
|
||||||
|
Return(&models.Election{
|
||||||
|
ID: 1,
|
||||||
|
Name: "Guy of the year",
|
||||||
|
Tokens: 100,
|
||||||
|
AreVotersKnown: false,
|
||||||
|
MaxVoters: 100,
|
||||||
|
CreatedAt: time.Now(),
|
||||||
|
ExpiresAt: time.Now().Add(24 * time.Hour),
|
||||||
|
Choices: []string{"Gandhi", "Buddha"},
|
||||||
|
}, nil)
|
||||||
|
|
||||||
|
mockVoters := app.voters.(*mockVoterModel)
|
||||||
|
mockVoters.
|
||||||
|
On("Exists", mock.Anything, mock.Anything).
|
||||||
|
Return(false, nil)
|
||||||
|
mockVoters.
|
||||||
|
On("Insert", mock.Anything, mock.Anything).
|
||||||
|
Return(1, nil)
|
||||||
|
mockVoters.
|
||||||
|
On("CountByElection", mock.Anything).
|
||||||
|
Return(0, nil)
|
||||||
|
|
||||||
|
mockVotes := app.votes.(*mockVoteModel)
|
||||||
|
mockVotes.
|
||||||
|
On("Insert", mock.Anything, mock.Anything, mock.Anything, mock.Anything).
|
||||||
|
Return(1, nil)
|
||||||
|
|
||||||
|
path := "/votes"
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
urlPath string
|
||||||
|
body any
|
||||||
|
expectedCode int
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "Valid request for unknown voters election",
|
||||||
|
urlPath: path,
|
||||||
|
body: api.CreateVotesRequest{
|
||||||
|
Choices: []struct {
|
||||||
|
ChoiceText string `json:"choiceText"`
|
||||||
|
Tokens int `json:"tokens"`
|
||||||
|
}{
|
||||||
|
{ChoiceText: "Gandhi", Tokens: 60},
|
||||||
|
{ChoiceText: "Buddha", Tokens: 40},
|
||||||
|
},
|
||||||
|
ElectionId: 1,
|
||||||
|
VoterIdentity: nil,
|
||||||
|
},
|
||||||
|
expectedCode: http.StatusCreated,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Invalid request for unknown voters election (too many tokens used)",
|
||||||
|
urlPath: path,
|
||||||
|
body: api.CreateVotesRequest{
|
||||||
|
Choices: []struct {
|
||||||
|
ChoiceText string `json:"choiceText"`
|
||||||
|
Tokens int `json:"tokens"`
|
||||||
|
}{
|
||||||
|
{ChoiceText: "Gandhi", Tokens: 60},
|
||||||
|
{ChoiceText: "Buddha", Tokens: 41},
|
||||||
|
},
|
||||||
|
ElectionId: 1,
|
||||||
|
VoterIdentity: nil,
|
||||||
|
},
|
||||||
|
expectedCode: http.StatusUnprocessableEntity,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Invalid request for unknown voters election (choice doesn't exist)",
|
||||||
|
urlPath: path,
|
||||||
|
body: api.CreateVotesRequest{
|
||||||
|
Choices: []struct {
|
||||||
|
ChoiceText string `json:"choiceText"`
|
||||||
|
Tokens int `json:"tokens"`
|
||||||
|
}{
|
||||||
|
{ChoiceText: "Gandhi", Tokens: 60},
|
||||||
|
{ChoiceText: "Buddh", Tokens: 40},
|
||||||
|
},
|
||||||
|
ElectionId: 1,
|
||||||
|
VoterIdentity: nil,
|
||||||
|
},
|
||||||
|
expectedCode: http.StatusUnprocessableEntity,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
requestBody, err := json.Marshal(tt.body)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
code, _, _ := server.post(t, tt.urlPath, bytes.NewReader(requestBody))
|
||||||
|
assert.Equal(t, tt.expectedCode, code)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCreateVotesKnownVotersElection(t *testing.T) {
|
||||||
|
app := newTestApplication(t)
|
||||||
|
server := newTestServer(t, app.routes())
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
mockElections := app.elections.(*mockElectionModel)
|
||||||
|
mockElections.
|
||||||
|
On("GetById", mock.Anything).
|
||||||
|
Return(&models.Election{
|
||||||
|
ID: 1,
|
||||||
|
Name: "Guy of the year",
|
||||||
|
Tokens: 100,
|
||||||
|
AreVotersKnown: true,
|
||||||
|
MaxVoters: 100,
|
||||||
|
CreatedAt: time.Now(),
|
||||||
|
ExpiresAt: time.Now().Add(24 * time.Hour),
|
||||||
|
Choices: []string{"Gandhi", "Buddha"},
|
||||||
|
}, nil)
|
||||||
|
|
||||||
|
EXISTING_VOTER_IDENTITY := "EXISTING_VOTER_IDENTITY"
|
||||||
|
NON_EXISTING_VOTER_IDENTITY := "NON_EXISTING_VOTER_IDENTITY"
|
||||||
|
mockVoters := app.voters.(*mockVoterModel)
|
||||||
|
mockVoters.
|
||||||
|
On("Exists", EXISTING_VOTER_IDENTITY, mock.Anything).
|
||||||
|
Return(true, nil)
|
||||||
|
mockVoters.
|
||||||
|
On("Exists", NON_EXISTING_VOTER_IDENTITY, mock.Anything).
|
||||||
|
Return(false, nil)
|
||||||
|
|
||||||
|
mockVotes := app.votes.(*mockVoteModel)
|
||||||
|
mockVotes.
|
||||||
|
On("Insert", mock.Anything, mock.Anything, mock.Anything, mock.Anything).
|
||||||
|
Return(1, nil)
|
||||||
|
mockVotes.
|
||||||
|
On("Exists", mock.Anything, mock.Anything).
|
||||||
|
Return(false, nil)
|
||||||
|
|
||||||
|
path := "/votes"
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
urlPath string
|
||||||
|
body any
|
||||||
|
expectedCode int
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "Valid request for unknown voters election",
|
||||||
|
urlPath: path,
|
||||||
|
body: api.CreateVotesRequest{
|
||||||
|
Choices: []struct {
|
||||||
|
ChoiceText string `json:"choiceText"`
|
||||||
|
Tokens int `json:"tokens"`
|
||||||
|
}{
|
||||||
|
{ChoiceText: "Gandhi", Tokens: 60},
|
||||||
|
{ChoiceText: "Buddha", Tokens: 40},
|
||||||
|
},
|
||||||
|
ElectionId: 1,
|
||||||
|
VoterIdentity: &EXISTING_VOTER_IDENTITY,
|
||||||
|
},
|
||||||
|
expectedCode: http.StatusCreated,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Invalid request for unknown voters election (non-existing voter identity)",
|
||||||
|
urlPath: path,
|
||||||
|
body: api.CreateVotesRequest{
|
||||||
|
Choices: []struct {
|
||||||
|
ChoiceText string `json:"choiceText"`
|
||||||
|
Tokens int `json:"tokens"`
|
||||||
|
}{
|
||||||
|
{ChoiceText: "Gandhi", Tokens: 60},
|
||||||
|
{ChoiceText: "Buddha", Tokens: 40},
|
||||||
|
},
|
||||||
|
ElectionId: 1,
|
||||||
|
VoterIdentity: &NON_EXISTING_VOTER_IDENTITY,
|
||||||
|
},
|
||||||
|
expectedCode: http.StatusUnprocessableEntity,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Invalid request for unknown voters election (too many tokens used)",
|
||||||
|
urlPath: path,
|
||||||
|
body: api.CreateVotesRequest{
|
||||||
|
Choices: []struct {
|
||||||
|
ChoiceText string `json:"choiceText"`
|
||||||
|
Tokens int `json:"tokens"`
|
||||||
|
}{
|
||||||
|
{ChoiceText: "Gandhi", Tokens: 60},
|
||||||
|
{ChoiceText: "Buddha", Tokens: 41},
|
||||||
|
},
|
||||||
|
ElectionId: 1,
|
||||||
|
VoterIdentity: &EXISTING_VOTER_IDENTITY,
|
||||||
|
},
|
||||||
|
expectedCode: http.StatusUnprocessableEntity,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Invalid request for unknown voters election (choice doesn't exist)",
|
||||||
|
urlPath: path,
|
||||||
|
body: api.CreateVotesRequest{
|
||||||
|
Choices: []struct {
|
||||||
|
ChoiceText string `json:"choiceText"`
|
||||||
|
Tokens int `json:"tokens"`
|
||||||
|
}{
|
||||||
|
{ChoiceText: "Gandhi", Tokens: 60},
|
||||||
|
{ChoiceText: "Buddh", Tokens: 40},
|
||||||
|
},
|
||||||
|
ElectionId: 1,
|
||||||
|
VoterIdentity: &EXISTING_VOTER_IDENTITY,
|
||||||
|
},
|
||||||
|
expectedCode: http.StatusUnprocessableEntity,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
requestBody, err := json.Marshal(tt.body)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
code, _, _ := server.post(t, tt.urlPath, bytes.NewReader(requestBody))
|
||||||
|
assert.Equal(t, tt.expectedCode, code)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCreateVotes_NonExistingElection(t *testing.T) {
|
||||||
|
app := newTestApplication(t)
|
||||||
|
server := newTestServer(t, app.routes())
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
mockElections := app.elections.(*mockElectionModel)
|
||||||
|
mockElections.
|
||||||
|
On("GetById", mock.Anything).
|
||||||
|
Return((*models.Election)(nil), sql.ErrNoRows)
|
||||||
|
|
||||||
|
path := "/votes"
|
||||||
|
requestBody := api.CreateVotesRequest{
|
||||||
|
Choices: []struct {
|
||||||
|
ChoiceText string `json:"choiceText"`
|
||||||
|
Tokens int `json:"tokens"`
|
||||||
|
}{
|
||||||
|
{ChoiceText: "Gandhi", Tokens: 60},
|
||||||
|
{ChoiceText: "Buddha", Tokens: 40},
|
||||||
|
},
|
||||||
|
ElectionId: 1,
|
||||||
|
VoterIdentity: nil,
|
||||||
|
}
|
||||||
|
requestBodyJson, err := json.Marshal(requestBody)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
code, _, _ := server.post(t, path, bytes.NewReader(requestBodyJson))
|
||||||
|
|
||||||
|
assert.Equal(t, http.StatusUnprocessableEntity, code)
|
||||||
|
}
|
||||||
|
@ -54,30 +54,27 @@ func (e *mockElectionModel) Insert(name string, tokens int, areVotersKnown bool,
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (e *mockElectionModel) GetById(id int) (*models.Election, error) {
|
func (e *mockElectionModel) GetById(id int) (*models.Election, error) {
|
||||||
return &models.Election{
|
args := e.Called(id)
|
||||||
ID: id,
|
return args.Get(0).(*models.Election), args.Error(1)
|
||||||
Name: "Guy of the year",
|
|
||||||
Tokens: 100,
|
|
||||||
AreVotersKnown: false,
|
|
||||||
MaxVoters: 10,
|
|
||||||
CreatedAt: time.Now(),
|
|
||||||
ExpiresAt: time.Now().Add(100 * time.Hour),
|
|
||||||
}, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type mockVoterModel struct {
|
type mockVoterModel struct {
|
||||||
|
mock.Mock
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *mockVoterModel) Insert(identity string, electionID int) (int, error) {
|
func (v *mockVoterModel) Insert(identity string, electionID int) (int, error) {
|
||||||
return 1, nil
|
args := v.Called(identity, electionID)
|
||||||
|
return args.Int(0), args.Error(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *mockVoterModel) CountByElection(electionID int) (int, error) {
|
func (v *mockVoterModel) CountByElection(electionID int) (int, error) {
|
||||||
return 10, nil
|
args := v.Called(electionID)
|
||||||
|
return args.Int(0), args.Error(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *mockVoterModel) Exists(voterIdentity string, electionID int) (bool, error) {
|
func (v *mockVoterModel) Exists(voterIdentity string, electionID int) (bool, error) {
|
||||||
return true, nil
|
args := v.Called(voterIdentity, electionID)
|
||||||
|
return args.Bool(0), args.Error(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
type mockVoteModel struct {
|
type mockVoteModel struct {
|
||||||
@ -90,5 +87,6 @@ func (v *mockVoteModel) Insert(voterIdentity string, electionId int, choiceText
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (v *mockVoteModel) Exists(voterIdentity string, electionID int) (bool, error) {
|
func (v *mockVoteModel) Exists(voterIdentity string, electionID int) (bool, error) {
|
||||||
return true, nil
|
args := v.Called(voterIdentity, electionID)
|
||||||
|
return args.Bool(0), args.Error(1)
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user