initial public release
This commit is contained in:
@@ -0,0 +1,190 @@
|
||||
package eval
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
_ "modernc.org/sqlite"
|
||||
)
|
||||
|
||||
func setupReportDB(t *testing.T) *sql.DB {
|
||||
t.Helper()
|
||||
db, err := sql.Open("sqlite", ":memory:")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
schema := `
|
||||
CREATE TABLE jobs (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
url TEXT UNIQUE NOT NULL,
|
||||
company TEXT NOT NULL,
|
||||
title TEXT NOT NULL,
|
||||
description TEXT,
|
||||
source TEXT,
|
||||
discovered_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
CREATE TABLE applications (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
job_id INTEGER NOT NULL,
|
||||
status TEXT NOT NULL DEFAULT 'Evaluated',
|
||||
score REAL,
|
||||
archetype TEXT,
|
||||
legitimacy TEXT,
|
||||
evaluated_at TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
CREATE TABLE reports (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
application_id INTEGER NOT NULL,
|
||||
report_md TEXT,
|
||||
seq INTEGER,
|
||||
slug TEXT,
|
||||
legitimacy TEXT,
|
||||
score REAL,
|
||||
block_a TEXT, block_b TEXT, block_c TEXT, block_d TEXT,
|
||||
block_e TEXT, block_f TEXT, block_g TEXT,
|
||||
file_path TEXT,
|
||||
stories TEXT,
|
||||
generated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
`
|
||||
if _, err := db.Exec(schema); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return db
|
||||
}
|
||||
|
||||
func TestSlugify(t *testing.T) {
|
||||
cases := map[string]string{
|
||||
"Acme Corp": "acme-corp",
|
||||
"Dragos, Inc.": "dragos-inc",
|
||||
" Red/Canary ": "redcanary",
|
||||
"../../etc/passwd": "etcpasswd",
|
||||
"": "unknown",
|
||||
"!@#$%^&*()": "unknown",
|
||||
"Foo ___ Bar": "foo-bar",
|
||||
strings.Repeat("x", 80): strings.Repeat("x", 64),
|
||||
}
|
||||
for in, want := range cases {
|
||||
if got := Slugify(in); got != want {
|
||||
t.Errorf("Slugify(%q) = %q, want %q", in, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestReportWriter_SaveEndToEnd(t *testing.T) {
|
||||
db := setupReportDB(t)
|
||||
defer db.Close()
|
||||
tmp := t.TempDir()
|
||||
w := &ReportWriter{DB: db, ReportsDir: tmp}
|
||||
|
||||
job := JobContext{
|
||||
URL: "https://example.com/jobs/42",
|
||||
Company: "Acme Corp",
|
||||
Title: "Staff LLMOps",
|
||||
Source: "greenhouse",
|
||||
JDText: "Job description body.",
|
||||
}
|
||||
eval := Evaluation{
|
||||
Archetype: "LLMOps",
|
||||
Score: 4.2,
|
||||
Legitimacy: TierHigh,
|
||||
BlockA: "## A) Role Summary\n\nStaff LLMOps role.",
|
||||
BlockB: "## B) CV Match\n\nStrong match.\n\n**Weighted score:** 4.2/5",
|
||||
BlockG: "## G) Posting Legitimacy\n\n**Assessment:** High Confidence",
|
||||
Raw: "full raw",
|
||||
}
|
||||
|
||||
saved, err := w.Save(context.Background(), job, eval)
|
||||
if err != nil {
|
||||
t.Fatalf("Save: %v", err)
|
||||
}
|
||||
if saved.Seq != 1 {
|
||||
t.Errorf("Seq = %d, want 1", saved.Seq)
|
||||
}
|
||||
if saved.ApplicationID == 0 || saved.ReportID == 0 {
|
||||
t.Errorf("missing ids: app=%d report=%d", saved.ApplicationID, saved.ReportID)
|
||||
}
|
||||
if filepath.Dir(saved.FilePath) != tmp {
|
||||
t.Errorf("file path outside ReportsDir: %q", saved.FilePath)
|
||||
}
|
||||
if _, err := os.Stat(saved.FilePath); err != nil {
|
||||
t.Fatalf("report file missing: %v", err)
|
||||
}
|
||||
|
||||
// Contents exercise RenderMarkdown: Block G appears before Block A.
|
||||
body, err := os.ReadFile(saved.FilePath)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
s := string(body)
|
||||
if !strings.Contains(s, "**Legitimacy:** high") {
|
||||
t.Errorf("missing legitimacy header in report:\n%s", s)
|
||||
}
|
||||
gIdx := strings.Index(s, "## G)")
|
||||
aIdx := strings.Index(s, "## A)")
|
||||
if gIdx == -1 || aIdx == -1 || gIdx > aIdx {
|
||||
t.Errorf("Block G should appear before Block A; gIdx=%d aIdx=%d", gIdx, aIdx)
|
||||
}
|
||||
|
||||
// Save second eval for the same URL: seq should become 2, application
|
||||
// should be updated (not duplicated).
|
||||
eval.Score = 4.5
|
||||
saved2, err := w.Save(context.Background(), job, eval)
|
||||
if err != nil {
|
||||
t.Fatalf("Save#2: %v", err)
|
||||
}
|
||||
if saved2.Seq != 2 {
|
||||
t.Errorf("Seq#2 = %d, want 2", saved2.Seq)
|
||||
}
|
||||
if saved2.ApplicationID != saved.ApplicationID {
|
||||
t.Errorf("application_id drifted: %d → %d", saved.ApplicationID, saved2.ApplicationID)
|
||||
}
|
||||
var appCount int
|
||||
if err := db.QueryRow(`SELECT COUNT(*) FROM applications`).Scan(&appCount); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if appCount != 1 {
|
||||
t.Errorf("applications count = %d, want 1", appCount)
|
||||
}
|
||||
var reportCount int
|
||||
if err := db.QueryRow(`SELECT COUNT(*) FROM reports`).Scan(&reportCount); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if reportCount != 2 {
|
||||
t.Errorf("reports count = %d, want 2", reportCount)
|
||||
}
|
||||
}
|
||||
|
||||
func TestReportWriter_StatusPreservedWhenReEvaluated(t *testing.T) {
|
||||
db := setupReportDB(t)
|
||||
defer db.Close()
|
||||
w := &ReportWriter{DB: db, ReportsDir: t.TempDir()}
|
||||
|
||||
job := JobContext{URL: "https://example.com/j/1", Company: "Beta", Title: "SWE", Source: "ashby"}
|
||||
eval := Evaluation{Score: 3.0, Legitimacy: TierCaution, BlockA: "## A) x", BlockG: "## G) y"}
|
||||
|
||||
if _, err := w.Save(context.Background(), job, eval); err != nil {
|
||||
t.Fatalf("first save: %v", err)
|
||||
}
|
||||
// Simulate user advancing the pipeline.
|
||||
if _, err := db.Exec(`UPDATE applications SET status = 'Applied' WHERE job_id = (SELECT id FROM jobs WHERE url = ?)`, job.URL); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
// Re-run eval — must NOT clobber 'Applied' back to 'Evaluated'.
|
||||
eval.Score = 3.5
|
||||
if _, err := w.Save(context.Background(), job, eval); err != nil {
|
||||
t.Fatalf("second save: %v", err)
|
||||
}
|
||||
var status string
|
||||
if err := db.QueryRow(`SELECT status FROM applications WHERE job_id = (SELECT id FROM jobs WHERE url = ?)`, job.URL).Scan(&status); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if status != "Applied" {
|
||||
t.Errorf("status = %q, want Applied (re-eval should not regress)", status)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user