Files
apex-public/internal/scan/scan_test.go
T
2026-07-06 11:05:50 -04:00

119 lines
3.3 KiB
Go

package scan
import (
"context"
"database/sql"
"testing"
_ "modernc.org/sqlite"
)
func TestDetectAdapter_Greenhouse(t *testing.T) {
c := Company{
Name: "Dragos",
CareersURL: "https://job-boards.greenhouse.io/dragos",
API: "https://boards-api.greenhouse.io/v1/boards/dragos/jobs",
}
info, ok := DetectAdapter(c)
if !ok || info.Type != AdapterGreenhouse {
t.Fatalf("expected greenhouse, got %v ok=%v", info.Type, ok)
}
}
func TestDetectAdapter_Ashby(t *testing.T) {
c := Company{Name: "Acme", CareersURL: "https://jobs.ashbyhq.com/acme"}
info, ok := DetectAdapter(c)
if !ok || info.Type != AdapterAshby {
t.Fatalf("expected ashby, got %v ok=%v", info.Type, ok)
}
}
func TestDetectAdapter_Lever(t *testing.T) {
c := Company{Name: "Acme", CareersURL: "https://jobs.lever.co/acme"}
info, ok := DetectAdapter(c)
if !ok || info.Type != AdapterLever {
t.Fatalf("expected lever, got %v ok=%v", info.Type, ok)
}
}
func TestDetectAdapter_Unknown(t *testing.T) {
c := Company{Name: "Acme", CareersURL: "https://acme.com/careers"}
_, ok := DetectAdapter(c)
if ok {
t.Fatalf("expected unsupported for arbitrary careers page")
}
}
func TestTitleMatcher_PositiveOnly(t *testing.T) {
m := NewTitleMatcher(TitleFilter{Positive: []string{"Red Team", "Penetration Test"}})
if !m("Senior Red Team Operator") {
t.Fatal("expected match")
}
if m("Senior Software Engineer") {
t.Fatal("expected no match")
}
}
func TestTitleMatcher_NegativeBlocks(t *testing.T) {
m := NewTitleMatcher(TitleFilter{
Positive: []string{"Security"},
Negative: []string{"Intern", "Junior"},
})
if m("Security Intern") {
t.Fatal("negative should block")
}
if !m("Security Engineer") {
t.Fatal("positive should match")
}
}
func TestRecordJobs_BatchDedup(t *testing.T) {
db, err := sql.Open("sqlite", ":memory:")
if err != nil {
t.Fatal(err)
}
defer db.Close()
if _, err := db.Exec(`
CREATE TABLE jobs (url TEXT UNIQUE NOT NULL, company TEXT, title TEXT, source TEXT);
CREATE TABLE scanned_urls (url TEXT UNIQUE NOT NULL, company TEXT, title TEXT, source TEXT, status TEXT, first_seen TIMESTAMP DEFAULT CURRENT_TIMESTAMP, last_seen TIMESTAMP DEFAULT CURRENT_TIMESTAMP);
`); err != nil {
t.Fatal(err)
}
r := &Runner{DB: db}
ctx := context.Background()
batch := []Job{
{Title: "Senior Red Team", URL: "https://example.com/jobs/1", Company: "Acme", Source: "test"},
{Title: "Staff Pentester", URL: "https://example.com/jobs/2", Company: "Acme", Source: "test"},
}
newJobs, err := r.recordJobs(ctx, batch)
if err != nil {
t.Fatalf("first batch: %v", err)
}
if len(newJobs) != 2 {
t.Fatalf("expected 2 new, got %d", len(newJobs))
}
// Re-run the same batch plus one fresh URL — only the new one should land.
batch = append(batch, Job{Title: "Principal OT", URL: "https://example.com/jobs/3", Company: "Acme", Source: "test"})
newJobs, err = r.recordJobs(ctx, batch)
if err != nil {
t.Fatalf("second batch: %v", err)
}
if len(newJobs) != 1 || newJobs[0].URL != "https://example.com/jobs/3" {
t.Fatalf("expected only jobs/3 new, got %+v", newJobs)
}
}
func TestLoadConfig(t *testing.T) {
cfg, err := LoadConfig("adapters.yaml")
if err != nil {
t.Fatalf("LoadConfig: %v", err)
}
if len(cfg.TrackedCompanies) == 0 {
t.Fatal("expected seeded companies")
}
if len(cfg.TitleFilter.Positive) == 0 {
t.Fatal("expected positive keywords")
}
}