247 lines
5.8 KiB
Go
247 lines
5.8 KiB
Go
package paperformatter
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestFormatPapers(t *testing.T) {
|
|
// Create temporary directory for test files
|
|
tmpDir, err := os.MkdirTemp("", "paperformatter-test-*")
|
|
if err != nil {
|
|
t.Fatalf("Failed to create temp directory: %v", err)
|
|
}
|
|
defer os.RemoveAll(tmpDir)
|
|
|
|
tests := []struct {
|
|
name string
|
|
input string
|
|
wantErr bool
|
|
errContains string
|
|
checkOutput func(t *testing.T, output string)
|
|
}{
|
|
{
|
|
name: "happy path - mixed decisions",
|
|
input: `[
|
|
{
|
|
"paper": {
|
|
"title": "Test Paper 1",
|
|
"abstract": "Abstract 1",
|
|
"arxiv_id": "2301.0001"
|
|
},
|
|
"decision": "accept",
|
|
"explanation": "Good paper"
|
|
},
|
|
{
|
|
"paper": {
|
|
"title": "Test Paper 2",
|
|
"abstract": "Abstract 2",
|
|
"arxiv_id": "2301.0002"
|
|
},
|
|
"decision": "reject",
|
|
"explanation": "Needs work"
|
|
}
|
|
]`,
|
|
wantErr: false,
|
|
checkOutput: func(t *testing.T, output string) {
|
|
// Check sections exist
|
|
if !strings.Contains(output, "# Accepted Papers") {
|
|
t.Error("Output missing Accepted Papers section")
|
|
}
|
|
if !strings.Contains(output, "# Rejected Papers") {
|
|
t.Error("Output missing Rejected Papers section")
|
|
}
|
|
|
|
// Check paper details
|
|
if !strings.Contains(output, "## Test Paper 1") {
|
|
t.Error("Output missing accepted paper title")
|
|
}
|
|
if !strings.Contains(output, "## Test Paper 2") {
|
|
t.Error("Output missing rejected paper title")
|
|
}
|
|
|
|
// Check formatting
|
|
if !strings.Contains(output, "[arXiv:2301.0001]") {
|
|
t.Error("Output missing arXiv link for accepted paper")
|
|
}
|
|
if !strings.Contains(output, "> Abstract 1") {
|
|
t.Error("Output missing abstract blockquote for accepted paper")
|
|
}
|
|
if !strings.Contains(output, "**Decision:** accept") {
|
|
t.Error("Output missing decision for accepted paper")
|
|
}
|
|
},
|
|
},
|
|
{
|
|
name: "empty input array",
|
|
input: `[]`,
|
|
wantErr: false,
|
|
checkOutput: func(t *testing.T, output string) {
|
|
if !strings.Contains(output, "# Accepted Papers") {
|
|
t.Error("Output missing Accepted Papers section")
|
|
}
|
|
if !strings.Contains(output, "# Rejected Papers") {
|
|
t.Error("Output missing Rejected Papers section")
|
|
}
|
|
},
|
|
},
|
|
{
|
|
name: "invalid JSON",
|
|
input: `not json`,
|
|
wantErr: true,
|
|
errContains: "JSON parsing error",
|
|
},
|
|
{
|
|
name: "missing title",
|
|
input: `[
|
|
{
|
|
"paper": {
|
|
"title": "",
|
|
"abstract": "Abstract",
|
|
"arxiv_id": "2301.0001"
|
|
},
|
|
"decision": "accept",
|
|
"explanation": "Good paper"
|
|
}
|
|
]`,
|
|
wantErr: true,
|
|
errContains: "validation error for title: title cannot be empty",
|
|
},
|
|
{
|
|
name: "missing abstract",
|
|
input: `[
|
|
{
|
|
"paper": {
|
|
"title": "Test Paper",
|
|
"abstract": "",
|
|
"arxiv_id": "2301.0001"
|
|
},
|
|
"decision": "accept",
|
|
"explanation": "Good paper"
|
|
}
|
|
]`,
|
|
wantErr: true,
|
|
errContains: "validation error for abstract: abstract cannot be empty",
|
|
},
|
|
{
|
|
name: "invalid decision",
|
|
input: `[
|
|
{
|
|
"paper": {
|
|
"title": "Test Paper",
|
|
"abstract": "Abstract",
|
|
"arxiv_id": "2301.0001"
|
|
},
|
|
"decision": "maybe",
|
|
"explanation": "Good paper"
|
|
}
|
|
]`,
|
|
wantErr: true,
|
|
errContains: "decision must be either 'accept' or 'reject'",
|
|
},
|
|
{
|
|
name: "case insensitive decision",
|
|
input: `[
|
|
{
|
|
"paper": {
|
|
"title": "Test Paper",
|
|
"abstract": "Abstract",
|
|
"arxiv_id": "2301.0001"
|
|
},
|
|
"decision": "ACCEPT",
|
|
"explanation": "Good paper"
|
|
}
|
|
]`,
|
|
wantErr: false,
|
|
checkOutput: func(t *testing.T, output string) {
|
|
if !strings.Contains(output, "## Test Paper") {
|
|
t.Error("Output missing paper with uppercase decision")
|
|
}
|
|
},
|
|
},
|
|
{
|
|
name: "multiline abstract",
|
|
input: `[
|
|
{
|
|
"paper": {
|
|
"title": "Test Paper",
|
|
"abstract": "Line 1\nLine 2\nLine 3",
|
|
"arxiv_id": "2301.0001"
|
|
},
|
|
"decision": "accept",
|
|
"explanation": "Good paper"
|
|
}
|
|
]`,
|
|
wantErr: false,
|
|
checkOutput: func(t *testing.T, output string) {
|
|
if !strings.Contains(output, "> Line 1\n> Line 2\n> Line 3") {
|
|
t.Error("Output not handling multiline abstract correctly")
|
|
}
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
// Create input file
|
|
inputPath := filepath.Join(tmpDir, "input.json")
|
|
if err := os.WriteFile(inputPath, []byte(tt.input), 0644); err != nil {
|
|
t.Fatalf("Failed to write input file: %v", err)
|
|
}
|
|
|
|
// Create output path
|
|
outputPath := filepath.Join(tmpDir, "output.md")
|
|
|
|
// Run the formatter
|
|
err := FormatPapers(inputPath, outputPath)
|
|
|
|
// Check error cases
|
|
if tt.wantErr {
|
|
if err == nil {
|
|
t.Error("Expected error but got none")
|
|
} else if tt.errContains != "" && !strings.Contains(err.Error(), tt.errContains) {
|
|
t.Errorf("Expected error containing %q but got %q", tt.errContains, err.Error())
|
|
}
|
|
return
|
|
}
|
|
|
|
// Check success cases
|
|
if err != nil {
|
|
t.Fatalf("Unexpected error: %v", err)
|
|
}
|
|
|
|
// Read and verify output
|
|
output, err := os.ReadFile(outputPath)
|
|
if err != nil {
|
|
t.Fatalf("Failed to read output file: %v", err)
|
|
}
|
|
|
|
if tt.checkOutput != nil {
|
|
tt.checkOutput(t, string(output))
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestFormatPapersFileErrors(t *testing.T) {
|
|
// Test non-existent input file
|
|
err := FormatPapers("nonexistent.json", "output.md")
|
|
if err == nil {
|
|
t.Error("Expected error for non-existent input file")
|
|
}
|
|
|
|
// Test invalid output path
|
|
tmpfile, err := os.CreateTemp("", "test.json")
|
|
if err != nil {
|
|
t.Fatalf("Failed to create temp file: %v", err)
|
|
}
|
|
defer os.Remove(tmpfile.Name())
|
|
|
|
err = FormatPapers(tmpfile.Name(), "/nonexistent/directory/output.md")
|
|
if err == nil {
|
|
t.Error("Expected error for invalid output path")
|
|
}
|
|
}
|