henry99a's picture
Clean commit for Hugging Face Spaces without binary files
ca7217f
package testkit
import (
"fmt"
"io"
"math/rand"
"net/http"
"os"
"reflect"
"strconv"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/metatube-community/metatube-sdk-go/model"
mt "github.com/metatube-community/metatube-sdk-go/provider"
)
type internalTestSuite struct {
t *testing.T
}
func (s *internalTestSuite) T() *testing.T {
return s.t
}
func (s *internalTestSuite) testItems(items []string, call func(*testing.T, string)) {
for i, item := range items {
s.T().Run(item, func(t *testing.T) {
call(t, item)
})
if i < len(items)-1 {
// Add random delay milliseconds.
time.Sleep(time.Duration(rand.Intn(500)+500) * time.Millisecond)
}
}
}
func (s *internalTestSuite) testGetInfo(f any, items []string, vfs ...ValidateFunc) {
ff := func(item string) (info interface{ IsValid() bool }, err error) {
switch v := f.(type) {
case func(string) (*model.ActorInfo, error):
info, err = v(item)
case func(string) (*model.MovieInfo, error):
info, err = v(item)
default:
return nil, fmt.Errorf("invalid function type: %T", v)
}
return
}
s.testItems(items, func(t *testing.T, item string) {
info, err := ff(item)
require.NoError(t, err)
require.NotNil(t, info)
for _, vf := range append([]ValidateFunc{
logJSONContent(),
assertIsValid(),
}, vfs...) {
vf(t, info)
}
})
}
func (s *internalTestSuite) TestGetActorInfoByID(p mt.ActorProvider, items []string, vfs ...ValidateFunc) {
s.testGetInfo(p.GetActorInfoByID, items, vfs...)
}
func (s *internalTestSuite) TestGetActorInfoByURL(p mt.ActorProvider, items []string, vfs ...ValidateFunc) {
s.testGetInfo(p.GetActorInfoByURL, items, vfs...)
}
func (s *internalTestSuite) TestGetMovieInfoByID(p mt.MovieProvider, items []string, vfs ...ValidateFunc) {
s.testGetInfo(p.GetMovieInfoByID, items, vfs...)
}
func (s *internalTestSuite) TestGetMovieInfoByURL(p mt.MovieProvider, items []string, vfs ...ValidateFunc) {
s.testGetInfo(p.GetMovieInfoByURL, items, vfs...)
}
func (s *internalTestSuite) testGetMovieReviews(f func(string) ([]*model.MovieReviewDetail, error), items []string, vfs ...ValidateFunc) {
s.testItems(items, func(t *testing.T, item string) {
reviews, err := f(item)
require.NoError(t, err)
require.NotEmpty(t, reviews)
for _, vf := range append([]ValidateFunc{
logJSONContent(),
assertIsValid(),
}, vfs...) {
vf(t, reviews)
}
})
}
func (s *internalTestSuite) TestGetMovieReviewsByID(p mt.MovieReviewer, items []string, vfs ...ValidateFunc) {
s.testGetMovieReviews(p.GetMovieReviewsByID, items, vfs...)
}
func (s *internalTestSuite) TestGetMovieReviewsByURL(p mt.MovieReviewer, items []string, vfs ...ValidateFunc) {
s.testGetMovieReviews(p.GetMovieReviewsByURL, items, vfs...)
}
func (s *internalTestSuite) TestSearchActor(p mt.ActorSearcher, items []string, vfs ...ValidateFunc) {
s.testItems(items, func(t *testing.T, item string) {
results, err := p.SearchActor(item)
require.NoError(t, err)
require.NotEmpty(t, results)
for _, vf := range append([]ValidateFunc{
logJSONContent(),
assertIsValid(),
}, vfs...) {
vf(t, results)
}
})
}
func (s *internalTestSuite) TestSearchMovie(p mt.MovieSearcher, items []string, vfs ...ValidateFunc) {
s.testItems(items, func(t *testing.T, item string) {
results, err := p.SearchMovie(p.NormalizeMovieKeyword(item))
require.NoError(t, err)
require.NotEmpty(t, results)
for _, vf := range append([]ValidateFunc{
logJSONContent(),
assertIsValid(),
}, vfs...) {
vf(t, results)
}
})
}
func (s *internalTestSuite) TestFetch(p mt.Fetcher, items []string, vfs ...ValidateFunc) {
s.testItems(items, func(t *testing.T, item string) {
resp, err := p.Fetch(item)
require.NoError(t, err)
require.NotNil(t, resp)
require.Equal(t, http.StatusOK, resp.StatusCode)
data, err := io.ReadAll(resp.Body)
require.NoError(t, err)
require.NoError(t, resp.Body.Close())
assert.NotEmpty(t, data)
for _, vf := range append([]ValidateFunc{
logJSONContent(),
}, vfs...) {
vf(t, data)
}
})
}
func Test[T mt.Provider](t *testing.T, new func() T, items []string, vfs ...ValidateFunc) {
if ci, _ := strconv.ParseBool(os.Getenv("GITHUB_ACTIONS")); ci {
t.SkipNow() // Skip in GitHub Actions
}
functionName := getFrame(1).Function
providerName, testMethod, err := parseTestFunction(functionName)
require.NoError(t, err)
provider := new()
structName := reflect.TypeOf(provider).Elem().Name()
require.Equal(t, providerName, structName)
s := &internalTestSuite{t}
m := reflect.ValueOf(s).MethodByName("Test" + testMethod)
require.Truef(t, m.IsValid(), "invalid test method: %s", testMethod)
// Build test function args.
args := []reflect.Value{
reflect.ValueOf(provider),
reflect.ValueOf(items),
}
for _, vf := range vfs {
args = append(args, reflect.ValueOf(vf))
}
// Make the test function call.
results := m.Call(args)
require.Empty(t, results)
}