diff --git a/.gitignore b/.gitignore index e4b25c6..c969d7b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ # Binaries -toolbox +build/ *.exe *.exe~ *.dll diff --git a/cmd/toolbox/main_test.go b/cmd/toolbox/main_test.go new file mode 100644 index 0000000..eae5222 --- /dev/null +++ b/cmd/toolbox/main_test.go @@ -0,0 +1,160 @@ +package main + +import ( + "bytes" + "encoding/json" + "fmt" + "net/http" + "os" + "os/exec" + "testing" + "time" +) + +const ( + testPort = "9999" + baseURL = "http://localhost:" + testPort +) + +func TestToolboxE2E(t *testing.T) { + // 1. Build the binary + fmt.Println("--- Step 1: Building binary... ---") + _ = os.MkdirAll("build", 0755) + buildPath := "build/toolbox_test_bin" + buildCmd := exec.Command("go", "build", "-o", buildPath, "main.go") + if err := buildCmd.Run(); err != nil { + t.Fatalf("Failed to build binary: %v", err) + } + defer func() { _ = os.Remove(buildPath) }() + + // 2. Start the server + fmt.Println("--- Step 2: Starting server... ---") + serverCmd := exec.Command("./"+buildPath, "-port", testPort) + if err := serverCmd.Start(); err != nil { + t.Fatalf("Failed to start server: %v", err) + } + defer func() { + if serverCmd.Process != nil { + _ = serverCmd.Process.Kill() + } + }() + + // 3. Wait for server to be ready + fmt.Println("--- Step 3: Waiting for server readiness... ---") + ready := false + for i := 0; i < 10; i++ { + resp, err := http.Get(baseURL + "/api/tools") + if err == nil && resp.StatusCode == http.StatusOK { + ready = true + _ = resp.Body.Close() + break + } + time.Sleep(500 * time.Millisecond) + } + if !ready { + t.Fatal("Server failed to become ready in time") + } + + // 4. Test endpoints + fmt.Println("--- Step 4: Testing tool endpoints... ---") + + testOutputDir, err := os.MkdirTemp("", "toolbox_test_output_*") + if err != nil { + t.Fatalf("Failed to create temp dir: %v", err) + } + fmt.Printf("--- Test Artifacts will be saved to: %s ---\n", testOutputDir) + + tests := []struct { + name string + path string + method string + fileName string + body interface{} + }{ + { + name: "Zitie Teaching", + path: "/api/zitie/teaching", + method: "POST", + fileName: "zitie_teaching.pdf", + body: map[string]string{"chars": "永和九年", "paper_size": "A4"}, + }, + { + name: "Zitie Step", + path: "/api/zitie/step", + method: "POST", + fileName: "zitie_step.pdf", + body: map[string]string{"chars": "永", "paper_size": "A4"}, + }, + { + name: "Zitie Manuscript", + path: "/api/zitie/manuscript", + method: "POST", + fileName: "zitie_manuscript.pdf", + body: map[string]string{"chars": "天道酬勤", "paper_size": "A4", "font_type": "kaiti"}, + }, + { + name: "Learn Number Counting", + path: "/api/learn-number/counting", + method: "POST", + fileName: "counting.pdf", + body: map[string]interface{}{"page_count": 1, "paper_size": "A4"}, + }, + { + name: "Learn Number Writing", + path: "/api/learn-number/writing", + method: "POST", + fileName: "writing.pdf", + body: map[string]interface{}{"start_num": 1, "end_num": 5, "paper_size": "A4"}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + var resp *http.Response + var err error + + if tt.method == "POST" { + b, _ := json.Marshal(tt.body) + resp, err = http.Post(baseURL+tt.path, "application/json", bytes.NewBuffer(b)) + } else { + resp, err = http.Get(baseURL + tt.path) + } + + if err != nil { + t.Errorf("%s failed: %v", tt.name, err) + return + } + defer func() { _ = resp.Body.Close() }() + + if resp.StatusCode != http.StatusOK { + t.Errorf("%s returned status %d", tt.name, resp.StatusCode) + return + } + + contentType := resp.Header.Get("Content-Type") + if contentType != "application/pdf" { + t.Errorf("%s expected application/pdf, got %s", tt.name, contentType) + } else { + // Save PDF to temp directory for human review + outPath := testOutputDir + "/" + tt.fileName + f, err := os.Create(outPath) + if err != nil { + t.Errorf("Failed to create output file: %v", err) + return + } + defer func() { _ = f.Close() }() + + _, err = f.ReadFrom(resp.Body) + + if err != nil { + t.Errorf("Failed to save PDF: %v", err) + return + } + + fmt.Printf("[PASS] %s: Saved to %s\n", tt.name, outPath) + } + }) + } + + fmt.Printf("\n--- ALL TESTS DONE. PLEASE REVIEW PDFS IN: %s ---\n", testOutputDir) +}