//go:build milestone2 // Package repository_test — Milestone 2 §2.3 failing SQLC query presence // tests. // // Build tag: gated behind `milestone2` so the default `task fullsuite:ci` // run does not execute it. See the comment in milestone2_migrations_test.go // for the workflow the golang engineer follows to flip these tests from // RED to GREEN. // // These tests prove that the next batch of SQLC queries required by // Milestone 2 (plan Section 6.3 / tracking §2.3) are available on the // generated *Queries type once the golang engineer runs `task generate` // against a new internal/database/queries/custommetadata.sql query file. // // They use reflection to introspect the *Queries receiver rather than // calling the methods directly so the test file can compile before the // queries exist — a hard compile-time reference would break the whole // package build and the rest of Milestone 1's tests with it. // // When the golang engineer adds the new SQL query blocks and re-runs // `task generate`, sqlc will emit the corresponding Go methods and // these tests will flip from failing to passing without any further // edits. package repository_test import ( "reflect" "testing" "queryorchestration/internal/database/repository" "github.com/stretchr/testify/require" ) // milestone2RequiredQueries is the full list of new SQLC-generated // method names that §2.3 of the v4 tracking doc requires. Every row // maps to a block in the forthcoming internal/database/queries/custommetadata.sql // file. The comment after each name traces back to the tracking line. // // Deliberately NOT in this list (see the "v4" notes in the tracking doc): // - DocumentHasLegacyExtractions: reuse existing HasFieldExtraction // - DeleteDocumentCustomMetadata: FK cascade replaces it // - NullifyDocumentCustomSchemaId: reset-metadata uses a direct UPDATE // - DeleteClientMetadataSchemas: FK cascade replaces it // - LockDocumentCustomMetadataForVersion: v3 name, replaced by // LockDocumentForMetadataWrite var milestone2RequiredQueries = []struct { method string trackRef string }{ { method: "CreateDocumentCustomMetadata", trackRef: "§2.3 CreateDocumentCustomMetadata (no schema_id parameter)", }, { method: "GetCurrentDocumentCustomMetadata", trackRef: "§2.3 GetCurrentDocumentCustomMetadata (ORDER BY version DESC LIMIT 1, joins documents + client_metadata_schemas)", }, { method: "GetDocumentCustomMetadataByVersion", trackRef: "§2.3 GetDocumentCustomMetadataByVersion (same join)", }, { method: "GetDocumentCustomMetadataHistory", trackRef: "§2.3 GetDocumentCustomMetadataHistory (no schema join)", }, { method: "LockDocumentForMetadataWrite", trackRef: "§2.3 LockDocumentForMetadataWrite (parent-row lock replacing v3's LockDocumentCustomMetadataForVersion)", }, { method: "GetMaxDocumentMetadataVersion", trackRef: "§2.3 GetMaxDocumentMetadataVersion (COALESCE(MAX(version), 0))", }, { method: "SetDocumentCustomSchemaId", trackRef: "§2.3 SetDocumentCustomSchemaId", }, { method: "GetDocumentCustomSchemaId", trackRef: "§2.3 GetDocumentCustomSchemaId", }, } // TestMilestone2_RequiredSQLCQueries asserts every method in // milestone2RequiredQueries is present on the generated *repository.Queries // type. Uses reflection so this file compiles even before the query file // lands — a hard Go reference would break the whole test binary and // every other Milestone 1 test with it. // // This test FAILS intentionally until the golang engineer adds the query // blocks to internal/database/queries/custommetadata.sql and runs // `task generate`. func TestMilestone2_RequiredSQLCQueries(t *testing.T) { t.Parallel() // No DB needed — this is a pure type-introspection check. // We still run under short mode since the assertion is a static // shape check and should be part of the fast unit sweep. var q repository.Queries qType := reflect.TypeOf(&q) for _, want := range milestone2RequiredQueries { want := want t.Run(want.method, func(t *testing.T) { t.Parallel() _, ok := qType.MethodByName(want.method) require.Truef(t, ok, "generated *repository.Queries must have method %q — source of truth: %s. "+ "Add the SQL block to internal/database/queries/custommetadata.sql and run `task generate`.", want.method, want.trackRef) }) } } // TestMilestone2_RemovedV3QueriesAbsent asserts the v3 query names that // v4 deliberately dropped never sneak back into the generated code. If a // future contributor copies a v3 snippet into custommetadata.sql these // assertions will fail loudly with a pointer to the tracking doc's // "v4 removed" notes. func TestMilestone2_RemovedV3QueriesAbsent(t *testing.T) { t.Parallel() forbidden := []struct { method string why string }{ { method: "DocumentHasLegacyExtractions", why: "v4 reuses existing HasFieldExtraction — see §2.3 'Reuse existing query'", }, { method: "DeleteDocumentCustomMetadata", why: "v4 relies on ON DELETE CASCADE via the document_id FK", }, { method: "NullifyDocumentCustomSchemaId", why: "v4 resets via direct UPDATE documents SET custom_schema_id = NULL", }, { method: "DeleteClientMetadataSchemas", why: "v4 relies on ON DELETE CASCADE via the client_id FK", }, { method: "LockDocumentCustomMetadataForVersion", why: "v4 uses LockDocumentForMetadataWrite (parent-row lock) instead", }, { method: "GetSchemaMetadataRecordCount", why: "v4 computes canDelete from GetSchemaDocumentCount alone", }, } var q repository.Queries qType := reflect.TypeOf(&q) for _, bad := range forbidden { bad := bad t.Run(bad.method, func(t *testing.T) { t.Parallel() _, ok := qType.MethodByName(bad.method) require.Falsef(t, ok, "*repository.Queries must NOT have method %q — %s", bad.method, bad.why) }) } }