Skip to content

Commit

Permalink
Create blogs API and write tests
Browse files Browse the repository at this point in the history
  • Loading branch information
cp-sumi-k committed Feb 28, 2023
1 parent 75073f5 commit 66a4e05
Show file tree
Hide file tree
Showing 20 changed files with 2,422 additions and 69 deletions.
1 change: 1 addition & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ jobs:
go test jobs
go test contact
go test sitemap
go test blogs
env:
DB_HOST: localhost
DB_NAME: website_admin_test
Expand Down
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
.DS_Store
.env
.env
*.json
3 changes: 2 additions & 1 deletion .prettierignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
*.yml
*.yml
*.json
100 changes: 100 additions & 0 deletions blogs/blog.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package blogs

import (
"encoding/json"
"io/ioutil"
"net/http"
"sort"
"strings"
"time"
"utils"

"github.com/gin-gonic/gin"
log "github.com/sirupsen/logrus"
)

const YYYYMMDD = "2006-01-02 15:04:05"
const MAX_BLOG_NUMBER = 3

type Item struct {
Title string `json:"title"`
Author string `json:"author"`
PubDate string `json:"pubDate"`
Link string `json:"link"`
GUID string `json:"guid"`
Thumbnail string `json:"thumbnail"`
Description string `json:"description"`
}

type Blog struct {
Items []Item `json:"items"`
}

func Get(c *gin.Context) {

// get blogs from API
response, err := http.Get("https://api.rss2json.com/v1/api.json?rss_url=https://medium.com/feed/canopas")

if err != nil {
log.Error(err)
c.AbortWithStatus(http.StatusInternalServerError)
return
}

defer response.Body.Close()

responseData, err := ioutil.ReadAll(response.Body)
if err != nil {
log.Error(err)
c.AbortWithStatus(http.StatusInternalServerError)
return
}

// bind data to struct
var blogs Blog
json.Unmarshal(responseData, &blogs)

filteredItems := []Item{}
fileName := "./blogs.json"

// filter weekly and newletteres
for _, item := range blogs.Items {
if !strings.Contains(strings.ToLower(item.Title), "weekly") && !strings.Contains(strings.ToLower(item.Title), "newsletter") {
filteredItems = append(filteredItems, item)
}
}

// read and append blog from file, if blogs are less then 3
if len(filteredItems) < MAX_BLOG_NUMBER {
filteredItems = append(filteredItems, utils.ReadSliceFromFile(fileName, []Item{})...)

// make blogs unique and get only 3 blogs
filteredItems = utils.Unique(filteredItems)
}

if len(filteredItems) > MAX_BLOG_NUMBER {
filteredItems = filteredItems[0:MAX_BLOG_NUMBER]
}

// sort blogs by published date
sortBlogs(filteredItems)

// write blogs to file
utils.WriteSliceToFile(fileName, filteredItems)

c.JSON(http.StatusOK, filteredItems)
}

func sortBlogs(blogs []Item) {
sort.Slice(blogs, func(i, j int) bool {
dateI, err := time.Parse(YYYYMMDD, blogs[i].PubDate)
if err != nil {
log.Warn(err)
}
dateJ, err := time.Parse(YYYYMMDD, blogs[j].PubDate)
if err != nil {
log.Warn(err)
}
return dateI.After(dateJ)
})
}
67 changes: 67 additions & 0 deletions blogs/blog_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package blogs

import (
"net/http"
"net/http/httptest"
"testing"
"utils"

"github.com/gin-gonic/gin"
"github.com/tj/assert"
)

func Test_Unique_Int_Success(t *testing.T) {
got := utils.Unique([]int{1, 1, 2, 2, 3, 3})
expected := []int{1, 2, 3}
assert.Equal(t, got, expected)
}

func Test_Unique_String_Fail(t *testing.T) {
got := utils.Unique([]string{"apple", "has", "apple", "logo"})
expected := []string{"apple", "has", "apple", "logo"}
assert.NotEqual(t, got, expected)
}

func Test_Unique_Struct_Success(t *testing.T) {
got := utils.Unique([]Item{{
Title: "test1",
}, {
Title: "test1",
}, {
Title: "test2",
}})
expected := []Item{{
Title: "test1",
}, {
Title: "test2",
}}
assert.Equal(t, got, expected)
}

func Test_ReadFile_Empty_Filepath(t *testing.T) {
got := utils.ReadSliceFromFile("", []Item{})
expected := []Item{}
assert.Equal(t, got, expected)
}

func Test_ReadFile_Wrong_Filepath(t *testing.T) {
got := utils.ReadSliceFromFile("test.json", []Item{})
expected := []Item{}
assert.Equal(t, got, expected)
}

func Test_GetBlogs_Integration(t *testing.T) {
w := httptest.NewRecorder()
req, err := http.NewRequest("GET", "/api/blogs", nil)

assert.NoError(t, err)

engine := gin.New()
setUpRouter(engine)
engine.ServeHTTP(w, req)
assert.Equal(t, http.StatusOK, w.Code)
}

func setUpRouter(engine *gin.Engine) {
engine.GET("/api/blogs", Get)
}
63 changes: 63 additions & 0 deletions blogs/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
module blogs

go 1.20

replace db => ../db

replace utils => ../utils

require (
github.com/gin-gonic/gin v1.9.0
github.com/sirupsen/logrus v1.9.0
github.com/tj/assert v0.0.3
utils v0.0.0-00010101000000-000000000000
)

require (
cloud.google.com/go/compute v1.7.0 // indirect
cloud.google.com/go/recaptchaenterprise v1.3.1 // indirect
cloud.google.com/go/recaptchaenterprise/v2 v2.0.1 // indirect
db v0.0.0-00010101000000-000000000000 // indirect
github.com/aws/aws-sdk-go v1.44.83 // indirect
github.com/bytedance/sonic v1.8.0 // indirect
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.11.2 // indirect
github.com/go-sql-driver/mysql v1.6.0 // indirect
github.com/goccy/go-json v0.10.0 // indirect
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/google/go-cmp v0.5.8 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.1.0 // indirect
github.com/googleapis/gax-go/v2 v2.4.0 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/jmoiron/sqlx v1.3.5 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/cpuid/v2 v2.0.9 // indirect
github.com/leodido/go-urn v1.2.1 // indirect
github.com/mattn/go-isatty v0.0.17 // indirect
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/pelletier/go-toml/v2 v2.0.6 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/stretchr/testify v1.8.1 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.9 // indirect
go.opencensus.io v0.23.0 // indirect
golang.org/x/arch v0.0.0-20210923205945-b76863e36670 // indirect
golang.org/x/crypto v0.5.0 // indirect
golang.org/x/net v0.7.0 // indirect
golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094 // indirect
golang.org/x/sys v0.5.0 // indirect
golang.org/x/text v0.7.0 // indirect
google.golang.org/api v0.94.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20220902135211-223410557253 // indirect
google.golang.org/grpc v1.48.0 // indirect
google.golang.org/protobuf v1.28.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
Loading

0 comments on commit 66a4e05

Please sign in to comment.