Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions ui-react/src/graphql/__tests__/model-tree-type-filter.test.ts
Original file line number Diff line number Diff line change
@@ -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']);
});
});
10 changes: 2 additions & 8 deletions ui-react/src/graphql/generated/graphql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27659,10 +27659,7 @@ export type UpdateModelParameterMutationResult = Apollo.MutationResult<UpdateMod
export type UpdateModelParameterMutationOptions = Apollo.BaseMutationOptions<UpdateModelParameterMutation, UpdateModelParameterMutationVariables>;
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}) {
Expand Down Expand Up @@ -28222,10 +28219,7 @@ export type GetStandardVariablesWithUnitsSuspenseQueryHookResult = ReturnType<ty
export type GetStandardVariablesWithUnitsQueryResult = Apollo.QueryResult<GetStandardVariablesWithUnitsQuery, GetStandardVariablesWithUnitsQueryVariables>;
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}) {
Expand Down
9 changes: 5 additions & 4 deletions ui-react/src/graphql/generated/modeling.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 }) {
Expand Down
18 changes: 10 additions & 8 deletions ui-react/src/graphql/queries/model-catalog.graphql
Original file line number Diff line number Diff line change
@@ -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 }) {
Expand Down Expand Up @@ -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 }) {
Expand Down
Loading