✅ Improve video tests
This commit is contained in:
1 parent
c0d4300871
commit
c14c60d977
2 files changed
+330
-24
No files matched your search
@@ -21,6 +21,7 @@ go_test(
|
||||
srcs = ["video_test.go"],
|
||||
embed = [":video"],
|
||||
deps = [
|
||||
"//pkg",
|
||||
"//pkg/common",
|
||||
"@org_golang_google_api//youtube/v3:youtube",
|
||||
],
|
||||
|
||||
+329
-24
@@ -16,6 +16,7 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/eat-pray-ai/yutu/pkg"
|
||||
"github.com/eat-pray-ai/yutu/pkg/common"
|
||||
"google.golang.org/api/youtube/v3"
|
||||
)
|
||||
@@ -373,6 +374,31 @@ func TestVideo_Get(t *testing.T) {
|
||||
wantLen: 1,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "get videos with hl, locale, categoryId",
|
||||
opts: []Option{
|
||||
WithHl("en"),
|
||||
WithLocale("en_US"),
|
||||
WithCategory("10"),
|
||||
WithMaxResults(1),
|
||||
},
|
||||
verify: func(r *http.Request) {
|
||||
if r.URL.Query().Get("hl") != "en" {
|
||||
t.Errorf("expected hl=en, got %s", r.URL.Query().Get("hl"))
|
||||
}
|
||||
if r.URL.Query().Get("locale") != "en_US" {
|
||||
t.Errorf("expected locale=en_US, got %s", r.URL.Query().Get("locale"))
|
||||
}
|
||||
if r.URL.Query().Get("videoCategoryId") != "10" {
|
||||
t.Errorf(
|
||||
"expected videoCategoryId=10, got %s",
|
||||
r.URL.Query().Get("videoCategoryId"),
|
||||
)
|
||||
}
|
||||
},
|
||||
wantLen: 1,
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
@@ -437,7 +463,7 @@ func TestVideo_List(t *testing.T) {
|
||||
"title": "Video 1"
|
||||
},
|
||||
"statistics": {
|
||||
"viewCount": 100
|
||||
"viewCount": "100"
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -450,16 +476,54 @@ func TestVideo_List(t *testing.T) {
|
||||
WithService(svc),
|
||||
WithOutput(output),
|
||||
WithIds([]string{"video-1"}),
|
||||
WithMaxResults(5),
|
||||
)
|
||||
return v.List
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
func TestVideo_List_NilFields(t *testing.T) {
|
||||
mockResponse := `{
|
||||
"items": [
|
||||
{"id": "video-1"},
|
||||
{"id": "video-2", "snippet": {"title": "Video 2", "channelId": "ch-2"}},
|
||||
{"id": "video-3", "statistics": {"viewCount": "500"}}
|
||||
]
|
||||
}`
|
||||
|
||||
svc := common.NewTestService(
|
||||
t, http.HandlerFunc(
|
||||
func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
_, _ = w.Write([]byte(mockResponse))
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
v := NewVideo(
|
||||
WithService(svc),
|
||||
WithOutput("table"),
|
||||
WithIds([]string{"video-1"}),
|
||||
WithMaxResults(5),
|
||||
)
|
||||
var buf bytes.Buffer
|
||||
if err := v.List(&buf); err != nil {
|
||||
t.Errorf("List() error = %v", err)
|
||||
}
|
||||
if buf.Len() == 0 {
|
||||
t.Error("List() output is empty")
|
||||
}
|
||||
}
|
||||
|
||||
func TestVideo_Insert(t *testing.T) {
|
||||
autoLevelsTrue := true
|
||||
notifySubscribersTrue := true
|
||||
stabilizeTrue := true
|
||||
forKidsTrue := true
|
||||
embeddableTrue := true
|
||||
containsSyntheticMediaTrue := true
|
||||
publicStatsViewableTrue := true
|
||||
|
||||
decodeMultipartVideo := func(t *testing.T, r *http.Request) *youtube.Video {
|
||||
t.Helper()
|
||||
@@ -571,15 +635,102 @@ func TestVideo_Insert(t *testing.T) {
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "insert video with recording date and boolean options",
|
||||
opts: []Option{
|
||||
WithFile("test_video.mp4"),
|
||||
WithTitle("Dated Video"),
|
||||
WithPrivacy("private"),
|
||||
WithRecordingDate("2024-06-15T10:00:00Z"),
|
||||
WithForKids(&forKidsTrue),
|
||||
WithEmbeddable(&embeddableTrue),
|
||||
WithContainsSyntheticMedia(&containsSyntheticMediaTrue),
|
||||
WithPublicStatsViewable(&publicStatsViewableTrue),
|
||||
},
|
||||
verify: func(r *http.Request) {
|
||||
if r.Method != "POST" {
|
||||
t.Errorf("expected POST, got %s", r.Method)
|
||||
}
|
||||
if !strings.Contains(r.URL.Query().Get("part"), "recordingDetails") {
|
||||
t.Errorf("expected part to contain recordingDetails, got %s", r.URL.Query().Get("part"))
|
||||
}
|
||||
body := decodeMultipartVideo(t, r)
|
||||
if body.RecordingDetails == nil || body.RecordingDetails.RecordingDate != "2024-06-15T10:00:00Z" {
|
||||
t.Errorf("expected recordingDetails.recordingDate=2024-06-15T10:00:00Z, got %+v", body.RecordingDetails)
|
||||
}
|
||||
if body.Status == nil || !body.Status.SelfDeclaredMadeForKids {
|
||||
t.Errorf("expected status.selfDeclaredMadeForKids=true")
|
||||
}
|
||||
if body.Status == nil || !body.Status.Embeddable {
|
||||
t.Errorf("expected status.embeddable=true")
|
||||
}
|
||||
if body.Status == nil || !body.Status.ContainsSyntheticMedia {
|
||||
t.Errorf("expected status.containsSyntheticMedia=true")
|
||||
}
|
||||
if body.Status == nil || !body.Status.PublicStatsViewable {
|
||||
t.Errorf("expected status.publicStatsViewable=true")
|
||||
}
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "insert video with empty title uses filename",
|
||||
opts: []Option{
|
||||
WithFile("test_video.mp4"),
|
||||
WithPrivacy("public"),
|
||||
},
|
||||
verify: func(r *http.Request) {
|
||||
if r.Method != "POST" {
|
||||
return
|
||||
}
|
||||
body := decodeMultipartVideo(t, r)
|
||||
if body.Snippet == nil || body.Snippet.Title != "test_video" {
|
||||
t.Errorf("expected snippet.title=test_video (from filename), got %+v", body.Snippet)
|
||||
}
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "insert video with existing yutu tag",
|
||||
opts: []Option{
|
||||
WithFile("test_video.mp4"),
|
||||
WithTitle("Tagged Video"),
|
||||
WithTags([]string{"yutu🐰", "existing"}),
|
||||
WithPrivacy("public"),
|
||||
},
|
||||
verify: func(r *http.Request) {
|
||||
if r.Method != "POST" {
|
||||
return
|
||||
}
|
||||
body := decodeMultipartVideo(t, r)
|
||||
count := 0
|
||||
for _, tag := range body.Snippet.Tags {
|
||||
if tag == "yutu🐰" {
|
||||
count++
|
||||
}
|
||||
}
|
||||
if count != 1 {
|
||||
t.Errorf("expected exactly 1 yutu🐰 tag, got %d in %v", count, body.Snippet.Tags)
|
||||
}
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
|
||||
err := os.WriteFile("test_video.mp4", []byte("dummy video content"), 0644)
|
||||
tmpDir := t.TempDir()
|
||||
root, err := os.OpenRoot(tmpDir)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to open root: %v", err)
|
||||
}
|
||||
oldRoot := pkg.Root
|
||||
pkg.Root = root
|
||||
defer func() { pkg.Root = oldRoot }()
|
||||
defer func() { _ = root.Close() }()
|
||||
|
||||
err = os.WriteFile(tmpDir+"/test_video.mp4", []byte("dummy video content"), 0644)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create dummy file: %v", err)
|
||||
}
|
||||
defer func() {
|
||||
_ = os.Remove("test_video.mp4")
|
||||
}()
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(
|
||||
@@ -607,12 +758,45 @@ func TestVideo_Insert(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestVideo_Insert_FileError(t *testing.T) {
|
||||
tmpDir := t.TempDir()
|
||||
root, err := os.OpenRoot(tmpDir)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to open root: %v", err)
|
||||
}
|
||||
oldRoot := pkg.Root
|
||||
pkg.Root = root
|
||||
defer func() { pkg.Root = oldRoot }()
|
||||
defer func() { _ = root.Close() }()
|
||||
|
||||
svc := common.NewTestService(
|
||||
t, http.HandlerFunc(
|
||||
func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
v := NewVideo(
|
||||
WithService(svc),
|
||||
WithFile("non_existent.mp4"),
|
||||
)
|
||||
var buf bytes.Buffer
|
||||
if err := v.Insert(&buf); err == nil {
|
||||
t.Error("expected error for non-existent file, got nil")
|
||||
}
|
||||
}
|
||||
|
||||
func TestVideo_Update(t *testing.T) {
|
||||
embeddableTrue := true
|
||||
containsSyntheticMediaTrue := true
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
opts []Option
|
||||
verify func(*http.Request)
|
||||
wantErr bool
|
||||
name string
|
||||
opts []Option
|
||||
getResponse string
|
||||
verify func(*http.Request)
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "update video",
|
||||
@@ -622,6 +806,7 @@ func TestVideo_Update(t *testing.T) {
|
||||
WithDescription("Updated Description"),
|
||||
WithMaxResults(1),
|
||||
},
|
||||
getResponse: `{"items": [{"id": "video-id", "snippet": {"title": "Old Title"}}]}`,
|
||||
verify: func(r *http.Request) {
|
||||
if r.Method == "PUT" {
|
||||
if r.URL.Query().Get("part") != "snippet,status" {
|
||||
@@ -660,6 +845,7 @@ func TestVideo_Update(t *testing.T) {
|
||||
WithMaxResults(1),
|
||||
WithOnBehalfOfContentOwner("owner-id"),
|
||||
},
|
||||
getResponse: `{"items": [{"id": "video-id", "snippet": {"title": "Old Title"}}]}`,
|
||||
verify: func(r *http.Request) {
|
||||
if r.Method == "PUT" {
|
||||
if r.URL.Query().Get("onBehalfOfContentOwner") != "owner-id" {
|
||||
@@ -672,6 +858,91 @@ func TestVideo_Update(t *testing.T) {
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "update video with tags, language, license, categoryId, privacy",
|
||||
opts: []Option{
|
||||
WithIds([]string{"video-id"}),
|
||||
WithTags([]string{"new-tag"}),
|
||||
WithLanguage("ja"),
|
||||
WithLicense("creativeCommon"),
|
||||
WithCategory("22"),
|
||||
WithPrivacy("unlisted"),
|
||||
WithMaxResults(1),
|
||||
},
|
||||
getResponse: `{"items": [{"id": "video-id", "snippet": {"title": "Old Title"}, "status": {"privacyStatus": "public", "license": "youtube", "embeddable": true, "publicStatsViewable": true}}]}`,
|
||||
verify: func(r *http.Request) {
|
||||
if r.Method == "PUT" {
|
||||
var body youtube.Video
|
||||
if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
|
||||
t.Fatalf("failed to decode update body: %v", err)
|
||||
}
|
||||
if body.Snippet.DefaultLanguage != "ja" {
|
||||
t.Errorf("expected defaultLanguage=ja, got %s", body.Snippet.DefaultLanguage)
|
||||
}
|
||||
if body.Status.License != "creativeCommon" {
|
||||
t.Errorf("expected license=creativeCommon, got %s", body.Status.License)
|
||||
}
|
||||
if body.Snippet.CategoryId != "22" {
|
||||
t.Errorf("expected categoryId=22, got %s", body.Snippet.CategoryId)
|
||||
}
|
||||
if body.Status.PrivacyStatus != "unlisted" {
|
||||
t.Errorf("expected privacyStatus=unlisted, got %s", body.Status.PrivacyStatus)
|
||||
}
|
||||
found := false
|
||||
for _, tag := range body.Snippet.Tags {
|
||||
if tag == "yutu🐰" {
|
||||
found = true
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
t.Errorf("expected yutu🐰 tag in %v", body.Snippet.Tags)
|
||||
}
|
||||
}
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "update video with embeddable, containsSyntheticMedia, recordingDate",
|
||||
opts: []Option{
|
||||
WithIds([]string{"video-id"}),
|
||||
WithEmbeddable(&embeddableTrue),
|
||||
WithContainsSyntheticMedia(&containsSyntheticMediaTrue),
|
||||
WithRecordingDate("2024-01-01T00:00:00Z"),
|
||||
WithMaxResults(1),
|
||||
},
|
||||
getResponse: `{"items": [{"id": "video-id", "snippet": {"title": "Old Title"}, "status": {"privacyStatus": "public"}}]}`,
|
||||
verify: func(r *http.Request) {
|
||||
if r.Method == "PUT" {
|
||||
if !strings.Contains(r.URL.Query().Get("part"), "recordingDetails") {
|
||||
t.Errorf("expected part to contain recordingDetails, got %s", r.URL.Query().Get("part"))
|
||||
}
|
||||
var body youtube.Video
|
||||
if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
|
||||
t.Fatalf("failed to decode update body: %v", err)
|
||||
}
|
||||
if !body.Status.Embeddable {
|
||||
t.Errorf("expected embeddable=true")
|
||||
}
|
||||
if !body.Status.ContainsSyntheticMedia {
|
||||
t.Errorf("expected containsSyntheticMedia=true")
|
||||
}
|
||||
if body.RecordingDetails == nil || body.RecordingDetails.RecordingDate != "2024-01-01T00:00:00Z" {
|
||||
t.Errorf("expected recordingDate=2024-01-01T00:00:00Z, got %+v", body.RecordingDetails)
|
||||
}
|
||||
}
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "update video not found",
|
||||
opts: []Option{
|
||||
WithIds([]string{"missing"}),
|
||||
WithTitle("X"),
|
||||
WithMaxResults(1),
|
||||
},
|
||||
getResponse: `{"items": []}`,
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
@@ -685,15 +956,9 @@ func TestVideo_Update(t *testing.T) {
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
if r.Method == "GET" {
|
||||
_, _ = w.Write(
|
||||
[]byte(`{
|
||||
"items": [
|
||||
{"id": "video-id", "snippet": {"title": "Old Title"}}
|
||||
]
|
||||
}`),
|
||||
)
|
||||
_, _ = w.Write([]byte(tt.getResponse))
|
||||
} else {
|
||||
_, _ = w.Write([]byte(`{"id": "video-id", "snippet": {"title": "Updated Title"}}`))
|
||||
_, _ = w.Write([]byte(`{"id": "video-id", "snippet": {"title": "Updated Title"}, "status": {"privacyStatus": "public"}}`))
|
||||
}
|
||||
},
|
||||
),
|
||||
@@ -727,15 +992,20 @@ func TestVideo_Rate(t *testing.T) {
|
||||
if r.Method != "POST" {
|
||||
t.Errorf("expected POST, got %s", r.Method)
|
||||
}
|
||||
if r.URL.Query().Get("id") != "video-id" {
|
||||
t.Errorf("expected id=video-id, got %s", r.URL.Query().Get("id"))
|
||||
}
|
||||
if r.URL.Query().Get("rating") != "like" {
|
||||
t.Errorf("expected rating=like, got %s", r.URL.Query().Get("rating"))
|
||||
}
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "rate multiple videos",
|
||||
opts: []Option{
|
||||
WithIds([]string{"video-1", "video-2"}),
|
||||
WithRating("dislike"),
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
@@ -771,9 +1041,10 @@ func TestVideo_GetRating(t *testing.T) {
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "get rating",
|
||||
name: "get rating table",
|
||||
opts: []Option{
|
||||
WithIds([]string{"video-id"}),
|
||||
WithOutput("table"),
|
||||
},
|
||||
verify: func(r *http.Request) {
|
||||
if r.URL.Query().Get("id") != "video-id" {
|
||||
@@ -782,6 +1053,22 @@ func TestVideo_GetRating(t *testing.T) {
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "get rating json",
|
||||
opts: []Option{
|
||||
WithIds([]string{"video-id"}),
|
||||
WithOutput("json"),
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "get rating yaml",
|
||||
opts: []Option{
|
||||
WithIds([]string{"video-id"}),
|
||||
WithOutput("yaml"),
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "get rating with onBehalfOfContentOwner",
|
||||
opts: []Option{
|
||||
@@ -827,6 +1114,9 @@ func TestVideo_GetRating(t *testing.T) {
|
||||
if err := v.GetRating(&buf); (err != nil) != tt.wantErr {
|
||||
t.Errorf("Video.GetRating() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
if buf.Len() == 0 {
|
||||
t.Errorf("GetRating(%s) output is empty", tt.name)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
@@ -848,9 +1138,6 @@ func TestVideo_Delete(t *testing.T) {
|
||||
if r.Method != "DELETE" {
|
||||
t.Errorf("expected DELETE, got %s", r.Method)
|
||||
}
|
||||
if r.URL.Query().Get("id") != "video-id" {
|
||||
t.Errorf("expected id=video-id, got %s", r.URL.Query().Get("id"))
|
||||
}
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
@@ -873,6 +1160,13 @@ func TestVideo_Delete(t *testing.T) {
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "delete multiple videos",
|
||||
opts: []Option{
|
||||
WithIds([]string{"video-1", "video-2"}),
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
@@ -912,6 +1206,9 @@ func TestVideo_ReportAbuse(t *testing.T) {
|
||||
opts: []Option{
|
||||
WithIds([]string{"video-id"}),
|
||||
WithReasonId("reason-id"),
|
||||
WithComments("spam"),
|
||||
WithLanguage("en"),
|
||||
WithSecondaryReasonId("secondary-reason"),
|
||||
},
|
||||
verify: func(r *http.Request) {
|
||||
if r.Method != "POST" {
|
||||
@@ -940,6 +1237,14 @@ func TestVideo_ReportAbuse(t *testing.T) {
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "report abuse multiple videos",
|
||||
opts: []Option{
|
||||
WithIds([]string{"video-1", "video-2"}),
|
||||
WithReasonId("reason-id"),
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
|
||||
Reference in new issue
Block a user