github.com/k0marov/go-socnet@v0.0.0-20220715154813-90d07867c782/features/comments/integration_test/comments_test.go (about)

     1  package integration_test
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"github.com/k0marov/go-socnet/core/general/core_values"
     7  	helpers "github.com/k0marov/go-socnet/core/helpers/http_test_helpers"
     8  	. "github.com/k0marov/go-socnet/core/helpers/test_helpers"
     9  	"net/http"
    10  	"net/http/httptest"
    11  	"testing"
    12  	"time"
    13  
    14  	"github.com/go-chi/chi/v5"
    15  	"github.com/k0marov/go-socnet/features/comments"
    16  	"github.com/k0marov/go-socnet/features/comments/delivery/http/handlers"
    17  	"github.com/k0marov/go-socnet/features/comments/delivery/http/responses"
    18  	"github.com/k0marov/go-socnet/features/comments/domain/values"
    19  	post_models "github.com/k0marov/go-socnet/features/posts/domain/models"
    20  	post_values "github.com/k0marov/go-socnet/features/posts/domain/values"
    21  	posts_db "github.com/k0marov/go-socnet/features/posts/store/sql_db"
    22  	"github.com/k0marov/go-socnet/features/profiles"
    23  	profile_responses "github.com/k0marov/go-socnet/features/profiles/delivery/http/responses"
    24  	auth "github.com/k0marov/golang-auth"
    25  	_ "github.com/mattn/go-sqlite3"
    26  )
    27  
    28  func TestComments(t *testing.T) {
    29  	// db
    30  	sql := OpenSqliteDB(t)
    31  	r := chi.NewRouter()
    32  	// profiles
    33  	fakeRegisterProfile := profiles.NewRegisterCallback(sql)
    34  	getProfile := profiles.NewProfileGetterImpl(sql)
    35  	// posts
    36  	postsDB, _ := posts_db.NewSqlDB(sql)
    37  	createPost := func(author core_values.UserId) post_values.PostId {
    38  		id, _ := postsDB.CreatePost(post_models.PostToCreate{
    39  			Author:    author,
    40  			Text:      RandomString(),
    41  			CreatedAt: RandomTime(),
    42  		})
    43  		return id
    44  	}
    45  	// comments
    46  	r.Route("/comments", comments.NewCommentsRouterImpl(sql, getProfile))
    47  
    48  	assertComments := func(t testing.TB, got, want []responses.CommentResponse) {
    49  		t.Helper()
    50  		AssertFatal(t, len(got), len(want), "number of returned comments")
    51  		for i, comment := range got {
    52  			Assert(t, comment, want[i], "comment")
    53  		}
    54  	}
    55  	addComment := func(t testing.TB, post post_values.PostId, caller auth.User) responses.CommentResponse {
    56  		t.Helper()
    57  
    58  		newComment := handlers.NewCommentRequest{Text: RandomString()}
    59  		body := bytes.NewBuffer(nil)
    60  		json.NewEncoder(body).Encode(newComment)
    61  		request := helpers.AddAuthDataToRequest(httptest.NewRequest(http.MethodPost, "/comments/?post_id="+post, body), caller)
    62  		response := httptest.NewRecorder()
    63  		r.ServeHTTP(response, request)
    64  
    65  		AssertStatusCode(t, response, http.StatusOK)
    66  		var returnedComment responses.CommentResponse
    67  		json.NewDecoder(response.Body).Decode(&returnedComment)
    68  
    69  		wantAuthor, _ := getProfile(caller.Id, caller.Id)
    70  		wantComment := responses.CommentResponse{
    71  			Id:        returnedComment.Id,
    72  			Author:    profile_responses.NewProfileResponse(wantAuthor),
    73  			Text:      newComment.Text,
    74  			CreatedAt: time.Now().Unix(),
    75  			Likes:     0,
    76  			IsLiked:   false,
    77  			IsMine:    true,
    78  		}
    79  		assertComments(t, []responses.CommentResponse{returnedComment}, []responses.CommentResponse{wantComment})
    80  
    81  		return returnedComment
    82  	}
    83  	getComments := func(t testing.TB, post post_values.PostId, caller auth.User) []responses.CommentResponse {
    84  		t.Helper()
    85  
    86  		request := helpers.AddAuthDataToRequest(httptest.NewRequest(http.MethodGet, "/comments/?post_id="+post, nil), caller)
    87  		response := httptest.NewRecorder()
    88  		r.ServeHTTP(response, request)
    89  
    90  		AssertStatusCode(t, response, http.StatusOK)
    91  		var commentsResponse responses.CommentsResponse
    92  		json.NewDecoder(response.Body).Decode(&commentsResponse)
    93  
    94  		return commentsResponse.Comments
    95  	}
    96  	toggleLike := func(t testing.TB, comment values.CommentId, caller auth.User) {
    97  		t.Helper()
    98  		request := helpers.AddAuthDataToRequest(httptest.NewRequest(http.MethodPost, "/comments/"+comment+"/toggle-like", nil), caller)
    99  		response := httptest.NewRecorder()
   100  		r.ServeHTTP(response, request)
   101  		AssertStatusCode(t, response, http.StatusOK)
   102  	}
   103  	deleteComment := func(t testing.TB, comment values.CommentId, caller auth.User) {
   104  		t.Helper()
   105  		request := helpers.AddAuthDataToRequest(httptest.NewRequest(http.MethodDelete, "/comments/"+comment, nil), caller)
   106  		response := httptest.NewRecorder()
   107  		r.ServeHTTP(response, request)
   108  		AssertStatusCode(t, response, http.StatusOK)
   109  	}
   110  
   111  	t.Run("creating, reading and deleting comments", func(t *testing.T) {
   112  
   113  		// create 2 profiles
   114  		user1 := RandomAuthUser()
   115  		user2 := RandomAuthUser()
   116  		fakeRegisterProfile(user1)
   117  		fakeRegisterProfile(user2)
   118  
   119  		// create post belonging to 1-st profile
   120  		post := createPost(user1.Id)
   121  		// add a comment to this post from 2-nd profile
   122  		comment1 := addComment(t, post, user2)
   123  		// assert it was created
   124  		comments := getComments(t, post, user2)
   125  		assertComments(t, comments, []responses.CommentResponse{comment1})
   126  
   127  		// wait so that createdAt difference is at least 1 second
   128  		time.Sleep(time.Second)
   129  
   130  		// create another comment from 2-nd profile
   131  		comment2 := addComment(t, post, user2)
   132  		// assert it was created and comments are returned in the right order (newest first)
   133  		comments = getComments(t, post, user2)
   134  		assertComments(t, comments, []responses.CommentResponse{comment2, comment1})
   135  
   136  		t.Run("liking comments", func(t *testing.T) {
   137  			// like the newest comment from 1-st profile
   138  			toggleLike(t, comment2.Id, user1)
   139  			// assert it is liked
   140  			comments = getComments(t, post, user1)
   141  			Assert(t, comments[0].IsLiked, true, "isLiked")
   142  			// unlike it
   143  			toggleLike(t, comment2.Id, user1)
   144  			// assert it is not liked
   145  			comments = getComments(t, post, user1)
   146  			Assert(t, comments[0].IsLiked, false, "isLiked")
   147  		})
   148  		// delete the second comment
   149  		deleteComment(t, comment2.Id, user2)
   150  		// assert it was deleted
   151  		comments = getComments(t, post, user2)
   152  		assertComments(t, comments, []responses.CommentResponse{comment1})
   153  		// delete the first comment
   154  		deleteComment(t, comment1.Id, user2)
   155  		// assert it was deleted
   156  		assertComments(t, getComments(t, post, user2), []responses.CommentResponse{})
   157  	})
   158  }