agent build
This commit is contained in:
99
go-api/internal/httpserver/positions_contract_test.go
Normal file
99
go-api/internal/httpserver/positions_contract_test.go
Normal file
@@ -0,0 +1,99 @@
|
||||
package httpserver_test
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// The exact body the Owliver create-position skill sends, byte for byte as
|
||||
// `runAction('create_position', …)` produces it for the brief's own example.
|
||||
// Generated from the frontend, not retyped: if the two ever drift, this fails.
|
||||
const owliverCreatePositionBody = `{
|
||||
"title": "Event Staff",
|
||||
"role_category": "Event Staff",
|
||||
"company": "Mac",
|
||||
"headcount": 1,
|
||||
"start_date": null,
|
||||
"duration_months": null,
|
||||
"priority": "normal",
|
||||
"custom_requirements": "",
|
||||
"physical_requirements": "",
|
||||
"leadership_expectations": "",
|
||||
"attendance_expectations": "",
|
||||
"min_experience_years": 3,
|
||||
"english_required": "native",
|
||||
"location": "Bay Area",
|
||||
"pay_range_min": 30,
|
||||
"pay_range_max": 40,
|
||||
"certifications_required": ["Background Check Cleared"],
|
||||
"skill_requirements": [],
|
||||
"vetting_criteria": {"experience":25,"english":20,"reliability":20,"certifications":20,"availability":15},
|
||||
"status": "active"
|
||||
}`
|
||||
|
||||
func TestOwliverCreatePositionPayloadIsAccepted(t *testing.T) {
|
||||
a := newAPI(t)
|
||||
|
||||
var body map[string]any
|
||||
if err := json.Unmarshal([]byte(owliverCreatePositionBody), &body); err != nil {
|
||||
t.Fatalf("the captured payload is not valid JSON: %v", err)
|
||||
}
|
||||
|
||||
got := a.do("POST", "/api/v1/job-postings", body)
|
||||
if got.code != http.StatusCreated {
|
||||
t.Fatalf("POST /api/v1/job-postings = %d, want 201\nbody: %v", got.code, got.body)
|
||||
}
|
||||
|
||||
rec, _ := got.body["data"].(map[string]any)
|
||||
if rec == nil {
|
||||
t.Fatalf("no record in the response: %v", got.body)
|
||||
}
|
||||
|
||||
// Every field the conversation collected must come back as it was sent —
|
||||
// a create that silently drops the pay range or the certification is a
|
||||
// create that looks fine and stores something else.
|
||||
for field, want := range map[string]any{
|
||||
"title": "Event Staff", "company": "Mac", "location": "Bay Area",
|
||||
"pay_range_min": float64(30), "pay_range_max": float64(40),
|
||||
"min_experience_years": float64(3), "english_required": "native",
|
||||
"status": "active",
|
||||
} {
|
||||
if rec[field] != want {
|
||||
t.Errorf("%s = %#v, want %#v", field, rec[field], want)
|
||||
}
|
||||
}
|
||||
certs, _ := rec["certifications_required"].([]any)
|
||||
if len(certs) != 1 || certs[0] != "Background Check Cleared" {
|
||||
t.Errorf("certifications_required = %#v", rec["certifications_required"])
|
||||
}
|
||||
id, _ := rec["id"].(string)
|
||||
if id == "" {
|
||||
t.Fatal("the created position has no id")
|
||||
}
|
||||
|
||||
// And it is in PostgreSQL, not just in the response: read it back through
|
||||
// the list endpoint the Positions page uses.
|
||||
list := a.do("GET", "/api/v1/job-postings?limit=200", nil)
|
||||
if list.code != http.StatusOK {
|
||||
t.Fatalf("GET /api/v1/job-postings = %d", list.code)
|
||||
}
|
||||
rows, _ := list.body["data"].([]any)
|
||||
for _, row := range rows {
|
||||
if r, ok := row.(map[string]any); ok && r["id"] == id {
|
||||
return
|
||||
}
|
||||
}
|
||||
t.Fatalf("the created position is not in GET /api/v1/job-postings (%d rows)", len(rows))
|
||||
}
|
||||
|
||||
// The path the brief names does not exist, and never did. The resource is
|
||||
// job-postings; /api/v1/positions is a phantom.
|
||||
func TestThereIsNoPositionsResource(t *testing.T) {
|
||||
a := newAPI(t)
|
||||
for _, m := range []string{"GET", "POST"} {
|
||||
if got := a.do(m, "/api/v1/positions", map[string]any{"title": "x"}); got.code != http.StatusNotFound {
|
||||
t.Errorf("%s /api/v1/positions = %d, want 404", m, got.code)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user