feat: expand companion platform, device controls, and memoir workflows
ci / verify (push) Canceled after 0s
ci / verify (push) Canceled after 0s
Add customer and operator login, BLE provisioning, device fleet controls, call memory, memoir generation, and refreshed family and maintenance portals. Include API contracts, migrations, firmware sources, tests, assets, and deployment documentation.
This commit is contained in:
@@ -0,0 +1,76 @@
|
||||
package dataexport
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/jackc/pgx/v5/pgxpool"
|
||||
)
|
||||
|
||||
func TestDirectStoryExportIncludesNativeEvidenceAndHonorsAvailability(t *testing.T) {
|
||||
url := os.Getenv("TEST_DATABASE_URL")
|
||||
if url == "" {
|
||||
t.Skip("TEST_DATABASE_URL required")
|
||||
}
|
||||
ctx := context.Background()
|
||||
pool, err := pgxpool.New(ctx, url)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer pool.Close()
|
||||
exec := func(query string, args ...any) {
|
||||
t.Helper()
|
||||
if _, err := pool.Exec(ctx, query, args...); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
subject, session, story, revision := uuid.NewString(), uuid.NewString(), uuid.NewString(), uuid.NewString()
|
||||
const tenant = "10000000-0000-0000-0000-000000000001"
|
||||
exec(`INSERT INTO subject_profile(id,tenant_id,household_id,preferred_name,status) VALUES($1::uuid,$2::uuid,'10000000-0000-0000-0000-000000000201','native-export','active')`, subject, tenant)
|
||||
exec(`INSERT INTO memory_user_state(subject_id,tenant_id) VALUES($1::uuid,$2::uuid)`, subject, tenant)
|
||||
exec(`INSERT INTO consent_record(tenant_id,subject_id,consent_type,scope,policy_version,notice_digest,actor_user_id,evidence_ref) SELECT tenant_id,$1::uuid,consent_type,scope,policy_version,notice_digest,actor_user_id,evidence_ref FROM consent_record WHERE subject_id='10000000-0000-0000-0000-000000000401' AND withdrawn_at IS NULL`, subject)
|
||||
exec(`INSERT INTO call_session(id,device_id,tenant_id,subject_id,boot_id,hook_event_id,call_generation,binding_generation,call_state,transcript_state,transcript_revision,budget_snapshot,ended_at) VALUES($1::uuid,'10000000-0000-0000-0000-000000000501',$2::uuid,$3::uuid,$1::uuid,$1,0,0,'ENDED','COMPLETE',1,'{"protocol":"DIRECT-CHAT-1","story_extraction_allowed":true}',now())`, session, tenant, subject)
|
||||
exec(`INSERT INTO call_utterance(session_id,utterance_id,source_revision,speaker,text_content,interrupted,source_at) VALUES($1::uuid,'native-evidence',1,'USER','小时候和爷爷一起种树。',false,now())`, session)
|
||||
exec(`INSERT INTO story_draft(id,tenant_id,subject_id,call_session_id,call_privacy_epoch,title,generation_version) VALUES($1::uuid,$2::uuid,$3::uuid,$4::uuid,0,'和爷爷种树',1)`, story, tenant, subject, session)
|
||||
exec(`INSERT INTO story_revision(id,story_id,revision_no,content,author_type) VALUES($1::uuid,$2::uuid,1,'小时候和爷爷一起种树。','model')`, revision, story)
|
||||
exec(`INSERT INTO story_source(story_revision_id,call_session_id,call_utterance_id,call_source_revision,source_role) VALUES($1::uuid,$2::uuid,'native-evidence',1,'subject')`, revision, session)
|
||||
exec(`UPDATE story_draft SET current_revision_id=$2::uuid WHERE id=$1::uuid`, story, revision)
|
||||
processor, err := NewProcessor(pool, &exportTestStore{}, time.Hour)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
type exportedStory struct {
|
||||
Session string `json:"call_session_id"`
|
||||
Conversation *string `json:"conversation_id"`
|
||||
Sources []struct {
|
||||
Session string `json:"call_session_id"`
|
||||
Utterance string `json:"utterance_id"`
|
||||
Revision int64 `json:"source_revision"`
|
||||
Text string `json:"text"`
|
||||
} `json:"sources"`
|
||||
}
|
||||
read := func() []exportedStory {
|
||||
t.Helper()
|
||||
raw, err := processor.collectCategory(ctx, "stories", tenant, subject)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
var items []exportedStory
|
||||
if err := json.Unmarshal(raw, &items); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return items
|
||||
}
|
||||
items := read()
|
||||
if len(items) != 1 || items[0].Session != session || items[0].Conversation != nil || len(items[0].Sources) != 1 || items[0].Sources[0].Session != session || items[0].Sources[0].Utterance != "native-evidence" || items[0].Sources[0].Revision != 1 || items[0].Sources[0].Text != "小时候和爷爷一起种树。" {
|
||||
t.Fatalf("native export=%+v", items)
|
||||
}
|
||||
exec(`UPDATE call_utterance SET source_revision=2 WHERE session_id=$1::uuid`, session)
|
||||
if items := read(); len(items) != 0 {
|
||||
t.Fatalf("stale source export=%+v", items)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user