package controllers import ( "context" "net/http" "net/http/httptest" "sync/atomic" "testing" "git.golem15.com/golem15/summercms/modules/backpack" "git.golem15.com/golem15/summercms/modules/compass" "git.golem15.com/golem15/summercms/modules/cooler" ) const purgeHelperToken = "controllers-purge-helper-token-0123456789" // purgeCounter is a purge receiver that counts requests. func purgeCounter(t *testing.T) (*httptest.Server, *atomic.Int64) { t.Helper() var hits atomic.Int64 srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { hits.Add(1) _, _ = w.Write([]byte(`{"purged":1}`)) })) t.Cleanup(srv.Close) return srv, &hits } // helperApp returns an app on a config without a database, with the // framework purge keys pointing at purgeURL when it is not empty. func helperApp(t *testing.T, purgeURL string) *backpack.App { t.Helper() cfg, err := compass.Open(compass.Options{Dir: t.TempDir(), Environ: []string{}}) if err != nil { t.Fatal(err) } if purgeURL != "" { if err := cfg.Set(cooler.SiteCachePurgeURLKey, purgeURL); err != nil { t.Fatal(err) } if err := cfg.Set(cooler.SiteCachePurgeTokenKey, purgeHelperToken); err != nil { t.Fatal(err) } } return backpack.New(cfg) } // TestPurgeSiteCacheWithoutTx: outside a save transaction the helper sends // nothing, even with a purger configured; a purge only ever follows a commit. func TestPurgeSiteCacheWithoutTx(t *testing.T) { srv, hits := purgeCounter(t) app := helperApp(t, srv.URL+"/api/__site__/cache/purge") if cooler.SiteCacheFromApp(app) == nil { t.Fatal("the test purger is not configured") } get := func() *backpack.App { return app } purgeSiteCache(context.Background(), get, "faq", "shipping") purgeSiteCache(context.TODO(), get, "menu", "main") if n := hits.Load(); n != 0 { t.Fatalf("%d purge requests outside a transaction, want 0", n) } } // TestPurgeSiteCacheWithoutPurger: without an app or a purge configuration // the helper does nothing and never panics. (Inside a save transaction // without a purger, the plugin's Docker admin suites run every save through // it.) func TestPurgeSiteCacheWithoutPurger(t *testing.T) { ctx := context.Background() purgeSiteCache(ctx, nil, "faq", "a") purgeSiteCache(ctx, func() *backpack.App { return nil }, "faq", "b") app := helperApp(t, "") purgeSiteCache(ctx, func() *backpack.App { return app }, "faq", "c") if p, ok := app.Lookup[*cooler.SiteCachePurger](); ok && p != nil { t.Fatal("the helper published a purger without configuration") } }