Parent directory

suite_test.go

4237 bytes
  1package ytrssil_test
  2
  3import (
  4	"context"
  5	"fmt"
  6	"log/slog"
  7	"net/http"
  8	"os"
  9	"os/exec"
 10	"strings"
 11	"time"
 12
 13	"github.com/gin-gonic/gin"
 14	"github.com/jackc/pgx/v5"
 15	"github.com/oklog/ulid/v2"
 16	"github.com/stretchr/testify/suite"
 17
 18	"github.com/TheEdgeOfRage/ytrssil-api/config"
 19	"github.com/TheEdgeOfRage/ytrssil-api/db"
 20	"github.com/TheEdgeOfRage/ytrssil-api/feedparser"
 21	"github.com/TheEdgeOfRage/ytrssil-api/handler"
 22	"github.com/TheEdgeOfRage/ytrssil-api/httpserver/ytrssil"
 23	mockFeedparser "github.com/TheEdgeOfRage/ytrssil-api/mocks/feedparser"
 24	mockYouTube "github.com/TheEdgeOfRage/ytrssil-api/mocks/youtube"
 25	"github.com/TheEdgeOfRage/ytrssil-api/models"
 26)
 27
 28func init() {
 29	time.Local = time.UTC
 30}
 31
 32type EndpointsTestSuite struct {
 33	suite.Suite
 34	cfg           config.Config
 35	schema        string
 36	db            db.DB
 37	dbConn        *pgx.Conn
 38	parser        *mockFeedparser.ParserMock
 39	youtubeClient *mockYouTube.ClientMock
 40	server        *http.Server
 41}
 42
 43func (s *EndpointsTestSuite) SetupSuite() {
 44	var err error
 45	l := slog.New(slog.NewTextHandler(os.Stderr, nil))
 46	s.cfg = config.TestConfig()
 47
 48	s.schema = fmt.Sprintf("ytrssil_test_%s", ulid.Make().String())
 49	s.dbConn, err = pgx.Connect(context.Background(), s.cfg.DBURI)
 50	if err != nil {
 51		panic(fmt.Sprintf("failed to connect to database: %v", err))
 52	}
 53	_, err = s.dbConn.Exec(context.Background(), fmt.Sprintf("CREATE SCHEMA %s", s.schema))
 54	if err != nil {
 55		panic(fmt.Sprintf("failed to create test schema: %v", err))
 56	}
 57
 58	testDBURI := fmt.Sprintf("%s&search_path=%s", s.cfg.DBURI, s.schema)
 59	cmd := exec.Command("./bin/migrate", "-database", testDBURI, "-path", "migrations", "up")
 60	cmd.Dir = "../.."
 61	output, err := cmd.CombinedOutput()
 62	if err != nil {
 63		panic(fmt.Sprintf("failed to run migrations: %v\nOutput: %s", err, string(output)))
 64	}
 65
 66	s.db, err = db.NewPostgresDB(l, testDBURI)
 67	if err != nil {
 68		panic(fmt.Sprintf("failed to connect to test database: %v", err))
 69	}
 70
 71	s.parser = &mockFeedparser.ParserMock{
 72		ParseFunc: func(channelID string) (*feedparser.Channel, error) {
 73			publishTime := time.Now().Add(-24 * time.Hour).Format(time.RFC3339)
 74			return &feedparser.Channel{
 75				ID:   channelID,
 76				Name: fmt.Sprintf("Test Channel %s", channelID),
 77				Videos: []*feedparser.Video{
 78					{
 79						ID:        fmt.Sprintf("yt:video:%s-video1", channelID),
 80						Title:     "Test Video 1",
 81						Published: feedparser.Date(publishTime),
 82						IsShort:   false,
 83					},
 84				},
 85			}, nil
 86		},
 87	}
 88
 89	s.youtubeClient = &mockYouTube.ClientMock{
 90		GetVideoDurationsFunc: func(ctx context.Context, videos map[string]*models.Video) error {
 91			for _, video := range videos {
 92				video.DurationSeconds = 300
 93			}
 94			return nil
 95		},
 96		GetVideoMetadataFunc: func(ctx context.Context, videoID string) (*models.Video, error) {
 97			return &models.Video{
 98				ID:              videoID,
 99				Title:           "Test Video",
100				PublishedTime:   time.Now().Add(-24 * time.Hour),
101				DurationSeconds: 300,
102				IsShort:         false,
103				ChannelID:       "test-channel",
104				ChannelName:     "Test Channel",
105			}, nil
106		},
107		GetChannelImageURLFunc: func(ctx context.Context, channelID string) (string, error) {
108			return fmt.Sprintf("https://example.com/%s.jpg", channelID), nil
109		},
110		ResolveChannelIDFunc: func(ctx context.Context, handle string) (string, error) {
111			return strings.TrimPrefix(handle, "@"), nil
112		},
113	}
114
115	h := handler.New(l, s.db, s.parser, s.youtubeClient, nil, s.cfg)
116
117	gin.SetMode(gin.TestMode)
118	router, err := ytrssil.SetupGinRouter(l, s.cfg, h)
119	if err != nil {
120		panic(fmt.Sprintf("failed to setup gin router: %v", err))
121	}
122
123	s.server = &http.Server{
124		Addr:    fmt.Sprintf(":%v", s.cfg.Port),
125		Handler: router,
126	}
127}
128
129func (s *EndpointsTestSuite) TearDownSuite() {
130	defer s.dbConn.Close(context.Background())
131	_, err := s.dbConn.Exec(context.Background(), fmt.Sprintf("DROP SCHEMA %s CASCADE", s.schema))
132	if err != nil {
133		panic(fmt.Sprintf("failed to drop test schema: %v", err))
134	}
135}
136
137func (s *EndpointsTestSuite) SetupTest() {
138	query := fmt.Sprintf("TRUNCATE TABLE %s.videos, %s.channels CASCADE", s.schema, s.schema)
139	_, err := s.dbConn.Exec(context.Background(), query)
140	if err != nil {
141		panic(fmt.Sprintf("failed to truncate test tables: %v", err))
142	}
143}