package tools
import (
"path/filepath"
"testing"
"skraak/utils"
)
func TestCallsModifyBookmark(t *testing.T) {
// Create a temp .data file with a bookmarked segment
tmpDir := t.TempDir()
tmpFile := filepath.Join(tmpDir, "test.data")
df := &utils.DataFile{
Meta: &utils.DataMeta{Operator: "test", Duration: 60},
Segments: []*utils.Segment{
{
StartTime: 10.0,
EndTime: 15.0,
FreqLow: 100,
FreqHigh: 5000,
Labels: []*utils.Label{
{Species: "Kiwi", Certainty: 80, Filter: "myfilter", CallType: "Duet", Bookmark: true},
},
},
},
}
if err := df.Write(tmpFile); err != nil {
t.Fatalf("failed to write test file: %v", err)
}
// Test 1: Adding bookmark when already true should do nothing
bookmark := true
result, err := CallsModify(CallsModifyInput{
File: tmpFile,
Reviewer: "tester",
Filter: "myfilter",
Segment: "10-15",
Certainty: 80,
Bookmark: &bookmark,
})
// Should return error "no changes needed"
if err == nil {
t.Errorf("expected error 'no changes needed' when bookmark already true, got nil")
}
if result.Error != "No changes needed: all values already match" {
t.Errorf("expected 'no changes needed' error, got: %s", result.Error)
}
// Verify bookmark is still true in the file
df2, err := utils.ParseDataFile(tmpFile)
if err != nil {
t.Fatalf("failed to parse file: %v", err)
}
if !df2.Segments[0].Labels[0].Bookmark {
t.Errorf("bookmark should still be true, got false")
}
}
func TestCallsModifyBookmarkFalse(t *testing.T) {
// Create a temp .data file WITHOUT a bookmark
tmpDir := t.TempDir()
tmpFile := filepath.Join(tmpDir, "test.data")
df := &utils.DataFile{
Meta: &utils.DataMeta{Operator: "test", Duration: 60},
Segments: []*utils.Segment{
{
StartTime: 10.0,
EndTime: 15.0,
FreqLow: 100,
FreqHigh: 5000,
Labels: []*utils.Label{
{Species: "Kiwi", Certainty: 80, Filter: "myfilter", CallType: "Duet", Bookmark: false},
},
},
},
}
if err := df.Write(tmpFile); err != nil {
t.Fatalf("failed to write test file: %v", err)
}
// Test: Adding bookmark when false should set it to true
bookmark := true
result, err := CallsModify(CallsModifyInput{
File: tmpFile,
Reviewer: "tester",
Filter: "myfilter",
Segment: "10-15",
Certainty: 80,
Bookmark: &bookmark,
})
if err != nil {
t.Errorf("unexpected error: %v", err)
}
if result.Bookmark == nil || !*result.Bookmark {
t.Errorf("expected bookmark=true in result, got %v", result.Bookmark)
}
// Verify bookmark is true in the file
df2, err := utils.ParseDataFile(tmpFile)
if err != nil {
t.Fatalf("failed to parse file: %v", err)
}
if !df2.Segments[0].Labels[0].Bookmark {
t.Errorf("bookmark should be true, got false")
}
}
func TestCallsModifyCommentAdditive(t *testing.T) {
// Create a temp .data file with an existing comment
tmpDir := t.TempDir()
tmpFile := filepath.Join(tmpDir, "test.data")
df := &utils.DataFile{
Meta: &utils.DataMeta{Operator: "test", Duration: 60},
Segments: []*utils.Segment{
{
StartTime: 10.0,
EndTime: 15.0,
FreqLow: 100,
FreqHigh: 5000,
Labels: []*utils.Label{
{Species: "Kiwi", Certainty: 80, Filter: "myfilter", Comment: "First observation"},
},
},
},
}
if err := df.Write(tmpFile); err != nil {
t.Fatalf("failed to write test file: %v", err)
}
// Test: Adding comment should be additive
result, err := CallsModify(CallsModifyInput{
File: tmpFile,
Reviewer: "tester",
Filter: "myfilter",
Segment: "10-15",
Certainty: 80,
Comment: "Good example",
})
if err != nil {
t.Errorf("unexpected error: %v", err)
}
expectedComment := "First observation | Good example"
if result.Comment != expectedComment {
t.Errorf("expected comment=%q, got %q", expectedComment, result.Comment)
}
// Verify comment in file
df2, err := utils.ParseDataFile(tmpFile)
if err != nil {
t.Fatalf("failed to parse file: %v", err)
}
if df2.Segments[0].Labels[0].Comment != expectedComment {
t.Errorf("expected comment in file=%q, got %q", expectedComment, df2.Segments[0].Labels[0].Comment)
}
}
func TestCallsModifyCommentAdditiveMultiple(t *testing.T) {
// Create a temp .data file and add multiple comments
tmpDir := t.TempDir()
tmpFile := filepath.Join(tmpDir, "test.data")
df := &utils.DataFile{
Meta: &utils.DataMeta{Operator: "test", Duration: 60},
Segments: []*utils.Segment{
{
StartTime: 10.0,
EndTime: 15.0,
FreqLow: 100,
FreqHigh: 5000,
Labels: []*utils.Label{
{Species: "Kiwi", Certainty: 80, Filter: "myfilter"},
},
},
},
}
if err := df.Write(tmpFile); err != nil {
t.Fatalf("failed to write test file: %v", err)
}
// Add first comment
_, err := CallsModify(CallsModifyInput{
File: tmpFile,
Reviewer: "tester",
Filter: "myfilter",
Segment: "10-15",
Certainty: 80,
Comment: "First",
})
if err != nil {
t.Fatalf("unexpected error on first comment: %v", err)
}
// Add second comment
_, err = CallsModify(CallsModifyInput{
File: tmpFile,
Reviewer: "tester",
Filter: "myfilter",
Segment: "10-15",
Certainty: 80,
Comment: "Second",
})
if err != nil {
t.Fatalf("unexpected error on second comment: %v", err)
}
// Add third comment
result, err := CallsModify(CallsModifyInput{
File: tmpFile,
Reviewer: "tester",
Filter: "myfilter",
Segment: "10-15",
Certainty: 80,
Comment: "Third",
})
if err != nil {
t.Fatalf("unexpected error on third comment: %v", err)
}
expectedComment := "First | Second | Third"
if result.Comment != expectedComment {
t.Errorf("expected comment=%q, got %q", expectedComment, result.Comment)
}
}
func TestCallsModifyCommentTooLong(t *testing.T) {
// Create a temp .data file with an existing long comment
tmpDir := t.TempDir()
tmpFile := filepath.Join(tmpDir, "test.data")
existingComment := "This is a fairly long existing comment that takes up space"
df := &utils.DataFile{
Meta: &utils.DataMeta{Operator: "test", Duration: 60},
Segments: []*utils.Segment{
{
StartTime: 10.0,
EndTime: 15.0,
FreqLow: 100,
FreqHigh: 5000,
Labels: []*utils.Label{
{Species: "Kiwi", Certainty: 80, Filter: "myfilter", Comment: existingComment},
},
},
},
}
if err := df.Write(tmpFile); err != nil {
t.Fatalf("failed to write test file: %v", err)
}
// Test: Adding a long comment that would exceed 140 chars should fail
longNewComment := "This is another very long comment that when combined with the existing one will exceed the limit"
result, err := CallsModify(CallsModifyInput{
File: tmpFile,
Reviewer: "tester",
Filter: "myfilter",
Segment: "10-15",
Certainty: 80,
Comment: longNewComment,
})
if err == nil {
t.Errorf("expected error for combined comment exceeding 140 chars, got nil")
}
if result.Error == "" {
t.Errorf("expected error message, got empty")
}
// Verify original comment is preserved
df2, err := utils.ParseDataFile(tmpFile)
if err != nil {
t.Fatalf("failed to parse file: %v", err)
}
if df2.Segments[0].Labels[0].Comment != existingComment {
t.Errorf("original comment should be preserved, got %q", df2.Segments[0].Labels[0].Comment)
}
}
func TestCallsModifyPreservesBookmarkOnOtherChange(t *testing.T) {
// Create a temp .data file with a bookmark
tmpDir := t.TempDir()
tmpFile := filepath.Join(tmpDir, "test.data")
df := &utils.DataFile{
Meta: &utils.DataMeta{Operator: "test", Duration: 60},
Segments: []*utils.Segment{
{
StartTime: 10.0,
EndTime: 15.0,
FreqLow: 100,
FreqHigh: 5000,
Labels: []*utils.Label{
{Species: "Kiwi", Certainty: 80, Filter: "myfilter", Bookmark: true},
},
},
},
}
if err := df.Write(tmpFile); err != nil {
t.Fatalf("failed to write test file: %v", err)
}
// Change certainty (without passing --bookmark) - bookmark should be preserved
result, err := CallsModify(CallsModifyInput{
File: tmpFile,
Reviewer: "tester",
Filter: "myfilter",
Segment: "10-15",
Certainty: 100,
// No Bookmark set
})
if err != nil {
t.Errorf("unexpected error: %v", err)
}
if result.Bookmark != nil {
t.Errorf("bookmark should not be in output when not changed, got %v", result.Bookmark)
}
// Verify bookmark is still true in the file
df2, err := utils.ParseDataFile(tmpFile)
if err != nil {
t.Fatalf("failed to parse file: %v", err)
}
if !df2.Segments[0].Labels[0].Bookmark {
t.Errorf("bookmark should still be true after changing certainty, got false")
}
}
func TestCallsModifyInvalidSegment(t *testing.T) {
tmpDir := t.TempDir()
tmpFile := filepath.Join(tmpDir, "test.data")
df := &utils.DataFile{
Meta: &utils.DataMeta{Operator: "test", Duration: 60},
Segments: []*utils.Segment{
{
StartTime: 10.0,
EndTime: 15.0,
FreqLow: 100,
FreqHigh: 5000,
Labels: []*utils.Label{
{Species: "Kiwi", Certainty: 80, Filter: "myfilter"},
},
},
},
}
if err := df.Write(tmpFile); err != nil {
t.Fatalf("failed to write test file: %v", err)
}
// Test: Non-existent segment should error
result, err := CallsModify(CallsModifyInput{
File: tmpFile,
Reviewer: "tester",
Filter: "myfilter",
Segment: "99-100",
Certainty: 80,
})
if err == nil {
t.Errorf("expected error for non-existent segment, got nil")
}
if result.Error == "" {
t.Errorf("expected error message, got empty")
}
}