Initial commit of Descrybe v2 without local scratch artifacts.

Drop one-shot tmp/axe scripts and agent i18n scratch so the Gitea tree is deployable.
This commit is contained in:
2026-08-09 22:47:43 +02:00
commit 8580c996c3
1285 changed files with 325780 additions and 0 deletions
@@ -0,0 +1,121 @@
package processing
import (
"context"
"errors"
"os"
"testing"
"time"
"github.com/descrybe/descrybe-v2/apps/api/internal/billing"
"github.com/google/uuid"
"github.com/jackc/pgx/v5/pgxpool"
)
func TestCleanupOrphanProcessedReportAndDelete(t *testing.T) {
dsn := os.Getenv("DATABASE_URL")
if dsn == "" {
t.Skip("DATABASE_URL not set")
}
ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second)
defer cancel()
pg, err := pgxpool.New(ctx, dsn)
if err != nil {
t.Fatal(err)
}
defer pg.Close()
var companyID uuid.UUID
// Prefer a non-A1 company so the A1 cohort guard does not block the delete path.
err = pg.QueryRow(ctx, `
SELECT id FROM companies
WHERE lower(trim(coalesce(legacy_company_id, ''))) <> lower($1)
ORDER BY created_at DESC
LIMIT 1`, billing.A1LegacyCompanyID).Scan(&companyID)
if errorsIsNoRows(err) {
t.Skip("no non-A1 companies available")
}
if err != nil {
t.Fatal(err)
}
rawID := uuid.New()
if _, err := pg.Exec(ctx, `
INSERT INTO raw_products (
id, company_id, gtin, raw_data, mapped_data, is_processed, processing_status
) VALUES ($1, $2, $3, '{}'::jsonb, '{}'::jsonb, false, 'unprocessed')`,
rawID, companyID, "orphan-test-"+rawID.String()[:8]); err != nil {
t.Fatal(err)
}
defer func() {
_, _ = pg.Exec(context.Background(), `DELETE FROM processed_products WHERE raw_product_id = $1`, rawID)
_, _ = pg.Exec(context.Background(), `DELETE FROM raw_products WHERE id = $1`, rawID)
}()
var processedID uuid.UUID
err = pg.QueryRow(ctx, `
INSERT INTO processed_products (
company_id, raw_product_id, product_id, name, status
) VALUES ($1, $2, $3, 'orphan cleanup fixture', 'needs_review')
RETURNING id`, companyID, rawID, "orphan-gtin").Scan(&processedID)
if err != nil {
t.Fatal(err)
}
report, err := ReportOrphanProcessed(ctx, pg)
if err != nil {
t.Fatal(err)
}
if report.Total < 1 {
t.Fatalf("report total=%d want >= 1", report.Total)
}
dry, err := CleanupOrphanProcessed(ctx, pg, false)
if err != nil {
t.Fatal(err)
}
if dry.Confirmed {
t.Fatal("dry-run should leave confirmed=false")
}
if dry.Deleted != 0 {
t.Fatalf("dry-run deleted=%d want 0", dry.Deleted)
}
var stillThere int
if err := pg.QueryRow(ctx, `SELECT COUNT(*) FROM processed_products WHERE id = $1`, processedID).Scan(&stillThere); err != nil {
t.Fatal(err)
}
if stillThere != 1 {
t.Fatalf("fixture row missing before confirm delete")
}
res, err := CleanupOrphanProcessed(ctx, pg, true)
if err != nil {
t.Fatal(err)
}
if res.Deleted < 1 {
t.Fatalf("deleted=%d want >= 1", res.Deleted)
}
if err := pg.QueryRow(ctx, `SELECT COUNT(*) FROM processed_products WHERE id = $1`, processedID).Scan(&stillThere); err != nil {
t.Fatal(err)
}
if stillThere != 0 {
t.Fatalf("fixture row still present after confirm delete")
}
// Fail-closed: confirm with zero remaining orphans must refuse.
after, err := ReportOrphanProcessed(ctx, pg)
if err != nil {
t.Fatal(err)
}
if after.Total != 0 {
t.Logf("skip empty-refuse assert: other orphans remain total=%d", after.Total)
return
}
_, err = CleanupOrphanProcessed(ctx, pg, true)
if !errors.Is(err, ErrOrphanCleanupEmpty) {
t.Fatalf("empty confirm err=%v want ErrOrphanCleanupEmpty", err)
}
}