[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill-encore-encore-go-testing":3,"mdc-5vpy7w-key":37,"related-repo-encore-encore-go-testing":2575,"related-org-encore-encore-go-testing":2678},{"slug":4,"name":4,"fn":5,"description":6,"org":7,"tags":12,"stars":24,"repoUrl":25,"updatedAt":26,"license":27,"forks":28,"topics":29,"repo":32,"sourceUrl":35,"mdContent":36},"encore-go-testing","test APIs and services with Encore Go","Write or run automated tests for Encore Go code with `encore test` and the standard library `testing` package. Covers isolated per-test databases, calling handlers directly, and `*testing.T` patterns.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},"encore","Encore","https:\u002F\u002Fpexgzepcugksgbtrxkhf.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Forg-logos\u002Fencore.png","encoredev",[13,15,18,21],{"name":9,"slug":8,"type":14},"tag",{"name":16,"slug":17,"type":14},"API Development","api-development",{"name":19,"slug":20,"type":14},"Testing","testing",{"name":22,"slug":23,"type":14},"Go","go",26,"https:\u002F\u002Fgithub.com\u002Fencoredev\u002Fskills","2026-04-06T18:09:57.338252",null,5,[30,31],"claude-code","skills",{"repoUrl":25,"stars":24,"forks":28,"topics":33,"description":34},[30,31],"Agent Skills for development with Encore.","https:\u002F\u002Fgithub.com\u002Fencoredev\u002Fskills\u002Ftree\u002FHEAD\u002Fencore\u002Fgo-testing","---\nname: encore-go-testing\ndescription: Write or run automated tests for Encore Go code with `encore test` and the standard library `testing` package. Covers isolated per-test databases, calling handlers directly, and `*testing.T` patterns.\nwhen_to_use: >-\n  User wants to add\u002Fwrite\u002Ffix a test in Go, write a `*_test.go` file, test an endpoint or service, set up `encore test`, configure isolated test databases, write `t.Cleanup`\u002F`t.Helper` for db cleanup, mock external dependencies, or assert on API request\u002Fresponse behaviour. Trigger phrases: \"write a Go test\", \"add tests for\", \"go test\", \"encore test\", \"test the endpoint\", \"test the service\", \"integration test\", \"isolated database\".\n---\n\n# Testing Encore Go Applications\n\n## Instructions\n\nEncore Go uses standard Go testing with `encore test`.\n\n### Run Tests\n\n```bash\n# Run all tests with Encore (recommended)\nencore test .\u002F...\n\n# Run tests for a specific package\nencore test .\u002Fuser\u002F...\n\n# Run with verbose output\nencore test -v .\u002F...\n```\n\nUsing `encore test` instead of `go test` is recommended because it:\n- Sets up test databases automatically\n- Provides isolated infrastructure per test\n- Handles service dependencies\n\n### Test an API Endpoint\n\n```go\n\u002F\u002F hello\u002Fhello_test.go\npackage hello\n\nimport (\n    \"context\"\n    \"testing\"\n)\n\nfunc TestHello(t *testing.T) {\n    ctx := context.Background()\n    \n    resp, err := Hello(ctx)\n    if err != nil {\n        t.Fatalf(\"unexpected error: %v\", err)\n    }\n    \n    if resp.Message != \"Hello, World!\" {\n        t.Errorf(\"expected 'Hello, World!', got '%s'\", resp.Message)\n    }\n}\n```\n\n### Test with Request Parameters\n\n```go\n\u002F\u002F user\u002Fuser_test.go\npackage user\n\nimport (\n    \"context\"\n    \"testing\"\n)\n\nfunc TestGetUser(t *testing.T) {\n    ctx := context.Background()\n    \n    user, err := GetUser(ctx, &GetUserParams{ID: \"123\"})\n    if err != nil {\n        t.Fatalf(\"unexpected error: %v\", err)\n    }\n    \n    if user.ID != \"123\" {\n        t.Errorf(\"expected ID '123', got '%s'\", user.ID)\n    }\n}\n```\n\n### Test Database Operations\n\nEncore provides isolated test databases:\n\n```go\n\u002F\u002F user\u002Fuser_test.go\npackage user\n\nimport (\n    \"context\"\n    \"testing\"\n    \n    \"encore.dev\u002Fstorage\u002Fsqldb\"\n)\n\nfunc TestCreateUser(t *testing.T) {\n    ctx := context.Background()\n    \n    \u002F\u002F Clean up\n    _, _ = sqldb.Exec(ctx, db, \"DELETE FROM users\")\n    \n    \u002F\u002F Create user\n    created, err := CreateUser(ctx, &CreateUserParams{\n        Email: \"test@example.com\",\n        Name:  \"Test User\",\n    })\n    if err != nil {\n        t.Fatalf(\"failed to create user: %v\", err)\n    }\n    \n    \u002F\u002F Retrieve and verify\n    retrieved, err := GetUser(ctx, &GetUserParams{ID: created.ID})\n    if err != nil {\n        t.Fatalf(\"failed to get user: %v\", err)\n    }\n    \n    if retrieved.Email != \"test@example.com\" {\n        t.Errorf(\"expected email 'test@example.com', got '%s'\", retrieved.Email)\n    }\n}\n```\n\n### Test Service-to-Service Calls\n\n```go\n\u002F\u002F order\u002Forder_test.go\npackage order\n\nimport (\n    \"context\"\n    \"testing\"\n)\n\nfunc TestCreateOrder(t *testing.T) {\n    ctx := context.Background()\n    \n    \u002F\u002F Service calls work normally in tests\n    order, err := CreateOrder(ctx, &CreateOrderParams{\n        UserID: \"user-123\",\n        Items: []OrderItem{\n            {ProductID: \"prod-1\", Quantity: 2},\n        },\n    })\n    if err != nil {\n        t.Fatalf(\"failed to create order: %v\", err)\n    }\n    \n    if order.Status != \"pending\" {\n        t.Errorf(\"expected status 'pending', got '%s'\", order.Status)\n    }\n}\n```\n\n### Test Error Cases\n\n```go\npackage user\n\nimport (\n    \"context\"\n    \"errors\"\n    \"testing\"\n    \n    \"encore.dev\u002Fbeta\u002Ferrs\"\n)\n\nfunc TestGetUser_NotFound(t *testing.T) {\n    ctx := context.Background()\n    \n    _, err := GetUser(ctx, &GetUserParams{ID: \"nonexistent\"})\n    if err == nil {\n        t.Fatal(\"expected error, got nil\")\n    }\n    \n    \u002F\u002F Check error code\n    var e *errs.Error\n    if errors.As(err, &e) {\n        if e.Code != errs.NotFound {\n            t.Errorf(\"expected NotFound, got %v\", e.Code)\n        }\n    } else {\n        t.Errorf(\"expected errs.Error, got %T\", err)\n    }\n}\n```\n\n### Test Pub\u002FSub\n\n```go\n\u002F\u002F notifications\u002Fnotifications_test.go\npackage notifications\n\nimport (\n    \"context\"\n    \"testing\"\n    \n    \"myapp\u002Fevents\"\n)\n\nfunc TestPublishOrderCreated(t *testing.T) {\n    ctx := context.Background()\n    \n    msgID, err := events.OrderCreated.Publish(ctx, &events.OrderCreatedEvent{\n        OrderID: \"order-123\",\n        UserID:  \"user-456\",\n        Total:   9999,\n    })\n    if err != nil {\n        t.Fatalf(\"failed to publish: %v\", err)\n    }\n    \n    if msgID == \"\" {\n        t.Error(\"expected message ID, got empty string\")\n    }\n}\n```\n\n### Test Cron Jobs\n\nTest the underlying function, not the cron schedule:\n\n```go\n\u002F\u002F cleanup\u002Fcleanup_test.go\npackage cleanup\n\nimport (\n    \"context\"\n    \"testing\"\n)\n\nfunc TestCleanupExpiredSessions(t *testing.T) {\n    ctx := context.Background()\n    \n    \u002F\u002F Create some expired sessions first\n    createExpiredSession(ctx)\n    \n    \u002F\u002F Call the endpoint directly\n    err := CleanupExpiredSessions(ctx)\n    if err != nil {\n        t.Fatalf(\"cleanup failed: %v\", err)\n    }\n    \n    \u002F\u002F Verify cleanup happened\n    count := countSessions(ctx)\n    if count != 0 {\n        t.Errorf(\"expected 0 sessions, got %d\", count)\n    }\n}\n```\n\n### Table-Driven Tests\n\n```go\nfunc TestValidateEmail(t *testing.T) {\n    tests := []struct {\n        name    string\n        email   string\n        wantErr bool\n    }{\n        {\"valid email\", \"user@example.com\", false},\n        {\"missing @\", \"userexample.com\", true},\n        {\"empty\", \"\", true},\n        {\"valid with subdomain\", \"user@mail.example.com\", false},\n    }\n    \n    for _, tt := range tests {\n        t.Run(tt.name, func(t *testing.T) {\n            err := validateEmail(tt.email)\n            if (err != nil) != tt.wantErr {\n                t.Errorf(\"validateEmail(%q) error = %v, wantErr %v\", tt.email, err, tt.wantErr)\n            }\n        })\n    }\n}\n```\n\n### Test with Subtests\n\n```go\nfunc TestUserCRUD(t *testing.T) {\n    ctx := context.Background()\n    var userID string\n    \n    t.Run(\"create\", func(t *testing.T) {\n        user, err := CreateUser(ctx, &CreateUserParams{\n            Email: \"test@example.com\",\n            Name:  \"Test\",\n        })\n        if err != nil {\n            t.Fatalf(\"create failed: %v\", err)\n        }\n        userID = user.ID\n    })\n    \n    t.Run(\"read\", func(t *testing.T) {\n        user, err := GetUser(ctx, &GetUserParams{ID: userID})\n        if err != nil {\n            t.Fatalf(\"read failed: %v\", err)\n        }\n        if user.Email != \"test@example.com\" {\n            t.Errorf(\"wrong email: %s\", user.Email)\n        }\n    })\n    \n    t.Run(\"delete\", func(t *testing.T) {\n        err := DeleteUser(ctx, &DeleteUserParams{ID: userID})\n        if err != nil {\n            t.Fatalf(\"delete failed: %v\", err)\n        }\n    })\n}\n```\n\n### Test Database Isolation\n\nCreate isolated, fully-migrated test databases using `et.NewTestDatabase()`:\n\n```go\nimport \"encore.dev\u002Fet\"\n\nfunc TestWithFreshDatabase(t *testing.T) {\n    \u002F\u002F Creates a new database with all migrations applied\n    testDB := et.NewTestDatabase(t, db)\n\n    \u002F\u002F Use testDB for queries - it's completely isolated\n    _, err := testDB.Exec(ctx, \"INSERT INTO users (email) VALUES ($1)\", \"test@example.com\")\n    if err != nil {\n        t.Fatal(err)\n    }\n}\n```\n\n### Service Instance Isolation\n\nBy default, service structs are shared across tests for performance. Enable isolation when tests modify service state:\n\n```go\nimport \"encore.dev\u002Fet\"\n\nfunc TestWithServiceIsolation(t *testing.T) {\n    \u002F\u002F Enable service instance isolation for this test\n    et.EnableServiceInstanceIsolation()\n\n    \u002F\u002F Now this test gets its own service struct instance\n    \u002F\u002F preventing state interference with other tests\n}\n```\n\n### Test Tracing Dashboard\n\nView test execution traces in the development dashboard at `http:\u002F\u002Flocalhost:9400` while tests run. This helps diagnose failures by showing:\n- Request\u002Fresponse data\n- Database queries\n- Service-to-service calls\n- Errors and stack traces\n\n### Mocking Endpoints and Services\n\nMock endpoints or entire services for isolated unit testing:\n\n```go\nimport \"encore.dev\u002Fet\"\n\nfunc TestWithMockedEndpoint(t *testing.T) {\n    \u002F\u002F Mock a specific endpoint\n    et.MockEndpoint(products.GetPrice, func(ctx context.Context, p *products.PriceParams) (*products.PriceResponse, error) {\n        return &products.PriceResponse{Price: 100}, nil\n    })\n\n    \u002F\u002F Mock an entire service\n    et.MockService(\"products\", &mockProductService{})\n}\n```\n\n### Guidelines\n\n- Use `encore test` to run tests with infrastructure setup\n- Each test gets access to real infrastructure (databases, Pub\u002FSub)\n- Test API endpoints by calling them directly as functions\n- Service-to-service calls work normally in tests\n- Use table-driven tests for testing multiple cases\n- Use `et.NewTestDatabase()` for isolated database testing\n- Use `et.EnableServiceInstanceIsolation()` when tests modify service state\n- Don't mock Encore infrastructure - use the real thing\n- Mock external dependencies (third-party APIs, email services, etc.)\n",{"data":38,"body":40},{"name":4,"description":6,"when_to_use":39},"User wants to add\u002Fwrite\u002Ffix a test in Go, write a `*_test.go` file, test an endpoint or service, set up `encore test`, configure isolated test databases, write `t.Cleanup`\u002F`t.Helper` for db cleanup, mock external dependencies, or assert on API request\u002Fresponse behaviour. Trigger phrases: \"write a Go test\", \"add tests for\", \"go test\", \"encore test\", \"test the endpoint\", \"test the service\", \"integration test\", \"isolated database\".",{"type":41,"children":42},"root",[43,52,59,74,81,197,217,237,243,419,425,578,584,589,870,876,1077,1083,1300,1306,1506,1512,1517,1718,1724,1895,1901,2149,2155,2168,2266,2272,2277,2352,2358,2371,2394,2400,2405,2495,2501,2569],{"type":44,"tag":45,"props":46,"children":48},"element","h1",{"id":47},"testing-encore-go-applications",[49],{"type":50,"value":51},"text","Testing Encore Go Applications",{"type":44,"tag":53,"props":54,"children":56},"h2",{"id":55},"instructions",[57],{"type":50,"value":58},"Instructions",{"type":44,"tag":60,"props":61,"children":62},"p",{},[63,65,72],{"type":50,"value":64},"Encore Go uses standard Go testing with ",{"type":44,"tag":66,"props":67,"children":69},"code",{"className":68},[],[70],{"type":50,"value":71},"encore test",{"type":50,"value":73},".",{"type":44,"tag":75,"props":76,"children":78},"h3",{"id":77},"run-tests",[79],{"type":50,"value":80},"Run Tests",{"type":44,"tag":82,"props":83,"children":88},"pre",{"className":84,"code":85,"language":86,"meta":87,"style":87},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","# Run all tests with Encore (recommended)\nencore test .\u002F...\n\n# Run tests for a specific package\nencore test .\u002Fuser\u002F...\n\n# Run with verbose output\nencore test -v .\u002F...\n","bash","",[89],{"type":44,"tag":66,"props":90,"children":91},{"__ignoreMap":87},[92,104,124,134,143,159,167,176],{"type":44,"tag":93,"props":94,"children":97},"span",{"class":95,"line":96},"line",1,[98],{"type":44,"tag":93,"props":99,"children":101},{"style":100},"--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic",[102],{"type":50,"value":103},"# Run all tests with Encore (recommended)\n",{"type":44,"tag":93,"props":105,"children":107},{"class":95,"line":106},2,[108,113,119],{"type":44,"tag":93,"props":109,"children":111},{"style":110},"--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B",[112],{"type":50,"value":8},{"type":44,"tag":93,"props":114,"children":116},{"style":115},"--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D",[117],{"type":50,"value":118}," test",{"type":44,"tag":93,"props":120,"children":121},{"style":115},[122],{"type":50,"value":123}," .\u002F...\n",{"type":44,"tag":93,"props":125,"children":127},{"class":95,"line":126},3,[128],{"type":44,"tag":93,"props":129,"children":131},{"emptyLinePlaceholder":130},true,[132],{"type":50,"value":133},"\n",{"type":44,"tag":93,"props":135,"children":137},{"class":95,"line":136},4,[138],{"type":44,"tag":93,"props":139,"children":140},{"style":100},[141],{"type":50,"value":142},"# Run tests for a specific package\n",{"type":44,"tag":93,"props":144,"children":145},{"class":95,"line":28},[146,150,154],{"type":44,"tag":93,"props":147,"children":148},{"style":110},[149],{"type":50,"value":8},{"type":44,"tag":93,"props":151,"children":152},{"style":115},[153],{"type":50,"value":118},{"type":44,"tag":93,"props":155,"children":156},{"style":115},[157],{"type":50,"value":158}," .\u002Fuser\u002F...\n",{"type":44,"tag":93,"props":160,"children":162},{"class":95,"line":161},6,[163],{"type":44,"tag":93,"props":164,"children":165},{"emptyLinePlaceholder":130},[166],{"type":50,"value":133},{"type":44,"tag":93,"props":168,"children":170},{"class":95,"line":169},7,[171],{"type":44,"tag":93,"props":172,"children":173},{"style":100},[174],{"type":50,"value":175},"# Run with verbose output\n",{"type":44,"tag":93,"props":177,"children":179},{"class":95,"line":178},8,[180,184,188,193],{"type":44,"tag":93,"props":181,"children":182},{"style":110},[183],{"type":50,"value":8},{"type":44,"tag":93,"props":185,"children":186},{"style":115},[187],{"type":50,"value":118},{"type":44,"tag":93,"props":189,"children":190},{"style":115},[191],{"type":50,"value":192}," -v",{"type":44,"tag":93,"props":194,"children":195},{"style":115},[196],{"type":50,"value":123},{"type":44,"tag":60,"props":198,"children":199},{},[200,202,207,209,215],{"type":50,"value":201},"Using ",{"type":44,"tag":66,"props":203,"children":205},{"className":204},[],[206],{"type":50,"value":71},{"type":50,"value":208}," instead of ",{"type":44,"tag":66,"props":210,"children":212},{"className":211},[],[213],{"type":50,"value":214},"go test",{"type":50,"value":216}," is recommended because it:",{"type":44,"tag":218,"props":219,"children":220},"ul",{},[221,227,232],{"type":44,"tag":222,"props":223,"children":224},"li",{},[225],{"type":50,"value":226},"Sets up test databases automatically",{"type":44,"tag":222,"props":228,"children":229},{},[230],{"type":50,"value":231},"Provides isolated infrastructure per test",{"type":44,"tag":222,"props":233,"children":234},{},[235],{"type":50,"value":236},"Handles service dependencies",{"type":44,"tag":75,"props":238,"children":240},{"id":239},"test-an-api-endpoint",[241],{"type":50,"value":242},"Test an API Endpoint",{"type":44,"tag":82,"props":244,"children":247},{"className":245,"code":246,"language":23,"meta":87,"style":87},"language-go shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","\u002F\u002F hello\u002Fhello_test.go\npackage hello\n\nimport (\n    \"context\"\n    \"testing\"\n)\n\nfunc TestHello(t *testing.T) {\n    ctx := context.Background()\n    \n    resp, err := Hello(ctx)\n    if err != nil {\n        t.Fatalf(\"unexpected error: %v\", err)\n    }\n    \n    if resp.Message != \"Hello, World!\" {\n        t.Errorf(\"expected 'Hello, World!', got '%s'\", resp.Message)\n    }\n}\n",[248],{"type":44,"tag":66,"props":249,"children":250},{"__ignoreMap":87},[251,259,267,274,282,290,298,306,313,322,331,340,349,358,367,376,384,393,402,410],{"type":44,"tag":93,"props":252,"children":253},{"class":95,"line":96},[254],{"type":44,"tag":93,"props":255,"children":256},{},[257],{"type":50,"value":258},"\u002F\u002F hello\u002Fhello_test.go\n",{"type":44,"tag":93,"props":260,"children":261},{"class":95,"line":106},[262],{"type":44,"tag":93,"props":263,"children":264},{},[265],{"type":50,"value":266},"package hello\n",{"type":44,"tag":93,"props":268,"children":269},{"class":95,"line":126},[270],{"type":44,"tag":93,"props":271,"children":272},{"emptyLinePlaceholder":130},[273],{"type":50,"value":133},{"type":44,"tag":93,"props":275,"children":276},{"class":95,"line":136},[277],{"type":44,"tag":93,"props":278,"children":279},{},[280],{"type":50,"value":281},"import (\n",{"type":44,"tag":93,"props":283,"children":284},{"class":95,"line":28},[285],{"type":44,"tag":93,"props":286,"children":287},{},[288],{"type":50,"value":289},"    \"context\"\n",{"type":44,"tag":93,"props":291,"children":292},{"class":95,"line":161},[293],{"type":44,"tag":93,"props":294,"children":295},{},[296],{"type":50,"value":297},"    \"testing\"\n",{"type":44,"tag":93,"props":299,"children":300},{"class":95,"line":169},[301],{"type":44,"tag":93,"props":302,"children":303},{},[304],{"type":50,"value":305},")\n",{"type":44,"tag":93,"props":307,"children":308},{"class":95,"line":178},[309],{"type":44,"tag":93,"props":310,"children":311},{"emptyLinePlaceholder":130},[312],{"type":50,"value":133},{"type":44,"tag":93,"props":314,"children":316},{"class":95,"line":315},9,[317],{"type":44,"tag":93,"props":318,"children":319},{},[320],{"type":50,"value":321},"func TestHello(t *testing.T) {\n",{"type":44,"tag":93,"props":323,"children":325},{"class":95,"line":324},10,[326],{"type":44,"tag":93,"props":327,"children":328},{},[329],{"type":50,"value":330},"    ctx := context.Background()\n",{"type":44,"tag":93,"props":332,"children":334},{"class":95,"line":333},11,[335],{"type":44,"tag":93,"props":336,"children":337},{},[338],{"type":50,"value":339},"    \n",{"type":44,"tag":93,"props":341,"children":343},{"class":95,"line":342},12,[344],{"type":44,"tag":93,"props":345,"children":346},{},[347],{"type":50,"value":348},"    resp, err := Hello(ctx)\n",{"type":44,"tag":93,"props":350,"children":352},{"class":95,"line":351},13,[353],{"type":44,"tag":93,"props":354,"children":355},{},[356],{"type":50,"value":357},"    if err != nil {\n",{"type":44,"tag":93,"props":359,"children":361},{"class":95,"line":360},14,[362],{"type":44,"tag":93,"props":363,"children":364},{},[365],{"type":50,"value":366},"        t.Fatalf(\"unexpected error: %v\", err)\n",{"type":44,"tag":93,"props":368,"children":370},{"class":95,"line":369},15,[371],{"type":44,"tag":93,"props":372,"children":373},{},[374],{"type":50,"value":375},"    }\n",{"type":44,"tag":93,"props":377,"children":379},{"class":95,"line":378},16,[380],{"type":44,"tag":93,"props":381,"children":382},{},[383],{"type":50,"value":339},{"type":44,"tag":93,"props":385,"children":387},{"class":95,"line":386},17,[388],{"type":44,"tag":93,"props":389,"children":390},{},[391],{"type":50,"value":392},"    if resp.Message != \"Hello, World!\" {\n",{"type":44,"tag":93,"props":394,"children":396},{"class":95,"line":395},18,[397],{"type":44,"tag":93,"props":398,"children":399},{},[400],{"type":50,"value":401},"        t.Errorf(\"expected 'Hello, World!', got '%s'\", resp.Message)\n",{"type":44,"tag":93,"props":403,"children":405},{"class":95,"line":404},19,[406],{"type":44,"tag":93,"props":407,"children":408},{},[409],{"type":50,"value":375},{"type":44,"tag":93,"props":411,"children":413},{"class":95,"line":412},20,[414],{"type":44,"tag":93,"props":415,"children":416},{},[417],{"type":50,"value":418},"}\n",{"type":44,"tag":75,"props":420,"children":422},{"id":421},"test-with-request-parameters",[423],{"type":50,"value":424},"Test with Request Parameters",{"type":44,"tag":82,"props":426,"children":428},{"className":245,"code":427,"language":23,"meta":87,"style":87},"\u002F\u002F user\u002Fuser_test.go\npackage user\n\nimport (\n    \"context\"\n    \"testing\"\n)\n\nfunc TestGetUser(t *testing.T) {\n    ctx := context.Background()\n    \n    user, err := GetUser(ctx, &GetUserParams{ID: \"123\"})\n    if err != nil {\n        t.Fatalf(\"unexpected error: %v\", err)\n    }\n    \n    if user.ID != \"123\" {\n        t.Errorf(\"expected ID '123', got '%s'\", user.ID)\n    }\n}\n",[429],{"type":44,"tag":66,"props":430,"children":431},{"__ignoreMap":87},[432,440,448,455,462,469,476,483,490,498,505,512,520,527,534,541,548,556,564,571],{"type":44,"tag":93,"props":433,"children":434},{"class":95,"line":96},[435],{"type":44,"tag":93,"props":436,"children":437},{},[438],{"type":50,"value":439},"\u002F\u002F user\u002Fuser_test.go\n",{"type":44,"tag":93,"props":441,"children":442},{"class":95,"line":106},[443],{"type":44,"tag":93,"props":444,"children":445},{},[446],{"type":50,"value":447},"package user\n",{"type":44,"tag":93,"props":449,"children":450},{"class":95,"line":126},[451],{"type":44,"tag":93,"props":452,"children":453},{"emptyLinePlaceholder":130},[454],{"type":50,"value":133},{"type":44,"tag":93,"props":456,"children":457},{"class":95,"line":136},[458],{"type":44,"tag":93,"props":459,"children":460},{},[461],{"type":50,"value":281},{"type":44,"tag":93,"props":463,"children":464},{"class":95,"line":28},[465],{"type":44,"tag":93,"props":466,"children":467},{},[468],{"type":50,"value":289},{"type":44,"tag":93,"props":470,"children":471},{"class":95,"line":161},[472],{"type":44,"tag":93,"props":473,"children":474},{},[475],{"type":50,"value":297},{"type":44,"tag":93,"props":477,"children":478},{"class":95,"line":169},[479],{"type":44,"tag":93,"props":480,"children":481},{},[482],{"type":50,"value":305},{"type":44,"tag":93,"props":484,"children":485},{"class":95,"line":178},[486],{"type":44,"tag":93,"props":487,"children":488},{"emptyLinePlaceholder":130},[489],{"type":50,"value":133},{"type":44,"tag":93,"props":491,"children":492},{"class":95,"line":315},[493],{"type":44,"tag":93,"props":494,"children":495},{},[496],{"type":50,"value":497},"func TestGetUser(t *testing.T) {\n",{"type":44,"tag":93,"props":499,"children":500},{"class":95,"line":324},[501],{"type":44,"tag":93,"props":502,"children":503},{},[504],{"type":50,"value":330},{"type":44,"tag":93,"props":506,"children":507},{"class":95,"line":333},[508],{"type":44,"tag":93,"props":509,"children":510},{},[511],{"type":50,"value":339},{"type":44,"tag":93,"props":513,"children":514},{"class":95,"line":342},[515],{"type":44,"tag":93,"props":516,"children":517},{},[518],{"type":50,"value":519},"    user, err := GetUser(ctx, &GetUserParams{ID: \"123\"})\n",{"type":44,"tag":93,"props":521,"children":522},{"class":95,"line":351},[523],{"type":44,"tag":93,"props":524,"children":525},{},[526],{"type":50,"value":357},{"type":44,"tag":93,"props":528,"children":529},{"class":95,"line":360},[530],{"type":44,"tag":93,"props":531,"children":532},{},[533],{"type":50,"value":366},{"type":44,"tag":93,"props":535,"children":536},{"class":95,"line":369},[537],{"type":44,"tag":93,"props":538,"children":539},{},[540],{"type":50,"value":375},{"type":44,"tag":93,"props":542,"children":543},{"class":95,"line":378},[544],{"type":44,"tag":93,"props":545,"children":546},{},[547],{"type":50,"value":339},{"type":44,"tag":93,"props":549,"children":550},{"class":95,"line":386},[551],{"type":44,"tag":93,"props":552,"children":553},{},[554],{"type":50,"value":555},"    if user.ID != \"123\" {\n",{"type":44,"tag":93,"props":557,"children":558},{"class":95,"line":395},[559],{"type":44,"tag":93,"props":560,"children":561},{},[562],{"type":50,"value":563},"        t.Errorf(\"expected ID '123', got '%s'\", user.ID)\n",{"type":44,"tag":93,"props":565,"children":566},{"class":95,"line":404},[567],{"type":44,"tag":93,"props":568,"children":569},{},[570],{"type":50,"value":375},{"type":44,"tag":93,"props":572,"children":573},{"class":95,"line":412},[574],{"type":44,"tag":93,"props":575,"children":576},{},[577],{"type":50,"value":418},{"type":44,"tag":75,"props":579,"children":581},{"id":580},"test-database-operations",[582],{"type":50,"value":583},"Test Database Operations",{"type":44,"tag":60,"props":585,"children":586},{},[587],{"type":50,"value":588},"Encore provides isolated test databases:",{"type":44,"tag":82,"props":590,"children":592},{"className":245,"code":591,"language":23,"meta":87,"style":87},"\u002F\u002F user\u002Fuser_test.go\npackage user\n\nimport (\n    \"context\"\n    \"testing\"\n    \n    \"encore.dev\u002Fstorage\u002Fsqldb\"\n)\n\nfunc TestCreateUser(t *testing.T) {\n    ctx := context.Background()\n    \n    \u002F\u002F Clean up\n    _, _ = sqldb.Exec(ctx, db, \"DELETE FROM users\")\n    \n    \u002F\u002F Create user\n    created, err := CreateUser(ctx, &CreateUserParams{\n        Email: \"test@example.com\",\n        Name:  \"Test User\",\n    })\n    if err != nil {\n        t.Fatalf(\"failed to create user: %v\", err)\n    }\n    \n    \u002F\u002F Retrieve and verify\n    retrieved, err := GetUser(ctx, &GetUserParams{ID: created.ID})\n    if err != nil {\n        t.Fatalf(\"failed to get user: %v\", err)\n    }\n    \n    if retrieved.Email != \"test@example.com\" {\n        t.Errorf(\"expected email 'test@example.com', got '%s'\", retrieved.Email)\n    }\n}\n",[593],{"type":44,"tag":66,"props":594,"children":595},{"__ignoreMap":87},[596,603,610,617,624,631,638,645,653,660,667,675,682,689,697,705,712,720,728,736,744,753,761,770,778,786,794,803,811,820,828,836,845,854,862],{"type":44,"tag":93,"props":597,"children":598},{"class":95,"line":96},[599],{"type":44,"tag":93,"props":600,"children":601},{},[602],{"type":50,"value":439},{"type":44,"tag":93,"props":604,"children":605},{"class":95,"line":106},[606],{"type":44,"tag":93,"props":607,"children":608},{},[609],{"type":50,"value":447},{"type":44,"tag":93,"props":611,"children":612},{"class":95,"line":126},[613],{"type":44,"tag":93,"props":614,"children":615},{"emptyLinePlaceholder":130},[616],{"type":50,"value":133},{"type":44,"tag":93,"props":618,"children":619},{"class":95,"line":136},[620],{"type":44,"tag":93,"props":621,"children":622},{},[623],{"type":50,"value":281},{"type":44,"tag":93,"props":625,"children":626},{"class":95,"line":28},[627],{"type":44,"tag":93,"props":628,"children":629},{},[630],{"type":50,"value":289},{"type":44,"tag":93,"props":632,"children":633},{"class":95,"line":161},[634],{"type":44,"tag":93,"props":635,"children":636},{},[637],{"type":50,"value":297},{"type":44,"tag":93,"props":639,"children":640},{"class":95,"line":169},[641],{"type":44,"tag":93,"props":642,"children":643},{},[644],{"type":50,"value":339},{"type":44,"tag":93,"props":646,"children":647},{"class":95,"line":178},[648],{"type":44,"tag":93,"props":649,"children":650},{},[651],{"type":50,"value":652},"    \"encore.dev\u002Fstorage\u002Fsqldb\"\n",{"type":44,"tag":93,"props":654,"children":655},{"class":95,"line":315},[656],{"type":44,"tag":93,"props":657,"children":658},{},[659],{"type":50,"value":305},{"type":44,"tag":93,"props":661,"children":662},{"class":95,"line":324},[663],{"type":44,"tag":93,"props":664,"children":665},{"emptyLinePlaceholder":130},[666],{"type":50,"value":133},{"type":44,"tag":93,"props":668,"children":669},{"class":95,"line":333},[670],{"type":44,"tag":93,"props":671,"children":672},{},[673],{"type":50,"value":674},"func TestCreateUser(t *testing.T) {\n",{"type":44,"tag":93,"props":676,"children":677},{"class":95,"line":342},[678],{"type":44,"tag":93,"props":679,"children":680},{},[681],{"type":50,"value":330},{"type":44,"tag":93,"props":683,"children":684},{"class":95,"line":351},[685],{"type":44,"tag":93,"props":686,"children":687},{},[688],{"type":50,"value":339},{"type":44,"tag":93,"props":690,"children":691},{"class":95,"line":360},[692],{"type":44,"tag":93,"props":693,"children":694},{},[695],{"type":50,"value":696},"    \u002F\u002F Clean up\n",{"type":44,"tag":93,"props":698,"children":699},{"class":95,"line":369},[700],{"type":44,"tag":93,"props":701,"children":702},{},[703],{"type":50,"value":704},"    _, _ = sqldb.Exec(ctx, db, \"DELETE FROM users\")\n",{"type":44,"tag":93,"props":706,"children":707},{"class":95,"line":378},[708],{"type":44,"tag":93,"props":709,"children":710},{},[711],{"type":50,"value":339},{"type":44,"tag":93,"props":713,"children":714},{"class":95,"line":386},[715],{"type":44,"tag":93,"props":716,"children":717},{},[718],{"type":50,"value":719},"    \u002F\u002F Create user\n",{"type":44,"tag":93,"props":721,"children":722},{"class":95,"line":395},[723],{"type":44,"tag":93,"props":724,"children":725},{},[726],{"type":50,"value":727},"    created, err := CreateUser(ctx, &CreateUserParams{\n",{"type":44,"tag":93,"props":729,"children":730},{"class":95,"line":404},[731],{"type":44,"tag":93,"props":732,"children":733},{},[734],{"type":50,"value":735},"        Email: \"test@example.com\",\n",{"type":44,"tag":93,"props":737,"children":738},{"class":95,"line":412},[739],{"type":44,"tag":93,"props":740,"children":741},{},[742],{"type":50,"value":743},"        Name:  \"Test User\",\n",{"type":44,"tag":93,"props":745,"children":747},{"class":95,"line":746},21,[748],{"type":44,"tag":93,"props":749,"children":750},{},[751],{"type":50,"value":752},"    })\n",{"type":44,"tag":93,"props":754,"children":756},{"class":95,"line":755},22,[757],{"type":44,"tag":93,"props":758,"children":759},{},[760],{"type":50,"value":357},{"type":44,"tag":93,"props":762,"children":764},{"class":95,"line":763},23,[765],{"type":44,"tag":93,"props":766,"children":767},{},[768],{"type":50,"value":769},"        t.Fatalf(\"failed to create user: %v\", err)\n",{"type":44,"tag":93,"props":771,"children":773},{"class":95,"line":772},24,[774],{"type":44,"tag":93,"props":775,"children":776},{},[777],{"type":50,"value":375},{"type":44,"tag":93,"props":779,"children":781},{"class":95,"line":780},25,[782],{"type":44,"tag":93,"props":783,"children":784},{},[785],{"type":50,"value":339},{"type":44,"tag":93,"props":787,"children":788},{"class":95,"line":24},[789],{"type":44,"tag":93,"props":790,"children":791},{},[792],{"type":50,"value":793},"    \u002F\u002F Retrieve and verify\n",{"type":44,"tag":93,"props":795,"children":797},{"class":95,"line":796},27,[798],{"type":44,"tag":93,"props":799,"children":800},{},[801],{"type":50,"value":802},"    retrieved, err := GetUser(ctx, &GetUserParams{ID: created.ID})\n",{"type":44,"tag":93,"props":804,"children":806},{"class":95,"line":805},28,[807],{"type":44,"tag":93,"props":808,"children":809},{},[810],{"type":50,"value":357},{"type":44,"tag":93,"props":812,"children":814},{"class":95,"line":813},29,[815],{"type":44,"tag":93,"props":816,"children":817},{},[818],{"type":50,"value":819},"        t.Fatalf(\"failed to get user: %v\", err)\n",{"type":44,"tag":93,"props":821,"children":823},{"class":95,"line":822},30,[824],{"type":44,"tag":93,"props":825,"children":826},{},[827],{"type":50,"value":375},{"type":44,"tag":93,"props":829,"children":831},{"class":95,"line":830},31,[832],{"type":44,"tag":93,"props":833,"children":834},{},[835],{"type":50,"value":339},{"type":44,"tag":93,"props":837,"children":839},{"class":95,"line":838},32,[840],{"type":44,"tag":93,"props":841,"children":842},{},[843],{"type":50,"value":844},"    if retrieved.Email != \"test@example.com\" {\n",{"type":44,"tag":93,"props":846,"children":848},{"class":95,"line":847},33,[849],{"type":44,"tag":93,"props":850,"children":851},{},[852],{"type":50,"value":853},"        t.Errorf(\"expected email 'test@example.com', got '%s'\", retrieved.Email)\n",{"type":44,"tag":93,"props":855,"children":857},{"class":95,"line":856},34,[858],{"type":44,"tag":93,"props":859,"children":860},{},[861],{"type":50,"value":375},{"type":44,"tag":93,"props":863,"children":865},{"class":95,"line":864},35,[866],{"type":44,"tag":93,"props":867,"children":868},{},[869],{"type":50,"value":418},{"type":44,"tag":75,"props":871,"children":873},{"id":872},"test-service-to-service-calls",[874],{"type":50,"value":875},"Test Service-to-Service Calls",{"type":44,"tag":82,"props":877,"children":879},{"className":245,"code":878,"language":23,"meta":87,"style":87},"\u002F\u002F order\u002Forder_test.go\npackage order\n\nimport (\n    \"context\"\n    \"testing\"\n)\n\nfunc TestCreateOrder(t *testing.T) {\n    ctx := context.Background()\n    \n    \u002F\u002F Service calls work normally in tests\n    order, err := CreateOrder(ctx, &CreateOrderParams{\n        UserID: \"user-123\",\n        Items: []OrderItem{\n            {ProductID: \"prod-1\", Quantity: 2},\n        },\n    })\n    if err != nil {\n        t.Fatalf(\"failed to create order: %v\", err)\n    }\n    \n    if order.Status != \"pending\" {\n        t.Errorf(\"expected status 'pending', got '%s'\", order.Status)\n    }\n}\n",[880],{"type":44,"tag":66,"props":881,"children":882},{"__ignoreMap":87},[883,891,899,906,913,920,927,934,941,949,956,963,971,979,987,995,1003,1011,1018,1025,1033,1040,1047,1055,1063,1070],{"type":44,"tag":93,"props":884,"children":885},{"class":95,"line":96},[886],{"type":44,"tag":93,"props":887,"children":888},{},[889],{"type":50,"value":890},"\u002F\u002F order\u002Forder_test.go\n",{"type":44,"tag":93,"props":892,"children":893},{"class":95,"line":106},[894],{"type":44,"tag":93,"props":895,"children":896},{},[897],{"type":50,"value":898},"package order\n",{"type":44,"tag":93,"props":900,"children":901},{"class":95,"line":126},[902],{"type":44,"tag":93,"props":903,"children":904},{"emptyLinePlaceholder":130},[905],{"type":50,"value":133},{"type":44,"tag":93,"props":907,"children":908},{"class":95,"line":136},[909],{"type":44,"tag":93,"props":910,"children":911},{},[912],{"type":50,"value":281},{"type":44,"tag":93,"props":914,"children":915},{"class":95,"line":28},[916],{"type":44,"tag":93,"props":917,"children":918},{},[919],{"type":50,"value":289},{"type":44,"tag":93,"props":921,"children":922},{"class":95,"line":161},[923],{"type":44,"tag":93,"props":924,"children":925},{},[926],{"type":50,"value":297},{"type":44,"tag":93,"props":928,"children":929},{"class":95,"line":169},[930],{"type":44,"tag":93,"props":931,"children":932},{},[933],{"type":50,"value":305},{"type":44,"tag":93,"props":935,"children":936},{"class":95,"line":178},[937],{"type":44,"tag":93,"props":938,"children":939},{"emptyLinePlaceholder":130},[940],{"type":50,"value":133},{"type":44,"tag":93,"props":942,"children":943},{"class":95,"line":315},[944],{"type":44,"tag":93,"props":945,"children":946},{},[947],{"type":50,"value":948},"func TestCreateOrder(t *testing.T) {\n",{"type":44,"tag":93,"props":950,"children":951},{"class":95,"line":324},[952],{"type":44,"tag":93,"props":953,"children":954},{},[955],{"type":50,"value":330},{"type":44,"tag":93,"props":957,"children":958},{"class":95,"line":333},[959],{"type":44,"tag":93,"props":960,"children":961},{},[962],{"type":50,"value":339},{"type":44,"tag":93,"props":964,"children":965},{"class":95,"line":342},[966],{"type":44,"tag":93,"props":967,"children":968},{},[969],{"type":50,"value":970},"    \u002F\u002F Service calls work normally in tests\n",{"type":44,"tag":93,"props":972,"children":973},{"class":95,"line":351},[974],{"type":44,"tag":93,"props":975,"children":976},{},[977],{"type":50,"value":978},"    order, err := CreateOrder(ctx, &CreateOrderParams{\n",{"type":44,"tag":93,"props":980,"children":981},{"class":95,"line":360},[982],{"type":44,"tag":93,"props":983,"children":984},{},[985],{"type":50,"value":986},"        UserID: \"user-123\",\n",{"type":44,"tag":93,"props":988,"children":989},{"class":95,"line":369},[990],{"type":44,"tag":93,"props":991,"children":992},{},[993],{"type":50,"value":994},"        Items: []OrderItem{\n",{"type":44,"tag":93,"props":996,"children":997},{"class":95,"line":378},[998],{"type":44,"tag":93,"props":999,"children":1000},{},[1001],{"type":50,"value":1002},"            {ProductID: \"prod-1\", Quantity: 2},\n",{"type":44,"tag":93,"props":1004,"children":1005},{"class":95,"line":386},[1006],{"type":44,"tag":93,"props":1007,"children":1008},{},[1009],{"type":50,"value":1010},"        },\n",{"type":44,"tag":93,"props":1012,"children":1013},{"class":95,"line":395},[1014],{"type":44,"tag":93,"props":1015,"children":1016},{},[1017],{"type":50,"value":752},{"type":44,"tag":93,"props":1019,"children":1020},{"class":95,"line":404},[1021],{"type":44,"tag":93,"props":1022,"children":1023},{},[1024],{"type":50,"value":357},{"type":44,"tag":93,"props":1026,"children":1027},{"class":95,"line":412},[1028],{"type":44,"tag":93,"props":1029,"children":1030},{},[1031],{"type":50,"value":1032},"        t.Fatalf(\"failed to create order: %v\", err)\n",{"type":44,"tag":93,"props":1034,"children":1035},{"class":95,"line":746},[1036],{"type":44,"tag":93,"props":1037,"children":1038},{},[1039],{"type":50,"value":375},{"type":44,"tag":93,"props":1041,"children":1042},{"class":95,"line":755},[1043],{"type":44,"tag":93,"props":1044,"children":1045},{},[1046],{"type":50,"value":339},{"type":44,"tag":93,"props":1048,"children":1049},{"class":95,"line":763},[1050],{"type":44,"tag":93,"props":1051,"children":1052},{},[1053],{"type":50,"value":1054},"    if order.Status != \"pending\" {\n",{"type":44,"tag":93,"props":1056,"children":1057},{"class":95,"line":772},[1058],{"type":44,"tag":93,"props":1059,"children":1060},{},[1061],{"type":50,"value":1062},"        t.Errorf(\"expected status 'pending', got '%s'\", order.Status)\n",{"type":44,"tag":93,"props":1064,"children":1065},{"class":95,"line":780},[1066],{"type":44,"tag":93,"props":1067,"children":1068},{},[1069],{"type":50,"value":375},{"type":44,"tag":93,"props":1071,"children":1072},{"class":95,"line":24},[1073],{"type":44,"tag":93,"props":1074,"children":1075},{},[1076],{"type":50,"value":418},{"type":44,"tag":75,"props":1078,"children":1080},{"id":1079},"test-error-cases",[1081],{"type":50,"value":1082},"Test Error Cases",{"type":44,"tag":82,"props":1084,"children":1086},{"className":245,"code":1085,"language":23,"meta":87,"style":87},"package user\n\nimport (\n    \"context\"\n    \"errors\"\n    \"testing\"\n    \n    \"encore.dev\u002Fbeta\u002Ferrs\"\n)\n\nfunc TestGetUser_NotFound(t *testing.T) {\n    ctx := context.Background()\n    \n    _, err := GetUser(ctx, &GetUserParams{ID: \"nonexistent\"})\n    if err == nil {\n        t.Fatal(\"expected error, got nil\")\n    }\n    \n    \u002F\u002F Check error code\n    var e *errs.Error\n    if errors.As(err, &e) {\n        if e.Code != errs.NotFound {\n            t.Errorf(\"expected NotFound, got %v\", e.Code)\n        }\n    } else {\n        t.Errorf(\"expected errs.Error, got %T\", err)\n    }\n}\n",[1087],{"type":44,"tag":66,"props":1088,"children":1089},{"__ignoreMap":87},[1090,1097,1104,1111,1118,1126,1133,1140,1148,1155,1162,1170,1177,1184,1192,1200,1208,1215,1222,1230,1238,1246,1254,1262,1270,1278,1286,1293],{"type":44,"tag":93,"props":1091,"children":1092},{"class":95,"line":96},[1093],{"type":44,"tag":93,"props":1094,"children":1095},{},[1096],{"type":50,"value":447},{"type":44,"tag":93,"props":1098,"children":1099},{"class":95,"line":106},[1100],{"type":44,"tag":93,"props":1101,"children":1102},{"emptyLinePlaceholder":130},[1103],{"type":50,"value":133},{"type":44,"tag":93,"props":1105,"children":1106},{"class":95,"line":126},[1107],{"type":44,"tag":93,"props":1108,"children":1109},{},[1110],{"type":50,"value":281},{"type":44,"tag":93,"props":1112,"children":1113},{"class":95,"line":136},[1114],{"type":44,"tag":93,"props":1115,"children":1116},{},[1117],{"type":50,"value":289},{"type":44,"tag":93,"props":1119,"children":1120},{"class":95,"line":28},[1121],{"type":44,"tag":93,"props":1122,"children":1123},{},[1124],{"type":50,"value":1125},"    \"errors\"\n",{"type":44,"tag":93,"props":1127,"children":1128},{"class":95,"line":161},[1129],{"type":44,"tag":93,"props":1130,"children":1131},{},[1132],{"type":50,"value":297},{"type":44,"tag":93,"props":1134,"children":1135},{"class":95,"line":169},[1136],{"type":44,"tag":93,"props":1137,"children":1138},{},[1139],{"type":50,"value":339},{"type":44,"tag":93,"props":1141,"children":1142},{"class":95,"line":178},[1143],{"type":44,"tag":93,"props":1144,"children":1145},{},[1146],{"type":50,"value":1147},"    \"encore.dev\u002Fbeta\u002Ferrs\"\n",{"type":44,"tag":93,"props":1149,"children":1150},{"class":95,"line":315},[1151],{"type":44,"tag":93,"props":1152,"children":1153},{},[1154],{"type":50,"value":305},{"type":44,"tag":93,"props":1156,"children":1157},{"class":95,"line":324},[1158],{"type":44,"tag":93,"props":1159,"children":1160},{"emptyLinePlaceholder":130},[1161],{"type":50,"value":133},{"type":44,"tag":93,"props":1163,"children":1164},{"class":95,"line":333},[1165],{"type":44,"tag":93,"props":1166,"children":1167},{},[1168],{"type":50,"value":1169},"func TestGetUser_NotFound(t *testing.T) {\n",{"type":44,"tag":93,"props":1171,"children":1172},{"class":95,"line":342},[1173],{"type":44,"tag":93,"props":1174,"children":1175},{},[1176],{"type":50,"value":330},{"type":44,"tag":93,"props":1178,"children":1179},{"class":95,"line":351},[1180],{"type":44,"tag":93,"props":1181,"children":1182},{},[1183],{"type":50,"value":339},{"type":44,"tag":93,"props":1185,"children":1186},{"class":95,"line":360},[1187],{"type":44,"tag":93,"props":1188,"children":1189},{},[1190],{"type":50,"value":1191},"    _, err := GetUser(ctx, &GetUserParams{ID: \"nonexistent\"})\n",{"type":44,"tag":93,"props":1193,"children":1194},{"class":95,"line":369},[1195],{"type":44,"tag":93,"props":1196,"children":1197},{},[1198],{"type":50,"value":1199},"    if err == nil {\n",{"type":44,"tag":93,"props":1201,"children":1202},{"class":95,"line":378},[1203],{"type":44,"tag":93,"props":1204,"children":1205},{},[1206],{"type":50,"value":1207},"        t.Fatal(\"expected error, got nil\")\n",{"type":44,"tag":93,"props":1209,"children":1210},{"class":95,"line":386},[1211],{"type":44,"tag":93,"props":1212,"children":1213},{},[1214],{"type":50,"value":375},{"type":44,"tag":93,"props":1216,"children":1217},{"class":95,"line":395},[1218],{"type":44,"tag":93,"props":1219,"children":1220},{},[1221],{"type":50,"value":339},{"type":44,"tag":93,"props":1223,"children":1224},{"class":95,"line":404},[1225],{"type":44,"tag":93,"props":1226,"children":1227},{},[1228],{"type":50,"value":1229},"    \u002F\u002F Check error code\n",{"type":44,"tag":93,"props":1231,"children":1232},{"class":95,"line":412},[1233],{"type":44,"tag":93,"props":1234,"children":1235},{},[1236],{"type":50,"value":1237},"    var e *errs.Error\n",{"type":44,"tag":93,"props":1239,"children":1240},{"class":95,"line":746},[1241],{"type":44,"tag":93,"props":1242,"children":1243},{},[1244],{"type":50,"value":1245},"    if errors.As(err, &e) {\n",{"type":44,"tag":93,"props":1247,"children":1248},{"class":95,"line":755},[1249],{"type":44,"tag":93,"props":1250,"children":1251},{},[1252],{"type":50,"value":1253},"        if e.Code != errs.NotFound {\n",{"type":44,"tag":93,"props":1255,"children":1256},{"class":95,"line":763},[1257],{"type":44,"tag":93,"props":1258,"children":1259},{},[1260],{"type":50,"value":1261},"            t.Errorf(\"expected NotFound, got %v\", e.Code)\n",{"type":44,"tag":93,"props":1263,"children":1264},{"class":95,"line":772},[1265],{"type":44,"tag":93,"props":1266,"children":1267},{},[1268],{"type":50,"value":1269},"        }\n",{"type":44,"tag":93,"props":1271,"children":1272},{"class":95,"line":780},[1273],{"type":44,"tag":93,"props":1274,"children":1275},{},[1276],{"type":50,"value":1277},"    } else {\n",{"type":44,"tag":93,"props":1279,"children":1280},{"class":95,"line":24},[1281],{"type":44,"tag":93,"props":1282,"children":1283},{},[1284],{"type":50,"value":1285},"        t.Errorf(\"expected errs.Error, got %T\", err)\n",{"type":44,"tag":93,"props":1287,"children":1288},{"class":95,"line":796},[1289],{"type":44,"tag":93,"props":1290,"children":1291},{},[1292],{"type":50,"value":375},{"type":44,"tag":93,"props":1294,"children":1295},{"class":95,"line":805},[1296],{"type":44,"tag":93,"props":1297,"children":1298},{},[1299],{"type":50,"value":418},{"type":44,"tag":75,"props":1301,"children":1303},{"id":1302},"test-pubsub",[1304],{"type":50,"value":1305},"Test Pub\u002FSub",{"type":44,"tag":82,"props":1307,"children":1309},{"className":245,"code":1308,"language":23,"meta":87,"style":87},"\u002F\u002F notifications\u002Fnotifications_test.go\npackage notifications\n\nimport (\n    \"context\"\n    \"testing\"\n    \n    \"myapp\u002Fevents\"\n)\n\nfunc TestPublishOrderCreated(t *testing.T) {\n    ctx := context.Background()\n    \n    msgID, err := events.OrderCreated.Publish(ctx, &events.OrderCreatedEvent{\n        OrderID: \"order-123\",\n        UserID:  \"user-456\",\n        Total:   9999,\n    })\n    if err != nil {\n        t.Fatalf(\"failed to publish: %v\", err)\n    }\n    \n    if msgID == \"\" {\n        t.Error(\"expected message ID, got empty string\")\n    }\n}\n",[1310],{"type":44,"tag":66,"props":1311,"children":1312},{"__ignoreMap":87},[1313,1321,1329,1336,1343,1350,1357,1364,1372,1379,1386,1394,1401,1408,1416,1424,1432,1440,1447,1454,1462,1469,1476,1484,1492,1499],{"type":44,"tag":93,"props":1314,"children":1315},{"class":95,"line":96},[1316],{"type":44,"tag":93,"props":1317,"children":1318},{},[1319],{"type":50,"value":1320},"\u002F\u002F notifications\u002Fnotifications_test.go\n",{"type":44,"tag":93,"props":1322,"children":1323},{"class":95,"line":106},[1324],{"type":44,"tag":93,"props":1325,"children":1326},{},[1327],{"type":50,"value":1328},"package notifications\n",{"type":44,"tag":93,"props":1330,"children":1331},{"class":95,"line":126},[1332],{"type":44,"tag":93,"props":1333,"children":1334},{"emptyLinePlaceholder":130},[1335],{"type":50,"value":133},{"type":44,"tag":93,"props":1337,"children":1338},{"class":95,"line":136},[1339],{"type":44,"tag":93,"props":1340,"children":1341},{},[1342],{"type":50,"value":281},{"type":44,"tag":93,"props":1344,"children":1345},{"class":95,"line":28},[1346],{"type":44,"tag":93,"props":1347,"children":1348},{},[1349],{"type":50,"value":289},{"type":44,"tag":93,"props":1351,"children":1352},{"class":95,"line":161},[1353],{"type":44,"tag":93,"props":1354,"children":1355},{},[1356],{"type":50,"value":297},{"type":44,"tag":93,"props":1358,"children":1359},{"class":95,"line":169},[1360],{"type":44,"tag":93,"props":1361,"children":1362},{},[1363],{"type":50,"value":339},{"type":44,"tag":93,"props":1365,"children":1366},{"class":95,"line":178},[1367],{"type":44,"tag":93,"props":1368,"children":1369},{},[1370],{"type":50,"value":1371},"    \"myapp\u002Fevents\"\n",{"type":44,"tag":93,"props":1373,"children":1374},{"class":95,"line":315},[1375],{"type":44,"tag":93,"props":1376,"children":1377},{},[1378],{"type":50,"value":305},{"type":44,"tag":93,"props":1380,"children":1381},{"class":95,"line":324},[1382],{"type":44,"tag":93,"props":1383,"children":1384},{"emptyLinePlaceholder":130},[1385],{"type":50,"value":133},{"type":44,"tag":93,"props":1387,"children":1388},{"class":95,"line":333},[1389],{"type":44,"tag":93,"props":1390,"children":1391},{},[1392],{"type":50,"value":1393},"func TestPublishOrderCreated(t *testing.T) {\n",{"type":44,"tag":93,"props":1395,"children":1396},{"class":95,"line":342},[1397],{"type":44,"tag":93,"props":1398,"children":1399},{},[1400],{"type":50,"value":330},{"type":44,"tag":93,"props":1402,"children":1403},{"class":95,"line":351},[1404],{"type":44,"tag":93,"props":1405,"children":1406},{},[1407],{"type":50,"value":339},{"type":44,"tag":93,"props":1409,"children":1410},{"class":95,"line":360},[1411],{"type":44,"tag":93,"props":1412,"children":1413},{},[1414],{"type":50,"value":1415},"    msgID, err := events.OrderCreated.Publish(ctx, &events.OrderCreatedEvent{\n",{"type":44,"tag":93,"props":1417,"children":1418},{"class":95,"line":369},[1419],{"type":44,"tag":93,"props":1420,"children":1421},{},[1422],{"type":50,"value":1423},"        OrderID: \"order-123\",\n",{"type":44,"tag":93,"props":1425,"children":1426},{"class":95,"line":378},[1427],{"type":44,"tag":93,"props":1428,"children":1429},{},[1430],{"type":50,"value":1431},"        UserID:  \"user-456\",\n",{"type":44,"tag":93,"props":1433,"children":1434},{"class":95,"line":386},[1435],{"type":44,"tag":93,"props":1436,"children":1437},{},[1438],{"type":50,"value":1439},"        Total:   9999,\n",{"type":44,"tag":93,"props":1441,"children":1442},{"class":95,"line":395},[1443],{"type":44,"tag":93,"props":1444,"children":1445},{},[1446],{"type":50,"value":752},{"type":44,"tag":93,"props":1448,"children":1449},{"class":95,"line":404},[1450],{"type":44,"tag":93,"props":1451,"children":1452},{},[1453],{"type":50,"value":357},{"type":44,"tag":93,"props":1455,"children":1456},{"class":95,"line":412},[1457],{"type":44,"tag":93,"props":1458,"children":1459},{},[1460],{"type":50,"value":1461},"        t.Fatalf(\"failed to publish: %v\", err)\n",{"type":44,"tag":93,"props":1463,"children":1464},{"class":95,"line":746},[1465],{"type":44,"tag":93,"props":1466,"children":1467},{},[1468],{"type":50,"value":375},{"type":44,"tag":93,"props":1470,"children":1471},{"class":95,"line":755},[1472],{"type":44,"tag":93,"props":1473,"children":1474},{},[1475],{"type":50,"value":339},{"type":44,"tag":93,"props":1477,"children":1478},{"class":95,"line":763},[1479],{"type":44,"tag":93,"props":1480,"children":1481},{},[1482],{"type":50,"value":1483},"    if msgID == \"\" {\n",{"type":44,"tag":93,"props":1485,"children":1486},{"class":95,"line":772},[1487],{"type":44,"tag":93,"props":1488,"children":1489},{},[1490],{"type":50,"value":1491},"        t.Error(\"expected message ID, got empty string\")\n",{"type":44,"tag":93,"props":1493,"children":1494},{"class":95,"line":780},[1495],{"type":44,"tag":93,"props":1496,"children":1497},{},[1498],{"type":50,"value":375},{"type":44,"tag":93,"props":1500,"children":1501},{"class":95,"line":24},[1502],{"type":44,"tag":93,"props":1503,"children":1504},{},[1505],{"type":50,"value":418},{"type":44,"tag":75,"props":1507,"children":1509},{"id":1508},"test-cron-jobs",[1510],{"type":50,"value":1511},"Test Cron Jobs",{"type":44,"tag":60,"props":1513,"children":1514},{},[1515],{"type":50,"value":1516},"Test the underlying function, not the cron schedule:",{"type":44,"tag":82,"props":1518,"children":1520},{"className":245,"code":1519,"language":23,"meta":87,"style":87},"\u002F\u002F cleanup\u002Fcleanup_test.go\npackage cleanup\n\nimport (\n    \"context\"\n    \"testing\"\n)\n\nfunc TestCleanupExpiredSessions(t *testing.T) {\n    ctx := context.Background()\n    \n    \u002F\u002F Create some expired sessions first\n    createExpiredSession(ctx)\n    \n    \u002F\u002F Call the endpoint directly\n    err := CleanupExpiredSessions(ctx)\n    if err != nil {\n        t.Fatalf(\"cleanup failed: %v\", err)\n    }\n    \n    \u002F\u002F Verify cleanup happened\n    count := countSessions(ctx)\n    if count != 0 {\n        t.Errorf(\"expected 0 sessions, got %d\", count)\n    }\n}\n",[1521],{"type":44,"tag":66,"props":1522,"children":1523},{"__ignoreMap":87},[1524,1532,1540,1547,1554,1561,1568,1575,1582,1590,1597,1604,1612,1620,1627,1635,1643,1650,1658,1665,1672,1680,1688,1696,1704,1711],{"type":44,"tag":93,"props":1525,"children":1526},{"class":95,"line":96},[1527],{"type":44,"tag":93,"props":1528,"children":1529},{},[1530],{"type":50,"value":1531},"\u002F\u002F cleanup\u002Fcleanup_test.go\n",{"type":44,"tag":93,"props":1533,"children":1534},{"class":95,"line":106},[1535],{"type":44,"tag":93,"props":1536,"children":1537},{},[1538],{"type":50,"value":1539},"package cleanup\n",{"type":44,"tag":93,"props":1541,"children":1542},{"class":95,"line":126},[1543],{"type":44,"tag":93,"props":1544,"children":1545},{"emptyLinePlaceholder":130},[1546],{"type":50,"value":133},{"type":44,"tag":93,"props":1548,"children":1549},{"class":95,"line":136},[1550],{"type":44,"tag":93,"props":1551,"children":1552},{},[1553],{"type":50,"value":281},{"type":44,"tag":93,"props":1555,"children":1556},{"class":95,"line":28},[1557],{"type":44,"tag":93,"props":1558,"children":1559},{},[1560],{"type":50,"value":289},{"type":44,"tag":93,"props":1562,"children":1563},{"class":95,"line":161},[1564],{"type":44,"tag":93,"props":1565,"children":1566},{},[1567],{"type":50,"value":297},{"type":44,"tag":93,"props":1569,"children":1570},{"class":95,"line":169},[1571],{"type":44,"tag":93,"props":1572,"children":1573},{},[1574],{"type":50,"value":305},{"type":44,"tag":93,"props":1576,"children":1577},{"class":95,"line":178},[1578],{"type":44,"tag":93,"props":1579,"children":1580},{"emptyLinePlaceholder":130},[1581],{"type":50,"value":133},{"type":44,"tag":93,"props":1583,"children":1584},{"class":95,"line":315},[1585],{"type":44,"tag":93,"props":1586,"children":1587},{},[1588],{"type":50,"value":1589},"func TestCleanupExpiredSessions(t *testing.T) {\n",{"type":44,"tag":93,"props":1591,"children":1592},{"class":95,"line":324},[1593],{"type":44,"tag":93,"props":1594,"children":1595},{},[1596],{"type":50,"value":330},{"type":44,"tag":93,"props":1598,"children":1599},{"class":95,"line":333},[1600],{"type":44,"tag":93,"props":1601,"children":1602},{},[1603],{"type":50,"value":339},{"type":44,"tag":93,"props":1605,"children":1606},{"class":95,"line":342},[1607],{"type":44,"tag":93,"props":1608,"children":1609},{},[1610],{"type":50,"value":1611},"    \u002F\u002F Create some expired sessions first\n",{"type":44,"tag":93,"props":1613,"children":1614},{"class":95,"line":351},[1615],{"type":44,"tag":93,"props":1616,"children":1617},{},[1618],{"type":50,"value":1619},"    createExpiredSession(ctx)\n",{"type":44,"tag":93,"props":1621,"children":1622},{"class":95,"line":360},[1623],{"type":44,"tag":93,"props":1624,"children":1625},{},[1626],{"type":50,"value":339},{"type":44,"tag":93,"props":1628,"children":1629},{"class":95,"line":369},[1630],{"type":44,"tag":93,"props":1631,"children":1632},{},[1633],{"type":50,"value":1634},"    \u002F\u002F Call the endpoint directly\n",{"type":44,"tag":93,"props":1636,"children":1637},{"class":95,"line":378},[1638],{"type":44,"tag":93,"props":1639,"children":1640},{},[1641],{"type":50,"value":1642},"    err := CleanupExpiredSessions(ctx)\n",{"type":44,"tag":93,"props":1644,"children":1645},{"class":95,"line":386},[1646],{"type":44,"tag":93,"props":1647,"children":1648},{},[1649],{"type":50,"value":357},{"type":44,"tag":93,"props":1651,"children":1652},{"class":95,"line":395},[1653],{"type":44,"tag":93,"props":1654,"children":1655},{},[1656],{"type":50,"value":1657},"        t.Fatalf(\"cleanup failed: %v\", err)\n",{"type":44,"tag":93,"props":1659,"children":1660},{"class":95,"line":404},[1661],{"type":44,"tag":93,"props":1662,"children":1663},{},[1664],{"type":50,"value":375},{"type":44,"tag":93,"props":1666,"children":1667},{"class":95,"line":412},[1668],{"type":44,"tag":93,"props":1669,"children":1670},{},[1671],{"type":50,"value":339},{"type":44,"tag":93,"props":1673,"children":1674},{"class":95,"line":746},[1675],{"type":44,"tag":93,"props":1676,"children":1677},{},[1678],{"type":50,"value":1679},"    \u002F\u002F Verify cleanup happened\n",{"type":44,"tag":93,"props":1681,"children":1682},{"class":95,"line":755},[1683],{"type":44,"tag":93,"props":1684,"children":1685},{},[1686],{"type":50,"value":1687},"    count := countSessions(ctx)\n",{"type":44,"tag":93,"props":1689,"children":1690},{"class":95,"line":763},[1691],{"type":44,"tag":93,"props":1692,"children":1693},{},[1694],{"type":50,"value":1695},"    if count != 0 {\n",{"type":44,"tag":93,"props":1697,"children":1698},{"class":95,"line":772},[1699],{"type":44,"tag":93,"props":1700,"children":1701},{},[1702],{"type":50,"value":1703},"        t.Errorf(\"expected 0 sessions, got %d\", count)\n",{"type":44,"tag":93,"props":1705,"children":1706},{"class":95,"line":780},[1707],{"type":44,"tag":93,"props":1708,"children":1709},{},[1710],{"type":50,"value":375},{"type":44,"tag":93,"props":1712,"children":1713},{"class":95,"line":24},[1714],{"type":44,"tag":93,"props":1715,"children":1716},{},[1717],{"type":50,"value":418},{"type":44,"tag":75,"props":1719,"children":1721},{"id":1720},"table-driven-tests",[1722],{"type":50,"value":1723},"Table-Driven Tests",{"type":44,"tag":82,"props":1725,"children":1727},{"className":245,"code":1726,"language":23,"meta":87,"style":87},"func TestValidateEmail(t *testing.T) {\n    tests := []struct {\n        name    string\n        email   string\n        wantErr bool\n    }{\n        {\"valid email\", \"user@example.com\", false},\n        {\"missing @\", \"userexample.com\", true},\n        {\"empty\", \"\", true},\n        {\"valid with subdomain\", \"user@mail.example.com\", false},\n    }\n    \n    for _, tt := range tests {\n        t.Run(tt.name, func(t *testing.T) {\n            err := validateEmail(tt.email)\n            if (err != nil) != tt.wantErr {\n                t.Errorf(\"validateEmail(%q) error = %v, wantErr %v\", tt.email, err, tt.wantErr)\n            }\n        })\n    }\n}\n",[1728],{"type":44,"tag":66,"props":1729,"children":1730},{"__ignoreMap":87},[1731,1739,1747,1755,1763,1771,1779,1787,1795,1803,1811,1818,1825,1833,1841,1849,1857,1865,1873,1881,1888],{"type":44,"tag":93,"props":1732,"children":1733},{"class":95,"line":96},[1734],{"type":44,"tag":93,"props":1735,"children":1736},{},[1737],{"type":50,"value":1738},"func TestValidateEmail(t *testing.T) {\n",{"type":44,"tag":93,"props":1740,"children":1741},{"class":95,"line":106},[1742],{"type":44,"tag":93,"props":1743,"children":1744},{},[1745],{"type":50,"value":1746},"    tests := []struct {\n",{"type":44,"tag":93,"props":1748,"children":1749},{"class":95,"line":126},[1750],{"type":44,"tag":93,"props":1751,"children":1752},{},[1753],{"type":50,"value":1754},"        name    string\n",{"type":44,"tag":93,"props":1756,"children":1757},{"class":95,"line":136},[1758],{"type":44,"tag":93,"props":1759,"children":1760},{},[1761],{"type":50,"value":1762},"        email   string\n",{"type":44,"tag":93,"props":1764,"children":1765},{"class":95,"line":28},[1766],{"type":44,"tag":93,"props":1767,"children":1768},{},[1769],{"type":50,"value":1770},"        wantErr bool\n",{"type":44,"tag":93,"props":1772,"children":1773},{"class":95,"line":161},[1774],{"type":44,"tag":93,"props":1775,"children":1776},{},[1777],{"type":50,"value":1778},"    }{\n",{"type":44,"tag":93,"props":1780,"children":1781},{"class":95,"line":169},[1782],{"type":44,"tag":93,"props":1783,"children":1784},{},[1785],{"type":50,"value":1786},"        {\"valid email\", \"user@example.com\", false},\n",{"type":44,"tag":93,"props":1788,"children":1789},{"class":95,"line":178},[1790],{"type":44,"tag":93,"props":1791,"children":1792},{},[1793],{"type":50,"value":1794},"        {\"missing @\", \"userexample.com\", true},\n",{"type":44,"tag":93,"props":1796,"children":1797},{"class":95,"line":315},[1798],{"type":44,"tag":93,"props":1799,"children":1800},{},[1801],{"type":50,"value":1802},"        {\"empty\", \"\", true},\n",{"type":44,"tag":93,"props":1804,"children":1805},{"class":95,"line":324},[1806],{"type":44,"tag":93,"props":1807,"children":1808},{},[1809],{"type":50,"value":1810},"        {\"valid with subdomain\", \"user@mail.example.com\", false},\n",{"type":44,"tag":93,"props":1812,"children":1813},{"class":95,"line":333},[1814],{"type":44,"tag":93,"props":1815,"children":1816},{},[1817],{"type":50,"value":375},{"type":44,"tag":93,"props":1819,"children":1820},{"class":95,"line":342},[1821],{"type":44,"tag":93,"props":1822,"children":1823},{},[1824],{"type":50,"value":339},{"type":44,"tag":93,"props":1826,"children":1827},{"class":95,"line":351},[1828],{"type":44,"tag":93,"props":1829,"children":1830},{},[1831],{"type":50,"value":1832},"    for _, tt := range tests {\n",{"type":44,"tag":93,"props":1834,"children":1835},{"class":95,"line":360},[1836],{"type":44,"tag":93,"props":1837,"children":1838},{},[1839],{"type":50,"value":1840},"        t.Run(tt.name, func(t *testing.T) {\n",{"type":44,"tag":93,"props":1842,"children":1843},{"class":95,"line":369},[1844],{"type":44,"tag":93,"props":1845,"children":1846},{},[1847],{"type":50,"value":1848},"            err := validateEmail(tt.email)\n",{"type":44,"tag":93,"props":1850,"children":1851},{"class":95,"line":378},[1852],{"type":44,"tag":93,"props":1853,"children":1854},{},[1855],{"type":50,"value":1856},"            if (err != nil) != tt.wantErr {\n",{"type":44,"tag":93,"props":1858,"children":1859},{"class":95,"line":386},[1860],{"type":44,"tag":93,"props":1861,"children":1862},{},[1863],{"type":50,"value":1864},"                t.Errorf(\"validateEmail(%q) error = %v, wantErr %v\", tt.email, err, tt.wantErr)\n",{"type":44,"tag":93,"props":1866,"children":1867},{"class":95,"line":395},[1868],{"type":44,"tag":93,"props":1869,"children":1870},{},[1871],{"type":50,"value":1872},"            }\n",{"type":44,"tag":93,"props":1874,"children":1875},{"class":95,"line":404},[1876],{"type":44,"tag":93,"props":1877,"children":1878},{},[1879],{"type":50,"value":1880},"        })\n",{"type":44,"tag":93,"props":1882,"children":1883},{"class":95,"line":412},[1884],{"type":44,"tag":93,"props":1885,"children":1886},{},[1887],{"type":50,"value":375},{"type":44,"tag":93,"props":1889,"children":1890},{"class":95,"line":746},[1891],{"type":44,"tag":93,"props":1892,"children":1893},{},[1894],{"type":50,"value":418},{"type":44,"tag":75,"props":1896,"children":1898},{"id":1897},"test-with-subtests",[1899],{"type":50,"value":1900},"Test with Subtests",{"type":44,"tag":82,"props":1902,"children":1904},{"className":245,"code":1903,"language":23,"meta":87,"style":87},"func TestUserCRUD(t *testing.T) {\n    ctx := context.Background()\n    var userID string\n    \n    t.Run(\"create\", func(t *testing.T) {\n        user, err := CreateUser(ctx, &CreateUserParams{\n            Email: \"test@example.com\",\n            Name:  \"Test\",\n        })\n        if err != nil {\n            t.Fatalf(\"create failed: %v\", err)\n        }\n        userID = user.ID\n    })\n    \n    t.Run(\"read\", func(t *testing.T) {\n        user, err := GetUser(ctx, &GetUserParams{ID: userID})\n        if err != nil {\n            t.Fatalf(\"read failed: %v\", err)\n        }\n        if user.Email != \"test@example.com\" {\n            t.Errorf(\"wrong email: %s\", user.Email)\n        }\n    })\n    \n    t.Run(\"delete\", func(t *testing.T) {\n        err := DeleteUser(ctx, &DeleteUserParams{ID: userID})\n        if err != nil {\n            t.Fatalf(\"delete failed: %v\", err)\n        }\n    })\n}\n",[1905],{"type":44,"tag":66,"props":1906,"children":1907},{"__ignoreMap":87},[1908,1916,1923,1931,1938,1946,1954,1962,1970,1977,1985,1993,2000,2008,2015,2022,2030,2038,2045,2053,2060,2068,2076,2083,2090,2097,2105,2113,2120,2128,2135,2142],{"type":44,"tag":93,"props":1909,"children":1910},{"class":95,"line":96},[1911],{"type":44,"tag":93,"props":1912,"children":1913},{},[1914],{"type":50,"value":1915},"func TestUserCRUD(t *testing.T) {\n",{"type":44,"tag":93,"props":1917,"children":1918},{"class":95,"line":106},[1919],{"type":44,"tag":93,"props":1920,"children":1921},{},[1922],{"type":50,"value":330},{"type":44,"tag":93,"props":1924,"children":1925},{"class":95,"line":126},[1926],{"type":44,"tag":93,"props":1927,"children":1928},{},[1929],{"type":50,"value":1930},"    var userID string\n",{"type":44,"tag":93,"props":1932,"children":1933},{"class":95,"line":136},[1934],{"type":44,"tag":93,"props":1935,"children":1936},{},[1937],{"type":50,"value":339},{"type":44,"tag":93,"props":1939,"children":1940},{"class":95,"line":28},[1941],{"type":44,"tag":93,"props":1942,"children":1943},{},[1944],{"type":50,"value":1945},"    t.Run(\"create\", func(t *testing.T) {\n",{"type":44,"tag":93,"props":1947,"children":1948},{"class":95,"line":161},[1949],{"type":44,"tag":93,"props":1950,"children":1951},{},[1952],{"type":50,"value":1953},"        user, err := CreateUser(ctx, &CreateUserParams{\n",{"type":44,"tag":93,"props":1955,"children":1956},{"class":95,"line":169},[1957],{"type":44,"tag":93,"props":1958,"children":1959},{},[1960],{"type":50,"value":1961},"            Email: \"test@example.com\",\n",{"type":44,"tag":93,"props":1963,"children":1964},{"class":95,"line":178},[1965],{"type":44,"tag":93,"props":1966,"children":1967},{},[1968],{"type":50,"value":1969},"            Name:  \"Test\",\n",{"type":44,"tag":93,"props":1971,"children":1972},{"class":95,"line":315},[1973],{"type":44,"tag":93,"props":1974,"children":1975},{},[1976],{"type":50,"value":1880},{"type":44,"tag":93,"props":1978,"children":1979},{"class":95,"line":324},[1980],{"type":44,"tag":93,"props":1981,"children":1982},{},[1983],{"type":50,"value":1984},"        if err != nil {\n",{"type":44,"tag":93,"props":1986,"children":1987},{"class":95,"line":333},[1988],{"type":44,"tag":93,"props":1989,"children":1990},{},[1991],{"type":50,"value":1992},"            t.Fatalf(\"create failed: %v\", err)\n",{"type":44,"tag":93,"props":1994,"children":1995},{"class":95,"line":342},[1996],{"type":44,"tag":93,"props":1997,"children":1998},{},[1999],{"type":50,"value":1269},{"type":44,"tag":93,"props":2001,"children":2002},{"class":95,"line":351},[2003],{"type":44,"tag":93,"props":2004,"children":2005},{},[2006],{"type":50,"value":2007},"        userID = user.ID\n",{"type":44,"tag":93,"props":2009,"children":2010},{"class":95,"line":360},[2011],{"type":44,"tag":93,"props":2012,"children":2013},{},[2014],{"type":50,"value":752},{"type":44,"tag":93,"props":2016,"children":2017},{"class":95,"line":369},[2018],{"type":44,"tag":93,"props":2019,"children":2020},{},[2021],{"type":50,"value":339},{"type":44,"tag":93,"props":2023,"children":2024},{"class":95,"line":378},[2025],{"type":44,"tag":93,"props":2026,"children":2027},{},[2028],{"type":50,"value":2029},"    t.Run(\"read\", func(t *testing.T) {\n",{"type":44,"tag":93,"props":2031,"children":2032},{"class":95,"line":386},[2033],{"type":44,"tag":93,"props":2034,"children":2035},{},[2036],{"type":50,"value":2037},"        user, err := GetUser(ctx, &GetUserParams{ID: userID})\n",{"type":44,"tag":93,"props":2039,"children":2040},{"class":95,"line":395},[2041],{"type":44,"tag":93,"props":2042,"children":2043},{},[2044],{"type":50,"value":1984},{"type":44,"tag":93,"props":2046,"children":2047},{"class":95,"line":404},[2048],{"type":44,"tag":93,"props":2049,"children":2050},{},[2051],{"type":50,"value":2052},"            t.Fatalf(\"read failed: %v\", err)\n",{"type":44,"tag":93,"props":2054,"children":2055},{"class":95,"line":412},[2056],{"type":44,"tag":93,"props":2057,"children":2058},{},[2059],{"type":50,"value":1269},{"type":44,"tag":93,"props":2061,"children":2062},{"class":95,"line":746},[2063],{"type":44,"tag":93,"props":2064,"children":2065},{},[2066],{"type":50,"value":2067},"        if user.Email != \"test@example.com\" {\n",{"type":44,"tag":93,"props":2069,"children":2070},{"class":95,"line":755},[2071],{"type":44,"tag":93,"props":2072,"children":2073},{},[2074],{"type":50,"value":2075},"            t.Errorf(\"wrong email: %s\", user.Email)\n",{"type":44,"tag":93,"props":2077,"children":2078},{"class":95,"line":763},[2079],{"type":44,"tag":93,"props":2080,"children":2081},{},[2082],{"type":50,"value":1269},{"type":44,"tag":93,"props":2084,"children":2085},{"class":95,"line":772},[2086],{"type":44,"tag":93,"props":2087,"children":2088},{},[2089],{"type":50,"value":752},{"type":44,"tag":93,"props":2091,"children":2092},{"class":95,"line":780},[2093],{"type":44,"tag":93,"props":2094,"children":2095},{},[2096],{"type":50,"value":339},{"type":44,"tag":93,"props":2098,"children":2099},{"class":95,"line":24},[2100],{"type":44,"tag":93,"props":2101,"children":2102},{},[2103],{"type":50,"value":2104},"    t.Run(\"delete\", func(t *testing.T) {\n",{"type":44,"tag":93,"props":2106,"children":2107},{"class":95,"line":796},[2108],{"type":44,"tag":93,"props":2109,"children":2110},{},[2111],{"type":50,"value":2112},"        err := DeleteUser(ctx, &DeleteUserParams{ID: userID})\n",{"type":44,"tag":93,"props":2114,"children":2115},{"class":95,"line":805},[2116],{"type":44,"tag":93,"props":2117,"children":2118},{},[2119],{"type":50,"value":1984},{"type":44,"tag":93,"props":2121,"children":2122},{"class":95,"line":813},[2123],{"type":44,"tag":93,"props":2124,"children":2125},{},[2126],{"type":50,"value":2127},"            t.Fatalf(\"delete failed: %v\", err)\n",{"type":44,"tag":93,"props":2129,"children":2130},{"class":95,"line":822},[2131],{"type":44,"tag":93,"props":2132,"children":2133},{},[2134],{"type":50,"value":1269},{"type":44,"tag":93,"props":2136,"children":2137},{"class":95,"line":830},[2138],{"type":44,"tag":93,"props":2139,"children":2140},{},[2141],{"type":50,"value":752},{"type":44,"tag":93,"props":2143,"children":2144},{"class":95,"line":838},[2145],{"type":44,"tag":93,"props":2146,"children":2147},{},[2148],{"type":50,"value":418},{"type":44,"tag":75,"props":2150,"children":2152},{"id":2151},"test-database-isolation",[2153],{"type":50,"value":2154},"Test Database Isolation",{"type":44,"tag":60,"props":2156,"children":2157},{},[2158,2160,2166],{"type":50,"value":2159},"Create isolated, fully-migrated test databases using ",{"type":44,"tag":66,"props":2161,"children":2163},{"className":2162},[],[2164],{"type":50,"value":2165},"et.NewTestDatabase()",{"type":50,"value":2167},":",{"type":44,"tag":82,"props":2169,"children":2171},{"className":245,"code":2170,"language":23,"meta":87,"style":87},"import \"encore.dev\u002Fet\"\n\nfunc TestWithFreshDatabase(t *testing.T) {\n    \u002F\u002F Creates a new database with all migrations applied\n    testDB := et.NewTestDatabase(t, db)\n\n    \u002F\u002F Use testDB for queries - it's completely isolated\n    _, err := testDB.Exec(ctx, \"INSERT INTO users (email) VALUES ($1)\", \"test@example.com\")\n    if err != nil {\n        t.Fatal(err)\n    }\n}\n",[2172],{"type":44,"tag":66,"props":2173,"children":2174},{"__ignoreMap":87},[2175,2183,2190,2198,2206,2214,2221,2229,2237,2244,2252,2259],{"type":44,"tag":93,"props":2176,"children":2177},{"class":95,"line":96},[2178],{"type":44,"tag":93,"props":2179,"children":2180},{},[2181],{"type":50,"value":2182},"import \"encore.dev\u002Fet\"\n",{"type":44,"tag":93,"props":2184,"children":2185},{"class":95,"line":106},[2186],{"type":44,"tag":93,"props":2187,"children":2188},{"emptyLinePlaceholder":130},[2189],{"type":50,"value":133},{"type":44,"tag":93,"props":2191,"children":2192},{"class":95,"line":126},[2193],{"type":44,"tag":93,"props":2194,"children":2195},{},[2196],{"type":50,"value":2197},"func TestWithFreshDatabase(t *testing.T) {\n",{"type":44,"tag":93,"props":2199,"children":2200},{"class":95,"line":136},[2201],{"type":44,"tag":93,"props":2202,"children":2203},{},[2204],{"type":50,"value":2205},"    \u002F\u002F Creates a new database with all migrations applied\n",{"type":44,"tag":93,"props":2207,"children":2208},{"class":95,"line":28},[2209],{"type":44,"tag":93,"props":2210,"children":2211},{},[2212],{"type":50,"value":2213},"    testDB := et.NewTestDatabase(t, db)\n",{"type":44,"tag":93,"props":2215,"children":2216},{"class":95,"line":161},[2217],{"type":44,"tag":93,"props":2218,"children":2219},{"emptyLinePlaceholder":130},[2220],{"type":50,"value":133},{"type":44,"tag":93,"props":2222,"children":2223},{"class":95,"line":169},[2224],{"type":44,"tag":93,"props":2225,"children":2226},{},[2227],{"type":50,"value":2228},"    \u002F\u002F Use testDB for queries - it's completely isolated\n",{"type":44,"tag":93,"props":2230,"children":2231},{"class":95,"line":178},[2232],{"type":44,"tag":93,"props":2233,"children":2234},{},[2235],{"type":50,"value":2236},"    _, err := testDB.Exec(ctx, \"INSERT INTO users (email) VALUES ($1)\", \"test@example.com\")\n",{"type":44,"tag":93,"props":2238,"children":2239},{"class":95,"line":315},[2240],{"type":44,"tag":93,"props":2241,"children":2242},{},[2243],{"type":50,"value":357},{"type":44,"tag":93,"props":2245,"children":2246},{"class":95,"line":324},[2247],{"type":44,"tag":93,"props":2248,"children":2249},{},[2250],{"type":50,"value":2251},"        t.Fatal(err)\n",{"type":44,"tag":93,"props":2253,"children":2254},{"class":95,"line":333},[2255],{"type":44,"tag":93,"props":2256,"children":2257},{},[2258],{"type":50,"value":375},{"type":44,"tag":93,"props":2260,"children":2261},{"class":95,"line":342},[2262],{"type":44,"tag":93,"props":2263,"children":2264},{},[2265],{"type":50,"value":418},{"type":44,"tag":75,"props":2267,"children":2269},{"id":2268},"service-instance-isolation",[2270],{"type":50,"value":2271},"Service Instance Isolation",{"type":44,"tag":60,"props":2273,"children":2274},{},[2275],{"type":50,"value":2276},"By default, service structs are shared across tests for performance. Enable isolation when tests modify service state:",{"type":44,"tag":82,"props":2278,"children":2280},{"className":245,"code":2279,"language":23,"meta":87,"style":87},"import \"encore.dev\u002Fet\"\n\nfunc TestWithServiceIsolation(t *testing.T) {\n    \u002F\u002F Enable service instance isolation for this test\n    et.EnableServiceInstanceIsolation()\n\n    \u002F\u002F Now this test gets its own service struct instance\n    \u002F\u002F preventing state interference with other tests\n}\n",[2281],{"type":44,"tag":66,"props":2282,"children":2283},{"__ignoreMap":87},[2284,2291,2298,2306,2314,2322,2329,2337,2345],{"type":44,"tag":93,"props":2285,"children":2286},{"class":95,"line":96},[2287],{"type":44,"tag":93,"props":2288,"children":2289},{},[2290],{"type":50,"value":2182},{"type":44,"tag":93,"props":2292,"children":2293},{"class":95,"line":106},[2294],{"type":44,"tag":93,"props":2295,"children":2296},{"emptyLinePlaceholder":130},[2297],{"type":50,"value":133},{"type":44,"tag":93,"props":2299,"children":2300},{"class":95,"line":126},[2301],{"type":44,"tag":93,"props":2302,"children":2303},{},[2304],{"type":50,"value":2305},"func TestWithServiceIsolation(t *testing.T) {\n",{"type":44,"tag":93,"props":2307,"children":2308},{"class":95,"line":136},[2309],{"type":44,"tag":93,"props":2310,"children":2311},{},[2312],{"type":50,"value":2313},"    \u002F\u002F Enable service instance isolation for this test\n",{"type":44,"tag":93,"props":2315,"children":2316},{"class":95,"line":28},[2317],{"type":44,"tag":93,"props":2318,"children":2319},{},[2320],{"type":50,"value":2321},"    et.EnableServiceInstanceIsolation()\n",{"type":44,"tag":93,"props":2323,"children":2324},{"class":95,"line":161},[2325],{"type":44,"tag":93,"props":2326,"children":2327},{"emptyLinePlaceholder":130},[2328],{"type":50,"value":133},{"type":44,"tag":93,"props":2330,"children":2331},{"class":95,"line":169},[2332],{"type":44,"tag":93,"props":2333,"children":2334},{},[2335],{"type":50,"value":2336},"    \u002F\u002F Now this test gets its own service struct instance\n",{"type":44,"tag":93,"props":2338,"children":2339},{"class":95,"line":178},[2340],{"type":44,"tag":93,"props":2341,"children":2342},{},[2343],{"type":50,"value":2344},"    \u002F\u002F preventing state interference with other tests\n",{"type":44,"tag":93,"props":2346,"children":2347},{"class":95,"line":315},[2348],{"type":44,"tag":93,"props":2349,"children":2350},{},[2351],{"type":50,"value":418},{"type":44,"tag":75,"props":2353,"children":2355},{"id":2354},"test-tracing-dashboard",[2356],{"type":50,"value":2357},"Test Tracing Dashboard",{"type":44,"tag":60,"props":2359,"children":2360},{},[2361,2363,2369],{"type":50,"value":2362},"View test execution traces in the development dashboard at ",{"type":44,"tag":66,"props":2364,"children":2366},{"className":2365},[],[2367],{"type":50,"value":2368},"http:\u002F\u002Flocalhost:9400",{"type":50,"value":2370}," while tests run. This helps diagnose failures by showing:",{"type":44,"tag":218,"props":2372,"children":2373},{},[2374,2379,2384,2389],{"type":44,"tag":222,"props":2375,"children":2376},{},[2377],{"type":50,"value":2378},"Request\u002Fresponse data",{"type":44,"tag":222,"props":2380,"children":2381},{},[2382],{"type":50,"value":2383},"Database queries",{"type":44,"tag":222,"props":2385,"children":2386},{},[2387],{"type":50,"value":2388},"Service-to-service calls",{"type":44,"tag":222,"props":2390,"children":2391},{},[2392],{"type":50,"value":2393},"Errors and stack traces",{"type":44,"tag":75,"props":2395,"children":2397},{"id":2396},"mocking-endpoints-and-services",[2398],{"type":50,"value":2399},"Mocking Endpoints and Services",{"type":44,"tag":60,"props":2401,"children":2402},{},[2403],{"type":50,"value":2404},"Mock endpoints or entire services for isolated unit testing:",{"type":44,"tag":82,"props":2406,"children":2408},{"className":245,"code":2407,"language":23,"meta":87,"style":87},"import \"encore.dev\u002Fet\"\n\nfunc TestWithMockedEndpoint(t *testing.T) {\n    \u002F\u002F Mock a specific endpoint\n    et.MockEndpoint(products.GetPrice, func(ctx context.Context, p *products.PriceParams) (*products.PriceResponse, error) {\n        return &products.PriceResponse{Price: 100}, nil\n    })\n\n    \u002F\u002F Mock an entire service\n    et.MockService(\"products\", &mockProductService{})\n}\n",[2409],{"type":44,"tag":66,"props":2410,"children":2411},{"__ignoreMap":87},[2412,2419,2426,2434,2442,2450,2458,2465,2472,2480,2488],{"type":44,"tag":93,"props":2413,"children":2414},{"class":95,"line":96},[2415],{"type":44,"tag":93,"props":2416,"children":2417},{},[2418],{"type":50,"value":2182},{"type":44,"tag":93,"props":2420,"children":2421},{"class":95,"line":106},[2422],{"type":44,"tag":93,"props":2423,"children":2424},{"emptyLinePlaceholder":130},[2425],{"type":50,"value":133},{"type":44,"tag":93,"props":2427,"children":2428},{"class":95,"line":126},[2429],{"type":44,"tag":93,"props":2430,"children":2431},{},[2432],{"type":50,"value":2433},"func TestWithMockedEndpoint(t *testing.T) {\n",{"type":44,"tag":93,"props":2435,"children":2436},{"class":95,"line":136},[2437],{"type":44,"tag":93,"props":2438,"children":2439},{},[2440],{"type":50,"value":2441},"    \u002F\u002F Mock a specific endpoint\n",{"type":44,"tag":93,"props":2443,"children":2444},{"class":95,"line":28},[2445],{"type":44,"tag":93,"props":2446,"children":2447},{},[2448],{"type":50,"value":2449},"    et.MockEndpoint(products.GetPrice, func(ctx context.Context, p *products.PriceParams) (*products.PriceResponse, error) {\n",{"type":44,"tag":93,"props":2451,"children":2452},{"class":95,"line":161},[2453],{"type":44,"tag":93,"props":2454,"children":2455},{},[2456],{"type":50,"value":2457},"        return &products.PriceResponse{Price: 100}, nil\n",{"type":44,"tag":93,"props":2459,"children":2460},{"class":95,"line":169},[2461],{"type":44,"tag":93,"props":2462,"children":2463},{},[2464],{"type":50,"value":752},{"type":44,"tag":93,"props":2466,"children":2467},{"class":95,"line":178},[2468],{"type":44,"tag":93,"props":2469,"children":2470},{"emptyLinePlaceholder":130},[2471],{"type":50,"value":133},{"type":44,"tag":93,"props":2473,"children":2474},{"class":95,"line":315},[2475],{"type":44,"tag":93,"props":2476,"children":2477},{},[2478],{"type":50,"value":2479},"    \u002F\u002F Mock an entire service\n",{"type":44,"tag":93,"props":2481,"children":2482},{"class":95,"line":324},[2483],{"type":44,"tag":93,"props":2484,"children":2485},{},[2486],{"type":50,"value":2487},"    et.MockService(\"products\", &mockProductService{})\n",{"type":44,"tag":93,"props":2489,"children":2490},{"class":95,"line":333},[2491],{"type":44,"tag":93,"props":2492,"children":2493},{},[2494],{"type":50,"value":418},{"type":44,"tag":75,"props":2496,"children":2498},{"id":2497},"guidelines",[2499],{"type":50,"value":2500},"Guidelines",{"type":44,"tag":218,"props":2502,"children":2503},{},[2504,2516,2521,2526,2531,2536,2547,2559,2564],{"type":44,"tag":222,"props":2505,"children":2506},{},[2507,2509,2514],{"type":50,"value":2508},"Use ",{"type":44,"tag":66,"props":2510,"children":2512},{"className":2511},[],[2513],{"type":50,"value":71},{"type":50,"value":2515}," to run tests with infrastructure setup",{"type":44,"tag":222,"props":2517,"children":2518},{},[2519],{"type":50,"value":2520},"Each test gets access to real infrastructure (databases, Pub\u002FSub)",{"type":44,"tag":222,"props":2522,"children":2523},{},[2524],{"type":50,"value":2525},"Test API endpoints by calling them directly as functions",{"type":44,"tag":222,"props":2527,"children":2528},{},[2529],{"type":50,"value":2530},"Service-to-service calls work normally in tests",{"type":44,"tag":222,"props":2532,"children":2533},{},[2534],{"type":50,"value":2535},"Use table-driven tests for testing multiple cases",{"type":44,"tag":222,"props":2537,"children":2538},{},[2539,2540,2545],{"type":50,"value":2508},{"type":44,"tag":66,"props":2541,"children":2543},{"className":2542},[],[2544],{"type":50,"value":2165},{"type":50,"value":2546}," for isolated database testing",{"type":44,"tag":222,"props":2548,"children":2549},{},[2550,2551,2557],{"type":50,"value":2508},{"type":44,"tag":66,"props":2552,"children":2554},{"className":2553},[],[2555],{"type":50,"value":2556},"et.EnableServiceInstanceIsolation()",{"type":50,"value":2558}," when tests modify service state",{"type":44,"tag":222,"props":2560,"children":2561},{},[2562],{"type":50,"value":2563},"Don't mock Encore infrastructure - use the real thing",{"type":44,"tag":222,"props":2565,"children":2566},{},[2567],{"type":50,"value":2568},"Mock external dependencies (third-party APIs, email services, etc.)",{"type":44,"tag":2570,"props":2571,"children":2572},"style",{},[2573],{"type":50,"value":2574},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"items":2576,"total":805},[2577,2589,2601,2619,2635,2647,2663],{"slug":2578,"name":2578,"fn":2579,"description":2580,"org":2581,"tags":2582,"stars":24,"repoUrl":25,"updatedAt":2588},"encore-api","build type-safe APIs with Encore","Define typed API endpoints in Encore.ts using `api(...)` from `encore.dev\u002Fapi`. Covers typed request\u002Fresponse interfaces, path\u002Fquery\u002Fheader\u002Fcookie params, request validation, and `APIError`. For raw endpoints (`api.raw()`) and inbound webhooks, use `encore-webhook` instead.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[2583,2584,2585],{"name":16,"slug":17,"type":14},{"name":9,"slug":8,"type":14},{"name":2586,"slug":2587,"type":14},"TypeScript","typescript","2026-04-06T18:09:46.044101",{"slug":2590,"name":2590,"fn":2591,"description":2592,"org":2593,"tags":2594,"stars":24,"repoUrl":25,"updatedAt":2600},"encore-auth","implement Encore.ts authentication","Protect Encore.ts endpoints with authentication and authorize callers. Covers `authHandler`, `Gateway`, `getAuthData`, and `auth: true`.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[2595,2598,2599],{"name":2596,"slug":2597,"type":14},"Auth","auth",{"name":9,"slug":8,"type":14},{"name":2586,"slug":2587,"type":14},"2026-04-06T18:09:47.336322",{"slug":2602,"name":2602,"fn":2603,"description":2604,"org":2605,"tags":2606,"stars":24,"repoUrl":25,"updatedAt":2618},"encore-bucket","store files in Encore.ts buckets","Store unstructured files in Encore.ts using `Bucket` from `encore.dev\u002Fstorage\u002Fobjects` — uploads, images, documents, blobs.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[2607,2610,2611,2614,2617],{"name":2608,"slug":2609,"type":14},"Backend","backend",{"name":9,"slug":8,"type":14},{"name":2612,"slug":2613,"type":14},"File Storage","file-storage",{"name":2615,"slug":2616,"type":14},"File Uploads","file-uploads",{"name":2586,"slug":2587,"type":14},"2026-05-16T05:59:52.813772",{"slug":2620,"name":2620,"fn":2621,"description":2622,"org":2623,"tags":2624,"stars":24,"repoUrl":25,"updatedAt":2634},"encore-cache","cache data in Redis with Encore.ts","Cache data in Redis from Encore.ts using `CacheCluster` and typed keyspaces from `encore.dev\u002Fstorage\u002Fcache`. Type-safe key\u002Fvalue access with TTLs, atomic increments, and per-keyspace data shapes.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[2625,2626,2629,2630,2633],{"name":2608,"slug":2609,"type":14},{"name":2627,"slug":2628,"type":14},"Caching","caching",{"name":9,"slug":8,"type":14},{"name":2631,"slug":2632,"type":14},"Redis","redis",{"name":2586,"slug":2587,"type":14},"2026-05-16T05:59:56.808328",{"slug":2636,"name":2636,"fn":2637,"description":2638,"org":2639,"tags":2640,"stars":24,"repoUrl":25,"updatedAt":2646},"encore-code-review","review Encore.ts code","Review existing Encore.ts code for best practices and common anti-patterns.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[2641,2644,2645],{"name":2642,"slug":2643,"type":14},"Code Review","code-review",{"name":9,"slug":8,"type":14},{"name":2586,"slug":2587,"type":14},"2026-04-06T18:10:01.123999",{"slug":2648,"name":2648,"fn":2649,"description":2650,"org":2651,"tags":2652,"stars":24,"repoUrl":25,"updatedAt":2662},"encore-cron","schedule recurring jobs in Encore.ts","Schedule periodic \u002F recurring work in Encore.ts using `CronJob` from `encore.dev\u002Fcron`. Covers `every: \"1h\"` interval syntax and `schedule: \"0 9 * * 1\"` cron expressions.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[2653,2656,2657,2658,2661],{"name":2654,"slug":2655,"type":14},"Automation","automation",{"name":2608,"slug":2609,"type":14},{"name":9,"slug":8,"type":14},{"name":2659,"slug":2660,"type":14},"Scheduling","scheduling",{"name":2586,"slug":2587,"type":14},"2026-05-16T05:59:54.146651",{"slug":2664,"name":2664,"fn":2665,"description":2666,"org":2667,"tags":2668,"stars":24,"repoUrl":25,"updatedAt":2677},"encore-database","build Encore databases","Work with PostgreSQL in Encore.ts using `SQLDatabase` from `encore.dev\u002Fstorage\u002Fsqldb` — schema migrations and SQL queries.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[2669,2672,2673,2676],{"name":2670,"slug":2671,"type":14},"Database","database",{"name":9,"slug":8,"type":14},{"name":2674,"slug":2675,"type":14},"ORM","orm",{"name":2586,"slug":2587,"type":14},"2026-04-06T18:09:54.823017",{"items":2679,"total":805},[2680,2686,2692,2700,2708,2714,2722,2729,2746,2763,2773,2784],{"slug":2578,"name":2578,"fn":2579,"description":2580,"org":2681,"tags":2682,"stars":24,"repoUrl":25,"updatedAt":2588},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[2683,2684,2685],{"name":16,"slug":17,"type":14},{"name":9,"slug":8,"type":14},{"name":2586,"slug":2587,"type":14},{"slug":2590,"name":2590,"fn":2591,"description":2592,"org":2687,"tags":2688,"stars":24,"repoUrl":25,"updatedAt":2600},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[2689,2690,2691],{"name":2596,"slug":2597,"type":14},{"name":9,"slug":8,"type":14},{"name":2586,"slug":2587,"type":14},{"slug":2602,"name":2602,"fn":2603,"description":2604,"org":2693,"tags":2694,"stars":24,"repoUrl":25,"updatedAt":2618},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[2695,2696,2697,2698,2699],{"name":2608,"slug":2609,"type":14},{"name":9,"slug":8,"type":14},{"name":2612,"slug":2613,"type":14},{"name":2615,"slug":2616,"type":14},{"name":2586,"slug":2587,"type":14},{"slug":2620,"name":2620,"fn":2621,"description":2622,"org":2701,"tags":2702,"stars":24,"repoUrl":25,"updatedAt":2634},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[2703,2704,2705,2706,2707],{"name":2608,"slug":2609,"type":14},{"name":2627,"slug":2628,"type":14},{"name":9,"slug":8,"type":14},{"name":2631,"slug":2632,"type":14},{"name":2586,"slug":2587,"type":14},{"slug":2636,"name":2636,"fn":2637,"description":2638,"org":2709,"tags":2710,"stars":24,"repoUrl":25,"updatedAt":2646},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[2711,2712,2713],{"name":2642,"slug":2643,"type":14},{"name":9,"slug":8,"type":14},{"name":2586,"slug":2587,"type":14},{"slug":2648,"name":2648,"fn":2649,"description":2650,"org":2715,"tags":2716,"stars":24,"repoUrl":25,"updatedAt":2662},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[2717,2718,2719,2720,2721],{"name":2654,"slug":2655,"type":14},{"name":2608,"slug":2609,"type":14},{"name":9,"slug":8,"type":14},{"name":2659,"slug":2660,"type":14},{"name":2586,"slug":2587,"type":14},{"slug":2664,"name":2664,"fn":2665,"description":2666,"org":2723,"tags":2724,"stars":24,"repoUrl":25,"updatedAt":2677},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[2725,2726,2727,2728],{"name":2670,"slug":2671,"type":14},{"name":9,"slug":8,"type":14},{"name":2674,"slug":2675,"type":14},{"name":2586,"slug":2587,"type":14},{"slug":2730,"name":2730,"fn":2731,"description":2732,"org":2733,"tags":2734,"stars":24,"repoUrl":25,"updatedAt":2745},"encore-frontend","connect frontend to Encore backend","Connect a frontend application (React, Next.js, Vue, Svelte, etc.) to an Encore.ts backend.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[2735,2736,2739,2742],{"name":9,"slug":8,"type":14},{"name":2737,"slug":2738,"type":14},"Frontend","frontend",{"name":2740,"slug":2741,"type":14},"Next.js","next-js",{"name":2743,"slug":2744,"type":14},"React","react","2026-04-06T18:09:56.091006",{"slug":2747,"name":2747,"fn":2748,"description":2749,"org":2750,"tags":2751,"stars":24,"repoUrl":25,"updatedAt":2762},"encore-getting-started","build and run applications with Encore.ts","Bootstrap a brand-new Encore.ts project from zero. Only for first-time CLI install and `encore app create` — not for architecture or feature questions.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[2752,2753,2754,2755,2758,2759],{"name":16,"slug":17,"type":14},{"name":2608,"slug":2609,"type":14},{"name":9,"slug":8,"type":14},{"name":2756,"slug":2757,"type":14},"Local Development","local-development",{"name":2586,"slug":2587,"type":14},{"name":2760,"slug":2761,"type":14},"Web Development","web-development","2026-04-06T18:10:04.885446",{"slug":2764,"name":2764,"fn":2765,"description":2766,"org":2767,"tags":2768,"stars":24,"repoUrl":25,"updatedAt":2772},"encore-go-api","build APIs with Encore Go","Define typed API endpoints in Encore Go using `\u002F\u002Fencore:api` annotations. Covers typed request\u002Fresponse structs, path\u002Fquery\u002Fheader\u002Fcookie params, and error returns. For raw endpoints (`\u002F\u002Fencore:api raw`) and inbound webhooks, use `encore-go-webhook` instead.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[2769,2770,2771],{"name":16,"slug":17,"type":14},{"name":9,"slug":8,"type":14},{"name":22,"slug":23,"type":14},"2026-04-06T18:09:48.578781",{"slug":2774,"name":2774,"fn":2775,"description":2776,"org":2777,"tags":2778,"stars":24,"repoUrl":25,"updatedAt":2783},"encore-go-auth","implement authentication with Encore Go","Protect Encore Go endpoints with authentication and authorize callers. Covers `auth.AuthHandler`, `auth.UserID`, the `Authorization` header, and `\u002F\u002Fencore:api auth`.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[2779,2780,2781,2782],{"name":2596,"slug":2597,"type":14},{"name":2608,"slug":2609,"type":14},{"name":9,"slug":8,"type":14},{"name":22,"slug":23,"type":14},"2026-04-06T18:09:51.065102",{"slug":2785,"name":2785,"fn":2786,"description":2787,"org":2788,"tags":2789,"stars":24,"repoUrl":25,"updatedAt":2797},"encore-go-bucket","store files in Encore Go buckets","Store unstructured files in Encore Go using `objects.NewBucket` from `encore.dev\u002Fstorage\u002Fobjects` — uploads, images, documents, blobs.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[2790,2791,2792,2793,2794],{"name":2608,"slug":2609,"type":14},{"name":9,"slug":8,"type":14},{"name":2612,"slug":2613,"type":14},{"name":22,"slug":23,"type":14},{"name":2795,"slug":2796,"type":14},"Storage","storage","2026-05-16T06:00:03.633918"]