fix(02-03): re-record on --update and honor case capture rules
Ordered PHP self-replay needs regenerated share tokens captured into vars, and --update must overwrite already-recorded route fixtures. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -65,6 +65,7 @@ type RouteCase struct {
|
|||||||
Headers map[string]string `yaml:"headers,omitempty"`
|
Headers map[string]string `yaml:"headers,omitempty"`
|
||||||
Fixture string `yaml:"fixture,omitempty"`
|
Fixture string `yaml:"fixture,omitempty"`
|
||||||
Request *Request `yaml:"request,omitempty"`
|
Request *Request `yaml:"request,omitempty"`
|
||||||
|
Capture []CaptureRule `yaml:"capture,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ManifestConfig drives recording or replay of a manifest.
|
// ManifestConfig drives recording or replay of a manifest.
|
||||||
@@ -296,7 +297,7 @@ func RecordManifest(ctx context.Context, m Manifest, cfg ManifestConfig) (Covera
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if allRecorded {
|
if allRecorded && !cfg.Update {
|
||||||
cov.markRecorded(route)
|
cov.markRecorded(route)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -396,6 +397,7 @@ func recordRoute(ctx context.Context, route Route, cfg ManifestConfig) error {
|
|||||||
ID: c.ID,
|
ID: c.ID,
|
||||||
RouteID: route.ID,
|
RouteID: route.ID,
|
||||||
Request: caseRequest(route, c),
|
Request: caseRequest(route, c),
|
||||||
|
Capture: c.Capture,
|
||||||
Normalize: route.Normalize,
|
Normalize: route.Normalize,
|
||||||
Headers: mergeHeaders(route.Headers, c.Headers),
|
Headers: mergeHeaders(route.Headers, c.Headers),
|
||||||
}},
|
}},
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
@@ -406,3 +407,69 @@ func TestRecordSeedResolvesRelativeSpec(t *testing.T) {
|
|||||||
t.Fatalf("existing seed must not re-hit PHP: %d", hits)
|
t.Fatalf("existing seed must not re-hit PHP: %d", hits)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRecordManifestUpdateRerecords(t *testing.T) {
|
||||||
|
fixtures := t.TempDir()
|
||||||
|
hits := 0
|
||||||
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
hits++
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
_, _ = w.Write([]byte(`{"n":` + strconv.Itoa(hits) + `}`))
|
||||||
|
}))
|
||||||
|
t.Cleanup(srv.Close)
|
||||||
|
m := Manifest{
|
||||||
|
Version: 1,
|
||||||
|
AuthGroups: []string{"public"},
|
||||||
|
Routes: []Route{{
|
||||||
|
ID: "GET /x public", Method: http.MethodGet, Path: "/x",
|
||||||
|
AuthGroup: "public", Status: StatusPending,
|
||||||
|
Cases: []RouteCase{{
|
||||||
|
ID: "ok", Status: 200, Fixture: "routes/x.yaml",
|
||||||
|
Request: &Request{Method: http.MethodGet, Path: "/x"},
|
||||||
|
}},
|
||||||
|
}},
|
||||||
|
}
|
||||||
|
if _, err := RecordManifest(context.Background(), m, ManifestConfig{Target: srv.URL, Fixtures: fixtures, Resume: true}); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if _, err := RecordManifest(context.Background(), m, ManifestConfig{Target: srv.URL, Fixtures: fixtures, Resume: true, Update: true}); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if hits != 2 {
|
||||||
|
t.Fatalf("update must recapture, hits=%d", hits)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRouteCaseCaptureUpdatesStore(t *testing.T) {
|
||||||
|
fixtures := t.TempDir()
|
||||||
|
vars := filepath.Join(t.TempDir(), "vars.yaml")
|
||||||
|
store, err := OpenStore(vars)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
_, _ = w.Write([]byte(`{"data":{"token":"shareTokValue99"}}`))
|
||||||
|
}))
|
||||||
|
t.Cleanup(srv.Close)
|
||||||
|
m := Manifest{
|
||||||
|
Version: 1,
|
||||||
|
AuthGroups: []string{"public"},
|
||||||
|
Routes: []Route{{
|
||||||
|
ID: "POST /share public", Method: http.MethodPost, Path: "/share",
|
||||||
|
AuthGroup: "public", Status: StatusPending,
|
||||||
|
Cases: []RouteCase{{
|
||||||
|
ID: "ok", Status: 200, Fixture: "routes/share.yaml",
|
||||||
|
Request: &Request{Method: http.MethodPost, Path: "/share"},
|
||||||
|
Capture: []CaptureRule{{From: "response.json", Path: "$.data.token", As: "share:collection"}},
|
||||||
|
}},
|
||||||
|
}},
|
||||||
|
}
|
||||||
|
if _, err := RecordManifest(context.Background(), m, ManifestConfig{Target: srv.URL, Fixtures: fixtures, Store: store}); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
got, ok := store.Get("share:collection")
|
||||||
|
if !ok || got != "shareTokValue99" {
|
||||||
|
t.Fatalf("capture: ok=%v val=%q", ok, got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user