textmachine/backend/internal/pipeline/checks_integration_test.go

69 lines
2.5 KiB
Go

package pipeline
// checks_integration_test.go: the driver-side fixtures for the check subsystems — the ones that need a
// live Runner (a cheap-gate count must reach the persisted retrieval-state and the status report) or the
// memory bank (the DC3 gender constraint is rendered by the bank's injection renderer). The pure
// per-rule fixtures live with their rules in internal/checks.
import (
"context"
"testing"
"textmachine/backend/internal/lang"
)
// testLangPack loads the real in-repo zh→ru language pack (configs/langpacks/) for the driver-side
// fixtures that need pair data. The book-scoped overlay (internal/miner/testdata) is deliberately NOT
// loaded: it adds only the 蛊真人 clan surname, which no checker or seed fixture reads — the miner keeps
// its own overlay-loading helper for the surname-anchored cases.
func testLangPack(t *testing.T) *lang.Pack {
t.Helper()
p, err := lang.Load("../../configs/langpacks", "zh", "ru")
if err != nil {
t.Fatalf("load langpack: %v", err)
}
return p
}
// TestCheapGatesSurfaceInStatus is the end-to-end wiring test: a chunk whose FINAL text has a style
// issue (a hyphen-led dialogue line) records a style flag in retrieval_state and surfaces it in the
// status projection — WITHOUT flagging the chunk (observability, never a disposition).
func TestCheapGatesSurfaceInStatus(t *testing.T) {
rec := &reqRec{}
srv := newJSONProvider(rec, func(body string) (string, string) {
if isEditBody(body) {
return "- Привет, — сказал он.", "stop" // hyphen dialogue → dialogue-dash flag
}
return "ЧЕРНОВИК ПЕРЕВОДА", "stop"
})
defer srv.Close()
bookPath := setupProjectOpts(t, srv.URL, projectOpts{source: "テキスト。", regenerate: 0})
ctx := context.Background()
r := newRunner(t, bookPath)
defer r.Close()
res, err := r.TranslateBook(ctx)
if err != nil {
t.Fatal(err)
}
if res.Flagged != 0 {
t.Fatalf("a style flag must not flag the chunk (observability only), got flagged=%d", res.Flagged)
}
rs, err := r.Store.GetRetrievalState("test-book", 1, 0)
if err != nil || rs == nil {
t.Fatalf("no retrieval state persisted: %v", err)
}
if rs.NStyleFlags == 0 {
t.Fatalf("style flag not persisted in retrieval_state: %+v", rs)
}
rep, err := r.Status(ctx)
if err != nil {
t.Fatal(err)
}
if rep.StyleFlags == 0 {
t.Fatal("status must surface the book-wide style-flag count")
}
if rep.Done != 1 || rep.Flagged != 0 {
t.Fatalf("the chunk must be done, not flagged: done=%d flagged=%d", rep.Done, rep.Flagged)
}
}