mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-12-16 09:51:59 +03:00
962ae79e99
## Description
This PR moves all the tests that were added to
`crates/engine/tests/validate_metadata_artifacts/aggregate_expressions`
to the metadata-resolve `metadata_golden_tests`.
All the `error.txt` files got renamed to `expected_error.txt` and the
`metadata is not consistent:` bit on the front of the error got trimmed
off.
I had to change the way that `test_failing_metadata` works so that
instead of looking for directories under `failing/` it looks for
`metadata.json` files under `failing/`. This is because not every
directory has a test in it, some directories are just used for grouping
(eg `failing/aggregate_expressions/`). This doesn't change what tests
get run. The only side effect is that every test name has `_metadata`
suffixed to it (the filename). 😢 `test-each` doesn't appear to offer a
way to disable this behaviour.
V3_GIT_ORIGIN_REV_ID: dece7cd3bb4623c51050d12471d2c0990fd69bfd
378 lines
13 KiB
Rust
378 lines
13 KiB
Rust
use std::fs;
|
|
use std::path::PathBuf;
|
|
|
|
use metadata_resolve::BooleanExpressionError;
|
|
use metadata_resolve::Error as ResolveError;
|
|
use schema::Error as SchemaError;
|
|
use schema::GDS;
|
|
|
|
#[test]
|
|
fn test_select_many_model_arguments_without_arguments_input_type() -> anyhow::Result<()> {
|
|
let metadata = read_metadata("validate_metadata_artifacts/metadata_with_model_arguments_without_arguments_input_type.json")?;
|
|
|
|
let gds = GDS::new_with_default_flags(metadata)?;
|
|
|
|
assert_eq!(
|
|
GDS::build_schema(&gds).unwrap_err().to_string(),
|
|
"Cannot generate arguments for model Actors (in subgraph default) since argumentsInputType and it's corresponding graphql config argumentsInput isn't defined"
|
|
);
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn test_duplicate_field_path_relationship_mappings() -> anyhow::Result<()> {
|
|
let metadata = read_metadata(
|
|
"validate_metadata_artifacts/metadata_with_duplicate_field_mappings_in_relationship.json",
|
|
)?;
|
|
|
|
let gds = GDS::new_with_default_flags(metadata);
|
|
|
|
assert_eq!(
|
|
gds.unwrap_err().to_string(),
|
|
"metadata is not consistent: Mapping for source field movie_id already exists in the relationship Movies on type actor (in subgraph default)"
|
|
);
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn test_field_path_to_argument_relationship_mapping() -> anyhow::Result<()> {
|
|
let metadata = read_metadata("validate_metadata_artifacts/metadata_with_field_path_to_argument_relationship_mapping.json")?;
|
|
|
|
let gds = GDS::new_with_default_flags(metadata);
|
|
|
|
assert_eq!(
|
|
gds.unwrap_err().to_string(),
|
|
"metadata is not consistent: Relationship mappings to model arguments expressions are not supported yet."
|
|
);
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn test_relationship_mapping_unknown_source_field() -> anyhow::Result<()> {
|
|
let metadata = read_metadata("validate_metadata_artifacts/metadata_with_unknown_source_field_in_relationship_mapping.json")?;
|
|
|
|
let gds = GDS::new_with_default_flags(metadata);
|
|
|
|
assert_eq!(
|
|
gds.unwrap_err().to_string(),
|
|
"metadata is not consistent: source field author_id_unknown_field in field mapping for relationship author on type Article (in subgraph default) is unknown."
|
|
);
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn test_relationship_mapping_unknown_target_field() -> anyhow::Result<()> {
|
|
let metadata = read_metadata("validate_metadata_artifacts/metadata_with_unknown_target_field_in_relationship_mapping.json")?;
|
|
|
|
let gds = GDS::new_with_default_flags(metadata);
|
|
|
|
assert_eq!(
|
|
gds.unwrap_err().to_string(),
|
|
"metadata is not consistent: target field author_id in field mapping for relationship author on type Article (in subgraph default) to model Authors (in subgraph default) is unknown."
|
|
);
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn test_pre_namespace_aware_metadata() -> anyhow::Result<()> {
|
|
let metadata =
|
|
read_metadata("validate_metadata_artifacts/metadata_before_namespace_aware_open_dd.json")?;
|
|
|
|
let gds = GDS::new_with_default_flags(metadata);
|
|
|
|
gds?; // assert that it is OK
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn test_pre_subgraph_terminology_metadata() -> anyhow::Result<()> {
|
|
let metadata = read_metadata(
|
|
"validate_metadata_artifacts/metadata_before_subgraph_terminology_open_dd.json",
|
|
)?;
|
|
|
|
let gds = GDS::new_with_default_flags(metadata);
|
|
|
|
gds?; // assert that it is OK
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn test_scalar_comparison_type_reuse() -> anyhow::Result<()> {
|
|
let metadata = read_metadata(
|
|
"validate_metadata_artifacts/metadata_with_scalar_comparison_type_reused.json",
|
|
)?;
|
|
|
|
let gds = GDS::new_with_default_flags(metadata)?;
|
|
let built_schema = gds.build_schema();
|
|
built_schema?; // assert that it is OK
|
|
|
|
let metadata = read_metadata("validate_metadata_artifacts/metadata_with_scalar_comparison_type_reused_for_different_scalars.json")?;
|
|
|
|
let gds = GDS::new_with_default_flags(metadata)?;
|
|
let built_schema = gds.build_schema();
|
|
assert_eq!(built_schema.unwrap_err().to_string(),
|
|
"internal error while building schema: multiple definitions of graphql type: Int_Comparison_Exp"
|
|
);
|
|
Ok(())
|
|
}
|
|
|
|
// Test Global GraphQL Config
|
|
|
|
// Filter Expression (Where clause) Tests
|
|
|
|
// `filterExpressionType` is present in the `graphql` field of the model
|
|
// but `filterInput` is not present in the `GraphqlConfig` kind
|
|
#[test]
|
|
fn test_filter_error_filter_expression_type_present_filter_input_not_present() -> anyhow::Result<()>
|
|
{
|
|
let metadata = read_metadata("validate_metadata_artifacts/global_graphql_config/metadata_with_filter_expression_type_present_filter_input_not_present.json")?;
|
|
|
|
let gds = GDS::new_with_default_flags(metadata);
|
|
|
|
assert_eq!(
|
|
gds.unwrap_err().to_string(),
|
|
"metadata is not consistent: the filterInput needs to be defined in GraphqlConfig, when models have filterExpressionType"
|
|
);
|
|
Ok(())
|
|
}
|
|
|
|
// Order By Tests
|
|
|
|
// `orderByExpressionType` is present in the `graphql` field of the model
|
|
// but `orderByInput` is not present in the `GraphqlConfig` kind
|
|
#[test]
|
|
fn test_order_by_error_order_by_expression_type_present_order_by_input_not_present(
|
|
) -> anyhow::Result<()> {
|
|
let metadata = read_metadata("validate_metadata_artifacts/global_graphql_config/metadata_with_order_by_expression_type_present_order_by_input_not_present.json")?;
|
|
|
|
let gds = GDS::new_with_default_flags(metadata);
|
|
|
|
assert_eq!(
|
|
gds.unwrap_err().to_string(),
|
|
"metadata is not consistent: the orderByInput needs to be defined in GraphqlConfig, when models have orderByExpressionType"
|
|
);
|
|
Ok(())
|
|
}
|
|
|
|
// `orderByExpressionType` is present in the `graphql` field of the model
|
|
// but `enumTypeNames` directions is other than `["asc", "desc"]` in the`orderByInput` in the `GraphqlConfig` kind
|
|
#[test]
|
|
fn test_order_by_error_order_by_expression_type_present_and_only_asc_in_enum_type_directions_in_order_by_input_present(
|
|
) -> anyhow::Result<()> {
|
|
let metadata = read_metadata("validate_metadata_artifacts/global_graphql_config/metadata_with_order_by_expression_type_present_and_only_asc_in_enum_type_directions_in_order_by_input_present.json")?;
|
|
|
|
let gds = GDS::new_with_default_flags(metadata);
|
|
|
|
assert_eq!(
|
|
gds.unwrap_err().to_string(),
|
|
"metadata is not consistent: invalid directions: Asc defined in orderByInput of GraphqlConfig , currently there is no support for partial directions. Please specify a type which has both 'asc' and 'desc' directions"
|
|
);
|
|
Ok(())
|
|
}
|
|
|
|
// Argument Tests
|
|
|
|
// `argumentsInputType` is present in the `graphql` field of the model
|
|
// but `argumentsInput` is not present in the `GraphqlConfig` kind
|
|
#[test]
|
|
fn test_arguments_error_arguments_input_type_present_arguments_input_not_present(
|
|
) -> anyhow::Result<()> {
|
|
let metadata = read_metadata("validate_metadata_artifacts/global_graphql_config/metadata_with_arguments_input_type_present_arguments_input_not_present.json")?;
|
|
|
|
let gds = GDS::new_with_default_flags(metadata);
|
|
|
|
assert_eq!(
|
|
gds.unwrap_err().to_string(),
|
|
"metadata is not consistent: the fieldName for argumentsInput needs to be defined in GraphqlConfig, when models have argumentsInputType"
|
|
);
|
|
Ok(())
|
|
}
|
|
|
|
// "require_graphql_config" flag test
|
|
// The `require_graphql_flag` is set to true but there is no `GraphqlConfig` object in metadata
|
|
#[test]
|
|
fn test_require_graphql_config_flag_no_graphql_config_present() -> anyhow::Result<()> {
|
|
let metadata = read_metadata("validate_metadata_artifacts/global_graphql_config/metadata_with_require_grapqhl_config_flag_graphql_config_not_present.json")?;
|
|
|
|
let gds = GDS::new_with_default_flags(metadata);
|
|
|
|
assert_eq!(
|
|
gds.unwrap_err().to_string(),
|
|
"metadata is not consistent: graphql configuration is not defined in supergraph"
|
|
);
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn test_global_if_fields_present_in_object_type_but_no_model_has_global_id_source_true_for_object_type(
|
|
) -> anyhow::Result<()> {
|
|
let metadata = read_metadata("validate_metadata_artifacts/metadata_with_global_if_fields_present_in_object_type_but_no_model_has_global_id_source_true_for_object_type.json")?;
|
|
|
|
let gds = GDS::new_with_default_flags(metadata);
|
|
|
|
assert_eq!(
|
|
gds.unwrap_err().to_string(),
|
|
"metadata is not consistent: 'globalIdFields' for type actor (in subgraph default) found, but no model found with 'globalIdSource: true' for type actor (in subgraph default)"
|
|
);
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
// Remove this test (and add an execution test instead) if we ever support this use case
|
|
fn test_disallow_object_mapped_to_scalar() -> anyhow::Result<()> {
|
|
let metadata = read_metadata(
|
|
"validate_metadata_artifacts/metadata_with_opendd_object_mapped_to_ndc_scalar.json",
|
|
)?;
|
|
|
|
let gds = GDS::new_with_default_flags(metadata);
|
|
|
|
assert!(
|
|
matches!(
|
|
gds,
|
|
Err(SchemaError::ResolveError {
|
|
error: ResolveError::ModelTypeMappingCollectionError { .. }
|
|
})
|
|
),
|
|
"actual: {gds:?}"
|
|
);
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn test_disallow_filter_expression_without_source() -> anyhow::Result<()> {
|
|
let metadata = read_metadata(
|
|
"validate_metadata_artifacts/boolean_expressions/filter_expression_without_source.json",
|
|
)?;
|
|
|
|
let gds = GDS::new_with_default_flags(metadata);
|
|
|
|
assert!(
|
|
matches!(
|
|
gds,
|
|
Err(SchemaError::ResolveError {
|
|
error: ResolveError::CannotUseFilterExpressionsWithoutSource { .. }
|
|
})
|
|
),
|
|
"actual: {gds:?}"
|
|
);
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn test_disallow_filter_expression_with_object_type_mismatch() -> anyhow::Result<()> {
|
|
let metadata = read_metadata("validate_metadata_artifacts/boolean_expressions/filter_expression_with_object_type_mismatch.json")?;
|
|
|
|
let gds = GDS::new_with_default_flags(metadata);
|
|
|
|
assert!(
|
|
matches!(
|
|
gds,
|
|
Err(SchemaError::ResolveError {
|
|
error: ResolveError::BooleanExpressionError {
|
|
boolean_expression_error:
|
|
BooleanExpressionError::BooleanExpressionTypeForInvalidObjectTypeInModel { .. }
|
|
}
|
|
})
|
|
),
|
|
"actual: {gds:?}"
|
|
);
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn test_disallow_filter_expression_with_data_connector_mismatch() -> anyhow::Result<()> {
|
|
let metadata = read_metadata("validate_metadata_artifacts/boolean_expressions/filter_expression_with_data_connector_mismatch.json")?;
|
|
|
|
let gds = GDS::new_with_default_flags(metadata);
|
|
|
|
assert!(
|
|
matches!(
|
|
gds,
|
|
Err(SchemaError::ResolveError {
|
|
error: ResolveError::DifferentDataConnectorInFilterExpression { .. }
|
|
})
|
|
),
|
|
"actual: {gds:?}"
|
|
);
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn test_disallow_filter_expression_with_data_connector_object_type_mismatch() -> anyhow::Result<()>
|
|
{
|
|
let metadata = read_metadata("validate_metadata_artifacts/boolean_expressions/filter_expression_with_data_connector_object_type_mismatch.json")?;
|
|
|
|
let gds = GDS::new_with_default_flags(metadata);
|
|
|
|
assert!(
|
|
matches!(
|
|
gds,
|
|
Err(SchemaError::ResolveError {
|
|
error: ResolveError::DifferentDataConnectorObjectTypeInFilterExpression { .. }
|
|
})
|
|
),
|
|
"actual: {gds:?}"
|
|
);
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn test_disallow_boolean_expression_without_mapping() -> anyhow::Result<()> {
|
|
let metadata = read_metadata(
|
|
"validate_metadata_artifacts/boolean_expressions/boolean_expression_without_mapping.json",
|
|
)?;
|
|
|
|
let gds = GDS::new_with_default_flags(metadata);
|
|
assert!(
|
|
matches!(
|
|
gds,
|
|
Err(SchemaError::ResolveError {
|
|
error: ResolveError::BooleanExpressionError { boolean_expression_error:BooleanExpressionError::NoDataConnectorTypeMappingForObjectTypeInBooleanExpression { .. }}
|
|
})
|
|
),
|
|
"actual: {gds:?}"
|
|
);
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn test_disallow_conflicting_object_field_name_and_relationship_name() -> anyhow::Result<()> {
|
|
let metadata = read_metadata("validate_metadata_artifacts/relationships/conflicting_object_field_name_and_relationship_name.json")?;
|
|
|
|
let gds = GDS::new_with_default_flags(metadata)?;
|
|
let schema = gds.build_schema();
|
|
|
|
assert!(
|
|
matches!(
|
|
schema,
|
|
Err(SchemaError::RelationshipFieldNameConflict { .. })
|
|
),
|
|
"actual: {schema:?}"
|
|
);
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn test_allow_metadata_with_deprecated_field() -> anyhow::Result<()> {
|
|
// {"kind": "Relationship", "source": "<source>"} is deprecated in favor of "sourceType"
|
|
let metadata =
|
|
read_metadata("validate_metadata_artifacts/metadata_with_deprecated_field.json")?;
|
|
|
|
let gds = GDS::new_with_default_flags(metadata);
|
|
|
|
gds?; // assert that it is OK
|
|
Ok(())
|
|
}
|
|
|
|
fn read_metadata(path: &str) -> anyhow::Result<open_dds::Metadata> {
|
|
let json = read_file(path)?;
|
|
let value = open_dds::Metadata::from_json_str(&json)?;
|
|
Ok(value)
|
|
}
|
|
|
|
fn read_file(path: &str) -> anyhow::Result<String> {
|
|
let test_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("tests");
|
|
let schema = fs::read_to_string(test_dir.join(path))?;
|
|
Ok(schema)
|
|
}
|