|
| 1 | +package connector |
| 2 | + |
| 3 | +import ( |
| 4 | + "context" |
| 5 | + "strings" |
| 6 | + "testing" |
| 7 | +) |
| 8 | + |
| 9 | +func TestChunkText_Chars(t *testing.T) { |
| 10 | + // "abcdefg" (7), size 3, overlap 1 → step 2: windows 0-3, 2-5, 4-7. |
| 11 | + // The last window reaches the end, so there is no trailing "g" chunk. |
| 12 | + got, err := chunkText("abcdefg", 3, 1, "chars") |
| 13 | + if err != nil { |
| 14 | + t.Fatalf("chunkText error: %v", err) |
| 15 | + } |
| 16 | + want := []string{"abc", "cde", "efg"} |
| 17 | + if strings.Join(got, "|") != strings.Join(want, "|") { |
| 18 | + t.Errorf("chunks = %v, want %v", got, want) |
| 19 | + } |
| 20 | +} |
| 21 | + |
| 22 | +func TestChunkText_NoOverlapExactFit(t *testing.T) { |
| 23 | + // 6 chars, size 3, overlap 0 → [abc, def], no trailing empty chunk. |
| 24 | + got, err := chunkText("abcdef", 3, 0, "chars") |
| 25 | + if err != nil { |
| 26 | + t.Fatalf("error: %v", err) |
| 27 | + } |
| 28 | + if len(got) != 2 || got[0] != "abc" || got[1] != "def" { |
| 29 | + t.Errorf("chunks = %v, want [abc def]", got) |
| 30 | + } |
| 31 | +} |
| 32 | + |
| 33 | +func TestChunkText_Words(t *testing.T) { |
| 34 | + got, err := chunkText("the quick brown fox jumps", 2, 0, "words") |
| 35 | + if err != nil { |
| 36 | + t.Fatalf("error: %v", err) |
| 37 | + } |
| 38 | + want := []string{"the quick", "brown fox", "jumps"} |
| 39 | + if strings.Join(got, "|") != strings.Join(want, "|") { |
| 40 | + t.Errorf("chunks = %v, want %v", got, want) |
| 41 | + } |
| 42 | +} |
| 43 | + |
| 44 | +func TestChunkText_ShorterThanSize(t *testing.T) { |
| 45 | + got, err := chunkText("hi", 100, 10, "chars") |
| 46 | + if err != nil { |
| 47 | + t.Fatalf("error: %v", err) |
| 48 | + } |
| 49 | + if len(got) != 1 || got[0] != "hi" { |
| 50 | + t.Errorf("chunks = %v, want [hi]", got) |
| 51 | + } |
| 52 | +} |
| 53 | + |
| 54 | +func TestChunkText_Unicode(t *testing.T) { |
| 55 | + // Multibyte runes must not be split mid-character. |
| 56 | + got, err := chunkText("héllo wörld", 3, 0, "chars") |
| 57 | + if err != nil { |
| 58 | + t.Fatalf("error: %v", err) |
| 59 | + } |
| 60 | + // 11 runes / size 3 → 4 chunks; first is "hél". |
| 61 | + if got[0] != "hél" { |
| 62 | + t.Errorf("first chunk = %q, want %q", got[0], "hél") |
| 63 | + } |
| 64 | +} |
| 65 | + |
| 66 | +func TestChunkText_Errors(t *testing.T) { |
| 67 | + cases := []struct { |
| 68 | + name string |
| 69 | + text string |
| 70 | + size, overlap int |
| 71 | + unit string |
| 72 | + }{ |
| 73 | + {"empty text", " ", 10, 0, "chars"}, |
| 74 | + {"zero size", "abc", 0, 0, "chars"}, |
| 75 | + {"negative overlap", "abc", 10, -1, "chars"}, |
| 76 | + {"overlap >= size", "abc", 5, 5, "chars"}, |
| 77 | + {"unknown unit", "abc", 5, 0, "tokens"}, |
| 78 | + } |
| 79 | + for _, tc := range cases { |
| 80 | + t.Run(tc.name, func(t *testing.T) { |
| 81 | + if _, err := chunkText(tc.text, tc.size, tc.overlap, tc.unit); err == nil { |
| 82 | + t.Errorf("expected error for %s", tc.name) |
| 83 | + } |
| 84 | + }) |
| 85 | + } |
| 86 | +} |
| 87 | + |
| 88 | +func TestTextChunkConnector_Output(t *testing.T) { |
| 89 | + out, err := (&TextChunkConnector{}).Execute(context.Background(), map[string]any{ |
| 90 | + "text": "one two three four five", |
| 91 | + "chunk_size": 2, |
| 92 | + "chunk_overlap": 0, |
| 93 | + "unit": "words", |
| 94 | + }) |
| 95 | + if err != nil { |
| 96 | + t.Fatalf("Execute error: %v", err) |
| 97 | + } |
| 98 | + chunks := out["chunks"].([]string) |
| 99 | + if out["count"].(int) != len(chunks) || len(chunks) != 3 { |
| 100 | + t.Errorf("count/chunks = %v / %v", out["count"], chunks) |
| 101 | + } |
| 102 | +} |
0 commit comments