init
Release Please / release-please (push) Failing after 4m2s
Web CI / web typecheck + build (push) Successful in 3m39s
CodeQL Analysis / Analyze (javascript-typescript) (push) Failing after 1h1m49s
CodeQL Analysis / Analyze (go) (push) Failing after 1h1m49s

This commit is contained in:
redlineo committed 2026-07-13 10:14:00 +03:00
commit d295c7f139
1527 files changed
+270726

No files matched your search

+266
View File
@@ -0,0 +1,266 @@
package data
import (
"os"
"path/filepath"
"strings"
"testing"
)
// Regression for #1180: a status word appearing as a substring of an earlier
// cell (Company "Applied Materials" contains "Applied") must not be rewritten;
// only the Status column changes.
func TestUpdateApplicationStatusOnlyRewritesStatusColumn(t *testing.T) {
tempDir := t.TempDir()
dataDir := filepath.Join(tempDir, "data")
if err := os.MkdirAll(dataDir, 0o755); err != nil {
t.Fatalf("failed to create data dir: %v", err)
}
applications := `# Applications Tracker
| # | Date | Company | Role | Score | Status | PDF | Report | Notes |
|---|------|---------|------|-------|--------|-----|--------|-------|
| 7 | 2026-06-23 | Applied Materials | Staff Android Engineer | 4.2/5 | Applied | ✅ | [7](reports/007.md) | substring trap |
`
path := filepath.Join(dataDir, "applications.md")
if err := os.WriteFile(path, []byte(applications), 0o644); err != nil {
t.Fatalf("failed to write tracker: %v", err)
}
apps := ParseApplications(tempDir)
if len(apps) != 1 {
t.Fatalf("expected 1 parsed application, got %d", len(apps))
}
if err := UpdateApplicationStatus(tempDir, apps[0], "Interview"); err != nil {
t.Fatalf("UpdateApplicationStatus: %v", err)
}
got, err := os.ReadFile(path)
if err != nil {
t.Fatalf("read back: %v", err)
}
out := string(got)
if !strings.Contains(out, "| Applied Materials |") {
t.Errorf("Company cell was corrupted, file now:\n%s", out)
}
if !strings.Contains(out, "| Interview |") {
t.Errorf("Status cell was not updated to Interview, file now:\n%s", out)
}
if strings.Contains(out, "Interview Materials") {
t.Errorf("status word was replaced inside the Company cell, file now:\n%s", out)
}
reparsed := ParseApplications(tempDir)
if reparsed[0].Company != "Applied Materials" {
t.Errorf("company = %q, want \"Applied Materials\"", reparsed[0].Company)
}
if reparsed[0].Status != "Interview" {
t.Errorf("status = %q, want \"Interview\"", reparsed[0].Status)
}
}
func TestParseApplicationsUsesTrackerNumberColumn(t *testing.T) {
tempDir := t.TempDir()
dataDir := filepath.Join(tempDir, "data")
if err := os.MkdirAll(dataDir, 0o755); err != nil {
t.Fatalf("failed to create data dir: %v", err)
}
applications := `# Applications Tracker
| # | Date | Company | Role | Score | Status | PDF | Report | Notes |
|---|------|---------|------|-------|--------|-----|--------|-------|
| 140 | 2026-04-16 | Arize AI | AI Engineer, Instrumentation | 4.7/5 | Evaluated | ✅ | [140](reports/140-arize-ai-engineer-instrumentation-2026-04-16.md) | Strong fit |
| 143 | 2026-04-16 | Arize AI | AI Sales Engineer, US | 4.1/5 | Evaluated | ❌ | [143](reports/143-arize-ai-sales-engineer-us-2026-04-16.md) | Good fit |
`
applicationsPath := filepath.Join(dataDir, "applications.md")
if err := os.WriteFile(applicationsPath, []byte(applications), 0o644); err != nil {
t.Fatalf("failed to write applications tracker: %v", err)
}
apps := ParseApplications(tempDir)
if len(apps) != 2 {
t.Fatalf("expected 2 parsed applications, got %d", len(apps))
}
if apps[0].Number != 140 {
t.Fatalf("expected first application number to be 140, got %d", apps[0].Number)
}
if apps[1].Number != 143 {
t.Fatalf("expected second application number to be 143, got %d", apps[1].Number)
}
if apps[0].ReportNumber != "140" || apps[1].ReportNumber != "143" {
t.Fatalf("expected report numbers to stay aligned with tracker IDs, got %q and %q", apps[0].ReportNumber, apps[1].ReportNumber)
}
}
func TestParseApplicationsResolvesTrackerRelativeReportLinks(t *testing.T) {
tempDir := t.TempDir()
dataDir := filepath.Join(tempDir, "data")
reportsDir := filepath.Join(tempDir, "reports")
for _, dir := range []string{dataDir, reportsDir} {
if err := os.MkdirAll(dir, 0o755); err != nil {
t.Fatalf("failed to create dir %s: %v", dir, err)
}
}
// Tracker links are written relative to the tracker file itself
// (merge-tracker.mjs normalization): ../reports/... when the tracker
// lives under data/. Legacy trackers may still carry root-relative
// links; both must resolve to the same on-disk report.
applications := `# Applications Tracker
| # | Date | Company | Role | Score | Status | PDF | Report | Notes |
|---|------|---------|------|-------|--------|-----|--------|-------|
| 1 | 2026-06-03 | Acme | Engineer | 4.0/5 | Evaluated | ✅ | [1](../reports/001-acme-2026-06-03.md) | Tracker-relative link |
| 2 | 2026-06-03 | Legacy Co | Engineer | 3.0/5 | Evaluated | ❌ | [2](reports/002-legacy-2026-06-03.md) | Legacy root-relative link |
`
if err := os.WriteFile(filepath.Join(dataDir, "applications.md"), []byte(applications), 0o644); err != nil {
t.Fatalf("failed to write applications tracker: %v", err)
}
for _, name := range []string{"001-acme-2026-06-03.md", "002-legacy-2026-06-03.md"} {
if err := os.WriteFile(filepath.Join(reportsDir, name), []byte("# Report\n"), 0o644); err != nil {
t.Fatalf("failed to write report %s: %v", name, err)
}
}
apps := ParseApplications(tempDir)
if len(apps) != 2 {
t.Fatalf("expected 2 parsed applications, got %d", len(apps))
}
wantFirst := filepath.Join("reports", "001-acme-2026-06-03.md")
if apps[0].ReportPath != wantFirst {
t.Fatalf("expected tracker-relative link to resolve to %q, got %q", wantFirst, apps[0].ReportPath)
}
wantSecond := filepath.Join("reports", "002-legacy-2026-06-03.md")
if apps[1].ReportPath != wantSecond {
t.Fatalf("expected legacy root-relative link to resolve to %q, got %q", wantSecond, apps[1].ReportPath)
}
// Every consumer joins ReportPath against careerOpsPath — both rows
// must point at files that exist.
for i, app := range apps {
if _, err := os.Stat(filepath.Join(tempDir, app.ReportPath)); err != nil {
t.Fatalf("row %d: resolved report path %q does not exist: %v", i, app.ReportPath, err)
}
}
}
// writeTracker writes applications.md under data/ and returns the temp root and
// the tracker path.
func writeTracker(t *testing.T, body string) (string, string) {
t.Helper()
tempDir := t.TempDir()
dataDir := filepath.Join(tempDir, "data")
if err := os.MkdirAll(dataDir, 0o755); err != nil {
t.Fatalf("mkdir: %v", err)
}
path := filepath.Join(dataDir, "applications.md")
if err := os.WriteFile(path, []byte(body), 0o644); err != nil {
t.Fatalf("write tracker: %v", err)
}
return tempDir, path
}
const insertedColumnTracker = `# Applications Tracker
| # | Date | Company | Role | Location | Score | Status | PDF | Report | Notes |
|---|------|---------|------|----------|-------|--------|-----|--------|-------|
| 1 | 2026-06-01 | Acme | VP Marketing | Remote | 4.5/5 | Applied | ✅ | [1](reports/001.md) | hot lead |
`
// A tracker with a Location column inserted before Score (the customized layout
// the Node tracker tooling supports since #954) must not desync the Go reader.
// Without header-aware mapping, Status reads the Score cell and the report link
// reads the PDF cell, so ReportNumber comes back empty.
func TestParseApplicationsMapsColumnsByHeader(t *testing.T) {
tempDir, _ := writeTracker(t, insertedColumnTracker)
apps := ParseApplications(tempDir)
if len(apps) != 1 {
t.Fatalf("expected 1 application, got %d", len(apps))
}
a := apps[0]
if a.Company != "Acme" {
t.Errorf("Company = %q, want \"Acme\"", a.Company)
}
if a.Role != "VP Marketing" {
t.Errorf("Role = %q, want \"VP Marketing\"", a.Role)
}
if a.Status != "Applied" {
t.Errorf("Status = %q, want \"Applied\"", a.Status)
}
if a.ScoreRaw != "4.5/5" {
t.Errorf("ScoreRaw = %q, want \"4.5/5\"", a.ScoreRaw)
}
if !a.HasPDF {
t.Errorf("HasPDF = false, want true")
}
if a.ReportNumber != "1" {
t.Errorf("ReportNumber = %q, want \"1\"", a.ReportNumber)
}
}
// End-to-end status update on the inserted-column layout: parse, update, and
// re-parse. Only the Status cell may change; every other cell stays intact.
func TestUpdateApplicationStatusInsertedColumn(t *testing.T) {
tempDir, path := writeTracker(t, insertedColumnTracker)
apps := ParseApplications(tempDir)
if len(apps) != 1 {
t.Fatalf("expected 1 application, got %d", len(apps))
}
if err := UpdateApplicationStatus(tempDir, apps[0], "Interview"); err != nil {
t.Fatalf("UpdateApplicationStatus: %v", err)
}
out, err := os.ReadFile(path)
if err != nil {
t.Fatalf("read back: %v", err)
}
got := string(out)
if !strings.Contains(got, "| Interview |") {
t.Errorf("Status cell not updated to Interview, file now:\n%s", got)
}
if strings.Count(got, "Interview") != 1 {
t.Errorf("write touched an unintended cell; %d occurrences of Interview:\n%s", strings.Count(got, "Interview"), got)
}
for _, cell := range []string{"| Acme |", "| VP Marketing |", "| Remote |", "| 4.5/5 |", "| ✅ |"} {
if !strings.Contains(got, cell) {
t.Errorf("expected intact cell %q missing after write:\n%s", cell, got)
}
}
reparsed := ParseApplications(tempDir)
if reparsed[0].Status != "Interview" {
t.Errorf("reparsed Status = %q, want \"Interview\"", reparsed[0].Status)
}
if reparsed[0].ScoreRaw != "4.5/5" {
t.Errorf("reparsed ScoreRaw = %q, want \"4.5/5\"", reparsed[0].ScoreRaw)
}
}
// resolveTrackerColumns detects the header layout, and falls back to the legacy
// fixed layout when no recognizable header row is present.
func TestResolveTrackerColumns(t *testing.T) {
header := strings.Split(insertedColumnTracker, "\n")
cols := resolveTrackerColumns(header)
if cols["status"] != 6 {
t.Errorf("status index = %d, want 6 (inserted Location column)", cols["status"])
}
if cols["score"] != 5 {
t.Errorf("score index = %d, want 5", cols["score"])
}
headerless := []string{"| 1 | 2026-06-01 | Acme | VP Marketing | 4.5/5 | Applied | ✅ | [1](reports/001.md) | note |"}
fallback := resolveTrackerColumns(headerless)
if fallback["status"] != 5 {
t.Errorf("fallback status index = %d, want 5 (legacy layout)", fallback["status"])
}
}