diff --git a/ui-react/src/graphql/__tests__/model-tree-type-filter.test.ts b/ui-react/src/graphql/__tests__/model-tree-type-filter.test.ts new file mode 100644 index 0000000..2a75b19 --- /dev/null +++ b/ui-react/src/graphql/__tests__/model-tree-type-filter.test.ts @@ -0,0 +1,52 @@ +import { describe, it, expect } from 'vitest'; +import { print, type DocumentNode } from 'graphql'; +import { GetModelTreeDocument, GetModelFamiliesDocument } from '@/graphql/generated/graphql'; +import { GetModelTreeWithRegionsDocument } from '@/graphql/generated/modeling'; + +/** + * Regression guard for #98. + * + * `modelcatalog_software.type` classifies a model — Empirical, Coupled, + * Theory-Guided, and so on. It does not say whether a row is a model. Every row + * the ETL migrated matched `?id a sdm:Model` in the RDF, and the column holds + * the most specific subtype found; rows written through the REST API's generic + * `softwares` resource carry the ontology superclass `sd#Software`. So any + * predicate on `type` hides real, runnable models. + * + * Against TACC's catalog the old `type: { _eq: "sdm#Model" }` predicate reduced + * the model tree to 18 of 175 leaf configurations, and to 0 of the 61 that have + * every required input annotated in CKAN. + * + * An allowlist of "model" subtypes is not the fix either. `model-catalog-api` + * keeps one (`getSoftwareTypeFilter` in `service.ts`) and it is already stale — + * it returns 44 of TACC's 55 software rows, silently dropping three subtypes it + * was never taught plus every `sd#Software` row. + */ + +const DOCUMENTS: Array<[string, DocumentNode]> = [ + ['GetModelTree', GetModelTreeDocument], + ['GetModelFamilies', GetModelFamiliesDocument], + ['GetModelTreeWithRegions', GetModelTreeWithRegionsDocument], +]; + +describe('model-tree queries do not filter software by ontology type', () => { + it.each(DOCUMENTS)('%s selects modelcatalog_software', (_name, doc) => { + expect(print(doc)).toContain('modelcatalog_software'); + }); + + it.each(DOCUMENTS)('%s carries no type predicate', (_name, doc) => { + expect(print(doc)).not.toContain('type:'); + expect(print(doc)).not.toContain('w3id.org/okn/o/sdm#'); + expect(print(doc)).not.toContain('w3id.org/okn/o/sd#'); + }); + + it.each(DOCUMENTS)('%s passes modelcatalog_software no where argument', (_name, doc) => { + const rootField = doc.definitions + .flatMap((def) => (def.kind === 'OperationDefinition' ? def.selectionSet.selections : [])) + .find((sel) => sel.kind === 'Field' && sel.name.value === 'modelcatalog_software'); + + expect(rootField).toBeDefined(); + const args = rootField && rootField.kind === 'Field' ? (rootField.arguments ?? []) : []; + expect(args.map((a) => a.name.value)).toEqual(['order_by']); + }); +}); diff --git a/ui-react/src/graphql/generated/graphql.ts b/ui-react/src/graphql/generated/graphql.ts index d48f5e3..7f6f1ac 100644 --- a/ui-react/src/graphql/generated/graphql.ts +++ b/ui-react/src/graphql/generated/graphql.ts @@ -27659,10 +27659,7 @@ export type UpdateModelParameterMutationResult = Apollo.MutationResult; export const GetModelTreeDocument = gql` query GetModelTree { - modelcatalog_software( - order_by: {label: asc} - where: {type: {_eq: "https://w3id.org/okn/o/sdm#Model"}} - ) { + modelcatalog_software(order_by: {label: asc}) { id label versions(order_by: {label: asc}) { @@ -28222,10 +28219,7 @@ export type GetStandardVariablesWithUnitsSuspenseQueryHookResult = ReturnType; export const GetModelFamiliesDocument = gql` query GetModelFamilies { - modelcatalog_software( - order_by: {label: asc} - where: {type: {_eq: "https://w3id.org/okn/o/sdm#Model"}} - ) { + modelcatalog_software(order_by: {label: asc}) { id label versions(order_by: {label: asc}) { diff --git a/ui-react/src/graphql/generated/modeling.ts b/ui-react/src/graphql/generated/modeling.ts index ea6f08f..4e7e1c7 100644 --- a/ui-react/src/graphql/generated/modeling.ts +++ b/ui-react/src/graphql/generated/modeling.ts @@ -1389,12 +1389,13 @@ export function extractModelIO(config: ModelIOConfig): ModelIO { return { inputs, outputs, producesVariableIds }; } +// No type predicate — deliberate. `modelcatalog_software.type` classifies a model +// (Empirical, Coupled, Theory-Guided, ...); it does not say whether a row is a model. +// Filtering on `sdm#Model` showed the thread wizard 18 of TACC's 175 runnable leaf +// configurations, and none of the 61 that have data annotated. See #98. export const GetModelTreeWithRegionsDocument = gql` query GetModelTreeWithRegions { - modelcatalog_software( - order_by: { label: asc } - where: { type: { _eq: "https://w3id.org/okn/o/sdm#Model" } } - ) { + modelcatalog_software(order_by: { label: asc }) { id label versions(order_by: { label: asc }) { diff --git a/ui-react/src/graphql/queries/model-catalog.graphql b/ui-react/src/graphql/queries/model-catalog.graphql index 0fb02e1..8183835 100644 --- a/ui-react/src/graphql/queries/model-catalog.graphql +++ b/ui-react/src/graphql/queries/model-catalog.graphql @@ -1,11 +1,13 @@ #import "../fragments/model-catalog.graphql" #import "../fragments/region.graphql" +# No type predicate — deliberate. `modelcatalog_software.type` classifies a model +# (Empirical, Coupled, Theory-Guided, ...); it does not say whether a row is a model. +# The ETL only migrated `?id a sdm:Model` and stored the most specific subtype, and +# rows created through the REST API's generic `softwares` resource carry the +# superclass `sd#Software`. Filtering on any one value hides real models. See #98. query GetModelTree { - modelcatalog_software( - order_by: { label: asc } - where: { type: { _eq: "https://w3id.org/okn/o/sdm#Model" } } - ) { + modelcatalog_software(order_by: { label: asc }) { id label versions(order_by: { label: asc }) { @@ -163,11 +165,11 @@ query GetStandardVariablesWithUnits { } } +# No type predicate — same rule as GetModelTree above (#98). This feeds the +# "Model Family" picker on registration; filtering it made it impossible to +# register a new version under any model whose type is a subtype of sdm#Model. query GetModelFamilies { - modelcatalog_software( - order_by: { label: asc } - where: { type: { _eq: "https://w3id.org/okn/o/sdm#Model" } } - ) { + modelcatalog_software(order_by: { label: asc }) { id label versions(order_by: { label: asc }) {