487 lines
12 KiB
Go
487 lines
12 KiB
Go
package cmd
|
|
|
|
import (
|
|
"bytes"
|
|
"io"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
|
|
"sub-cli/internal/config"
|
|
)
|
|
|
|
// setupTestEnv creates a testing environment with redirected stdout
|
|
// and returns the output buffer and cleanup function
|
|
func setupTestEnv() (*bytes.Buffer, func()) {
|
|
// Save original stdout
|
|
oldStdout := os.Stdout
|
|
|
|
// Create pipe to capture stdout
|
|
r, w, _ := os.Pipe()
|
|
os.Stdout = w
|
|
|
|
// Create buffer to store output
|
|
outBuf := &bytes.Buffer{}
|
|
|
|
// Create cleanup function
|
|
cleanup := func() {
|
|
// Restore original stdout
|
|
os.Stdout = oldStdout
|
|
|
|
// Close writer
|
|
w.Close()
|
|
|
|
// Read from pipe
|
|
io.Copy(outBuf, r)
|
|
r.Close()
|
|
}
|
|
|
|
return outBuf, cleanup
|
|
}
|
|
|
|
// TestExecute_Version tests the version command
|
|
func TestExecute_Version(t *testing.T) {
|
|
// Save original args
|
|
oldArgs := os.Args
|
|
defer func() { os.Args = oldArgs }()
|
|
|
|
// Set up test environment
|
|
outBuf, cleanup := setupTestEnv()
|
|
|
|
// Set args for version command
|
|
os.Args = []string{"sub-cli", "version"}
|
|
|
|
// Execute command
|
|
Execute()
|
|
|
|
// Get output
|
|
cleanup()
|
|
output := outBuf.String()
|
|
|
|
// Verify output
|
|
expectedOutput := "sub-cli version " + config.Version
|
|
if !strings.Contains(output, expectedOutput) {
|
|
t.Errorf("Expected version output to contain '%s', got '%s'", expectedOutput, output)
|
|
}
|
|
}
|
|
|
|
// TestExecute_Help tests the help command
|
|
func TestExecute_Help(t *testing.T) {
|
|
// Save original args
|
|
oldArgs := os.Args
|
|
defer func() { os.Args = oldArgs }()
|
|
|
|
// Set up test environment
|
|
outBuf, cleanup := setupTestEnv()
|
|
|
|
// Set args for help command
|
|
os.Args = []string{"sub-cli", "help"}
|
|
|
|
// Execute command
|
|
Execute()
|
|
|
|
// Get output
|
|
cleanup()
|
|
output := outBuf.String()
|
|
|
|
// Verify output contains usage information
|
|
if !strings.Contains(output, "Usage:") {
|
|
t.Errorf("Expected help output to contain usage information")
|
|
}
|
|
|
|
if !strings.Contains(output, "Commands:") {
|
|
t.Errorf("Expected help output to contain commands information")
|
|
}
|
|
}
|
|
|
|
// TestExecute_NoArgs tests execution with no arguments
|
|
func TestExecute_NoArgs(t *testing.T) {
|
|
// Save original args
|
|
oldArgs := os.Args
|
|
defer func() { os.Args = oldArgs }()
|
|
|
|
// Set up test environment
|
|
outBuf, cleanup := setupTestEnv()
|
|
|
|
// Set args with no command
|
|
os.Args = []string{"sub-cli"}
|
|
|
|
// Execute command
|
|
Execute()
|
|
|
|
// Get output
|
|
cleanup()
|
|
output := outBuf.String()
|
|
|
|
// Verify output contains usage information
|
|
if !strings.Contains(output, "Usage:") {
|
|
t.Errorf("Expected output to contain usage information when no args provided")
|
|
}
|
|
}
|
|
|
|
// TestExecute_UnknownCommand tests execution with unknown command
|
|
func TestExecute_UnknownCommand(t *testing.T) {
|
|
// Save original args
|
|
oldArgs := os.Args
|
|
defer func() { os.Args = oldArgs }()
|
|
|
|
// Set up test environment
|
|
outBuf, cleanup := setupTestEnv()
|
|
|
|
// Set args with unknown command
|
|
os.Args = []string{"sub-cli", "unknown-command"}
|
|
|
|
// Execute command
|
|
Execute()
|
|
|
|
// Get output
|
|
cleanup()
|
|
output := outBuf.String()
|
|
|
|
// Verify output
|
|
if !strings.Contains(output, "Unknown command") {
|
|
t.Errorf("Expected output to contain 'Unknown command' message")
|
|
}
|
|
|
|
if !strings.Contains(output, "Usage:") {
|
|
t.Errorf("Expected output to contain usage information when unknown command provided")
|
|
}
|
|
}
|
|
|
|
// TestExecute_SyncCommand tests the sync command through Execute
|
|
func TestExecute_SyncCommand(t *testing.T) {
|
|
// Save original args
|
|
oldArgs := os.Args
|
|
defer func() { os.Args = oldArgs }()
|
|
|
|
// Create temporary test directory
|
|
tempDir := t.TempDir()
|
|
|
|
// Create source and target files
|
|
sourceFile := filepath.Join(tempDir, "source.lrc")
|
|
targetFile := filepath.Join(tempDir, "target.lrc")
|
|
|
|
if err := os.WriteFile(sourceFile, []byte("[00:01.00]Test line"), 0644); err != nil {
|
|
t.Fatalf("Failed to create source file: %v", err)
|
|
}
|
|
|
|
if err := os.WriteFile(targetFile, []byte("[00:10.00]Target line"), 0644); err != nil {
|
|
t.Fatalf("Failed to create target file: %v", err)
|
|
}
|
|
|
|
// Set up test environment
|
|
outBuf, cleanup := setupTestEnv()
|
|
|
|
// Set args for sync command
|
|
os.Args = []string{"sub-cli", "sync", sourceFile, targetFile}
|
|
|
|
// Execute command
|
|
Execute()
|
|
|
|
// Get output
|
|
cleanup()
|
|
output := outBuf.String()
|
|
|
|
// Verify no error message or expected error format
|
|
if strings.Contains(output, "Error:") && !strings.Contains(output, "Error: ") {
|
|
t.Errorf("Expected formatted error or no error, got: %s", output)
|
|
}
|
|
}
|
|
|
|
// TestExecute_ConvertCommand tests the convert command through Execute
|
|
func TestExecute_ConvertCommand(t *testing.T) {
|
|
// Save original args
|
|
oldArgs := os.Args
|
|
defer func() { os.Args = oldArgs }()
|
|
|
|
// Create temporary test directory
|
|
tempDir := t.TempDir()
|
|
|
|
// Create source file
|
|
sourceContent := `1
|
|
00:00:01,000 --> 00:00:04,000
|
|
This is a test subtitle.`
|
|
sourceFile := filepath.Join(tempDir, "source.srt")
|
|
if err := os.WriteFile(sourceFile, []byte(sourceContent), 0644); err != nil {
|
|
t.Fatalf("Failed to create source file: %v", err)
|
|
}
|
|
|
|
// Define target file
|
|
targetFile := filepath.Join(tempDir, "target.lrc")
|
|
|
|
// Set up test environment
|
|
outBuf, cleanup := setupTestEnv()
|
|
|
|
// Set args for convert command
|
|
os.Args = []string{"sub-cli", "convert", sourceFile, targetFile}
|
|
|
|
// Execute command
|
|
Execute()
|
|
|
|
// Get output
|
|
cleanup()
|
|
output := outBuf.String()
|
|
|
|
// Verify no error message
|
|
if strings.Contains(output, "Error:") {
|
|
t.Errorf("Expected no error, but got: %s", output)
|
|
}
|
|
|
|
// Verify target file exists
|
|
if _, err := os.Stat(targetFile); os.IsNotExist(err) {
|
|
t.Errorf("Target file was not created")
|
|
}
|
|
}
|
|
|
|
// TestHandleSync tests the sync command
|
|
func TestHandleSync(t *testing.T) {
|
|
// Create temporary test directory
|
|
tempDir := t.TempDir()
|
|
|
|
// Create source file
|
|
sourceContent := `[00:01.00]This is line one.
|
|
[00:05.00]This is line two.`
|
|
sourceFile := filepath.Join(tempDir, "source.lrc")
|
|
if err := os.WriteFile(sourceFile, []byte(sourceContent), 0644); err != nil {
|
|
t.Fatalf("Failed to create source file: %v", err)
|
|
}
|
|
|
|
// Create target file
|
|
targetContent := `[00:10.00]This is target line one.
|
|
[00:20.00]This is target line two.`
|
|
targetFile := filepath.Join(tempDir, "target.lrc")
|
|
if err := os.WriteFile(targetFile, []byte(targetContent), 0644); err != nil {
|
|
t.Fatalf("Failed to create target file: %v", err)
|
|
}
|
|
|
|
// Set up test environment
|
|
outBuf, cleanup := setupTestEnv()
|
|
|
|
// Execute sync command
|
|
handleSync([]string{sourceFile, targetFile})
|
|
|
|
// Get output
|
|
cleanup()
|
|
output := outBuf.String()
|
|
|
|
// Verify no error message
|
|
if strings.Contains(output, "Error:") {
|
|
t.Errorf("Expected no error, but got: %s", output)
|
|
}
|
|
|
|
// Verify target file has been modified
|
|
modifiedContent, err := os.ReadFile(targetFile)
|
|
if err != nil {
|
|
t.Fatalf("Failed to read modified target file: %v", err)
|
|
}
|
|
|
|
// Check that target file now has source timings
|
|
if !strings.Contains(string(modifiedContent), "[00:01.000]") {
|
|
t.Errorf("Expected modified target to contain source timing [00:01.000], got: %s", string(modifiedContent))
|
|
}
|
|
|
|
// Check that target content is preserved
|
|
if !strings.Contains(string(modifiedContent), "This is target line one.") {
|
|
t.Errorf("Expected modified target to preserve content 'This is target line one.', got: %s", string(modifiedContent))
|
|
}
|
|
}
|
|
|
|
// TestHandleSync_NoArgs tests sync command with insufficient arguments
|
|
func TestHandleSync_NoArgs(t *testing.T) {
|
|
// Set up test environment
|
|
outBuf, cleanup := setupTestEnv()
|
|
|
|
// Execute sync command with no args
|
|
handleSync([]string{})
|
|
|
|
// Get output
|
|
cleanup()
|
|
output := outBuf.String()
|
|
|
|
// Verify output contains usage information
|
|
if !strings.Contains(output, "Usage: sub-cli sync") {
|
|
t.Errorf("Expected sync usage information when no args provided")
|
|
}
|
|
}
|
|
|
|
// TestHandleSync_OneArg tests sync command with only one argument
|
|
func TestHandleSync_OneArg(t *testing.T) {
|
|
// Set up test environment
|
|
outBuf, cleanup := setupTestEnv()
|
|
|
|
// Execute sync command with one arg
|
|
handleSync([]string{"source.lrc"})
|
|
|
|
// Get output
|
|
cleanup()
|
|
output := outBuf.String()
|
|
|
|
// Verify output contains usage information
|
|
if !strings.Contains(output, "Usage: sub-cli sync") {
|
|
t.Errorf("Expected sync usage information when only one arg provided")
|
|
}
|
|
}
|
|
|
|
// TestHandleConvert tests the convert command
|
|
func TestHandleConvert(t *testing.T) {
|
|
// Create temporary test directory
|
|
tempDir := t.TempDir()
|
|
|
|
// Create source file
|
|
sourceContent := `1
|
|
00:00:01,000 --> 00:00:04,000
|
|
This is a test subtitle.`
|
|
sourceFile := filepath.Join(tempDir, "source.srt")
|
|
if err := os.WriteFile(sourceFile, []byte(sourceContent), 0644); err != nil {
|
|
t.Fatalf("Failed to create source file: %v", err)
|
|
}
|
|
|
|
// Define target file
|
|
targetFile := filepath.Join(tempDir, "target.vtt")
|
|
|
|
// Set up test environment
|
|
outBuf, cleanup := setupTestEnv()
|
|
|
|
// Execute convert command
|
|
handleConvert([]string{sourceFile, targetFile})
|
|
|
|
// Get output
|
|
cleanup()
|
|
output := outBuf.String()
|
|
|
|
// Verify no error message
|
|
if strings.Contains(output, "Error:") {
|
|
t.Errorf("Expected no error, but got: %s", output)
|
|
}
|
|
|
|
// Verify target file has been created
|
|
if _, err := os.Stat(targetFile); os.IsNotExist(err) {
|
|
t.Errorf("Target file was not created")
|
|
}
|
|
|
|
// Verify target file content
|
|
targetContent, err := os.ReadFile(targetFile)
|
|
if err != nil {
|
|
t.Fatalf("Failed to read target file: %v", err)
|
|
}
|
|
|
|
// Check that target file has VTT format
|
|
if !strings.Contains(string(targetContent), "WEBVTT") {
|
|
t.Errorf("Expected target file to have WEBVTT header, got: %s", string(targetContent))
|
|
}
|
|
|
|
// Check that content is preserved
|
|
if !strings.Contains(string(targetContent), "This is a test subtitle.") {
|
|
t.Errorf("Expected target file to preserve content, got: %s", string(targetContent))
|
|
}
|
|
}
|
|
|
|
// TestHandleConvert_NoArgs tests convert command with insufficient arguments
|
|
func TestHandleConvert_NoArgs(t *testing.T) {
|
|
// Set up test environment
|
|
outBuf, cleanup := setupTestEnv()
|
|
|
|
// Execute convert command with no args
|
|
handleConvert([]string{})
|
|
|
|
// Get output
|
|
cleanup()
|
|
output := outBuf.String()
|
|
|
|
// Verify output contains usage information
|
|
if !strings.Contains(output, "Usage: sub-cli convert") {
|
|
t.Errorf("Expected convert usage information when no args provided")
|
|
}
|
|
}
|
|
|
|
// TestHandleFormat tests the fmt command
|
|
func TestHandleFormat(t *testing.T) {
|
|
// Create temporary test directory
|
|
tempDir := t.TempDir()
|
|
|
|
// Create test file with non-sequential numbers
|
|
content := `2
|
|
00:00:05,000 --> 00:00:08,000
|
|
This is the second line.
|
|
|
|
1
|
|
00:00:01,000 --> 00:00:04,000
|
|
This is the first line.`
|
|
testFile := filepath.Join(tempDir, "test.srt")
|
|
if err := os.WriteFile(testFile, []byte(content), 0644); err != nil {
|
|
t.Fatalf("Failed to create test file: %v", err)
|
|
}
|
|
|
|
// Set up test environment
|
|
outBuf, cleanup := setupTestEnv()
|
|
|
|
// Execute fmt command
|
|
handleFormat([]string{testFile})
|
|
|
|
// Get output
|
|
cleanup()
|
|
output := outBuf.String()
|
|
|
|
// Verify no error message
|
|
if strings.Contains(output, "Error:") {
|
|
t.Errorf("Expected no error, but got: %s", output)
|
|
}
|
|
|
|
// Verify file has been modified
|
|
modifiedContent, err := os.ReadFile(testFile)
|
|
if err != nil {
|
|
t.Fatalf("Failed to read modified file: %v", err)
|
|
}
|
|
|
|
// Check that entries are correctly numbered - don't assume ordering by timestamp
|
|
contentStr := string(modifiedContent)
|
|
|
|
// Just check that identifiers 1 and 2 exist and content is preserved
|
|
if !strings.Contains(contentStr, "1\n00:00:") && !strings.Contains(contentStr, "2\n00:00:") {
|
|
t.Errorf("Output should contain sequential identifiers (1 and 2)")
|
|
}
|
|
|
|
// Check content preservation
|
|
if !strings.Contains(contentStr, "This is the first line.") ||
|
|
!strings.Contains(contentStr, "This is the second line.") {
|
|
t.Errorf("Output should preserve all content")
|
|
}
|
|
}
|
|
|
|
// TestHandleFormat_NoArgs tests fmt command with no arguments
|
|
func TestHandleFormat_NoArgs(t *testing.T) {
|
|
// Set up test environment
|
|
outBuf, cleanup := setupTestEnv()
|
|
|
|
// Execute fmt command with no args
|
|
handleFormat([]string{})
|
|
|
|
// Get output
|
|
cleanup()
|
|
output := outBuf.String()
|
|
|
|
// Verify output contains usage information
|
|
if !strings.Contains(output, "Usage: sub-cli fmt") {
|
|
t.Errorf("Expected fmt usage information when no args provided")
|
|
}
|
|
}
|
|
|
|
// TestHandleFormat_Error tests the error path in handleFormat
|
|
func TestHandleFormat_Error(t *testing.T) {
|
|
// Set up test environment
|
|
outBuf, cleanup := setupTestEnv()
|
|
|
|
// Execute format command with non-existent file
|
|
nonExistentFile := "/non/existent/path.srt"
|
|
handleFormat([]string{nonExistentFile})
|
|
|
|
// Get output
|
|
cleanup()
|
|
output := outBuf.String()
|
|
|
|
// Verify error message is printed
|
|
if !strings.Contains(output, "Error:") {
|
|
t.Errorf("Expected error message for non-existent file, got: %s", output)
|
|
}
|
|
}
|