feat(11.1-04): add the Backend section, the remaining Services pages and the concept map links
- docs/backend: admin controllers, forms, lists and filters, relation manager, users and permissions, settings, partials and widgets, admin SPA - docs/services: storage, outbound HTTP, realtime, Web Push, search, parity testing and the Frontend and AJAX (not provided) page - Examples for cabana (with testdata/docs YAML), fetchguard, lighthouse and its centrifugo driver, flare, beachcomber and typesense, tide; lighthouse and beachcomber TestDocs* regions run on their Postgres harnesses - concept map rows link their guide pages and the not-provided rows the Frontend and AJAX page; index lists Backend, Database and Services - TestDocsRequiredPages asserts the D-08 section order
This commit is contained in:
69
modules/tide/example_test.go
Normal file
69
modules/tide/example_test.go
Normal file
@@ -0,0 +1,69 @@
|
||||
package tide_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
|
||||
"git.golem15.com/golem15/summercms/modules/tide"
|
||||
)
|
||||
|
||||
// backend stands in for one implementation of GET /api/blog/posts.
|
||||
func backend(body string) *httptest.Server {
|
||||
return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
fmt.Fprint(w, body)
|
||||
}))
|
||||
}
|
||||
|
||||
func ExampleReplayFlow() {
|
||||
ctx := context.Background()
|
||||
// The reference (PHP) backend and two Go ports. IDs and *_at timestamps
|
||||
// legitimately differ; the second port changed a title.
|
||||
reference := backend(`{"data":[{"id":12,"title":"Hello","created_at":"2026-09-30T10:00:00+00:00"}]}`)
|
||||
defer reference.Close()
|
||||
port := backend(`{"data":[{"id":3,"title":"Hello","created_at":"2026-10-01T08:30:00+00:00"}]}`)
|
||||
defer port.Close()
|
||||
broken := backend(`{"data":[{"id":3,"title":"hello","created_at":"2026-10-01T08:30:00+00:00"}]}`)
|
||||
defer broken.Close()
|
||||
|
||||
raw, err := os.ReadFile("testdata/docs/posts-spec.yaml")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
spec, err := tide.ParseFlow(raw)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
// Record the reference once; the flow is what testdata/parity keeps.
|
||||
flow, err := tide.RecordFlow(ctx, spec, tide.RecordConfig{Target: reference.URL})
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
for _, target := range []string{port.URL, broken.URL} {
|
||||
res, err := tide.ReplayFlow(ctx, flow, tide.ReplayConfig{Target: target})
|
||||
var mismatch *tide.MismatchError
|
||||
if errors.As(err, &mismatch) {
|
||||
res = mismatch.Result // a difference is an error carrying the result
|
||||
} else if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
fmt.Println("ok:", res.OK)
|
||||
for _, step := range res.Steps {
|
||||
for _, d := range step.Diffs {
|
||||
fmt.Printf(" %s %s: want %s, got %s\n", step.ID, d.Path, d.Expected, d.Actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
// Output:
|
||||
// ok: true
|
||||
// ok: false
|
||||
// list-posts $.data[0].title: want "Hello", got "hello"
|
||||
}
|
||||
Reference in New Issue
Block a user