1package daemon23import (4 "context"5 "testing"6 "time"78 "github.com/FelineStateMachine/tinyrelay/internal/work"9)1011func TestCustomViewTargetsRejectRecreatedRegistration(t *testing.T) {12 tenant, server, _ := viewTenant(t, []int{1}, nil)13 ctx := context.Background()14 note := signedEvent(t, testOwnerSecret, 1, time.Now().Unix(), nil, "```mermaid\ngraph TD; a-->b;\n```")15 if err := publishAs(t, tenant, note); err != nil {16 t.Fatal(err)17 }18 targets, err := tenant.customViews.CandidateTargets(ctx, note)19 if err != nil || len(targets) != 1 {20 t.Fatalf("candidate targets = %+v, %v", targets, err)21 }22 oldIntents, err := tenant.customViews.PrepareTargets(ctx, note, targets, false)23 if err != nil || len(oldIntents) != 1 {24 t.Fatalf("planned intents = %+v, %v", oldIntents, err)25 }26 if _, err := tenant.Execute(ctx, tenant.Policy().Owner, "removecustomview", viewParams(map[string]any{"name": "diagrams"})); err != nil {27 t.Fatal(err)28 }29 addView(t, tenant, map[string]any{30 "name": "diagrams",31 "kinds": []int{1},32 "transform": "https://render.example/tiny",33 "languages": []string{"mermaid"},34 "secret": "same-secret-value-1234",35 })36 targets, err = tenant.customViews.CandidateTargets(ctx, note)37 if err != nil || len(targets) != 1 {38 t.Fatalf("replacement candidate targets = %+v, %v", targets, err)39 }40 if _, err := tenant.Execute(ctx, tenant.Policy().Owner, "removecustomview", viewParams(map[string]any{"name": "diagrams"})); err != nil {41 t.Fatal(err)42 }43 addView(t, tenant, map[string]any{44 "name": "diagrams",45 "kinds": []int{1},46 "transform": "https://render.example/tiny",47 "languages": []string{"mermaid"},48 "secret": "same-secret-value-1234",49 })50 intents, err := tenant.customViews.PrepareTargets(ctx, note, targets, false)51 if err != nil {52 t.Fatal(err)53 }54 if len(intents) != 0 {55 t.Fatalf("recreated view received old targets: %+v", intents)56 }57 if err := tenant.customViews.handleViewTransform(ctx, work.Intent{ID: "stale", Kind: oldIntents[0].Kind, EventID: oldIntents[0].EventID, Target: oldIntents[0].Target, Payload: oldIntents[0].Payload}); err != nil {58 t.Fatal(err)59 }60 if server.count() != 0 {61 t.Fatalf("stale generation contacted transform: %d requests", server.count())62 }63}6465func TestCustomViewGenerationBackfillIsStable(t *testing.T) {66 tenant, _, _ := viewTenant(t, []int{1}, nil)67 ctx := context.Background()68 if _, err := tenant.store.DB().ExecContext(ctx, `ALTER TABLE custom_views DROP COLUMN generation`); err != nil {69 t.Fatal(err)70 }71 if err := tenant.customViews.initCustomViews(ctx); err != nil {72 t.Fatal(err)73 }74 var first string75 if err := tenant.store.DB().QueryRowContext(ctx, `SELECT generation FROM custom_views WHERE name='diagrams'`).Scan(&first); err != nil {76 t.Fatal(err)77 }78 if first == "" {79 t.Fatal("legacy view generation was not backfilled")80 }81 if err := tenant.customViews.initCustomViews(ctx); err != nil {82 t.Fatal(err)83 }84 var second string85 if err := tenant.store.DB().QueryRowContext(ctx, `SELECT generation FROM custom_views WHERE name='diagrams'`).Scan(&second); err != nil {86 t.Fatal(err)87 }88 if first != second {89 t.Fatalf("generation changed on reopen: %q != %q", first, second)90 }91}