add tests (ai gen)
This commit is contained in:
@@ -1 +1,5 @@
|
||||
my take on how notes and srs should be combind and simplified
|
||||
|
||||
# Tests
|
||||
|
||||
Run tests with `go test ./...`
|
||||
|
||||
+109
@@ -0,0 +1,109 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// tests creating a file in a temp dir
|
||||
func TestCreateFile(t *testing.T) {
|
||||
tmpDir, err := os.MkdirTemp("", "mend_fs_test")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(tmpDir)
|
||||
|
||||
// test valid creation
|
||||
filePath := filepath.Join(tmpDir, "test.md")
|
||||
err = createFile(filePath, []byte("content"))
|
||||
if err != nil {
|
||||
t.Errorf("expected no error, got %v", err)
|
||||
}
|
||||
|
||||
if _, err := os.Stat(filePath); os.IsNotExist(err) {
|
||||
t.Error("file was not created")
|
||||
}
|
||||
|
||||
// test creation failure (exists)
|
||||
err = createFile(filePath, []byte("content"))
|
||||
if err == nil {
|
||||
t.Error("expected error for existing file, got nil")
|
||||
}
|
||||
|
||||
// test empty path
|
||||
err = createFile("", []byte{})
|
||||
if err == nil {
|
||||
t.Error("expected error for empty path, got nil")
|
||||
}
|
||||
}
|
||||
|
||||
// tests creating a folder
|
||||
func TestCreateFolder(t *testing.T) {
|
||||
tmpDir, err := os.MkdirTemp("", "mend_fs_test")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(tmpDir)
|
||||
|
||||
folderPath := filepath.Join(tmpDir, "subfolder")
|
||||
err = createFolder(folderPath)
|
||||
if err != nil {
|
||||
t.Errorf("expected no error, got %v", err)
|
||||
}
|
||||
|
||||
info, err := os.Stat(folderPath)
|
||||
if os.IsNotExist(err) {
|
||||
t.Error("folder was not created")
|
||||
}
|
||||
if !info.IsDir() {
|
||||
t.Error("created path is not a directory")
|
||||
}
|
||||
|
||||
// test creation failure (exists)
|
||||
err = createFolder(folderPath)
|
||||
if err == nil {
|
||||
t.Error("expected error for existing folder, got nil")
|
||||
}
|
||||
|
||||
// test empty path
|
||||
err = createFolder("")
|
||||
if err == nil {
|
||||
t.Error("expected error for empty path, got nil")
|
||||
}
|
||||
}
|
||||
|
||||
// tests recursive deletion
|
||||
func TestDeletePath(t *testing.T) {
|
||||
tmpDir, err := os.MkdirTemp("", "mend_fs_test")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(tmpDir)
|
||||
|
||||
subDir := filepath.Join(tmpDir, "subdir")
|
||||
os.Mkdir(subDir, 0755)
|
||||
fileInSubDir := filepath.Join(subDir, "file.txt")
|
||||
os.WriteFile(fileInSubDir, []byte("data"), 0644)
|
||||
|
||||
err = deletePath(subDir)
|
||||
if err != nil {
|
||||
t.Errorf("expected no error, got %v", err)
|
||||
}
|
||||
|
||||
if _, err := os.Stat(subDir); !os.IsNotExist(err) {
|
||||
t.Error("directory was not deleted")
|
||||
}
|
||||
|
||||
// test delete non-existent
|
||||
err = deletePath(filepath.Join(tmpDir, "nonexistent"))
|
||||
if err == nil {
|
||||
t.Error("expected error for nonexistent path, got nil")
|
||||
}
|
||||
|
||||
// test empty path
|
||||
err = deletePath("")
|
||||
if err == nil {
|
||||
t.Error("expected error for empty path, got nil")
|
||||
}
|
||||
}
|
||||
+147
@@ -0,0 +1,147 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// tests creating a new fstree
|
||||
func TestNewFsTree(t *testing.T) {
|
||||
tmpDir, err := os.MkdirTemp("", "mend_fstree_test")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(tmpDir)
|
||||
|
||||
// setup structure:
|
||||
// root/
|
||||
// folder1/
|
||||
// file1.md
|
||||
// file2.md
|
||||
|
||||
os.Mkdir(filepath.Join(tmpDir, "folder1"), 0755)
|
||||
os.WriteFile(filepath.Join(tmpDir, "folder1", "file1.md"), []byte(""), 0644)
|
||||
os.WriteFile(filepath.Join(tmpDir, "file2.md"), []byte(""), 0644)
|
||||
|
||||
tree := NewFsTree(tmpDir, 0)
|
||||
|
||||
if tree == nil {
|
||||
t.Fatal("expected tree to be created, got nil")
|
||||
}
|
||||
if tree.root.path != tmpDir {
|
||||
t.Errorf("expected root path %s, got %s", tmpDir, tree.root.path)
|
||||
}
|
||||
// root children: folder1, file2.md
|
||||
if len(tree.root.children) != 2 {
|
||||
t.Errorf("expected 2 children, got %d", len(tree.root.children))
|
||||
}
|
||||
}
|
||||
|
||||
// tests creating nodes via tree
|
||||
func TestTreeCreateNode(t *testing.T) {
|
||||
tmpDir, err := os.MkdirTemp("", "mend_fstree_test")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(tmpDir)
|
||||
|
||||
tree := NewFsTree(tmpDir, 0)
|
||||
// create folder
|
||||
err = tree.CreateNode(tree.root, "new_folder", FolderNode)
|
||||
if err != nil {
|
||||
t.Errorf("expected no error creating folder, got %v", err)
|
||||
}
|
||||
// check fs
|
||||
if _, err := os.Stat(filepath.Join(tmpDir, "new_folder")); os.IsNotExist(err) {
|
||||
t.Error("folder not created on fs")
|
||||
}
|
||||
// check tree
|
||||
if len(tree.root.children) != 1 || tree.root.children[0].nodeType != FolderNode {
|
||||
t.Error("tree block not updated with new folder")
|
||||
}
|
||||
|
||||
// create file in new folder
|
||||
newFolder := tree.root.children[0]
|
||||
err = tree.CreateNode(newFolder, "new_file", FileNode)
|
||||
if err != nil {
|
||||
t.Errorf("expected no error creating file, got %v", err)
|
||||
}
|
||||
|
||||
// check fs (.md appended automatically)
|
||||
if _, err := os.Stat(filepath.Join(tmpDir, "new_folder", "new_file.md")); os.IsNotExist(err) {
|
||||
t.Error("file not created on fs")
|
||||
}
|
||||
// check tree
|
||||
if len(newFolder.children) != 1 || newFolder.children[0].nodeType != FileNode {
|
||||
t.Error("tree node not updated with new file")
|
||||
}
|
||||
}
|
||||
|
||||
// tests deleting nodes
|
||||
func TestTreeDeleteNode(t *testing.T) {
|
||||
tmpDir, err := os.MkdirTemp("", "mend_fstree_test")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(tmpDir)
|
||||
|
||||
// setup: root/file.md
|
||||
os.WriteFile(filepath.Join(tmpDir, "file.md"), []byte(""), 0644)
|
||||
|
||||
tree := NewFsTree(tmpDir, 0)
|
||||
targetNode := tree.root.children[0]
|
||||
|
||||
err = tree.DeleteNode(targetNode)
|
||||
if err != nil {
|
||||
t.Errorf("expected no error deleting node, got %v", err)
|
||||
}
|
||||
|
||||
// check fs
|
||||
if _, err := os.Stat(filepath.Join(tmpDir, "file.md")); !os.IsNotExist(err) {
|
||||
t.Error("file not deleted from fs")
|
||||
}
|
||||
// check tree
|
||||
if len(tree.root.children) != 0 {
|
||||
t.Error("tree node not updated after deletion")
|
||||
}
|
||||
}
|
||||
|
||||
// tests toggling expand
|
||||
func TestTreeToggleExpand(t *testing.T) {
|
||||
root := &FsNode{
|
||||
nodeType: FolderNode,
|
||||
expanded: true,
|
||||
children: []*FsNode{}, // Initialize children
|
||||
}
|
||||
|
||||
node := &FsNode{
|
||||
nodeType: FolderNode,
|
||||
expanded: true,
|
||||
parent: root,
|
||||
}
|
||||
root.children = append(root.children, node)
|
||||
|
||||
// mocked tree for this test
|
||||
tree := &FsTree{
|
||||
root: root,
|
||||
}
|
||||
// Initial buildLines to setup state
|
||||
tree.buildLines()
|
||||
|
||||
err := tree.ToggleExpand(node)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if node.expanded {
|
||||
t.Error("expected node to be collapsed")
|
||||
}
|
||||
|
||||
err = tree.ToggleExpand(node)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if !node.expanded {
|
||||
t.Error("expected node to be expanded")
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ require (
|
||||
github.com/charmbracelet/glamour v0.10.0
|
||||
github.com/charmbracelet/lipgloss v1.1.1-0.20250404203927-76690c660834
|
||||
github.com/mattn/go-runewidth v0.0.16
|
||||
github.com/yuin/goldmark v1.7.8
|
||||
)
|
||||
|
||||
require (
|
||||
@@ -33,7 +34,6 @@ require (
|
||||
github.com/muesli/termenv v0.16.0 // indirect
|
||||
github.com/rivo/uniseg v0.4.7 // indirect
|
||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
|
||||
github.com/yuin/goldmark v1.7.8 // indirect
|
||||
github.com/yuin/goldmark-emoji v1.0.5 // indirect
|
||||
golang.org/x/net v0.33.0 // indirect
|
||||
golang.org/x/sys v0.36.0 // indirect
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ=
|
||||
github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE=
|
||||
github.com/alecthomas/assert/v2 v2.7.0 h1:QtqSACNS3tF7oasA8CU6A6sXZSBDqnm7RfpLl9bZqbE=
|
||||
github.com/alecthomas/assert/v2 v2.7.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k=
|
||||
github.com/alecthomas/chroma/v2 v2.14.0 h1:R3+wzpnUArGcQz7fCETQBzO5n9IMNi13iIs46aU4V9E=
|
||||
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// tests hint extraction from text
|
||||
func TestExtractHints(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
content string
|
||||
expected []string
|
||||
}{
|
||||
{
|
||||
name: "single bold hint",
|
||||
content: "This is a **hint**.",
|
||||
expected: []string{"hint"},
|
||||
},
|
||||
{
|
||||
name: "multiple bold hints",
|
||||
content: "**one** and **two**",
|
||||
expected: []string{"one", "two"},
|
||||
},
|
||||
{
|
||||
name: "underscore hints",
|
||||
content: "__one__ and __two__",
|
||||
expected: []string{"one", "two"},
|
||||
},
|
||||
{
|
||||
name: "mixed hints",
|
||||
content: "**one** and __two__",
|
||||
expected: []string{"one", "two"},
|
||||
},
|
||||
{
|
||||
name: "no hints",
|
||||
content: "just plain text",
|
||||
expected: []string{},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got := extractHints(tt.content)
|
||||
if !reflect.DeepEqual(got, tt.expected) {
|
||||
t.Errorf("extractHints() = %v, want %v", got, tt.expected)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// tests section parsing from markdown
|
||||
func TestParseSections(t *testing.T) {
|
||||
content := []byte(`# Title 1
|
||||
Content 1 with **hint1**.
|
||||
|
||||
# Title 2
|
||||
Content 2 with __hint2__.
|
||||
`)
|
||||
|
||||
sections := parseSections(content)
|
||||
|
||||
if len(sections) != 2 {
|
||||
t.Fatalf("expected 2 sections, got %d", len(sections))
|
||||
}
|
||||
|
||||
// verify first section
|
||||
if sections[0].Title != "# Title 1" {
|
||||
t.Errorf("expected title '# Title 1', got '%s'", sections[0].Title)
|
||||
}
|
||||
if sections[0].Content != "Content 1 with **hint1**." {
|
||||
t.Errorf("expected content match for section 1, got '%s'", sections[0].Content)
|
||||
}
|
||||
if len(sections[0].Hints) != 1 || sections[0].Hints[0] != "hint1" {
|
||||
t.Error("failed to extract hint from section 1")
|
||||
}
|
||||
|
||||
// verify second section
|
||||
if sections[1].Title != "# Title 2" {
|
||||
t.Errorf("expected title '# Title 2', got '%s'", sections[1].Title)
|
||||
}
|
||||
if sections[1].Content != "Content 2 with __hint2__." {
|
||||
t.Errorf("expected content match for section 2, got '%s'", sections[1].Content)
|
||||
}
|
||||
if len(sections[1].Hints) != 1 || sections[1].Hints[0] != "hint2" {
|
||||
t.Error("failed to extract hint from section 2")
|
||||
}
|
||||
}
|
||||
|
||||
// tests parsing with no headers
|
||||
func TestParseSectionsNoHeaders(t *testing.T) {
|
||||
content := []byte(`Just some content without any headers.
|
||||
It has **one hint**.`)
|
||||
|
||||
sections := parseSections(content)
|
||||
|
||||
if len(sections) != 1 {
|
||||
t.Fatalf("expected 1 section, got %d", len(sections))
|
||||
}
|
||||
|
||||
if sections[0].Title != "no title" {
|
||||
t.Errorf("expected 'no title', got '%s'", sections[0].Title)
|
||||
}
|
||||
if len(sections[0].Hints) != 1 || sections[0].Hints[0] != "one hint" {
|
||||
t.Error("failed to extract hint")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user