github.com/ngocphuongnb/tetua@v0.0.7-alpha/app/web/web_test.go (about)

     1  package web_test
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"fmt"
     7  	"net/http"
     8  	"strings"
     9  	"testing"
    10  	"time"
    11  
    12  	"github.com/PuerkitoBio/goquery"
    13  	"github.com/ngocphuongnb/tetua/app/auth"
    14  	"github.com/ngocphuongnb/tetua/app/cache"
    15  	"github.com/ngocphuongnb/tetua/app/config"
    16  	"github.com/ngocphuongnb/tetua/app/entities"
    17  	"github.com/ngocphuongnb/tetua/app/fs"
    18  	"github.com/ngocphuongnb/tetua/app/mock"
    19  	mockrepository "github.com/ngocphuongnb/tetua/app/mock/repository"
    20  	"github.com/ngocphuongnb/tetua/app/repositories"
    21  	"github.com/ngocphuongnb/tetua/app/server"
    22  	"github.com/ngocphuongnb/tetua/app/web"
    23  	"github.com/stretchr/testify/assert"
    24  	"github.com/tdewolff/minify/v2"
    25  	"github.com/tdewolff/minify/v2/xml"
    26  )
    27  
    28  var m = minify.New()
    29  var mockLogger *mock.MockLogger
    30  var post1, post2 *entities.Post
    31  var file1, file2, file3 *entities.File
    32  var topic1 *entities.Topic
    33  
    34  func init() {
    35  	m.AddFunc("xml", xml.Minify)
    36  	fs.New("disk_mock", []fs.FSDisk{&mock.Disk{}})
    37  	cache.Roles = []*entities.Role{auth.ROLE_ADMIN, auth.ROLE_USER, auth.ROLE_GUEST}
    38  	mockLogger = mock.CreateLogger(true)
    39  	mock.CreateRepositories()
    40  	config.Settings([]*config.SettingItem{{
    41  		Name:  "app_base_url",
    42  		Value: "http://localhost:8080",
    43  	}})
    44  
    45  	topic1, _ = repositories.Topic.Create(context.Background(), &entities.Topic{
    46  		ID:   1,
    47  		Name: "Test Topic",
    48  		Slug: "test-topic",
    49  	})
    50  
    51  	post1, _ = repositories.Post.Create(context.Background(), &entities.Post{
    52  		ID:       1,
    53  		Name:     "test post 1",
    54  		Slug:     "test-post-1",
    55  		Draft:    false,
    56  		UserID:   1,
    57  		Topics:   []*entities.Topic{topic1},
    58  		TopicIDs: []int{topic1.ID},
    59  	})
    60  	post2, _ = repositories.Post.Create(context.Background(), &entities.Post{
    61  		ID:       2,
    62  		Name:     "test post 2",
    63  		Slug:     "test-post-2",
    64  		Draft:    false,
    65  		UserID:   2,
    66  		Topics:   []*entities.Topic{topic1},
    67  		TopicIDs: []int{topic1.ID},
    68  	})
    69  
    70  	file1, _ = repositories.File.Create(context.Background(), &entities.File{
    71  		ID:     1,
    72  		Disk:   "disk_mock",
    73  		Path:   "/test/file1.jpg",
    74  		Size:   100,
    75  		Type:   "image/jpg",
    76  		UserID: 1,
    77  	})
    78  	file2, _ = repositories.File.Create(context.Background(), &entities.File{
    79  		ID:     2,
    80  		Disk:   "disk_mock",
    81  		Path:   "/test/file2.jpg",
    82  		Size:   100,
    83  		Type:   "image/jpg",
    84  		UserID: 1,
    85  	})
    86  	file3, _ = repositories.File.Create(context.Background(), &entities.File{
    87  		ID:     3,
    88  		Disk:   "disk_mock",
    89  		Path:   "/test/file3.jpg",
    90  		Size:   100,
    91  		Type:   "image/jpg",
    92  		UserID: 2,
    93  	})
    94  }
    95  
    96  func TestWeb(t *testing.T) {
    97  	web.NewServer(web.Config{
    98  		JwtSigningKey: config.APP_KEY,
    99  		Theme:         config.APP_THEME,
   100  	})
   101  }
   102  
   103  func TestFeedError(t *testing.T) {
   104  	mockrepository.FakeRepoErrors["post_find"] = errors.New("Error finding posts")
   105  	mockServer := mock.CreateServer()
   106  	mockServer.Get("/feed", func(c server.Context) error {
   107  		return web.Feed(c)
   108  	})
   109  
   110  	body, resp := mock.GetRequest(mockServer, "/feed")
   111  	assert.Equal(t, "Error", body)
   112  	assert.Equal(t, http.StatusInternalServerError, resp.StatusCode)
   113  }
   114  
   115  func TestFeed(t *testing.T) {
   116  	mockrepository.FakeRepoErrors["post_find"] = nil
   117  	mockServer := mock.CreateServer()
   118  	mockServer.Get("/feed", func(c server.Context) error {
   119  		return web.Feed(c)
   120  	})
   121  
   122  	body, _ := mock.GetRequest(mockServer, "/feed")
   123  	body, err := m.String("xml", body)
   124  	assert.Nil(t, err)
   125  
   126  	expectFeed, _ := m.String("xml", fmt.Sprintf(`<?xml version="1.0" encoding="UTF-8"?>
   127  	<rss version="2.0"
   128  		xmlns:content="http://purl.org/rss/1.0/modules/content/">
   129  		<channel>
   130  			<title>Tetua</title>
   131  			<link>http://localhost:8080/</link>
   132  			<description>Tetua</description>
   133  			<item>
   134  				<title>test post 1</title>
   135  				<link>http://localhost:8080/test-post-1-1.html</link>
   136  				<description/>
   137  				<author>testuser1</author>
   138  				<guid>1</guid>
   139  				<pubDate>%s</pubDate>
   140  			</item>
   141  			<item>
   142  				<title>test post 2</title>
   143  				<link>http://localhost:8080/test-post-2-2.html</link>
   144  				<description/>
   145  				<author>testuser2</author>
   146  				<guid>2</guid>
   147  				<pubDate>%s</pubDate>
   148  			</item>
   149  		</channel>
   150  	</rss>`, post1.CreatedAt.Format(time.RFC1123Z), post2.CreatedAt.Format(time.RFC1123Z)))
   151  
   152  	assert.Equal(t, expectFeed, body)
   153  }
   154  
   155  func TestFileError(t *testing.T) {
   156  	mockrepository.FakeRepoErrors["file_find"] = errors.New("Error finding files")
   157  	mockServer := mock.CreateServer()
   158  	mockServer.Get("/files", web.FileList)
   159  
   160  	_, resp := mock.GetRequest(mockServer, "/files")
   161  	assert.Equal(t, http.StatusInternalServerError, resp.StatusCode)
   162  }
   163  
   164  func TestFileList(t *testing.T) {
   165  	mockrepository.FakeRepoErrors["file_find"] = nil
   166  
   167  	fileLinks := []string{
   168  		file1.Url(),
   169  		file2.Url(),
   170  	}
   171  
   172  	mockServer := mock.CreateServer()
   173  	mockServer.Get("/files", func(c server.Context) error {
   174  		c.Locals("user", &entities.User{ID: 1})
   175  		return web.FileList(c)
   176  	})
   177  
   178  	body, resp := mock.GetRequest(mockServer, "/files")
   179  	doc, err := goquery.NewDocumentFromReader(strings.NewReader(body))
   180  	assert.Nil(t, err)
   181  	foundLinks := make([]string, 0)
   182  	doc.Find(".files-list > div").Each(func(i int, s *goquery.Selection) {
   183  		href, _ := s.Find("a").Attr("href")
   184  		foundLinks = append(foundLinks, href)
   185  	})
   186  
   187  	assert.Equal(t, fileLinks, foundLinks)
   188  	assert.Equal(t, http.StatusOK, resp.StatusCode)
   189  }
   190  
   191  func TestFileDeleteError1(t *testing.T) {
   192  	mockrepository.FakeRepoErrors["file_deleteByID"] = errors.New("Error deleting file")
   193  	mockServer := mock.CreateServer()
   194  	mockServer.Delete("/files/:id", func(c server.Context) error {
   195  		file3, _ := repositories.File.ByID(context.Background(), 3)
   196  		c.Locals("file", file3)
   197  		return web.FileDelete(c)
   198  	})
   199  
   200  	body, resp := mock.Request(mockServer, "DELETE", "/files/3")
   201  	assert.Equal(t, errors.New("Error deleting file"), mockLogger.Last().Params[0])
   202  	assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
   203  	assert.Equal(t, `{"type":"error","message":"Error deleting file"}`, body)
   204  }
   205  
   206  func TestFileDeleteError2(t *testing.T) {
   207  	mockrepository.FakeRepoErrors["file_deleteByID"] = nil
   208  	mockServer := mock.CreateServer()
   209  	mockServer.Delete("/files/:id", func(c server.Context) error {
   210  		file3, _ := repositories.File.ByID(context.Background(), 3)
   211  		file3.Path = "/delete/error"
   212  		c.Locals("file", file3)
   213  		return web.FileDelete(c)
   214  	})
   215  
   216  	body, resp := mock.Request(mockServer, "DELETE", "/files/3")
   217  	assert.Equal(t, errors.New("Delete file error"), mockLogger.Last().Params[0])
   218  	assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
   219  	assert.Equal(t, `{"type":"error","message":"Error deleting file"}`, body)
   220  }
   221  
   222  func TestFileDelete(t *testing.T) {
   223  	mockrepository.FakeRepoErrors["file_deleteByID"] = nil
   224  	repositories.File.Create(context.Background(), file3)
   225  	mockServer := mock.CreateServer()
   226  	mockServer.Delete("/files/:id", func(c server.Context) error {
   227  		file3, _ := repositories.File.ByID(context.Background(), 3)
   228  		file3.Path = "/test/file3.jpg"
   229  		c.Locals("file", file3)
   230  		return web.FileDelete(c)
   231  	})
   232  
   233  	body, resp := mock.Request(mockServer, "DELETE", "/files/3")
   234  
   235  	assert.Equal(t, http.StatusOK, resp.StatusCode)
   236  	assert.Equal(t, `{"type":"success","message":"File deleted"}`, body)
   237  }
   238  
   239  func TestFileUpload(t *testing.T) {
   240  	mockServer := mock.CreateServer()
   241  	mockServer.Post("/files", func(c server.Context) error {
   242  		return web.Upload(c)
   243  	})
   244  
   245  	req := mock.CreateUploadRequest("POST", "/files", "some_field", "file.jpg")
   246  	body, _ := mock.SendRequest(mockServer, req)
   247  	assert.Equal(t, errors.New("there is no uploaded file associated with the given key"), mockLogger.Last().Params[0])
   248  	assert.Equal(t, `{"error":"Error saving file"}`, body)
   249  
   250  	req = mock.CreateUploadRequest("POST", "/files", "file", "error.jpg")
   251  	body, _ = mock.SendRequest(mockServer, req)
   252  	assert.Equal(t, errors.New("PutMultipart error"), mockLogger.Last().Params[0])
   253  	assert.Equal(t, `{"error":"Error saving file"}`, body)
   254  
   255  	mockrepository.FakeRepoErrors["file_create"] = errors.New("Error creating file")
   256  	req = mock.CreateUploadRequest("POST", "/files", "file", "image.jpg")
   257  	body, _ = mock.SendRequest(mockServer, req)
   258  	assert.Equal(t, errors.New("Error creating file"), mockLogger.Last().Params[0])
   259  	assert.Equal(t, `{"error":"Error saving file"}`, body)
   260  
   261  	mockrepository.FakeRepoErrors["file_create"] = nil
   262  	req = mock.CreateUploadRequest("POST", "/files", "file", "image.jpg")
   263  	body, _ = mock.SendRequest(mockServer, req)
   264  	assert.Equal(t, `{"size":100,"type":"image/jpeg","url":"/disk_mock/image.jpg"}`, body)
   265  }
   266  
   267  func TestIndex(t *testing.T) {
   268  	mockServer := mock.CreateServer()
   269  	mockServer.Get("/", func(c server.Context) error {
   270  		return web.Index(c)
   271  	})
   272  
   273  	mockrepository.FakeRepoErrors["post_paginate"] = errors.New("Error paginating posts")
   274  	body, resp := mock.GetRequest(mockServer, "/")
   275  	assert.Equal(t, http.StatusBadGateway, resp.StatusCode)
   276  	assert.Equal(t, errors.New("Error paginating posts"), mockLogger.Last().Params[0])
   277  	assert.Equal(t, true, strings.Contains(body, `<h1>Something went wrong</h1>`))
   278  
   279  	mockrepository.FakeRepoErrors["post_paginate"] = nil
   280  	mockrepository.FakeRepoErrors["post_find"] = errors.New("Error finding post")
   281  	body, resp = mock.GetRequest(mockServer, "/")
   282  	assert.Equal(t, http.StatusBadGateway, resp.StatusCode)
   283  	assert.Equal(t, errors.New("Error finding post"), mockLogger.Last().Params[0])
   284  	assert.Equal(t, true, strings.Contains(body, `<h1>Something went wrong</h1>`))
   285  
   286  	mockrepository.FakeRepoErrors["post_paginate"] = nil
   287  	mockrepository.FakeRepoErrors["post_find"] = nil
   288  	body, resp = mock.GetRequest(mockServer, "/")
   289  
   290  	doc, err := goquery.NewDocumentFromReader(strings.NewReader(body))
   291  	assert.Nil(t, err)
   292  	postLinks := []string{post1.Url(), post2.Url()}
   293  	mainLinks := make([]string, 0)
   294  	sideLinks := make([]string, 0)
   295  	doc.Find("main article").Each(func(i int, s *goquery.Selection) {
   296  		href, _ := s.Find("a.overlay").Attr("href")
   297  		mainLinks = append(mainLinks, href)
   298  	})
   299  
   300  	doc.Find(".right article").Each(func(i int, s *goquery.Selection) {
   301  		href, _ := s.Find("a").Attr("href")
   302  		sideLinks = append(sideLinks, href)
   303  	})
   304  
   305  	assert.Equal(t, postLinks, mainLinks)
   306  	assert.Equal(t, postLinks, sideLinks)
   307  	assert.Equal(t, http.StatusOK, resp.StatusCode)
   308  }
   309  
   310  func TestSearch(t *testing.T) {
   311  	mockServer := mock.CreateServer()
   312  	mockServer.Get("/search", func(c server.Context) error {
   313  		return web.Search(c)
   314  	})
   315  
   316  	mockrepository.FakeRepoErrors["post_paginate"] = errors.New("Error paginating posts")
   317  	body, resp := mock.GetRequest(mockServer, "/search?q=post")
   318  	assert.Equal(t, http.StatusBadGateway, resp.StatusCode)
   319  	assert.Equal(t, errors.New("Error paginating posts"), mockLogger.Last().Params[0])
   320  	assert.Equal(t, true, strings.Contains(body, `<h1>Something went wrong</h1>`))
   321  
   322  	mockrepository.FakeRepoErrors["post_paginate"] = nil
   323  	mockrepository.FakeRepoErrors["post_find"] = nil
   324  	body, resp = mock.GetRequest(mockServer, "/search?q=post")
   325  
   326  	doc, err := goquery.NewDocumentFromReader(strings.NewReader(body))
   327  	assert.Nil(t, err)
   328  	postLinks := []string{post1.Url(), post2.Url()}
   329  	mainLinks := make([]string, 0)
   330  	doc.Find("main article").Each(func(i int, s *goquery.Selection) {
   331  		href, _ := s.Find("a.overlay").Attr("href")
   332  		mainLinks = append(mainLinks, href)
   333  	})
   334  
   335  	assert.Equal(t, postLinks, mainLinks)
   336  	assert.Equal(t, true, strings.Contains(body, `<title>post - Search result for post - Tetua</title>`))
   337  }
   338  
   339  func TestTopicView(t *testing.T) {
   340  	mockServer := mock.CreateServer()
   341  	mockServer.Get("/:slug", func(c server.Context) error {
   342  		return web.TopicView(c)
   343  	})
   344  
   345  	body, resp := mock.GetRequest(mockServer, "/test-topic")
   346  	assert.Equal(t, http.StatusNotFound, resp.StatusCode)
   347  	assert.Equal(t, true, strings.Contains(body, `<title>Topic not found`))
   348  	assert.Equal(t, true, strings.Contains(body, `<h1>Topic not found</h1>`))
   349  
   350  	post1.TopicIDs = []int{topic1.ID}
   351  	post2.TopicIDs = []int{topic1.ID}
   352  	repositories.Post.Update(context.Background(), post1)
   353  	repositories.Post.Update(context.Background(), post2)
   354  	cache.CacheTopics()
   355  
   356  	mockrepository.FakeRepoErrors["post_paginate"] = errors.New("Error paginating posts")
   357  	body, resp = mock.GetRequest(mockServer, "/test-topic")
   358  	assert.Equal(t, http.StatusBadGateway, resp.StatusCode)
   359  	assert.Equal(t, errors.New("Error paginating posts"), mockLogger.Last().Params[0])
   360  	assert.Equal(t, true, strings.Contains(body, `<h1>Something went wrong</h1>`))
   361  
   362  	mockrepository.FakeRepoErrors["post_paginate"] = nil
   363  	mockrepository.FakeRepoErrors["post_find"] = errors.New("Error finding post")
   364  	body, resp = mock.GetRequest(mockServer, "/test-topic")
   365  	assert.Equal(t, http.StatusBadGateway, resp.StatusCode)
   366  	assert.Equal(t, errors.New("Error finding post"), mockLogger.Last().Params[0])
   367  	assert.Equal(t, true, strings.Contains(body, `<h1>Something went wrong</h1>`))
   368  
   369  	mockrepository.FakeRepoErrors["post_find"] = nil
   370  	body, resp = mock.GetRequest(mockServer, "/test-topic")
   371  	assert.Equal(t, http.StatusOK, resp.StatusCode)
   372  	assert.Equal(t, true, strings.Contains(body, `<title>Test Topic`))
   373  
   374  	doc, err := goquery.NewDocumentFromReader(strings.NewReader(body))
   375  	assert.Nil(t, err)
   376  	postLinks := []string{post1.Url(), post2.Url()}
   377  	mainLinks := make([]string, 0)
   378  	sideLinks := make([]string, 0)
   379  	doc.Find("main article").Each(func(i int, s *goquery.Selection) {
   380  		href, _ := s.Find("a.overlay").Attr("href")
   381  		mainLinks = append(mainLinks, href)
   382  	})
   383  
   384  	doc.Find(".right article").Each(func(i int, s *goquery.Selection) {
   385  		href, _ := s.Find("a").Attr("href")
   386  		sideLinks = append(sideLinks, href)
   387  	})
   388  
   389  	assert.Equal(t, postLinks, mainLinks)
   390  	assert.Equal(t, postLinks, sideLinks)
   391  	assert.Equal(t, http.StatusOK, resp.StatusCode)
   392  }
   393  
   394  func TestTopicFeedError(t *testing.T) {
   395  	mockrepository.FakeRepoErrors["post_find"] = errors.New("Error finding posts")
   396  	mockServer := mock.CreateServer()
   397  	mockServer.Get("/:slug/feed", func(c server.Context) error {
   398  		return web.TopicFeed(c)
   399  	})
   400  
   401  	topic1.Slug = "test-topic-updated"
   402  	repositories.Topic.Update(context.Background(), topic1)
   403  	cache.CacheTopics()
   404  	body, resp := mock.GetRequest(mockServer, "/test-topic/feed")
   405  	assert.Equal(t, "Topic not found", body)
   406  	assert.Equal(t, http.StatusNotFound, resp.StatusCode)
   407  
   408  	topic1.Slug = "test-topic"
   409  	mockrepository.FakeRepoErrors["post_find"] = nil
   410  	repositories.Topic.Update(context.Background(), topic1)
   411  	cache.CacheTopics()
   412  	body, resp = mock.GetRequest(mockServer, "/test-topic/feed")
   413  	assert.Equal(t, http.StatusOK, resp.StatusCode)
   414  
   415  	body, err := m.String("xml", body)
   416  	assert.Nil(t, err)
   417  
   418  	expectFeed, _ := m.String("xml", fmt.Sprintf(`<?xml version="1.0" encoding="UTF-8"?>
   419  	<rss version="2.0"
   420  		xmlns:content="http://purl.org/rss/1.0/modules/content/">
   421  		<channel>
   422  			<title>%s</title>
   423  			<link>%s</link>
   424  			<description></description>
   425  			<item>
   426  				<title>%s</title>
   427  				<link>%s</link>
   428  				<description></description>
   429  				<author>%s</author>
   430  				<guid>%d</guid>
   431  				<pubDate>%s</pubDate>
   432  			</item>
   433  			<item>
   434  				<title>%s</title>
   435  				<link>%s</link>
   436  				<description></description>
   437  				<author>%s</author>
   438  				<guid>%d</guid>
   439  				<pubDate>%s</pubDate>
   440  			</item>
   441  		</channel>
   442  	</rss>`,
   443  		topic1.Name,
   444  		topic1.Url(),
   445  
   446  		post1.Name,
   447  		post1.Url(),
   448  		post1.User.Username,
   449  		post1.ID,
   450  		post1.CreatedAt.Format(time.RFC1123Z),
   451  
   452  		post2.Name,
   453  		post2.Url(),
   454  		post2.User.Username,
   455  		post2.ID,
   456  		post2.CreatedAt.Format(time.RFC1123Z),
   457  	))
   458  	assert.Equal(t, expectFeed, body)
   459  }