To gitea and beyond, let's go(-yco)
This commit is contained in:
266
internal/e2e/votes_test.go
Normal file
266
internal/e2e/votes_test.go
Normal file
@@ -0,0 +1,266 @@
|
||||
package e2e
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestE2E_VoteManagement(t *testing.T) {
|
||||
ctx := setupTestContext(t)
|
||||
|
||||
t.Run("vote_operations", func(t *testing.T) {
|
||||
_, authClient := ctx.createUserAndLogin(t, "testuser", "StrongPass123!")
|
||||
|
||||
createdPost := authClient.CreatePost(t, "Vote Test Post", "https://example.com/vote", "Content for voting")
|
||||
|
||||
var voteResp *VoteResponse
|
||||
statusCode := retryOnRateLimit(t, 3, func() int {
|
||||
resp, code := authClient.VoteOnPostRaw(t, createdPost.ID, "up")
|
||||
if code == http.StatusOK {
|
||||
voteResp = resp
|
||||
}
|
||||
return code
|
||||
})
|
||||
if statusCode == http.StatusTooManyRequests {
|
||||
t.Skip("Skipping vote operations test: rate limited after retries")
|
||||
return
|
||||
}
|
||||
if statusCode != http.StatusOK {
|
||||
t.Fatalf("Vote failed with status %d", statusCode)
|
||||
}
|
||||
assertVoteResponse(t, voteResp, "up")
|
||||
|
||||
userVote := authClient.GetUserVote(t, createdPost.ID)
|
||||
if !userVote.Success {
|
||||
t.Errorf("Expected to get user vote, got failure: %s", userVote.Message)
|
||||
}
|
||||
userVoteData := assertVoteData(t, userVote)
|
||||
if hasVote, ok := userVoteData["has_vote"].(bool); !ok || !hasVote {
|
||||
t.Errorf("Expected has_vote true after casting vote, got %#v", userVoteData["has_vote"])
|
||||
}
|
||||
|
||||
postVotes := authClient.GetPostVotes(t, createdPost.ID)
|
||||
if !postVotes.Success {
|
||||
t.Errorf("Expected to get post votes, got failure: %s", postVotes.Message)
|
||||
}
|
||||
postVotesData := assertVoteData(t, postVotes)
|
||||
if count, ok := postVotesData["count"].(float64); !ok || count < 1 {
|
||||
t.Errorf("Expected post votes count to be >= 1, got %#v", postVotesData["count"])
|
||||
}
|
||||
|
||||
authClient.RemoveVote(t, createdPost.ID)
|
||||
|
||||
removedVote := authClient.GetUserVote(t, createdPost.ID)
|
||||
if !removedVote.Success {
|
||||
t.Errorf("Expected to get vote removal state, got failure: %s", removedVote.Message)
|
||||
}
|
||||
removedVoteData := assertVoteData(t, removedVote)
|
||||
if hasVote, ok := removedVoteData["has_vote"].(bool); ok && hasVote {
|
||||
t.Errorf("Expected has_vote false after removal, got true")
|
||||
}
|
||||
if voteVal, present := removedVoteData["vote"]; present && voteVal != nil {
|
||||
t.Errorf("Expected vote data to be nil after removal, got %#v", voteVal)
|
||||
}
|
||||
|
||||
postVotesAfter := authClient.GetPostVotes(t, createdPost.ID)
|
||||
if !postVotesAfter.Success {
|
||||
t.Errorf("Expected to get post votes after removal, got failure: %s", postVotesAfter.Message)
|
||||
}
|
||||
postVotesAfterData := assertVoteData(t, postVotesAfter)
|
||||
if count, ok := postVotesAfterData["count"].(float64); ok && count != 0 {
|
||||
t.Errorf("Expected post votes count to be 0 after removal, got %v", count)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestE2E_VoteAuthorization(t *testing.T) {
|
||||
ctx := setupTestContext(t)
|
||||
|
||||
t.Run("vote_authorization", func(t *testing.T) {
|
||||
createdUsers := ctx.createMultipleUsersWithCleanup(t, 2, "voteuser", "StrongPass123!")
|
||||
user1 := createdUsers[0]
|
||||
user2 := createdUsers[1]
|
||||
|
||||
authClient1 := ctx.loginUser(t, user1.Username, user1.Password)
|
||||
authClient2 := ctx.loginUser(t, user2.Username, user2.Password)
|
||||
|
||||
createdPost := authClient1.CreatePost(t, "Vote Test Post", "https://example.com/vote", "Content for voting tests")
|
||||
|
||||
t.Run("users_can_only_vote_with_own_token", func(t *testing.T) {
|
||||
voteResp1 := authClient1.VoteOnPost(t, createdPost.ID, "up")
|
||||
if !voteResp1.Success {
|
||||
t.Errorf("Expected User1 to be able to vote with their own token, got failure: %s", voteResp1.Message)
|
||||
}
|
||||
|
||||
userVote1 := authClient1.GetUserVote(t, createdPost.ID)
|
||||
if !userVote1.Success {
|
||||
t.Errorf("Expected to get User1's vote, got failure: %s", userVote1.Message)
|
||||
}
|
||||
userVote1Data := assertVoteData(t, userVote1)
|
||||
if hasVote, ok := userVote1Data["has_vote"].(bool); !ok || !hasVote {
|
||||
t.Errorf("Expected User1 to have a vote after voting, got has_vote=%v", userVote1Data["has_vote"])
|
||||
}
|
||||
|
||||
voteResp2 := authClient2.VoteOnPost(t, createdPost.ID, "up")
|
||||
if !voteResp2.Success {
|
||||
t.Errorf("Expected User2 to be able to vote with their own token, got failure: %s", voteResp2.Message)
|
||||
}
|
||||
|
||||
userVote2 := authClient2.GetUserVote(t, createdPost.ID)
|
||||
if !userVote2.Success {
|
||||
t.Errorf("Expected to get User2's vote, got failure: %s", userVote2.Message)
|
||||
}
|
||||
userVote2Data := assertVoteData(t, userVote2)
|
||||
if hasVote, ok := userVote2Data["has_vote"].(bool); !ok || !hasVote {
|
||||
t.Errorf("Expected User2 to have a vote after voting, got has_vote=%v", userVote2Data["has_vote"])
|
||||
}
|
||||
|
||||
userVote1After := authClient1.GetUserVote(t, createdPost.ID)
|
||||
if !userVote1After.Success {
|
||||
t.Errorf("Expected to still get User1's vote after User2 votes, got failure: %s", userVote1After.Message)
|
||||
}
|
||||
userVote1AfterData := assertVoteData(t, userVote1After)
|
||||
if hasVote, ok := userVote1AfterData["has_vote"].(bool); !ok || !hasVote {
|
||||
t.Errorf("Expected User1's vote to still exist after User2 votes, got has_vote=%v", userVote1AfterData["has_vote"])
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("vote_counts_reflect_authenticated_votes", func(t *testing.T) {
|
||||
postVotes := authClient1.GetPostVotes(t, createdPost.ID)
|
||||
if !postVotes.Success {
|
||||
t.Errorf("Expected to get post votes, got failure: %s", postVotes.Message)
|
||||
}
|
||||
|
||||
postVotesData := assertVoteData(t, postVotes)
|
||||
|
||||
count, ok := postVotesData["count"].(float64)
|
||||
if !ok {
|
||||
t.Fatalf("Expected count to be a number, got %T", postVotesData["count"])
|
||||
}
|
||||
if count < 2 {
|
||||
t.Errorf("Expected vote count to be at least 2 (User1 and User2 both voted), got %v", count)
|
||||
}
|
||||
|
||||
votesArray, ok := postVotesData["votes"].([]any)
|
||||
if !ok {
|
||||
t.Fatalf("Expected votes to be an array, got %T", postVotesData["votes"])
|
||||
}
|
||||
if len(votesArray) < 2 {
|
||||
t.Errorf("Expected at least 2 votes in the votes array, got %d", len(votesArray))
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("users_can_only_modify_own_votes", func(t *testing.T) {
|
||||
authClient1.RemoveVote(t, createdPost.ID)
|
||||
|
||||
userVote1After := authClient1.GetUserVote(t, createdPost.ID)
|
||||
if !userVote1After.Success {
|
||||
t.Errorf("Expected to get vote state after removal, got failure: %s", userVote1After.Message)
|
||||
}
|
||||
userVote1AfterData := assertVoteData(t, userVote1After)
|
||||
if hasVote, ok := userVote1AfterData["has_vote"].(bool); ok && hasVote {
|
||||
t.Errorf("Expected User1's vote to be removed, but has_vote is still true")
|
||||
}
|
||||
|
||||
userVote2After := authClient2.GetUserVote(t, createdPost.ID)
|
||||
if !userVote2After.Success {
|
||||
t.Errorf("Expected to get User2's vote, got failure: %s", userVote2After.Message)
|
||||
}
|
||||
userVote2AfterData := assertVoteData(t, userVote2After)
|
||||
if hasVote, ok := userVote2AfterData["has_vote"].(bool); !ok || !hasVote {
|
||||
t.Errorf("Expected User2's vote to still exist after User1 removes their vote, got has_vote=%v", userVote2AfterData["has_vote"])
|
||||
}
|
||||
|
||||
postVotesAfter := authClient1.GetPostVotes(t, createdPost.ID)
|
||||
if !postVotesAfter.Success {
|
||||
t.Errorf("Expected to get post votes after removal, got failure: %s", postVotesAfter.Message)
|
||||
}
|
||||
postVotesAfterData := assertVoteData(t, postVotesAfter)
|
||||
countAfter, ok := postVotesAfterData["count"].(float64)
|
||||
if !ok {
|
||||
t.Fatalf("Expected count to be a number, got %T", postVotesAfterData["count"])
|
||||
}
|
||||
|
||||
if countAfter < 1 {
|
||||
t.Errorf("Expected vote count to be at least 1 after User1 removes vote, got %v", countAfter)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("vote_counts_accurate_with_different_types", func(t *testing.T) {
|
||||
voteResp1Down := authClient1.VoteOnPost(t, createdPost.ID, "down")
|
||||
if !voteResp1Down.Success {
|
||||
t.Errorf("Expected User1 to be able to vote down, got failure: %s", voteResp1Down.Message)
|
||||
}
|
||||
|
||||
postVotes := authClient2.GetPostVotes(t, createdPost.ID)
|
||||
if !postVotes.Success {
|
||||
t.Errorf("Expected to get post votes, got failure: %s", postVotes.Message)
|
||||
}
|
||||
|
||||
postVotesData := assertVoteData(t, postVotes)
|
||||
|
||||
count := postVotesData["count"].(float64)
|
||||
if count < 2 {
|
||||
t.Errorf("Expected vote count to be at least 2 (User1 downvote, User2 upvote), got %v", count)
|
||||
}
|
||||
|
||||
userVote1 := authClient1.GetUserVote(t, createdPost.ID)
|
||||
userVote1Data := assertVoteData(t, userVote1)
|
||||
if voteData, exists := userVote1Data["vote"].(map[string]any); exists {
|
||||
if voteType, exists := voteData["type"].(string); exists {
|
||||
if voteType != "down" {
|
||||
t.Errorf("Expected User1's vote type to be 'down', got '%s'", voteType)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
userVote2 := authClient2.GetUserVote(t, createdPost.ID)
|
||||
userVote2Data := assertVoteData(t, userVote2)
|
||||
if voteData, exists := userVote2Data["vote"].(map[string]any); exists {
|
||||
if voteType, exists := voteData["type"].(string); exists {
|
||||
if voteType != "up" {
|
||||
t.Errorf("Expected User2's vote type to be 'up', got '%s'", voteType)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("multiple_users_vote_independently", func(t *testing.T) {
|
||||
user3 := ctx.createUserWithCleanup(t, "voteuser3", "StrongPass123!")
|
||||
authClient3 := ctx.loginUser(t, user3.Username, user3.Password)
|
||||
|
||||
voteResp3 := authClient3.VoteOnPost(t, createdPost.ID, "up")
|
||||
if !voteResp3.Success {
|
||||
t.Errorf("Expected User3 to be able to vote, got failure: %s", voteResp3.Message)
|
||||
}
|
||||
|
||||
userVote1 := authClient1.GetUserVote(t, createdPost.ID)
|
||||
userVote1Data := assertVoteData(t, userVote1)
|
||||
if hasVote, ok := userVote1Data["has_vote"].(bool); !ok || !hasVote {
|
||||
t.Errorf("Expected User1 to still have a vote")
|
||||
}
|
||||
|
||||
userVote2 := authClient2.GetUserVote(t, createdPost.ID)
|
||||
userVote2Data := assertVoteData(t, userVote2)
|
||||
if hasVote, ok := userVote2Data["has_vote"].(bool); !ok || !hasVote {
|
||||
t.Errorf("Expected User2 to still have a vote")
|
||||
}
|
||||
|
||||
userVote3 := authClient3.GetUserVote(t, createdPost.ID)
|
||||
userVote3Data := assertVoteData(t, userVote3)
|
||||
if hasVote, ok := userVote3Data["has_vote"].(bool); !ok || !hasVote {
|
||||
t.Errorf("Expected User3 to have a vote after voting")
|
||||
}
|
||||
|
||||
postVotes := authClient3.GetPostVotes(t, createdPost.ID)
|
||||
postVotesData := assertVoteData(t, postVotes)
|
||||
count, ok := postVotesData["count"].(float64)
|
||||
if !ok {
|
||||
t.Fatalf("Expected count to be a number, got %T", postVotesData["count"])
|
||||
}
|
||||
if count < 3 {
|
||||
t.Errorf("Expected vote count to be at least 3 (three users voted), got %v", count)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user