To gitea and beyond, let's go(-yco)
This commit is contained in:
611
internal/e2e/workflows_realistic_test.go
Normal file
611
internal/e2e/workflows_realistic_test.go
Normal file
@@ -0,0 +1,611 @@
|
||||
package e2e
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"goyco/internal/testutils"
|
||||
)
|
||||
|
||||
func findPostInList(postsResp *testutils.PostsListResponse, postID uint) *testutils.Post {
|
||||
if postsResp == nil || postsResp.Data.Posts == nil {
|
||||
return nil
|
||||
}
|
||||
for _, post := range postsResp.Data.Posts {
|
||||
if post.ID == postID {
|
||||
return &post
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestE2E_NewUserOnboarding(t *testing.T) {
|
||||
ctx := setupTestContext(t)
|
||||
|
||||
t.Run("new_user_onboarding", func(t *testing.T) {
|
||||
username := uniqueUsername(t, "newuser")
|
||||
email := uniqueEmail(t, "newuser")
|
||||
password := "Password123!"
|
||||
|
||||
ctx.server.EmailSender.Reset()
|
||||
statusCode := ctx.registerUserExpectStatus(t, username, email, password)
|
||||
if statusCode != http.StatusCreated {
|
||||
t.Fatalf("Expected registration to succeed, got status %d", statusCode)
|
||||
}
|
||||
|
||||
verificationToken := ctx.server.EmailSender.VerificationToken()
|
||||
if verificationToken == "" {
|
||||
t.Fatalf("Expected verification token")
|
||||
}
|
||||
|
||||
ctx.confirmEmail(t, verificationToken)
|
||||
|
||||
authClient := ctx.loginUser(t, username, password)
|
||||
if authClient.Token == "" {
|
||||
t.Fatalf("Expected login to succeed after email verification")
|
||||
}
|
||||
|
||||
createdPost := authClient.CreatePost(t, "My First Post", "https://example.com/first", "This is my first post content")
|
||||
if createdPost.ID == 0 {
|
||||
t.Errorf("Expected post creation to succeed")
|
||||
}
|
||||
|
||||
voteResp := authClient.VoteOnPost(t, createdPost.ID, "up")
|
||||
if !voteResp.Success {
|
||||
t.Errorf("Expected vote to succeed, got failure: %s", voteResp.Message)
|
||||
}
|
||||
|
||||
profile := authClient.GetProfile(t)
|
||||
if profile.Data.Username != username {
|
||||
t.Errorf("Expected profile username to match, got '%s'", profile.Data.Username)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestE2E_ReturningUserSession(t *testing.T) {
|
||||
ctx := setupTestContext(t)
|
||||
|
||||
t.Run("returning_user_session", func(t *testing.T) {
|
||||
createdUser := ctx.createUserWithCleanup(t, "returning", "Password123!")
|
||||
authClient := ctx.loginUser(t, createdUser.Username, createdUser.Password)
|
||||
|
||||
postsResp := authClient.GetPosts(t)
|
||||
if postsResp == nil {
|
||||
t.Errorf("Expected posts response")
|
||||
}
|
||||
|
||||
post1 := authClient.CreatePost(t, "Post 1", "https://example.com/post1", "Content 1")
|
||||
post2 := authClient.CreatePost(t, "Post 2", "https://example.com/post2", "Content 2")
|
||||
|
||||
voteResp := authClient.VoteOnPost(t, post1.ID, "up")
|
||||
if !voteResp.Success {
|
||||
t.Errorf("Expected vote to succeed")
|
||||
}
|
||||
|
||||
voteResp = authClient.VoteOnPost(t, post2.ID, "down")
|
||||
if !voteResp.Success {
|
||||
t.Errorf("Expected vote to succeed")
|
||||
}
|
||||
|
||||
postsResp = authClient.GetPosts(t)
|
||||
if postsResp == nil || len(postsResp.Data.Posts) == 0 {
|
||||
t.Errorf("Expected to retrieve posts")
|
||||
}
|
||||
|
||||
authClient.Logout(t)
|
||||
})
|
||||
}
|
||||
|
||||
func TestE2E_PowerUserWorkflow(t *testing.T) {
|
||||
ctx := setupTestContext(t)
|
||||
|
||||
t.Run("power_user_workflow", func(t *testing.T) {
|
||||
createdUser := ctx.createUserWithCleanup(t, "poweruser", "Password123!")
|
||||
authClient := ctx.loginUser(t, createdUser.Username, createdUser.Password)
|
||||
|
||||
var postIDs []uint
|
||||
for i := 1; i <= 5; i++ {
|
||||
post := authClient.CreatePost(t,
|
||||
uniqueTestID(t)+" Post "+fmt.Sprintf("%d", i),
|
||||
"https://example.com/power"+uniqueTestID(t)+fmt.Sprintf("%d", i),
|
||||
"Content "+fmt.Sprintf("%d", i))
|
||||
postIDs = append(postIDs, post.ID)
|
||||
}
|
||||
|
||||
for i, postID := range postIDs {
|
||||
voteType := "up"
|
||||
if i%2 == 0 {
|
||||
voteType = "down"
|
||||
}
|
||||
voteResp := authClient.VoteOnPost(t, postID, voteType)
|
||||
if !voteResp.Success {
|
||||
t.Errorf("Expected vote to succeed on post %d", postID)
|
||||
}
|
||||
}
|
||||
|
||||
postsResp := authClient.GetPosts(t)
|
||||
firstPost := findPostInList(postsResp, postIDs[0])
|
||||
if firstPost == nil {
|
||||
t.Fatalf("Expected to retrieve first post")
|
||||
}
|
||||
|
||||
authClient.UpdatePost(t, postIDs[0], "Updated Title", "https://example.com/updated", "Updated content")
|
||||
updatedPostsResp := authClient.GetPosts(t)
|
||||
updatedPost := findPostInList(updatedPostsResp, postIDs[0])
|
||||
if updatedPost == nil {
|
||||
t.Fatalf("Expected to retrieve updated post")
|
||||
}
|
||||
if updatedPost.Title != "Updated Title" {
|
||||
t.Errorf("Expected post title to be updated, got '%s'", updatedPost.Title)
|
||||
}
|
||||
|
||||
authClient.DeletePost(t, postIDs[len(postIDs)-1])
|
||||
finalPostsResp := authClient.GetPosts(t)
|
||||
deletedPost := findPostInList(finalPostsResp, postIDs[len(postIDs)-1])
|
||||
if deletedPost != nil {
|
||||
t.Errorf("Expected deleted post to not be accessible")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestE2E_PasswordResetFlowRealistic(t *testing.T) {
|
||||
ctx := setupTestContext(t)
|
||||
|
||||
t.Run("password_reset_flow", func(t *testing.T) {
|
||||
createdUser := ctx.createUserWithCleanup(t, "resetflow", "Password123!")
|
||||
_ = ctx.loginUser(t, createdUser.Username, createdUser.Password)
|
||||
|
||||
ctx.server.EmailSender.Reset()
|
||||
testutils.RequestPasswordReset(t, ctx.client, ctx.baseURL, createdUser.Email, testutils.GenerateTestIP())
|
||||
|
||||
resetToken := ctx.server.EmailSender.PasswordResetToken()
|
||||
if resetToken == "" {
|
||||
t.Fatalf("Expected password reset token")
|
||||
}
|
||||
|
||||
newPassword := "NewPassword456!"
|
||||
statusCode := testutils.ResetPassword(t, ctx.client, ctx.baseURL, resetToken, newPassword, testutils.GenerateTestIP())
|
||||
if statusCode != http.StatusOK {
|
||||
t.Fatalf("Expected password reset to succeed, got status %d", statusCode)
|
||||
}
|
||||
|
||||
oldLoginStatus := ctx.loginExpectStatus(t, createdUser.Username, "Password123!", http.StatusUnauthorized)
|
||||
if oldLoginStatus == http.StatusOK {
|
||||
t.Log("Old password may still work briefly (acceptable)")
|
||||
}
|
||||
|
||||
newClient := ctx.loginUser(t, createdUser.Username, newPassword)
|
||||
if newClient.Token == "" {
|
||||
t.Errorf("Expected login with new password to succeed")
|
||||
}
|
||||
|
||||
newClient.UpdatePassword(t, newPassword, "AnotherPassword789!")
|
||||
finalClient := ctx.loginUser(t, createdUser.Username, "AnotherPassword789!")
|
||||
if finalClient.Token == "" {
|
||||
t.Errorf("Expected login with final password to succeed")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestE2E_PostLifecycle(t *testing.T) {
|
||||
ctx := setupTestContext(t)
|
||||
|
||||
t.Run("post_lifecycle", func(t *testing.T) {
|
||||
createdUser := ctx.createUserWithCleanup(t, "lifecycle", "Password123!")
|
||||
authClient := ctx.loginUser(t, createdUser.Username, createdUser.Password)
|
||||
|
||||
createdPost := authClient.CreatePost(t, "Original Title", "https://example.com/lifecycle", "Original content")
|
||||
if createdPost.ID == 0 {
|
||||
t.Fatalf("Expected post creation to succeed")
|
||||
}
|
||||
|
||||
voteResp := authClient.VoteOnPost(t, createdPost.ID, "up")
|
||||
if !voteResp.Success {
|
||||
t.Errorf("Expected vote to succeed")
|
||||
}
|
||||
|
||||
authClient.UpdatePost(t, createdPost.ID, "Updated Title", "https://example.com/lifecycle", "Updated content")
|
||||
postsResp := authClient.GetPosts(t)
|
||||
updatedPost := findPostInList(postsResp, createdPost.ID)
|
||||
if updatedPost == nil {
|
||||
t.Fatalf("Expected to retrieve updated post")
|
||||
}
|
||||
if updatedPost.Title != "Updated Title" {
|
||||
t.Errorf("Expected post to be updated")
|
||||
}
|
||||
|
||||
voteResp = authClient.VoteOnPost(t, createdPost.ID, "down")
|
||||
if !voteResp.Success {
|
||||
t.Errorf("Expected vote change to succeed")
|
||||
}
|
||||
|
||||
authClient.UpdatePost(t, createdPost.ID, "Final Title", "https://example.com/lifecycle", "Final content")
|
||||
finalPostsResp := authClient.GetPosts(t)
|
||||
finalPost := findPostInList(finalPostsResp, createdPost.ID)
|
||||
if finalPost == nil {
|
||||
t.Fatalf("Expected to retrieve final post")
|
||||
}
|
||||
if finalPost.Title != "Final Title" {
|
||||
t.Errorf("Expected post to be updated again")
|
||||
}
|
||||
|
||||
authClient.DeletePost(t, createdPost.ID)
|
||||
deletedPostsResp := authClient.GetPosts(t)
|
||||
deletedPost := findPostInList(deletedPostsResp, createdPost.ID)
|
||||
if deletedPost != nil {
|
||||
t.Errorf("Expected deleted post to not be accessible")
|
||||
}
|
||||
|
||||
recreatedPost := authClient.CreatePost(t, "Recreated Title", "https://example.com/lifecycle-recreated", "Recreated content")
|
||||
if recreatedPost.ID == 0 {
|
||||
t.Errorf("Expected post recreation to succeed")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestE2E_VotePatterns(t *testing.T) {
|
||||
ctx := setupTestContext(t)
|
||||
|
||||
t.Run("vote_patterns", func(t *testing.T) {
|
||||
createdUser := ctx.createUserWithCleanup(t, "votepattern", "Password123!")
|
||||
authClient := ctx.loginUser(t, createdUser.Username, createdUser.Password)
|
||||
|
||||
post := authClient.CreatePost(t, "Vote Test Post", "https://example.com/vote", "Content")
|
||||
|
||||
voteResp := authClient.VoteOnPost(t, post.ID, "up")
|
||||
if !voteResp.Success {
|
||||
t.Errorf("Expected upvote to succeed")
|
||||
}
|
||||
|
||||
userVote := authClient.GetUserVote(t, post.ID)
|
||||
if userVote == nil || userVote.Data == nil {
|
||||
t.Errorf("Expected to retrieve user vote")
|
||||
}
|
||||
|
||||
voteResp = authClient.VoteOnPost(t, post.ID, "down")
|
||||
if !voteResp.Success {
|
||||
t.Errorf("Expected downvote to succeed")
|
||||
}
|
||||
|
||||
voteResp = authClient.VoteOnPost(t, post.ID, "none")
|
||||
if !voteResp.Success {
|
||||
t.Errorf("Expected vote removal to succeed")
|
||||
}
|
||||
|
||||
userVote = authClient.GetUserVote(t, post.ID)
|
||||
if userVote != nil && userVote.Data != nil {
|
||||
voteData, ok := userVote.Data.(map[string]any)
|
||||
if ok {
|
||||
if voteType, exists := voteData["type"]; exists && voteType != nil && voteType != "none" {
|
||||
t.Errorf("Expected vote to be removed")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
voteResp = authClient.VoteOnPost(t, post.ID, "up")
|
||||
if !voteResp.Success {
|
||||
t.Errorf("Expected upvote after removal to succeed")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestE2E_ProfileUpdateFlow(t *testing.T) {
|
||||
ctx := setupTestContext(t)
|
||||
|
||||
t.Run("profile_update_flow", func(t *testing.T) {
|
||||
createdUser := ctx.createUserWithCleanup(t, "profile", "Password123!")
|
||||
authClient := ctx.loginUser(t, createdUser.Username, createdUser.Password)
|
||||
|
||||
_ = authClient.GetProfile(t)
|
||||
|
||||
newUsername := uniqueUsername(t, "updated")
|
||||
authClient.UpdateUsername(t, newUsername)
|
||||
updatedProfile := authClient.GetProfile(t)
|
||||
if updatedProfile.Data.Username != newUsername {
|
||||
t.Errorf("Expected username to be updated, got '%s'", updatedProfile.Data.Username)
|
||||
}
|
||||
|
||||
ctx.server.EmailSender.Reset()
|
||||
newEmail := uniqueEmail(t, "updated")
|
||||
authClient.UpdateEmail(t, newEmail)
|
||||
emailProfile := authClient.GetProfile(t)
|
||||
normalizedNewEmail := strings.ToLower(strings.TrimSpace(newEmail))
|
||||
if emailProfile.Data.Email != normalizedNewEmail {
|
||||
t.Errorf("Expected email to be updated, got '%s'", emailProfile.Data.Email)
|
||||
}
|
||||
|
||||
verificationToken := ctx.server.EmailSender.VerificationToken()
|
||||
if verificationToken == "" {
|
||||
t.Fatalf("Expected verification token after email update")
|
||||
}
|
||||
ctx.confirmEmail(t, verificationToken)
|
||||
|
||||
authClient.UpdatePassword(t, "Password123!", "NewPassword999!")
|
||||
passwordClient := ctx.loginUser(t, newUsername, "NewPassword999!")
|
||||
if passwordClient.Token == "" {
|
||||
t.Errorf("Expected login with new password to succeed")
|
||||
}
|
||||
|
||||
finalProfile := passwordClient.GetProfile(t)
|
||||
if finalProfile.Data.Username != newUsername {
|
||||
t.Errorf("Expected username to remain updated, got '%s'", finalProfile.Data.Username)
|
||||
}
|
||||
if finalProfile.Data.Email != normalizedNewEmail {
|
||||
t.Errorf("Expected email to remain updated, got '%s'", finalProfile.Data.Email)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestE2E_MultiUserInteraction(t *testing.T) {
|
||||
ctx := setupTestContext(t)
|
||||
|
||||
t.Run("multi_user_interaction", func(t *testing.T) {
|
||||
userA := ctx.createUserWithCleanup(t, "usera", "Password123!")
|
||||
userB := ctx.createUserWithCleanup(t, "userb", "Password123!")
|
||||
|
||||
clientA := ctx.loginUser(t, userA.Username, userA.Password)
|
||||
clientB := ctx.loginUser(t, userB.Username, userB.Password)
|
||||
|
||||
post := clientA.CreatePost(t, "User A's Post", "https://example.com/usera", "Content from User A")
|
||||
if post.ID == 0 {
|
||||
t.Fatalf("Expected post creation to succeed")
|
||||
}
|
||||
|
||||
voteResp := clientB.VoteOnPost(t, post.ID, "up")
|
||||
if !voteResp.Success {
|
||||
t.Errorf("Expected User B to vote on User A's post")
|
||||
}
|
||||
|
||||
clientA.UpdatePost(t, post.ID, "Updated by User A", "https://example.com/usera", "Updated content")
|
||||
postsResp := clientB.GetPosts(t)
|
||||
updatedPost := findPostInList(postsResp, post.ID)
|
||||
if updatedPost == nil {
|
||||
t.Fatalf("Expected to retrieve updated post")
|
||||
}
|
||||
if updatedPost.Title != "Updated by User A" {
|
||||
t.Errorf("Expected User B to see updated post")
|
||||
}
|
||||
|
||||
voteResp = clientB.VoteOnPost(t, post.ID, "down")
|
||||
if !voteResp.Success {
|
||||
t.Errorf("Expected User B to change vote")
|
||||
}
|
||||
|
||||
finalPostsResp := clientA.GetPosts(t)
|
||||
finalPost := findPostInList(finalPostsResp, post.ID)
|
||||
if finalPost == nil {
|
||||
t.Errorf("Expected User A to retrieve final post")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestE2E_ContentDiscovery(t *testing.T) {
|
||||
ctx := setupTestContext(t)
|
||||
|
||||
t.Run("content_discovery", func(t *testing.T) {
|
||||
createdUser := ctx.createUserWithCleanup(t, "discovery", "Password123!")
|
||||
authClient := ctx.loginUser(t, createdUser.Username, createdUser.Password)
|
||||
|
||||
post1 := authClient.CreatePost(t, "Golang Tutorial", "https://example.com/golang", "Learn Go programming")
|
||||
post2 := authClient.CreatePost(t, "Python Guide", "https://example.com/python", "Python programming guide")
|
||||
post3 := authClient.CreatePost(t, "Rust Basics", "https://example.com/rust", "Rust programming basics")
|
||||
|
||||
authClient.VoteOnPost(t, post1.ID, "up")
|
||||
authClient.VoteOnPost(t, post2.ID, "up")
|
||||
authClient.VoteOnPost(t, post3.ID, "down")
|
||||
|
||||
searchResp := authClient.SearchPosts(t, "Golang")
|
||||
if searchResp == nil || len(searchResp.Data.Posts) == 0 {
|
||||
t.Errorf("Expected search to find posts")
|
||||
}
|
||||
|
||||
postsResp := authClient.GetPosts(t)
|
||||
if postsResp == nil || len(postsResp.Data.Posts) == 0 {
|
||||
t.Errorf("Expected to retrieve posts")
|
||||
}
|
||||
|
||||
authClient.VoteOnPost(t, post1.ID, "up")
|
||||
updatedPostsResp := authClient.GetPosts(t)
|
||||
updatedPost := findPostInList(updatedPostsResp, post1.ID)
|
||||
if updatedPost == nil {
|
||||
t.Errorf("Expected to retrieve updated post")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestE2E_SessionPersistence(t *testing.T) {
|
||||
ctx := setupTestContext(t)
|
||||
|
||||
t.Run("session_persistence", func(t *testing.T) {
|
||||
createdUser := ctx.createUserWithCleanup(t, "session", "Password123!")
|
||||
authClient := ctx.loginUser(t, createdUser.Username, createdUser.Password)
|
||||
|
||||
profile1 := authClient.GetProfile(t)
|
||||
if profile1.Data.Username != createdUser.Username {
|
||||
t.Errorf("Expected first profile request to succeed")
|
||||
}
|
||||
|
||||
ctx.assertEventually(t, func() bool {
|
||||
profile2 := authClient.GetProfile(t)
|
||||
return profile2 != nil && profile2.Data.Username == createdUser.Username
|
||||
}, 2*time.Second)
|
||||
|
||||
profile2 := authClient.GetProfile(t)
|
||||
if profile2.Data.Username != createdUser.Username {
|
||||
t.Errorf("Expected second profile request to succeed")
|
||||
}
|
||||
|
||||
postsResp1 := authClient.GetPosts(t)
|
||||
postsResp2 := authClient.GetPosts(t)
|
||||
|
||||
if postsResp1 == nil || postsResp2 == nil {
|
||||
t.Errorf("Expected multiple requests with same session to work")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestE2E_ConcurrentRequestsWithSameSession(t *testing.T) {
|
||||
ctx := setupTestContext(t)
|
||||
|
||||
t.Run("concurrent_requests_same_session", func(t *testing.T) {
|
||||
createdUser := ctx.createUserWithCleanup(t, "concurrent", "Password123!")
|
||||
authClient := ctx.loginUser(t, createdUser.Username, createdUser.Password)
|
||||
|
||||
results := make(chan bool, 5)
|
||||
for i := 0; i < 5; i++ {
|
||||
go func() {
|
||||
profile := authClient.GetProfile(t)
|
||||
results <- (profile != nil && profile.Data.Username == createdUser.Username)
|
||||
}()
|
||||
}
|
||||
|
||||
successCount := 0
|
||||
for i := 0; i < 5; i++ {
|
||||
if <-results {
|
||||
successCount++
|
||||
}
|
||||
}
|
||||
|
||||
if successCount == 0 {
|
||||
t.Errorf("Expected at least some concurrent requests to succeed")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestE2E_UserAgentHeaders(t *testing.T) {
|
||||
ctx := setupTestContext(t)
|
||||
|
||||
t.Run("user_agent_headers", func(t *testing.T) {
|
||||
createdUser := ctx.createUserWithCleanup(t, "useragent", "Password123!")
|
||||
authClient := ctx.loginUser(t, createdUser.Username, createdUser.Password)
|
||||
|
||||
userAgents := []string{
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64)",
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)",
|
||||
"Mozilla/5.0 (X11; Linux x86_64)",
|
||||
"Go-http-client/1.1",
|
||||
}
|
||||
|
||||
for _, ua := range userAgents {
|
||||
request, err := testutils.NewRequestBuilder("GET", ctx.baseURL+"/api/auth/me").
|
||||
WithAuth(authClient.Token).
|
||||
WithHeader("User-Agent", ua).
|
||||
Build()
|
||||
if err != nil {
|
||||
t.Errorf("Failed to create request with User-Agent: %s", ua)
|
||||
continue
|
||||
}
|
||||
|
||||
resp, err := ctx.client.Do(request)
|
||||
if err != nil {
|
||||
t.Errorf("Request failed with User-Agent %s: %v", ua, err)
|
||||
continue
|
||||
}
|
||||
resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
t.Errorf("Expected status 200 with User-Agent %s, got %d", ua, resp.StatusCode)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestE2E_RefererHeaders(t *testing.T) {
|
||||
ctx := setupTestContext(t)
|
||||
|
||||
t.Run("referer_headers", func(t *testing.T) {
|
||||
createdUser := ctx.createUserWithCleanup(t, "referer", "Password123!")
|
||||
authClient := ctx.loginUser(t, createdUser.Username, createdUser.Password)
|
||||
|
||||
referers := []string{
|
||||
"https://example.com/page1",
|
||||
"https://example.com/page2",
|
||||
"http://localhost:3000",
|
||||
"",
|
||||
}
|
||||
|
||||
for _, referer := range referers {
|
||||
builder := testutils.NewRequestBuilder("GET", ctx.baseURL+"/api/auth/me").
|
||||
WithAuth(authClient.Token)
|
||||
if referer != "" {
|
||||
builder = builder.WithHeader("Referer", referer)
|
||||
}
|
||||
request, err := builder.Build()
|
||||
if err != nil {
|
||||
t.Errorf("Failed to create request with Referer: %s", referer)
|
||||
continue
|
||||
}
|
||||
|
||||
resp, err := ctx.client.Do(request)
|
||||
if err != nil {
|
||||
t.Errorf("Request failed with Referer %s: %v", referer, err)
|
||||
continue
|
||||
}
|
||||
resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
t.Errorf("Expected status 200 with Referer %s, got %d", referer, resp.StatusCode)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestE2E_RapidSuccessiveActions(t *testing.T) {
|
||||
ctx := setupTestContext(t)
|
||||
|
||||
t.Run("rapid_successive_actions", func(t *testing.T) {
|
||||
createdUser := ctx.createUserWithCleanup(t, "rapid", "Password123!")
|
||||
authClient := ctx.loginUser(t, createdUser.Username, createdUser.Password)
|
||||
|
||||
post := authClient.CreatePost(t, "Rapid Vote Test", "https://example.com/rapid", "Content")
|
||||
|
||||
for i := 0; i < 10; i++ {
|
||||
voteType := "up"
|
||||
if i%2 == 0 {
|
||||
voteType = "down"
|
||||
}
|
||||
voteResp := authClient.VoteOnPost(t, post.ID, voteType)
|
||||
if !voteResp.Success {
|
||||
t.Logf("Vote %d may have been rate limited (acceptable)", i+1)
|
||||
}
|
||||
}
|
||||
|
||||
finalPostsResp := authClient.GetPosts(t)
|
||||
finalPost := findPostInList(finalPostsResp, post.ID)
|
||||
if finalPost == nil {
|
||||
t.Errorf("Expected to retrieve post after rapid votes")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestE2E_LongRunningSession(t *testing.T) {
|
||||
ctx := setupTestContext(t)
|
||||
|
||||
t.Run("long_running_session", func(t *testing.T) {
|
||||
createdUser := ctx.createUserWithCleanup(t, "longsession", "Password123!")
|
||||
authClient := ctx.loginUser(t, createdUser.Username, createdUser.Password)
|
||||
|
||||
profile1 := authClient.GetProfile(t)
|
||||
if profile1 == nil {
|
||||
t.Fatalf("Expected initial profile request to succeed")
|
||||
}
|
||||
|
||||
post := authClient.CreatePost(t, "Long Session Post", "https://example.com/long", "Content")
|
||||
if post.ID == 0 {
|
||||
t.Errorf("Expected post creation after delay to succeed")
|
||||
}
|
||||
|
||||
profile2 := authClient.GetProfile(t)
|
||||
if profile2 == nil || profile2.Data.Username != createdUser.Username {
|
||||
t.Errorf("Expected profile request after delay to succeed")
|
||||
}
|
||||
|
||||
voteResp := authClient.VoteOnPost(t, post.ID, "up")
|
||||
if !voteResp.Success {
|
||||
t.Errorf("Expected vote after delay to succeed")
|
||||
}
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user