Fork channel

Create a new channel as a copy of main.

Rename channel

Rename main to:

Delete channel

Delete main? This cannot be undone.

calls_clip_test.go
package calls

import (
	"testing"

	"skraak/datafile"
)

// --- filterSegments ---

func TestFilterSegments(t *testing.T) {
	makeSeg := func(labels []*datafile.Label) *datafile.Segment {
		return &datafile.Segment{Labels: labels}
	}

	kiwiLabel := &datafile.Label{Filter: "kiwi.txt", Species: "Kiwi", CallType: "song", Certainty: 100}
	tomtitLabel := &datafile.Label{Filter: "tomtit.txt", Species: "Tomtit", Certainty: 80}

	segments := []*datafile.Segment{
		makeSeg([]*datafile.Label{kiwiLabel}),
		makeSeg([]*datafile.Label{tomtitLabel}),
		makeSeg([]*datafile.Label{kiwiLabel, tomtitLabel}),
		makeSeg([]*datafile.Label{}),
	}

	t.Run("no filters returns all", func(t *testing.T) {
		got := filterSegments(segments, "", "", "", -1)
		if len(got) != 4 {
			t.Errorf("expected 4 segments (no filters), got %d", len(got))
		}
	})

	t.Run("filter by species", func(t *testing.T) {
		got := filterSegments(segments, "", "Kiwi", "", -1)
		if len(got) != 2 {
			t.Errorf("expected 2 segments with Kiwi, got %d", len(got))
		}
	})

	t.Run("filter by filter name", func(t *testing.T) {
		got := filterSegments(segments, "kiwi.txt", "", "", -1)
		if len(got) != 2 {
			t.Errorf("expected 2 segments with kiwi.txt filter, got %d", len(got))
		}
	})

	t.Run("filter by certainty", func(t *testing.T) {
		got := filterSegments(segments, "", "", "", 100)
		if len(got) != 2 {
			t.Errorf("expected 2 segments with certainty=100, got %d", len(got))
		}
	})

	t.Run("no matching segments", func(t *testing.T) {
		got := filterSegments(segments, "", "Phantom", "", -1)
		if len(got) != 0 {
			t.Errorf("expected 0 segments, got %d", len(got))
		}
	})

	t.Run("nil segments slice", func(t *testing.T) {
		got := filterSegments(nil, "", "", "", -1)
		if len(got) != 0 {
			t.Errorf("expected 0, got %d", len(got))
		}
	})
}

// --- validateClipInput ---

func TestValidateClipInput(t *testing.T) {
	t.Run("missing file and folder", func(t *testing.T) {
		var out CallsClipOutput
		err := validateClipInput(&out, CallsClipInput{})
		if err == nil {
			t.Error("expected error")
		}
		if len(out.Errors) != 1 {
			t.Errorf("expected 1 output error, got %d", len(out.Errors))
		}
	})

	t.Run("missing output", func(t *testing.T) {
		var out CallsClipOutput
		err := validateClipInput(&out, CallsClipInput{File: "test.data"})
		if err == nil {
			t.Error("expected error for missing output")
		}
	})

	t.Run("missing prefix", func(t *testing.T) {
		var out CallsClipOutput
		err := validateClipInput(&out, CallsClipInput{File: "test.data", Output: "/tmp"})
		if err == nil {
			t.Error("expected error for missing prefix")
		}
	})

	t.Run("all required fields present via file", func(t *testing.T) {
		var out CallsClipOutput
		err := validateClipInput(&out, CallsClipInput{File: "test.data", Output: "/tmp", Prefix: "clip"})
		if err != nil {
			t.Errorf("unexpected error: %v", err)
		}
	})

	t.Run("all required fields present via folder", func(t *testing.T) {
		var out CallsClipOutput
		err := validateClipInput(&out, CallsClipInput{Folder: "/data", Output: "/tmp", Prefix: "clip"})
		if err != nil {
			t.Errorf("unexpected error: %v", err)
		}
	})
}

// --- accumulateFileResult ---

func TestAccumulateFileResult(t *testing.T) {
	t.Run("accumulates clips and errors", func(t *testing.T) {
		var out CallsClipOutput
		accumulateFileResult(&out, []string{"a.wav", "a.png"}, 0, []string{"warn1"}, false)

		if out.SegmentsClipped != 2 {
			t.Errorf("SegmentsClipped=%d want 2", out.SegmentsClipped)
		}
		if out.FilesProcessed != 1 {
			t.Errorf("FilesProcessed=%d want 1", out.FilesProcessed)
		}
		if len(out.OutputFiles) != 2 {
			t.Errorf("OutputFiles=%d want 2", len(out.OutputFiles))
		}
		if len(out.Errors) != 1 {
			t.Errorf("Errors=%d want 1", len(out.Errors))
		}
	})

	t.Run("night skip goes to NightSkipped", func(t *testing.T) {
		var out CallsClipOutput
		accumulateFileResult(&out, []string{"a.wav"}, 3, nil, true)
		if out.NightSkipped != 3 {
			t.Errorf("NightSkipped=%d want 3", out.NightSkipped)
		}
	})

	t.Run("day skip goes to DaySkipped", func(t *testing.T) {
		var out CallsClipOutput
		accumulateFileResult(&out, []string{"a.wav"}, 5, nil, false)
		if out.DaySkipped != 5 {
			t.Errorf("DaySkipped=%d want 5", out.DaySkipped)
		}
	})

	t.Run("no clips and no errors counts as processed", func(t *testing.T) {
		var out CallsClipOutput
		accumulateFileResult(&out, nil, 0, nil, false)
		// len(clips)==0 but len(errs)==0, so file is considered processed
		if out.FilesProcessed != 1 {
			t.Errorf("FilesProcessed=%d want 1", out.FilesProcessed)
		}
	})
}