chore: seperate large files
This commit is contained in:
parent
ebbf516689
commit
76e1298ded
44 changed files with 5745 additions and 4173 deletions
179
internal/format/vtt/converter_test.go
Normal file
179
internal/format/vtt/converter_test.go
Normal file
|
@ -0,0 +1,179 @@
|
|||
package vtt
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"sub-cli/internal/model"
|
||||
)
|
||||
|
||||
func TestConvertToSubtitle(t *testing.T) {
|
||||
// Create a temporary test file
|
||||
content := `WEBVTT - Test Title
|
||||
|
||||
STYLE
|
||||
::cue {
|
||||
color: white;
|
||||
}
|
||||
|
||||
NOTE This is a test comment
|
||||
|
||||
1
|
||||
00:00:01.000 --> 00:00:04.000 align:start position:10%
|
||||
This is <i>styled</i> text.
|
||||
|
||||
2
|
||||
00:00:05.000 --> 00:00:08.000
|
||||
This is the second line.
|
||||
`
|
||||
tempDir := t.TempDir()
|
||||
testFile := filepath.Join(tempDir, "test.vtt")
|
||||
if err := os.WriteFile(testFile, []byte(content), 0644); err != nil {
|
||||
t.Fatalf("Failed to create test file: %v", err)
|
||||
}
|
||||
|
||||
// Convert to subtitle
|
||||
subtitle, err := ConvertToSubtitle(testFile)
|
||||
if err != nil {
|
||||
t.Fatalf("ConvertToSubtitle failed: %v", err)
|
||||
}
|
||||
|
||||
// Check result
|
||||
if subtitle.Format != "vtt" {
|
||||
t.Errorf("Expected format 'vtt', got '%s'", subtitle.Format)
|
||||
}
|
||||
|
||||
if subtitle.Title != "Test Title" {
|
||||
t.Errorf("Expected title 'Test Title', got '%s'", subtitle.Title)
|
||||
}
|
||||
|
||||
// Check style conversion
|
||||
if _, ok := subtitle.Styles["css"]; !ok {
|
||||
t.Errorf("Expected CSS style to be preserved in subtitle.Styles['css'], got: %v", subtitle.Styles)
|
||||
}
|
||||
|
||||
// Check entry count and content
|
||||
if len(subtitle.Entries) != 2 {
|
||||
t.Errorf("Expected 2 entries, got %d", len(subtitle.Entries))
|
||||
}
|
||||
|
||||
// Check first entry
|
||||
if subtitle.Entries[0].Index != 1 {
|
||||
t.Errorf("First entry index: expected 1, got %d", subtitle.Entries[0].Index)
|
||||
}
|
||||
// The VTT parser does not strip HTML tags by default
|
||||
if subtitle.Entries[0].Text != "This is <i>styled</i> text." {
|
||||
t.Errorf("First entry text: expected 'This is <i>styled</i> text.', got '%s'", subtitle.Entries[0].Text)
|
||||
}
|
||||
if subtitle.Entries[0].Styles["align"] != "start" {
|
||||
t.Errorf("Expected align style 'start', got '%s'", subtitle.Entries[0].Styles["align"])
|
||||
}
|
||||
// 检查 FormatData 中是否记录了 HTML 标签存在
|
||||
if val, ok := subtitle.Entries[0].FormatData["has_html_tags"]; !ok || val != true {
|
||||
t.Errorf("Expected FormatData['has_html_tags'] to be true for entry with HTML tags")
|
||||
}
|
||||
}
|
||||
|
||||
func TestConvertFromSubtitle(t *testing.T) {
|
||||
// Create a subtitle
|
||||
subtitle := model.NewSubtitle()
|
||||
subtitle.Format = "vtt"
|
||||
subtitle.Title = "Test VTT"
|
||||
subtitle.Styles = map[string]string{"css": "::cue { color: white; }"}
|
||||
subtitle.Comments = append(subtitle.Comments, "This is a test comment")
|
||||
|
||||
// Create a region
|
||||
region := model.NewSubtitleRegion("region1")
|
||||
region.Settings["width"] = "40%"
|
||||
region.Settings["lines"] = "3"
|
||||
subtitle.Regions = append(subtitle.Regions, region)
|
||||
|
||||
// Create entries
|
||||
entry1 := model.NewSubtitleEntry()
|
||||
entry1.Index = 1
|
||||
entry1.StartTime = model.Timestamp{Hours: 0, Minutes: 0, Seconds: 1, Milliseconds: 0}
|
||||
entry1.EndTime = model.Timestamp{Hours: 0, Minutes: 0, Seconds: 4, Milliseconds: 0}
|
||||
entry1.Text = "This is the first line."
|
||||
entry1.Styles["region"] = "region1"
|
||||
|
||||
entry2 := model.NewSubtitleEntry()
|
||||
entry2.Index = 2
|
||||
entry2.StartTime = model.Timestamp{Hours: 0, Minutes: 0, Seconds: 5, Milliseconds: 0}
|
||||
entry2.EndTime = model.Timestamp{Hours: 0, Minutes: 0, Seconds: 8, Milliseconds: 0}
|
||||
entry2.Text = "This is <i>italic</i> text."
|
||||
|
||||
subtitle.Entries = append(subtitle.Entries, entry1, entry2)
|
||||
|
||||
// Convert to VTT
|
||||
tempDir := t.TempDir()
|
||||
outputFile := filepath.Join(tempDir, "output.vtt")
|
||||
err := ConvertFromSubtitle(subtitle, outputFile)
|
||||
if err != nil {
|
||||
t.Fatalf("ConvertFromSubtitle failed: %v", err)
|
||||
}
|
||||
|
||||
// Verify by reading the file directly
|
||||
content, err := os.ReadFile(outputFile)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to read output file: %v", err)
|
||||
}
|
||||
|
||||
contentStr := string(content)
|
||||
|
||||
// Check header
|
||||
if !strings.HasPrefix(contentStr, "WEBVTT - Test VTT") {
|
||||
t.Errorf("Expected header with title in output")
|
||||
}
|
||||
|
||||
// Check style section
|
||||
if !strings.Contains(contentStr, "STYLE") {
|
||||
t.Errorf("Expected STYLE section in output")
|
||||
}
|
||||
|
||||
if !strings.Contains(contentStr, "::cue { color: white; }") {
|
||||
t.Errorf("Expected CSS content in style section")
|
||||
}
|
||||
|
||||
// Check comment
|
||||
if !strings.Contains(contentStr, "NOTE This is a test comment") {
|
||||
t.Errorf("Expected comment in output")
|
||||
}
|
||||
|
||||
// Check region
|
||||
if !strings.Contains(contentStr, "REGION") || !strings.Contains(contentStr, "region1") {
|
||||
t.Errorf("Expected region definition in output")
|
||||
}
|
||||
|
||||
// Check region applied to first entry
|
||||
if !strings.Contains(contentStr, "region:region1") {
|
||||
t.Errorf("Expected region style to be applied to first entry")
|
||||
}
|
||||
|
||||
// Check HTML tags
|
||||
if !strings.Contains(contentStr, "<i>") || !strings.Contains(contentStr, "</i>") {
|
||||
t.Errorf("Expected HTML italic tags in second entry")
|
||||
}
|
||||
}
|
||||
|
||||
func TestConvertToSubtitle_FileError(t *testing.T) {
|
||||
// Test with non-existent file
|
||||
_, err := ConvertToSubtitle("/nonexistent/file.vtt")
|
||||
if err == nil {
|
||||
t.Error("Expected error when converting non-existent file, got nil")
|
||||
}
|
||||
}
|
||||
|
||||
func TestConvertFromSubtitle_FileError(t *testing.T) {
|
||||
// Create simple subtitle
|
||||
subtitle := model.NewSubtitle()
|
||||
subtitle.Format = "vtt"
|
||||
subtitle.Entries = append(subtitle.Entries, model.NewSubtitleEntry())
|
||||
|
||||
// Test with invalid path
|
||||
err := ConvertFromSubtitle(subtitle, "/nonexistent/directory/file.vtt")
|
||||
if err == nil {
|
||||
t.Error("Expected error when converting to invalid path, got nil")
|
||||
}
|
||||
}
|
78
internal/format/vtt/formatter_test.go
Normal file
78
internal/format/vtt/formatter_test.go
Normal file
|
@ -0,0 +1,78 @@
|
|||
package vtt
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestFormat(t *testing.T) {
|
||||
// Create a temporary test file with valid VTT content
|
||||
// 注意格式必须严格符合 WebVTT 规范,否则 Parse 会失败
|
||||
content := `WEBVTT
|
||||
|
||||
1
|
||||
00:00:01.000 --> 00:00:04.000
|
||||
This is the first line.
|
||||
|
||||
2
|
||||
00:00:05.000 --> 00:00:08.000 align:center
|
||||
This is the second line.
|
||||
|
||||
3
|
||||
00:00:09.500 --> 00:00:12.800
|
||||
This is the third line
|
||||
with a line break.
|
||||
`
|
||||
tempDir := t.TempDir()
|
||||
testFile := filepath.Join(tempDir, "test.vtt")
|
||||
if err := os.WriteFile(testFile, []byte(content), 0644); err != nil {
|
||||
t.Fatalf("Failed to create test file: %v", err)
|
||||
}
|
||||
|
||||
// Format the file
|
||||
err := Format(testFile)
|
||||
if err != nil {
|
||||
t.Fatalf("Format failed: %v", err)
|
||||
}
|
||||
|
||||
// Read the formatted file
|
||||
formatted, err := os.ReadFile(testFile)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to read formatted file: %v", err)
|
||||
}
|
||||
|
||||
// 检查基本的内容是否存在
|
||||
formattedStr := string(formatted)
|
||||
|
||||
// 检查标题行
|
||||
if !strings.Contains(formattedStr, "WEBVTT") {
|
||||
t.Errorf("Expected WEBVTT header in output, not found")
|
||||
}
|
||||
|
||||
// 检查内容是否保留
|
||||
if !strings.Contains(formattedStr, "This is the first line.") {
|
||||
t.Errorf("Expected 'This is the first line.' in output, not found")
|
||||
}
|
||||
|
||||
if !strings.Contains(formattedStr, "This is the second line.") {
|
||||
t.Errorf("Expected 'This is the second line.' in output, not found")
|
||||
}
|
||||
|
||||
if !strings.Contains(formattedStr, "This is the third line") {
|
||||
t.Errorf("Expected 'This is the third line' in output, not found")
|
||||
}
|
||||
|
||||
if !strings.Contains(formattedStr, "with a line break.") {
|
||||
t.Errorf("Expected 'with a line break.' in output, not found")
|
||||
}
|
||||
}
|
||||
|
||||
func TestFormat_FileErrors(t *testing.T) {
|
||||
// Test with non-existent file
|
||||
err := Format("/nonexistent/file.vtt")
|
||||
if err == nil {
|
||||
t.Error("Expected error when formatting non-existent file, got nil")
|
||||
}
|
||||
}
|
148
internal/format/vtt/generator_test.go
Normal file
148
internal/format/vtt/generator_test.go
Normal file
|
@ -0,0 +1,148 @@
|
|||
package vtt
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"sub-cli/internal/model"
|
||||
)
|
||||
|
||||
func TestGenerate(t *testing.T) {
|
||||
// Create a test subtitle
|
||||
subtitle := model.NewSubtitle()
|
||||
subtitle.Format = "vtt"
|
||||
subtitle.Title = "Test VTT"
|
||||
|
||||
// Add style section
|
||||
subtitle.Styles = map[string]string{"css": "::cue { color: white; }"}
|
||||
|
||||
// Add comments
|
||||
subtitle.Comments = append(subtitle.Comments, "This is a test comment")
|
||||
|
||||
// Create entries
|
||||
entry1 := model.NewSubtitleEntry()
|
||||
entry1.Index = 1
|
||||
entry1.StartTime = model.Timestamp{Hours: 0, Minutes: 0, Seconds: 1, Milliseconds: 0}
|
||||
entry1.EndTime = model.Timestamp{Hours: 0, Minutes: 0, Seconds: 4, Milliseconds: 0}
|
||||
entry1.Text = "This is the first line."
|
||||
|
||||
entry2 := model.NewSubtitleEntry()
|
||||
entry2.Index = 2
|
||||
entry2.StartTime = model.Timestamp{Hours: 0, Minutes: 0, Seconds: 5, Milliseconds: 0}
|
||||
entry2.EndTime = model.Timestamp{Hours: 0, Minutes: 0, Seconds: 8, Milliseconds: 0}
|
||||
entry2.Text = "This is the second line."
|
||||
entry2.Styles = map[string]string{"align": "center"}
|
||||
|
||||
subtitle.Entries = append(subtitle.Entries, entry1, entry2)
|
||||
|
||||
// Generate VTT file
|
||||
tempDir := t.TempDir()
|
||||
outputFile := filepath.Join(tempDir, "output.vtt")
|
||||
err := Generate(subtitle, outputFile)
|
||||
if err != nil {
|
||||
t.Fatalf("Generate failed: %v", err)
|
||||
}
|
||||
|
||||
// Verify generated content
|
||||
content, err := os.ReadFile(outputFile)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to read output file: %v", err)
|
||||
}
|
||||
|
||||
// Check content
|
||||
contentStr := string(content)
|
||||
|
||||
// Verify header
|
||||
if !strings.HasPrefix(contentStr, "WEBVTT - Test VTT") {
|
||||
t.Errorf("Expected header with title, got: %s", strings.Split(contentStr, "\n")[0])
|
||||
}
|
||||
|
||||
// Verify style section
|
||||
if !strings.Contains(contentStr, "STYLE") {
|
||||
t.Errorf("Expected STYLE section in output")
|
||||
}
|
||||
|
||||
if !strings.Contains(contentStr, "::cue { color: white; }") {
|
||||
t.Errorf("Expected CSS content in style section")
|
||||
}
|
||||
|
||||
// Verify comment
|
||||
if !strings.Contains(contentStr, "NOTE This is a test comment") {
|
||||
t.Errorf("Expected comment in output")
|
||||
}
|
||||
|
||||
// Verify first entry
|
||||
if !strings.Contains(contentStr, "00:00:01.000 --> 00:00:04.000") {
|
||||
t.Errorf("Expected first entry timestamp in output")
|
||||
}
|
||||
if !strings.Contains(contentStr, "This is the first line.") {
|
||||
t.Errorf("Expected first entry text in output")
|
||||
}
|
||||
|
||||
// Verify second entry with style
|
||||
if !strings.Contains(contentStr, "00:00:05.000 --> 00:00:08.000 align:center") {
|
||||
t.Errorf("Expected second entry timestamp with align style in output")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGenerate_WithRegions(t *testing.T) {
|
||||
// Create a subtitle with regions
|
||||
subtitle := model.NewSubtitle()
|
||||
subtitle.Format = "vtt"
|
||||
|
||||
// Add a region
|
||||
region := model.NewSubtitleRegion("region1")
|
||||
region.Settings["width"] = "40%"
|
||||
region.Settings["lines"] = "3"
|
||||
region.Settings["regionanchor"] = "0%,100%"
|
||||
subtitle.Regions = append(subtitle.Regions, region)
|
||||
|
||||
// Add an entry using the region
|
||||
entry := model.NewSubtitleEntry()
|
||||
entry.Index = 1
|
||||
entry.StartTime = model.Timestamp{Hours: 0, Minutes: 0, Seconds: 1, Milliseconds: 0}
|
||||
entry.EndTime = model.Timestamp{Hours: 0, Minutes: 0, Seconds: 4, Milliseconds: 0}
|
||||
entry.Text = "This is a regional cue."
|
||||
entry.Styles = map[string]string{"region": "region1"}
|
||||
subtitle.Entries = append(subtitle.Entries, entry)
|
||||
|
||||
// Generate VTT file
|
||||
tempDir := t.TempDir()
|
||||
outputFile := filepath.Join(tempDir, "regions.vtt")
|
||||
err := Generate(subtitle, outputFile)
|
||||
if err != nil {
|
||||
t.Fatalf("Generate failed: %v", err)
|
||||
}
|
||||
|
||||
// Verify by reading file content
|
||||
content, err := os.ReadFile(outputFile)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to read output file: %v", err)
|
||||
}
|
||||
|
||||
// Check if region is included
|
||||
if !strings.Contains(string(content), "REGION region1:") {
|
||||
t.Errorf("Expected REGION definition in output")
|
||||
}
|
||||
|
||||
for k, v := range region.Settings {
|
||||
if !strings.Contains(string(content), fmt.Sprintf("%s=%s", k, v)) {
|
||||
t.Errorf("Expected region setting '%s=%s' in output", k, v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGenerate_FileError(t *testing.T) {
|
||||
// Create test subtitle
|
||||
subtitle := model.NewSubtitle()
|
||||
subtitle.Format = "vtt"
|
||||
|
||||
// Test with invalid path
|
||||
err := Generate(subtitle, "/nonexistent/directory/file.vtt")
|
||||
if err == nil {
|
||||
t.Error("Expected error when generating to invalid path, got nil")
|
||||
}
|
||||
}
|
215
internal/format/vtt/parser_test.go
Normal file
215
internal/format/vtt/parser_test.go
Normal file
|
@ -0,0 +1,215 @@
|
|||
package vtt
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestParse(t *testing.T) {
|
||||
// Create a temporary test file
|
||||
content := `WEBVTT
|
||||
|
||||
1
|
||||
00:00:01.000 --> 00:00:04.000
|
||||
This is the first line.
|
||||
|
||||
2
|
||||
00:00:05.000 --> 00:00:08.000
|
||||
This is the second line.
|
||||
|
||||
3
|
||||
00:00:09.500 --> 00:00:12.800
|
||||
This is the third line
|
||||
with a line break.
|
||||
`
|
||||
tempDir := t.TempDir()
|
||||
testFile := filepath.Join(tempDir, "test.vtt")
|
||||
if err := os.WriteFile(testFile, []byte(content), 0644); err != nil {
|
||||
t.Fatalf("Failed to create test file: %v", err)
|
||||
}
|
||||
|
||||
// Test parsing
|
||||
subtitle, err := Parse(testFile)
|
||||
if err != nil {
|
||||
t.Fatalf("Parse failed: %v", err)
|
||||
}
|
||||
|
||||
// Verify results
|
||||
if subtitle.Format != "vtt" {
|
||||
t.Errorf("Expected format 'vtt', got '%s'", subtitle.Format)
|
||||
}
|
||||
|
||||
if len(subtitle.Entries) != 3 {
|
||||
t.Errorf("Expected 3 entries, got %d", len(subtitle.Entries))
|
||||
}
|
||||
|
||||
// Check first entry
|
||||
if subtitle.Entries[0].Index != 1 {
|
||||
t.Errorf("First entry index: expected 1, got %d", subtitle.Entries[0].Index)
|
||||
}
|
||||
if subtitle.Entries[0].StartTime.Hours != 0 || subtitle.Entries[0].StartTime.Minutes != 0 ||
|
||||
subtitle.Entries[0].StartTime.Seconds != 1 || subtitle.Entries[0].StartTime.Milliseconds != 0 {
|
||||
t.Errorf("First entry start time: expected 00:00:01.000, got %+v", subtitle.Entries[0].StartTime)
|
||||
}
|
||||
if subtitle.Entries[0].EndTime.Hours != 0 || subtitle.Entries[0].EndTime.Minutes != 0 ||
|
||||
subtitle.Entries[0].EndTime.Seconds != 4 || subtitle.Entries[0].EndTime.Milliseconds != 0 {
|
||||
t.Errorf("First entry end time: expected 00:00:04.000, got %+v", subtitle.Entries[0].EndTime)
|
||||
}
|
||||
if subtitle.Entries[0].Text != "This is the first line." {
|
||||
t.Errorf("First entry text: expected 'This is the first line.', got '%s'", subtitle.Entries[0].Text)
|
||||
}
|
||||
|
||||
// Check third entry with line break
|
||||
if subtitle.Entries[2].Index != 3 {
|
||||
t.Errorf("Third entry index: expected 3, got %d", subtitle.Entries[2].Index)
|
||||
}
|
||||
expectedText := "This is the third line\nwith a line break."
|
||||
if subtitle.Entries[2].Text != expectedText {
|
||||
t.Errorf("Third entry text: expected '%s', got '%s'", expectedText, subtitle.Entries[2].Text)
|
||||
}
|
||||
}
|
||||
|
||||
func TestParse_WithHeader(t *testing.T) {
|
||||
// Create a temporary test file with title
|
||||
content := `WEBVTT - Test Title
|
||||
|
||||
1
|
||||
00:00:01.000 --> 00:00:04.000
|
||||
This is the first line.
|
||||
`
|
||||
tempDir := t.TempDir()
|
||||
testFile := filepath.Join(tempDir, "test.vtt")
|
||||
if err := os.WriteFile(testFile, []byte(content), 0644); err != nil {
|
||||
t.Fatalf("Failed to create test file: %v", err)
|
||||
}
|
||||
|
||||
// Test parsing
|
||||
subtitle, err := Parse(testFile)
|
||||
if err != nil {
|
||||
t.Fatalf("Parse failed: %v", err)
|
||||
}
|
||||
|
||||
// Verify title was extracted
|
||||
if subtitle.Title != "Test Title" {
|
||||
t.Errorf("Expected title 'Test Title', got '%s'", subtitle.Title)
|
||||
}
|
||||
}
|
||||
|
||||
func TestParse_WithStyles(t *testing.T) {
|
||||
// Create a temporary test file with CSS styling
|
||||
content := `WEBVTT
|
||||
|
||||
STYLE
|
||||
::cue {
|
||||
color: white;
|
||||
background-color: black;
|
||||
}
|
||||
|
||||
1
|
||||
00:00:01.000 --> 00:00:04.000 align:start position:10%
|
||||
This is <b>styled</b> text.
|
||||
`
|
||||
tempDir := t.TempDir()
|
||||
testFile := filepath.Join(tempDir, "test.vtt")
|
||||
if err := os.WriteFile(testFile, []byte(content), 0644); err != nil {
|
||||
t.Fatalf("Failed to create test file: %v", err)
|
||||
}
|
||||
|
||||
// Test parsing
|
||||
subtitle, err := Parse(testFile)
|
||||
if err != nil {
|
||||
t.Fatalf("Parse failed: %v", err)
|
||||
}
|
||||
|
||||
// First check if we have entries at all
|
||||
if len(subtitle.Entries) == 0 {
|
||||
t.Fatalf("No entries found in parsed subtitle")
|
||||
}
|
||||
|
||||
// Verify styling was captured
|
||||
if subtitle.Entries[0].Styles == nil {
|
||||
t.Fatalf("Entry styles map is nil")
|
||||
}
|
||||
|
||||
// Verify HTML tags were detected
|
||||
if _, ok := subtitle.Entries[0].FormatData["has_html_tags"]; !ok {
|
||||
t.Errorf("Expected HTML tags to be detected in entry")
|
||||
}
|
||||
|
||||
// Verify cue settings were captured
|
||||
if subtitle.Entries[0].Styles["align"] != "start" {
|
||||
t.Errorf("Expected align style 'start', got '%s'", subtitle.Entries[0].Styles["align"])
|
||||
}
|
||||
if subtitle.Entries[0].Styles["position"] != "10%" {
|
||||
t.Errorf("Expected position style '10%%', got '%s'", subtitle.Entries[0].Styles["position"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestParse_WithComments(t *testing.T) {
|
||||
// Create a temporary test file with comments
|
||||
content := `WEBVTT
|
||||
|
||||
NOTE This is a comment
|
||||
NOTE This is another comment
|
||||
|
||||
1
|
||||
00:00:01.000 --> 00:00:04.000
|
||||
This is the first line.
|
||||
`
|
||||
tempDir := t.TempDir()
|
||||
testFile := filepath.Join(tempDir, "test_comments.vtt")
|
||||
if err := os.WriteFile(testFile, []byte(content), 0644); err != nil {
|
||||
t.Fatalf("Failed to create test file: %v", err)
|
||||
}
|
||||
|
||||
// Test parsing
|
||||
subtitle, err := Parse(testFile)
|
||||
if err != nil {
|
||||
t.Fatalf("Parse failed: %v", err)
|
||||
}
|
||||
|
||||
// Verify comments were captured
|
||||
if len(subtitle.Comments) != 2 {
|
||||
t.Errorf("Expected 2 comments, got %d", len(subtitle.Comments))
|
||||
}
|
||||
|
||||
if subtitle.Comments[0] != "This is a comment" {
|
||||
t.Errorf("Expected first comment 'This is a comment', got '%s'", subtitle.Comments[0])
|
||||
}
|
||||
|
||||
if subtitle.Comments[1] != "This is another comment" {
|
||||
t.Errorf("Expected second comment 'This is another comment', got '%s'", subtitle.Comments[1])
|
||||
}
|
||||
}
|
||||
|
||||
func TestParse_FileErrors(t *testing.T) {
|
||||
// Test with empty file
|
||||
tempDir := t.TempDir()
|
||||
emptyFile := filepath.Join(tempDir, "empty.vtt")
|
||||
if err := os.WriteFile(emptyFile, []byte(""), 0644); err != nil {
|
||||
t.Fatalf("Failed to create empty file: %v", err)
|
||||
}
|
||||
|
||||
_, err := Parse(emptyFile)
|
||||
if err == nil {
|
||||
t.Error("Expected error when parsing empty file, got nil")
|
||||
}
|
||||
|
||||
// Test with invalid WEBVTT header
|
||||
invalidFile := filepath.Join(tempDir, "invalid.vtt")
|
||||
if err := os.WriteFile(invalidFile, []byte("INVALID HEADER\n\n"), 0644); err != nil {
|
||||
t.Fatalf("Failed to create invalid file: %v", err)
|
||||
}
|
||||
|
||||
_, err = Parse(invalidFile)
|
||||
if err == nil {
|
||||
t.Error("Expected error when parsing file with invalid header, got nil")
|
||||
}
|
||||
|
||||
// Test with non-existent file
|
||||
_, err = Parse("/nonexistent/file.vtt")
|
||||
if err == nil {
|
||||
t.Error("Expected error when parsing non-existent file, got nil")
|
||||
}
|
||||
}
|
39
internal/format/vtt/utils_test.go
Normal file
39
internal/format/vtt/utils_test.go
Normal file
|
@ -0,0 +1,39 @@
|
|||
package vtt
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"sub-cli/internal/model"
|
||||
)
|
||||
|
||||
func TestParseVTTTimestamp(t *testing.T) {
|
||||
testCases := []struct {
|
||||
input string
|
||||
expected model.Timestamp
|
||||
}{
|
||||
// Standard format
|
||||
{"00:00:01.000", model.Timestamp{Hours: 0, Minutes: 0, Seconds: 1, Milliseconds: 0}},
|
||||
// Without leading zeros
|
||||
{"0:0:1.0", model.Timestamp{Hours: 0, Minutes: 0, Seconds: 1, Milliseconds: 0}},
|
||||
// Different millisecond formats
|
||||
{"00:00:01.1", model.Timestamp{Hours: 0, Minutes: 0, Seconds: 1, Milliseconds: 100}},
|
||||
{"00:00:01.12", model.Timestamp{Hours: 0, Minutes: 0, Seconds: 1, Milliseconds: 120}},
|
||||
{"00:00:01.123", model.Timestamp{Hours: 0, Minutes: 0, Seconds: 1, Milliseconds: 123}},
|
||||
// Long milliseconds (should truncate)
|
||||
{"00:00:01.1234", model.Timestamp{Hours: 0, Minutes: 0, Seconds: 1, Milliseconds: 123}},
|
||||
// Unusual but valid format
|
||||
{"01:02:03.456", model.Timestamp{Hours: 1, Minutes: 2, Seconds: 3, Milliseconds: 456}},
|
||||
// Invalid format (should return a zero timestamp)
|
||||
{"invalid", model.Timestamp{Hours: 0, Minutes: 0, Seconds: 0, Milliseconds: 0}},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(fmt.Sprintf("Timestamp_%s", tc.input), func(t *testing.T) {
|
||||
result := parseVTTTimestamp(tc.input)
|
||||
if result != tc.expected {
|
||||
t.Errorf("parseVTTTimestamp(%s) = %+v, want %+v", tc.input, result, tc.expected)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -1,507 +0,0 @@
|
|||
package vtt
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"sub-cli/internal/model"
|
||||
)
|
||||
|
||||
func TestParse(t *testing.T) {
|
||||
// Create a temporary test file
|
||||
content := `WEBVTT
|
||||
|
||||
1
|
||||
00:00:01.000 --> 00:00:04.000
|
||||
This is the first line.
|
||||
|
||||
2
|
||||
00:00:05.000 --> 00:00:08.000
|
||||
This is the second line.
|
||||
|
||||
3
|
||||
00:00:09.500 --> 00:00:12.800
|
||||
This is the third line
|
||||
with a line break.
|
||||
`
|
||||
tempDir := t.TempDir()
|
||||
testFile := filepath.Join(tempDir, "test.vtt")
|
||||
if err := os.WriteFile(testFile, []byte(content), 0644); err != nil {
|
||||
t.Fatalf("Failed to create test file: %v", err)
|
||||
}
|
||||
|
||||
// Test parsing
|
||||
subtitle, err := Parse(testFile)
|
||||
if err != nil {
|
||||
t.Fatalf("Parse failed: %v", err)
|
||||
}
|
||||
|
||||
// Verify results
|
||||
if subtitle.Format != "vtt" {
|
||||
t.Errorf("Expected format 'vtt', got '%s'", subtitle.Format)
|
||||
}
|
||||
|
||||
if len(subtitle.Entries) != 3 {
|
||||
t.Errorf("Expected 3 entries, got %d", len(subtitle.Entries))
|
||||
}
|
||||
|
||||
// Check first entry
|
||||
if subtitle.Entries[0].Index != 1 {
|
||||
t.Errorf("First entry index: expected 1, got %d", subtitle.Entries[0].Index)
|
||||
}
|
||||
if subtitle.Entries[0].StartTime.Hours != 0 || subtitle.Entries[0].StartTime.Minutes != 0 ||
|
||||
subtitle.Entries[0].StartTime.Seconds != 1 || subtitle.Entries[0].StartTime.Milliseconds != 0 {
|
||||
t.Errorf("First entry start time: expected 00:00:01.000, got %+v", subtitle.Entries[0].StartTime)
|
||||
}
|
||||
if subtitle.Entries[0].EndTime.Hours != 0 || subtitle.Entries[0].EndTime.Minutes != 0 ||
|
||||
subtitle.Entries[0].EndTime.Seconds != 4 || subtitle.Entries[0].EndTime.Milliseconds != 0 {
|
||||
t.Errorf("First entry end time: expected 00:00:04.000, got %+v", subtitle.Entries[0].EndTime)
|
||||
}
|
||||
if subtitle.Entries[0].Text != "This is the first line." {
|
||||
t.Errorf("First entry text: expected 'This is the first line.', got '%s'", subtitle.Entries[0].Text)
|
||||
}
|
||||
|
||||
// Check third entry with line break
|
||||
if subtitle.Entries[2].Index != 3 {
|
||||
t.Errorf("Third entry index: expected 3, got %d", subtitle.Entries[2].Index)
|
||||
}
|
||||
expectedText := "This is the third line\nwith a line break."
|
||||
if subtitle.Entries[2].Text != expectedText {
|
||||
t.Errorf("Third entry text: expected '%s', got '%s'", expectedText, subtitle.Entries[2].Text)
|
||||
}
|
||||
}
|
||||
|
||||
func TestParse_WithHeader(t *testing.T) {
|
||||
// Create a temporary test file with title
|
||||
content := `WEBVTT - Test Title
|
||||
|
||||
1
|
||||
00:00:01.000 --> 00:00:04.000
|
||||
This is the first line.
|
||||
`
|
||||
tempDir := t.TempDir()
|
||||
testFile := filepath.Join(tempDir, "test.vtt")
|
||||
if err := os.WriteFile(testFile, []byte(content), 0644); err != nil {
|
||||
t.Fatalf("Failed to create test file: %v", err)
|
||||
}
|
||||
|
||||
// Test parsing
|
||||
subtitle, err := Parse(testFile)
|
||||
if err != nil {
|
||||
t.Fatalf("Parse failed: %v", err)
|
||||
}
|
||||
|
||||
// Verify title was extracted
|
||||
if subtitle.Title != "Test Title" {
|
||||
t.Errorf("Expected title 'Test Title', got '%s'", subtitle.Title)
|
||||
}
|
||||
}
|
||||
|
||||
func TestParse_WithStyles(t *testing.T) {
|
||||
// Create a temporary test file with CSS styling
|
||||
content := `WEBVTT
|
||||
|
||||
STYLE
|
||||
::cue {
|
||||
color: white;
|
||||
background-color: black;
|
||||
}
|
||||
|
||||
1
|
||||
00:00:01.000 --> 00:00:04.000 align:start position:10%
|
||||
This is <b>styled</b> text.
|
||||
`
|
||||
tempDir := t.TempDir()
|
||||
testFile := filepath.Join(tempDir, "test.vtt")
|
||||
if err := os.WriteFile(testFile, []byte(content), 0644); err != nil {
|
||||
t.Fatalf("Failed to create test file: %v", err)
|
||||
}
|
||||
|
||||
// Test parsing
|
||||
subtitle, err := Parse(testFile)
|
||||
if err != nil {
|
||||
t.Fatalf("Parse failed: %v", err)
|
||||
}
|
||||
|
||||
// First check if we have entries at all
|
||||
if len(subtitle.Entries) == 0 {
|
||||
t.Fatalf("No entries found in parsed subtitle")
|
||||
}
|
||||
|
||||
// Verify styling was captured
|
||||
if subtitle.Entries[0].Styles == nil {
|
||||
t.Fatalf("Entry styles map is nil")
|
||||
}
|
||||
|
||||
// Verify HTML tags were detected
|
||||
if _, ok := subtitle.Entries[0].FormatData["has_html_tags"]; !ok {
|
||||
t.Errorf("Expected HTML tags to be detected in entry")
|
||||
}
|
||||
|
||||
// Verify cue settings were captured
|
||||
if subtitle.Entries[0].Styles["align"] != "start" {
|
||||
t.Errorf("Expected align style 'start', got '%s'", subtitle.Entries[0].Styles["align"])
|
||||
}
|
||||
if subtitle.Entries[0].Styles["position"] != "10%" {
|
||||
t.Errorf("Expected position style '10%%', got '%s'", subtitle.Entries[0].Styles["position"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestGenerate(t *testing.T) {
|
||||
// Create test subtitle
|
||||
subtitle := model.NewSubtitle()
|
||||
subtitle.Format = "vtt"
|
||||
subtitle.Title = "Test VTT"
|
||||
|
||||
entry1 := model.NewSubtitleEntry()
|
||||
entry1.Index = 1
|
||||
entry1.StartTime = model.Timestamp{Hours: 0, Minutes: 0, Seconds: 1, Milliseconds: 0}
|
||||
entry1.EndTime = model.Timestamp{Hours: 0, Minutes: 0, Seconds: 4, Milliseconds: 0}
|
||||
entry1.Text = "This is the first line."
|
||||
|
||||
entry2 := model.NewSubtitleEntry()
|
||||
entry2.Index = 2
|
||||
entry2.StartTime = model.Timestamp{Hours: 0, Minutes: 0, Seconds: 5, Milliseconds: 0}
|
||||
entry2.EndTime = model.Timestamp{Hours: 0, Minutes: 0, Seconds: 8, Milliseconds: 0}
|
||||
entry2.Text = "This is the second line."
|
||||
entry2.Styles["align"] = "center"
|
||||
|
||||
subtitle.Entries = append(subtitle.Entries, entry1, entry2)
|
||||
|
||||
// Generate VTT file
|
||||
tempDir := t.TempDir()
|
||||
outputFile := filepath.Join(tempDir, "output.vtt")
|
||||
err := Generate(subtitle, outputFile)
|
||||
if err != nil {
|
||||
t.Fatalf("Generate failed: %v", err)
|
||||
}
|
||||
|
||||
// Verify generated content
|
||||
content, err := os.ReadFile(outputFile)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to read output file: %v", err)
|
||||
}
|
||||
|
||||
// Check content
|
||||
lines := strings.Split(string(content), "\n")
|
||||
if len(lines) < 9 { // Header + title + blank + cue1 (4 lines) + cue2 (4 lines with style)
|
||||
t.Fatalf("Expected at least 9 lines, got %d", len(lines))
|
||||
}
|
||||
|
||||
// Check header
|
||||
if !strings.HasPrefix(lines[0], "WEBVTT") {
|
||||
t.Errorf("Expected first line to start with WEBVTT, got '%s'", lines[0])
|
||||
}
|
||||
|
||||
// Check title
|
||||
if !strings.Contains(lines[0], "Test VTT") {
|
||||
t.Errorf("Expected header to contain title 'Test VTT', got '%s'", lines[0])
|
||||
}
|
||||
|
||||
// Parse the generated file to fully validate
|
||||
parsedSubtitle, err := Parse(outputFile)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to parse generated file: %v", err)
|
||||
}
|
||||
|
||||
if len(parsedSubtitle.Entries) != 2 {
|
||||
t.Errorf("Expected 2 entries in parsed output, got %d", len(parsedSubtitle.Entries))
|
||||
}
|
||||
|
||||
// Check style preservation
|
||||
if parsedSubtitle.Entries[1].Styles["align"] != "center" {
|
||||
t.Errorf("Expected align style 'center', got '%s'", parsedSubtitle.Entries[1].Styles["align"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestConvertToSubtitle(t *testing.T) {
|
||||
// Create a temporary test file
|
||||
content := `WEBVTT
|
||||
|
||||
1
|
||||
00:00:01.000 --> 00:00:04.000
|
||||
This is the first line.
|
||||
|
||||
2
|
||||
00:00:05.000 --> 00:00:08.000
|
||||
This is the second line.
|
||||
`
|
||||
tempDir := t.TempDir()
|
||||
testFile := filepath.Join(tempDir, "test.vtt")
|
||||
if err := os.WriteFile(testFile, []byte(content), 0644); err != nil {
|
||||
t.Fatalf("Failed to create test file: %v", err)
|
||||
}
|
||||
|
||||
// Convert to subtitle
|
||||
subtitle, err := ConvertToSubtitle(testFile)
|
||||
if err != nil {
|
||||
t.Fatalf("ConvertToSubtitle failed: %v", err)
|
||||
}
|
||||
|
||||
// Check result
|
||||
if subtitle.Format != "vtt" {
|
||||
t.Errorf("Expected format 'vtt', got '%s'", subtitle.Format)
|
||||
}
|
||||
|
||||
if len(subtitle.Entries) != 2 {
|
||||
t.Errorf("Expected 2 entries, got %d", len(subtitle.Entries))
|
||||
}
|
||||
|
||||
// Check first entry
|
||||
if subtitle.Entries[0].Text != "This is the first line." {
|
||||
t.Errorf("Expected first entry text 'This is the first line.', got '%s'", subtitle.Entries[0].Text)
|
||||
}
|
||||
}
|
||||
|
||||
func TestConvertFromSubtitle(t *testing.T) {
|
||||
// Create test subtitle
|
||||
subtitle := model.NewSubtitle()
|
||||
subtitle.Format = "vtt"
|
||||
subtitle.Title = "Test VTT"
|
||||
|
||||
entry1 := model.NewSubtitleEntry()
|
||||
entry1.Index = 1
|
||||
entry1.StartTime = model.Timestamp{Hours: 0, Minutes: 0, Seconds: 1, Milliseconds: 0}
|
||||
entry1.EndTime = model.Timestamp{Hours: 0, Minutes: 0, Seconds: 4, Milliseconds: 0}
|
||||
entry1.Text = "This is the first line."
|
||||
|
||||
entry2 := model.NewSubtitleEntry()
|
||||
entry2.Index = 2
|
||||
entry2.StartTime = model.Timestamp{Hours: 0, Minutes: 0, Seconds: 5, Milliseconds: 0}
|
||||
entry2.EndTime = model.Timestamp{Hours: 0, Minutes: 0, Seconds: 8, Milliseconds: 0}
|
||||
entry2.Text = "This is the second line."
|
||||
|
||||
subtitle.Entries = append(subtitle.Entries, entry1, entry2)
|
||||
|
||||
// Convert from subtitle to VTT
|
||||
tempDir := t.TempDir()
|
||||
outputFile := filepath.Join(tempDir, "output.vtt")
|
||||
err := ConvertFromSubtitle(subtitle, outputFile)
|
||||
if err != nil {
|
||||
t.Fatalf("ConvertFromSubtitle failed: %v", err)
|
||||
}
|
||||
|
||||
// Verify by parsing back
|
||||
parsedSubtitle, err := Parse(outputFile)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to parse output file: %v", err)
|
||||
}
|
||||
|
||||
if len(parsedSubtitle.Entries) != 2 {
|
||||
t.Errorf("Expected 2 entries, got %d", len(parsedSubtitle.Entries))
|
||||
}
|
||||
|
||||
if parsedSubtitle.Entries[0].Text != "This is the first line." {
|
||||
t.Errorf("Expected first entry text 'This is the first line.', got '%s'", parsedSubtitle.Entries[0].Text)
|
||||
}
|
||||
|
||||
if parsedSubtitle.Title != "Test VTT" {
|
||||
t.Errorf("Expected title 'Test VTT', got '%s'", parsedSubtitle.Title)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFormat(t *testing.T) {
|
||||
// Create test file with non-sequential identifiers
|
||||
content := `WEBVTT
|
||||
|
||||
5
|
||||
00:00:01.000 --> 00:00:04.000
|
||||
This is the first line.
|
||||
|
||||
10
|
||||
00:00:05.000 --> 00:00:08.000
|
||||
This is the second line.
|
||||
`
|
||||
tempDir := t.TempDir()
|
||||
testFile := filepath.Join(tempDir, "test.vtt")
|
||||
if err := os.WriteFile(testFile, []byte(content), 0644); err != nil {
|
||||
t.Fatalf("Failed to create test file: %v", err)
|
||||
}
|
||||
|
||||
// Format the file
|
||||
err := Format(testFile)
|
||||
if err != nil {
|
||||
t.Fatalf("Format failed: %v", err)
|
||||
}
|
||||
|
||||
// Verify by parsing back
|
||||
subtitle, err := Parse(testFile)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to parse formatted file: %v", err)
|
||||
}
|
||||
|
||||
// Check that identifiers are sequential
|
||||
if subtitle.Entries[0].Index != 1 {
|
||||
t.Errorf("Expected first entry index to be 1, got %d", subtitle.Entries[0].Index)
|
||||
}
|
||||
if subtitle.Entries[1].Index != 2 {
|
||||
t.Errorf("Expected second entry index to be 2, got %d", subtitle.Entries[1].Index)
|
||||
}
|
||||
}
|
||||
|
||||
func TestParse_FileErrors(t *testing.T) {
|
||||
// Test with non-existent file
|
||||
_, err := Parse("/nonexistent/file.vtt")
|
||||
if err == nil {
|
||||
t.Error("Expected error when parsing non-existent file, got nil")
|
||||
}
|
||||
|
||||
// Test with empty file
|
||||
tempDir := t.TempDir()
|
||||
emptyFile := filepath.Join(tempDir, "empty.vtt")
|
||||
if err := os.WriteFile(emptyFile, []byte{}, 0644); err != nil {
|
||||
t.Fatalf("Failed to create empty test file: %v", err)
|
||||
}
|
||||
|
||||
_, err = Parse(emptyFile)
|
||||
if err == nil {
|
||||
t.Error("Expected error when parsing empty file, got nil")
|
||||
}
|
||||
|
||||
// Test with invalid header
|
||||
invalidFile := filepath.Join(tempDir, "invalid.vtt")
|
||||
if err := os.WriteFile(invalidFile, []byte("NOT A WEBVTT FILE\n\n"), 0644); err != nil {
|
||||
t.Fatalf("Failed to create invalid test file: %v", err)
|
||||
}
|
||||
|
||||
_, err = Parse(invalidFile)
|
||||
if err == nil {
|
||||
t.Error("Expected error when parsing file with invalid header, got nil")
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseVTTTimestamp(t *testing.T) {
|
||||
testCases := []struct {
|
||||
input string
|
||||
expected model.Timestamp
|
||||
}{
|
||||
// Standard format
|
||||
{"00:00:01.000", model.Timestamp{Hours: 0, Minutes: 0, Seconds: 1, Milliseconds: 0}},
|
||||
// Without leading zeros
|
||||
{"0:0:1.0", model.Timestamp{Hours: 0, Minutes: 0, Seconds: 1, Milliseconds: 0}},
|
||||
// Different millisecond formats
|
||||
{"00:00:01.1", model.Timestamp{Hours: 0, Minutes: 0, Seconds: 1, Milliseconds: 100}},
|
||||
{"00:00:01.12", model.Timestamp{Hours: 0, Minutes: 0, Seconds: 1, Milliseconds: 120}},
|
||||
{"00:00:01.123", model.Timestamp{Hours: 0, Minutes: 0, Seconds: 1, Milliseconds: 123}},
|
||||
// Long milliseconds (should truncate)
|
||||
{"00:00:01.1234", model.Timestamp{Hours: 0, Minutes: 0, Seconds: 1, Milliseconds: 123}},
|
||||
// Unusual but valid format
|
||||
{"01:02:03.456", model.Timestamp{Hours: 1, Minutes: 2, Seconds: 3, Milliseconds: 456}},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(fmt.Sprintf("Timestamp_%s", tc.input), func(t *testing.T) {
|
||||
result := parseVTTTimestamp(tc.input)
|
||||
if result != tc.expected {
|
||||
t.Errorf("parseVTTTimestamp(%s) = %+v, want %+v", tc.input, result, tc.expected)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestParse_WithComments(t *testing.T) {
|
||||
// Create a temporary test file with comments
|
||||
content := `WEBVTT
|
||||
|
||||
NOTE This is a comment
|
||||
NOTE This is another comment
|
||||
|
||||
1
|
||||
00:00:01.000 --> 00:00:04.000
|
||||
This is the first line.
|
||||
`
|
||||
tempDir := t.TempDir()
|
||||
testFile := filepath.Join(tempDir, "test_comments.vtt")
|
||||
if err := os.WriteFile(testFile, []byte(content), 0644); err != nil {
|
||||
t.Fatalf("Failed to create test file: %v", err)
|
||||
}
|
||||
|
||||
// Test parsing
|
||||
subtitle, err := Parse(testFile)
|
||||
if err != nil {
|
||||
t.Fatalf("Parse failed: %v", err)
|
||||
}
|
||||
|
||||
// Verify comments were captured
|
||||
if len(subtitle.Comments) != 2 {
|
||||
t.Errorf("Expected 2 comments, got %d", len(subtitle.Comments))
|
||||
}
|
||||
|
||||
if subtitle.Comments[0] != "This is a comment" {
|
||||
t.Errorf("Expected first comment 'This is a comment', got '%s'", subtitle.Comments[0])
|
||||
}
|
||||
|
||||
if subtitle.Comments[1] != "This is another comment" {
|
||||
t.Errorf("Expected second comment 'This is another comment', got '%s'", subtitle.Comments[1])
|
||||
}
|
||||
}
|
||||
|
||||
func TestGenerate_WithRegions(t *testing.T) {
|
||||
// Create a subtitle with regions
|
||||
subtitle := model.NewSubtitle()
|
||||
subtitle.Format = "vtt"
|
||||
|
||||
// Add a region
|
||||
region := model.NewSubtitleRegion("region1")
|
||||
region.Settings["width"] = "40%"
|
||||
region.Settings["lines"] = "3"
|
||||
region.Settings["regionanchor"] = "0%,100%"
|
||||
subtitle.Regions = append(subtitle.Regions, region)
|
||||
|
||||
// Add an entry using the region
|
||||
entry := model.NewSubtitleEntry()
|
||||
entry.Index = 1
|
||||
entry.StartTime = model.Timestamp{Hours: 0, Minutes: 0, Seconds: 1, Milliseconds: 0}
|
||||
entry.EndTime = model.Timestamp{Hours: 0, Minutes: 0, Seconds: 4, Milliseconds: 0}
|
||||
entry.Text = "This is a regional cue."
|
||||
entry.Styles["region"] = "region1"
|
||||
subtitle.Entries = append(subtitle.Entries, entry)
|
||||
|
||||
// Generate VTT file
|
||||
tempDir := t.TempDir()
|
||||
outputFile := filepath.Join(tempDir, "regions.vtt")
|
||||
err := Generate(subtitle, outputFile)
|
||||
if err != nil {
|
||||
t.Fatalf("Generate failed: %v", err)
|
||||
}
|
||||
|
||||
// Verify by reading file content
|
||||
content, err := os.ReadFile(outputFile)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to read output file: %v", err)
|
||||
}
|
||||
|
||||
// Check if region is included
|
||||
if !strings.Contains(string(content), "REGION region1:") {
|
||||
t.Errorf("Expected REGION definition in output")
|
||||
}
|
||||
|
||||
for k, v := range region.Settings {
|
||||
if !strings.Contains(string(content), fmt.Sprintf("%s=%s", k, v)) {
|
||||
t.Errorf("Expected region setting '%s=%s' in output", k, v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestFormat_FileErrors(t *testing.T) {
|
||||
// Test with non-existent file
|
||||
err := Format("/nonexistent/file.vtt")
|
||||
if err == nil {
|
||||
t.Error("Expected error when formatting non-existent file, got nil")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGenerate_FileError(t *testing.T) {
|
||||
// Create test subtitle
|
||||
subtitle := model.NewSubtitle()
|
||||
subtitle.Format = "vtt"
|
||||
|
||||
// Test with invalid path
|
||||
err := Generate(subtitle, "/nonexistent/directory/file.vtt")
|
||||
if err == nil {
|
||||
t.Error("Expected error when generating to invalid path, got nil")
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue