342 lines
10 KiB
Go
342 lines
10 KiB
Go
package tests
|
|
|
|
import (
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
// TestIntegration_EndToEnd runs a series of commands to test the entire workflow
|
|
func TestIntegration_EndToEnd(t *testing.T) {
|
|
// Skip if not running integration tests
|
|
if os.Getenv("RUN_INTEGRATION_TESTS") == "" {
|
|
t.Skip("Skipping integration tests. Set RUN_INTEGRATION_TESTS=1 to run.")
|
|
}
|
|
|
|
// Get the path to the built binary
|
|
binaryPath := os.Getenv("BINARY_PATH")
|
|
if binaryPath == "" {
|
|
// Default to looking in the current directory
|
|
binaryPath = "sub-cli"
|
|
}
|
|
|
|
// Create temporary directory for test files
|
|
tempDir := t.TempDir()
|
|
|
|
// Test files
|
|
srtFile := filepath.Join(tempDir, "test.srt")
|
|
lrcFile := filepath.Join(tempDir, "test.lrc")
|
|
vttFile := filepath.Join(tempDir, "test.vtt")
|
|
txtFile := filepath.Join(tempDir, "test.txt")
|
|
|
|
// Create SRT test file
|
|
srtContent := `1
|
|
00:00:01,000 --> 00:00:04,000
|
|
This is the first subtitle line.
|
|
|
|
2
|
|
00:00:05,000 --> 00:00:08,000
|
|
This is the second subtitle line.
|
|
|
|
3
|
|
00:00:09,500 --> 00:00:12,800
|
|
This is the third subtitle line
|
|
with a line break.
|
|
`
|
|
if err := os.WriteFile(srtFile, []byte(srtContent), 0644); err != nil {
|
|
t.Fatalf("Failed to create SRT test file: %v", err)
|
|
}
|
|
|
|
// Step 1: Test conversion from SRT to LRC
|
|
t.Log("Testing SRT to LRC conversion...")
|
|
cmd := exec.Command(binaryPath, "convert", srtFile, lrcFile)
|
|
output, err := cmd.CombinedOutput()
|
|
if err != nil {
|
|
t.Fatalf("Convert command failed: %v\nOutput: %s", err, output)
|
|
}
|
|
|
|
// Verify LRC file was created
|
|
if _, err := os.Stat(lrcFile); os.IsNotExist(err) {
|
|
t.Fatalf("LRC file was not created")
|
|
}
|
|
|
|
// Read LRC content
|
|
lrcContent, err := os.ReadFile(lrcFile)
|
|
if err != nil {
|
|
t.Fatalf("Failed to read LRC file: %v", err)
|
|
}
|
|
|
|
// Verify LRC content
|
|
if !strings.Contains(string(lrcContent), "[00:01.000]") {
|
|
t.Errorf("Expected LRC to contain timeline [00:01.000], got: %s", string(lrcContent))
|
|
}
|
|
if !strings.Contains(string(lrcContent), "This is the first subtitle line.") {
|
|
t.Errorf("Expected LRC to contain text content, got: %s", string(lrcContent))
|
|
}
|
|
|
|
// Step 2: Create a new SRT file with different timing
|
|
srtModifiedContent := `1
|
|
00:00:10,000 --> 00:00:14,000
|
|
This is the first subtitle line.
|
|
|
|
2
|
|
00:00:15,000 --> 00:00:18,000
|
|
This is the second subtitle line.
|
|
|
|
3
|
|
00:00:19,500 --> 00:00:22,800
|
|
This is the third subtitle line
|
|
with a line break.
|
|
`
|
|
srtModifiedFile := filepath.Join(tempDir, "modified.srt")
|
|
if err := os.WriteFile(srtModifiedFile, []byte(srtModifiedContent), 0644); err != nil {
|
|
t.Fatalf("Failed to create modified SRT test file: %v", err)
|
|
}
|
|
|
|
// Step 3: Test sync between SRT files
|
|
t.Log("Testing SRT to SRT sync...")
|
|
cmd = exec.Command(binaryPath, "sync", srtModifiedFile, srtFile)
|
|
output, err = cmd.CombinedOutput()
|
|
if err != nil {
|
|
t.Fatalf("Sync command failed: %v\nOutput: %s", err, output)
|
|
}
|
|
|
|
// Read synced SRT content
|
|
syncedSrtContent, err := os.ReadFile(srtFile)
|
|
if err != nil {
|
|
t.Fatalf("Failed to read synced SRT file: %v", err)
|
|
}
|
|
|
|
// Verify synced content has new timings but original text
|
|
if !strings.Contains(string(syncedSrtContent), "00:00:10,000 -->") {
|
|
t.Errorf("Expected synced SRT to have new timing 00:00:10,000, got: %s", string(syncedSrtContent))
|
|
}
|
|
if !strings.Contains(string(syncedSrtContent), "This is the first subtitle line.") {
|
|
t.Errorf("Expected synced SRT to preserve original text, got: %s", string(syncedSrtContent))
|
|
}
|
|
|
|
// Step 4: Test conversion from SRT to VTT
|
|
t.Log("Testing SRT to VTT conversion...")
|
|
cmd = exec.Command(binaryPath, "convert", srtFile, vttFile)
|
|
output, err = cmd.CombinedOutput()
|
|
if err != nil {
|
|
t.Fatalf("Convert command failed: %v\nOutput: %s", err, output)
|
|
}
|
|
|
|
// Verify VTT file was created
|
|
if _, err := os.Stat(vttFile); os.IsNotExist(err) {
|
|
t.Fatalf("VTT file was not created")
|
|
}
|
|
|
|
// Read VTT content
|
|
vttContent, err := os.ReadFile(vttFile)
|
|
if err != nil {
|
|
t.Fatalf("Failed to read VTT file: %v", err)
|
|
}
|
|
|
|
// Verify VTT content
|
|
if !strings.Contains(string(vttContent), "WEBVTT") {
|
|
t.Errorf("Expected VTT to contain WEBVTT header, got: %s", string(vttContent))
|
|
}
|
|
if !strings.Contains(string(vttContent), "00:00:10.000 -->") {
|
|
t.Errorf("Expected VTT to contain timeline 00:00:10.000, got: %s", string(vttContent))
|
|
}
|
|
|
|
// Step 5: Create VTT file with styling
|
|
vttStyledContent := `WEBVTT - Styled Test
|
|
|
|
STYLE
|
|
::cue {
|
|
color: white;
|
|
background-color: black;
|
|
}
|
|
|
|
1
|
|
00:00:20.000 --> 00:00:24.000 align:start position:10%
|
|
This is a <b>styled</b> subtitle.
|
|
|
|
2
|
|
00:00:25.000 --> 00:00:28.000 align:middle
|
|
This is another styled subtitle.
|
|
`
|
|
vttStyledFile := filepath.Join(tempDir, "styled.vtt")
|
|
if err := os.WriteFile(vttStyledFile, []byte(vttStyledContent), 0644); err != nil {
|
|
t.Fatalf("Failed to create styled VTT test file: %v", err)
|
|
}
|
|
|
|
// Step 6: Test sync between VTT files (should preserve styling)
|
|
t.Log("Testing VTT to VTT sync...")
|
|
cmd = exec.Command(binaryPath, "sync", vttFile, vttStyledFile)
|
|
output, err = cmd.CombinedOutput()
|
|
if err != nil {
|
|
t.Fatalf("Sync command failed: %v\nOutput: %s", err, output)
|
|
}
|
|
|
|
// Read synced VTT content
|
|
syncedVttContent, err := os.ReadFile(vttStyledFile)
|
|
if err != nil {
|
|
t.Fatalf("Failed to read synced VTT file: %v", err)
|
|
}
|
|
|
|
// Verify synced content has new timings but preserves styling and text
|
|
if !strings.Contains(string(syncedVttContent), "00:00:10.000 -->") {
|
|
t.Errorf("Expected synced VTT to have new timing 00:00:10.000, got: %s", string(syncedVttContent))
|
|
}
|
|
if !strings.Contains(string(syncedVttContent), "align:") {
|
|
t.Errorf("Expected synced VTT to preserve styling, got: %s", string(syncedVttContent))
|
|
}
|
|
if !strings.Contains(string(syncedVttContent), "<b>styled</b>") {
|
|
t.Errorf("Expected synced VTT to preserve HTML formatting, got: %s", string(syncedVttContent))
|
|
}
|
|
|
|
// Step 7: Test format command with VTT file
|
|
t.Log("Testing VTT formatting...")
|
|
cmd = exec.Command(binaryPath, "fmt", vttStyledFile)
|
|
output, err = cmd.CombinedOutput()
|
|
if err != nil {
|
|
t.Fatalf("Format command failed: %v\nOutput: %s", err, output)
|
|
}
|
|
|
|
// Read formatted VTT content
|
|
formattedVttContent, err := os.ReadFile(vttStyledFile)
|
|
if err != nil {
|
|
t.Fatalf("Failed to read formatted VTT file: %v", err)
|
|
}
|
|
|
|
// Verify formatted content preserves styling and has sequential cue identifiers
|
|
if !strings.Contains(string(formattedVttContent), "1\n00:00:10.000") {
|
|
t.Errorf("Expected formatted VTT to have sequential identifiers, got: %s", string(formattedVttContent))
|
|
}
|
|
if !strings.Contains(string(formattedVttContent), "align:") {
|
|
t.Errorf("Expected formatted VTT to preserve styling, got: %s", string(formattedVttContent))
|
|
}
|
|
|
|
// Step 8: Test conversion to plain text
|
|
t.Log("Testing VTT to TXT conversion...")
|
|
cmd = exec.Command(binaryPath, "convert", vttStyledFile, txtFile)
|
|
output, err = cmd.CombinedOutput()
|
|
if err != nil {
|
|
t.Fatalf("Convert command failed: %v\nOutput: %s", err, output)
|
|
}
|
|
|
|
// Verify TXT file was created
|
|
if _, err := os.Stat(txtFile); os.IsNotExist(err) {
|
|
t.Fatalf("TXT file was not created")
|
|
}
|
|
|
|
// Read TXT content
|
|
txtContent, err := os.ReadFile(txtFile)
|
|
if err != nil {
|
|
t.Fatalf("Failed to read TXT file: %v", err)
|
|
}
|
|
|
|
// Verify TXT content has text but no timing or styling
|
|
if strings.Contains(string(txtContent), "00:00:") {
|
|
t.Errorf("Expected TXT to not contain timing information, got: %s", string(txtContent))
|
|
}
|
|
if strings.Contains(string(txtContent), "align:") {
|
|
t.Errorf("Expected TXT to not contain styling information, got: %s", string(txtContent))
|
|
}
|
|
if !strings.Contains(string(txtContent), "styled") {
|
|
t.Errorf("Expected TXT to contain text content, got: %s", string(txtContent))
|
|
}
|
|
|
|
t.Log("All integration tests passed!")
|
|
}
|
|
|
|
// TestIntegration_ErrorHandling tests how the CLI handles error conditions
|
|
func TestIntegration_ErrorHandling(t *testing.T) {
|
|
// Skip if not running integration tests
|
|
if os.Getenv("RUN_INTEGRATION_TESTS") == "" {
|
|
t.Skip("Skipping integration tests. Set RUN_INTEGRATION_TESTS=1 to run.")
|
|
}
|
|
|
|
// Get the path to the built binary
|
|
binaryPath := os.Getenv("BINARY_PATH")
|
|
if binaryPath == "" {
|
|
// Default to looking in the current directory
|
|
binaryPath = "sub-cli"
|
|
}
|
|
|
|
// Create temporary directory for test files
|
|
tempDir := t.TempDir()
|
|
|
|
// Test cases
|
|
testCases := []struct {
|
|
name string
|
|
args []string
|
|
errorMsg string
|
|
}{
|
|
{
|
|
name: "Nonexistent source file",
|
|
args: []string{"convert", "nonexistent.srt", filepath.Join(tempDir, "output.vtt")},
|
|
errorMsg: "no such file",
|
|
},
|
|
{
|
|
name: "Invalid source format",
|
|
args: []string{"convert", filepath.Join(tempDir, "test.xyz"), filepath.Join(tempDir, "output.vtt")},
|
|
errorMsg: "unsupported format",
|
|
},
|
|
{
|
|
name: "Invalid target format",
|
|
args: []string{"convert", filepath.Join(tempDir, "test.srt"), filepath.Join(tempDir, "output.xyz")},
|
|
errorMsg: "unsupported format",
|
|
},
|
|
{
|
|
name: "Sync different formats",
|
|
args: []string{"sync", filepath.Join(tempDir, "test.srt"), filepath.Join(tempDir, "test.lrc")},
|
|
errorMsg: "same format",
|
|
},
|
|
{
|
|
name: "Format unsupported file",
|
|
args: []string{"fmt", filepath.Join(tempDir, "test.txt")},
|
|
errorMsg: "unsupported format",
|
|
},
|
|
}
|
|
|
|
// Create a sample SRT file for testing
|
|
srtFile := filepath.Join(tempDir, "test.srt")
|
|
srtContent := `1
|
|
00:00:01,000 --> 00:00:04,000
|
|
This is a test subtitle.
|
|
`
|
|
if err := os.WriteFile(srtFile, []byte(srtContent), 0644); err != nil {
|
|
t.Fatalf("Failed to create SRT test file: %v", err)
|
|
}
|
|
|
|
// Create a sample LRC file for testing
|
|
lrcFile := filepath.Join(tempDir, "test.lrc")
|
|
lrcContent := `[00:01.00]This is a test lyric.
|
|
`
|
|
if err := os.WriteFile(lrcFile, []byte(lrcContent), 0644); err != nil {
|
|
t.Fatalf("Failed to create LRC test file: %v", err)
|
|
}
|
|
|
|
// Create a sample TXT file for testing
|
|
txtFile := filepath.Join(tempDir, "test.txt")
|
|
txtContent := `This is a plain text file.
|
|
`
|
|
if err := os.WriteFile(txtFile, []byte(txtContent), 0644); err != nil {
|
|
t.Fatalf("Failed to create TXT test file: %v", err)
|
|
}
|
|
|
|
// Run test cases
|
|
for _, tc := range testCases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
cmd := exec.Command(binaryPath, tc.args...)
|
|
output, err := cmd.CombinedOutput()
|
|
|
|
// We expect an error
|
|
if err == nil {
|
|
t.Fatalf("Expected command to fail, but it succeeded. Output: %s", output)
|
|
}
|
|
|
|
// Check error message
|
|
if !strings.Contains(string(output), tc.errorMsg) {
|
|
t.Errorf("Expected error message to contain '%s', got: %s", tc.errorMsg, output)
|
|
}
|
|
})
|
|
}
|
|
}
|