To gitea and beyond, let's go(-yco)

This commit is contained in:
2025-11-10 19:12:09 +01:00
parent 8f6133392d
commit 71a031342b
245 changed files with 83994 additions and 0 deletions

266
internal/e2e/votes_test.go Normal file
View 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)
}
})
})
}