Skip to content

Commit

Permalink
separated newsAlerts and alerts to make further development less messy
Browse files Browse the repository at this point in the history
  • Loading branch information
CommanderStorm committed Sep 13, 2023
1 parent ed36278 commit d5abf2e
Show file tree
Hide file tree
Showing 4 changed files with 169 additions and 106 deletions.
26 changes: 0 additions & 26 deletions server/backend/news.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,13 @@ package backend

import (
"context"
"errors"
"fmt"
pb "github.com/TUM-Dev/Campus-Backend/server/api/tumdev"
"github.com/TUM-Dev/Campus-Backend/server/model"
log "github.com/sirupsen/logrus"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/types/known/emptypb"
"google.golang.org/protobuf/types/known/timestamppb"
"gorm.io/gorm"
)

func (s *CampusServer) GetNewsSources(ctx context.Context, _ *emptypb.Empty) (newsSources *pb.NewsSourceReply, err error) {
Expand All @@ -36,26 +33,3 @@ func (s *CampusServer) GetNewsSources(ctx context.Context, _ *emptypb.Empty) (ne
}
return &pb.NewsSourceReply{Sources: resp}, nil
}

func (s *CampusServer) GetTopNews(ctx context.Context, _ *emptypb.Empty) (*pb.GetTopNewsReply, error) {
if err := s.checkDevice(ctx); err != nil {
return nil, err
}

var res *model.NewsAlert
err := s.db.Joins("Files").Where("NOW() between `from` and `to`").First(&res).Error
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, status.Error(codes.NotFound, "no currenty active top news")
} else if err != nil {
log.WithError(err).Error("could not GetTopNews")
return nil, status.Error(codes.Internal, "could not GetTopNews")
}

return &pb.GetTopNewsReply{
ImageUrl: res.Files.URL.String,
Link: res.Link.String,
Created: timestamppb.New(res.Created),
From: timestamppb.New(res.From),
To: timestamppb.New(res.To),
}, nil
}
37 changes: 37 additions & 0 deletions server/backend/newsAlerts.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package backend

import (
"context"
"errors"
pb "github.com/TUM-Dev/Campus-Backend/server/api/tumdev"
"github.com/TUM-Dev/Campus-Backend/server/model"
log "github.com/sirupsen/logrus"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/types/known/emptypb"
"google.golang.org/protobuf/types/known/timestamppb"
"gorm.io/gorm"
)

func (s *CampusServer) GetTopNews(ctx context.Context, _ *emptypb.Empty) (*pb.GetTopNewsReply, error) {
if err := s.checkDevice(ctx); err != nil {
return nil, err
}

var res *model.NewsAlert
err := s.db.Joins("Files").Where("NOW() between `from` and `to`").First(&res).Error
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, status.Error(codes.NotFound, "no current active top news")
} else if err != nil {
log.WithError(err).Error("could not GetTopNews")
return nil, status.Error(codes.Internal, "could not GetTopNews")
}

return &pb.GetTopNewsReply{
ImageUrl: res.Files.URL.String,
Link: res.Link.String,
Created: timestamppb.New(res.Created),
From: timestamppb.New(res.From),
To: timestamppb.New(res.To),
}, nil
}
114 changes: 114 additions & 0 deletions server/backend/newsAlerts_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
package backend

import (
"context"
"database/sql"
"github.com/DATA-DOG/go-sqlmock"
pb "github.com/TUM-Dev/Campus-Backend/server/api/tumdev"
"github.com/TUM-Dev/Campus-Backend/server/model"
"github.com/guregu/null"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/metadata"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/types/known/timestamppb"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"regexp"
"testing"
"time"
)

type NewsAlertSuite struct {
suite.Suite
DB *gorm.DB
mock sqlmock.Sqlmock
deviceBuf *deviceBuffer
}

func (s *NewsAlertSuite) SetupSuite() {
var (
db *sql.DB
err error
)

db, s.mock, err = sqlmock.New()
require.NoError(s.T(), err)

dialector := mysql.New(mysql.Config{
Conn: db,
DriverName: "mysql",
})
s.mock.ExpectQuery("SELECT VERSION()").
WillReturnRows(sqlmock.NewRows([]string{"VERSION()"}).AddRow("10.11.4-MariaDB"))
s.DB, err = gorm.Open(dialector, &gorm.Config{})
require.NoError(s.T(), err)

s.deviceBuf = newDeviceBuffer()
}

const ExpectedGetTopNewsQuery = "SELECT `news_alert`.`news_alert`,`news_alert`.`file`,`news_alert`.`name`,`news_alert`.`link`,`news_alert`.`created`,`news_alert`.`from`,`news_alert`.`to`,`Files`.`file` AS `Files__file`,`Files`.`name` AS `Files__name`,`Files`.`path` AS `Files__path`,`Files`.`downloads` AS `Files__downloads`,`Files`.`url` AS `Files__url`,`Files`.`downloaded` AS `Files__downloaded` FROM `news_alert` LEFT JOIN `files` `Files` ON `news_alert`.`file` = `Files`.`file` WHERE NOW() between `from` and `to` ORDER BY `news_alert`.`news_alert` LIMIT 1"

func (s *NewsAlertSuite) Test_GetTopNewsOne() {
expectedAlert := model.NewsAlert{
NewsAlert: 1,
FilesID: 3001,
Files: model.Files{
File: 3001,
Name: "Tournament_app_02-02.png",
Path: "newsalerts/",
Downloads: 0,
URL: sql.NullString{Valid: false},
Downloaded: sql.NullBool{Bool: true, Valid: true},
},
Name: null.String{NullString: sql.NullString{String: "Exzellenzuniversität", Valid: true}},
Link: null.String{NullString: sql.NullString{String: "https://tum.de", Valid: true}},
Created: time.Time.Add(time.Now(), time.Hour*-4),
From: time.Time.Add(time.Now(), time.Hour*-2),
To: time.Time.Add(time.Now(), time.Hour*2),
}
s.mock.ExpectQuery(regexp.QuoteMeta(ExpectedGetTopNewsQuery)).
WillReturnRows(sqlmock.NewRows([]string{"news_alert", "file", "name", "link", "created", "from", "to", "Files__file", "Files__name", "Files__path", "Files__downloads", "Files__url", "Files__downloaded"}).
AddRow(expectedAlert.NewsAlert, expectedAlert.FilesID, expectedAlert.Name, expectedAlert.Link, expectedAlert.Created, expectedAlert.From, expectedAlert.To, expectedAlert.Files.File, expectedAlert.Files.Name, expectedAlert.Files.Path, expectedAlert.Files.Downloads, expectedAlert.Files.URL, expectedAlert.Files.Downloaded))

meta := metadata.MD{}
server := CampusServer{db: s.DB, deviceBuf: s.deviceBuf}
response, err := server.GetTopNews(metadata.NewIncomingContext(context.Background(), meta), nil)
require.NoError(s.T(), err)
require.Equal(s.T(), &pb.GetTopNewsReply{
ImageUrl: expectedAlert.Files.URL.String,
Link: expectedAlert.Link.String,
Created: timestamppb.New(expectedAlert.Created),
From: timestamppb.New(expectedAlert.From),
To: timestamppb.New(expectedAlert.To),
}, response)
}
func (s *NewsAlertSuite) Test_GetTopNewsNone() {
s.mock.ExpectQuery(regexp.QuoteMeta(ExpectedGetTopNewsQuery)).WillReturnError(gorm.ErrRecordNotFound)

meta := metadata.MD{}
server := CampusServer{db: s.DB, deviceBuf: s.deviceBuf}
response, err := server.GetTopNews(metadata.NewIncomingContext(context.Background(), meta), nil)
require.Equal(s.T(), status.Error(codes.NotFound, "no current active top news"), err)
require.Nil(s.T(), response)
}
func (s *NewsAlertSuite) Test_GetTopNewsError() {
s.mock.ExpectQuery(regexp.QuoteMeta(ExpectedGetTopNewsQuery)).WillReturnError(gorm.ErrInvalidDB)

meta := metadata.MD{}
server := CampusServer{db: s.DB, deviceBuf: s.deviceBuf}
response, err := server.GetTopNews(metadata.NewIncomingContext(context.Background(), meta), nil)
require.Equal(s.T(), status.Error(codes.Internal, "could not GetTopNews"), err)
require.Nil(s.T(), response)
}

func (s *NewsAlertSuite) AfterTest(_, _ string) {
require.NoError(s.T(), s.mock.ExpectationsWereMet())
}

// In order for 'go test' to run this suite, we need to create
// a normal test function and pass our suite to suite.Run
func TestNewsAlertSuite(t *testing.T) {
suite.Run(t, new(NewsAlertSuite))
}
98 changes: 18 additions & 80 deletions server/backend/news_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,11 @@ import (
"github.com/guregu/null"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/metadata"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/types/known/timestamppb"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"regexp"
"testing"
"time"
)

type NewsSuite struct {
Expand Down Expand Up @@ -49,21 +45,25 @@ func (s *NewsSuite) SetupSuite() {
s.deviceBuf = newDeviceBuffer()
}

func file(id int32) *model.Files {
return &model.Files{
File: id,
Name: fmt.Sprintf("src_%d.png", id),
Path: "news/sources",
Downloads: 1,
URL: sql.NullString{Valid: false},
Downloaded: sql.NullBool{Bool: true, Valid: true},
}
}

func source1() *model.NewsSource {
return &model.NewsSource{
Source: 1,
Title: "Amazing News 1",
URL: null.String{NullString: sql.NullString{String: "https://example.com/amazing1", Valid: true}},
FilesID: 2,
Files: model.Files{
File: 2,
Name: "src_2.png",
Path: "news/sources",
Downloads: 1,
URL: sql.NullString{Valid: false},
Downloaded: sql.NullBool{Bool: true, Valid: true},
},
Hook: null.String{NullString: sql.NullString{String: "", Valid: true}},
FilesID: file(2).File,
Files: *file(2),
Hook: null.String{NullString: sql.NullString{String: "", Valid: true}},
}
}

Expand All @@ -72,16 +72,9 @@ func source2() *model.NewsSource {
Source: 2,
Title: "Amazing News 2",
URL: null.String{NullString: sql.NullString{String: "https://example.com/amazing2", Valid: true}},
FilesID: 2,
Files: model.Files{
File: 2,
Name: "src_2.png",
Path: "news/sources",
Downloads: 1,
URL: sql.NullString{Valid: false},
Downloaded: sql.NullBool{Bool: true, Valid: true},
},
Hook: null.String{NullString: sql.NullString{String: "hook", Valid: true}},
FilesID: file(2).File,
Files: *file(2),
Hook: null.String{NullString: sql.NullString{String: "hook", Valid: true}},
}
}

Expand Down Expand Up @@ -120,67 +113,12 @@ func (s *NewsSuite) Test_GetNewsSourcesNone() {
require.Equal(s.T(), expectedResp, response)
}

const ExpectedGetTopNewsQuery = "SELECT `news_alert`.`news_alert`,`news_alert`.`file`,`news_alert`.`name`,`news_alert`.`link`,`news_alert`.`created`,`news_alert`.`from`,`news_alert`.`to`,`Files`.`file` AS `Files__file`,`Files`.`name` AS `Files__name`,`Files`.`path` AS `Files__path`,`Files`.`downloads` AS `Files__downloads`,`Files`.`url` AS `Files__url`,`Files`.`downloaded` AS `Files__downloaded` FROM `news_alert` LEFT JOIN `files` `Files` ON `news_alert`.`file` = `Files`.`file` WHERE NOW() between `from` and `to` ORDER BY `news_alert`.`news_alert` LIMIT 1"

func (s *NewsSuite) Test_GetTopNewsOne() {
expectedAlert := model.NewsAlert{
NewsAlert: 1,
FilesID: 3001,
Files: model.Files{
File: 3001,
Name: "Tournament_app_02-02.png",
Path: "newsalerts/",
Downloads: 0,
URL: sql.NullString{Valid: false},
Downloaded: sql.NullBool{Bool: true, Valid: true},
},
Name: null.String{NullString: sql.NullString{String: "Exzellenzuniversität", Valid: true}},
Link: null.String{NullString: sql.NullString{String: "https://tum.de", Valid: true}},
Created: time.Time.Add(time.Now(), time.Hour*-4),
From: time.Time.Add(time.Now(), time.Hour*-2),
To: time.Time.Add(time.Now(), time.Hour*2),
}
s.mock.ExpectQuery(regexp.QuoteMeta(ExpectedGetTopNewsQuery)).
WillReturnRows(sqlmock.NewRows([]string{"news_alert", "file", "name", "link", "created", "from", "to", "Files__file", "Files__name", "Files__path", "Files__downloads", "Files__url", "Files__downloaded"}).
AddRow(expectedAlert.NewsAlert, expectedAlert.FilesID, expectedAlert.Name, expectedAlert.Link, expectedAlert.Created, expectedAlert.From, expectedAlert.To, expectedAlert.Files.File, expectedAlert.Files.Name, expectedAlert.Files.Path, expectedAlert.Files.Downloads, expectedAlert.Files.URL, expectedAlert.Files.Downloaded))

meta := metadata.MD{}
server := CampusServer{db: s.DB, deviceBuf: s.deviceBuf}
response, err := server.GetTopNews(metadata.NewIncomingContext(context.Background(), meta), nil)
require.NoError(s.T(), err)
require.Equal(s.T(), &pb.GetTopNewsReply{
ImageUrl: expectedAlert.Files.URL.String,
Link: expectedAlert.Link.String,
Created: timestamppb.New(expectedAlert.Created),
From: timestamppb.New(expectedAlert.From),
To: timestamppb.New(expectedAlert.To),
}, response)
}
func (s *NewsSuite) Test_GetTopNewsNone() {
s.mock.ExpectQuery(regexp.QuoteMeta(ExpectedGetTopNewsQuery)).WillReturnError(gorm.ErrRecordNotFound)

meta := metadata.MD{}
server := CampusServer{db: s.DB, deviceBuf: s.deviceBuf}
response, err := server.GetTopNews(metadata.NewIncomingContext(context.Background(), meta), nil)
require.Equal(s.T(), status.Error(codes.NotFound, "no currenty active top news"), err)
require.Nil(s.T(), response)
}
func (s *NewsSuite) Test_GetTopNewsError() {
s.mock.ExpectQuery(regexp.QuoteMeta(ExpectedGetTopNewsQuery)).WillReturnError(gorm.ErrInvalidDB)

meta := metadata.MD{}
server := CampusServer{db: s.DB, deviceBuf: s.deviceBuf}
response, err := server.GetTopNews(metadata.NewIncomingContext(context.Background(), meta), nil)
require.Equal(s.T(), status.Error(codes.Internal, "could not GetTopNews"), err)
require.Nil(s.T(), response)
}

func (s *NewsSuite) AfterTest(_, _ string) {
require.NoError(s.T(), s.mock.ExpectationsWereMet())
}

// In order for 'go test' to run this suite, we need to create
// a normal test function and pass our suite to suite.Run
func TestExampleTestSuite(t *testing.T) {
func TestNewsSuite(t *testing.T) {
suite.Run(t, new(NewsSuite))
}

0 comments on commit d5abf2e

Please sign in to comment.