feat: add tests

This commit is contained in:
CDN 2025-04-23 16:30:45 +08:00
parent 44c7e9bee5
commit bb87f058f0
Signed by: CDN
GPG key ID: 0C656827F9F80080
17 changed files with 4436 additions and 80 deletions

342
tests/integration_test.go Normal file
View file

@ -0,0 +1,342 @@
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)
}
})
}
}