From 6cd6356b7ffcd75c320bcdf27998e4b9024692e7 Mon Sep 17 00:00:00 2001 From: Josh Wilson Date: Thu, 11 Jun 2026 10:21:42 -0500 Subject: [PATCH] Remove remaining JSON schema usage from schema definition specs As noted on #1224, mentions of JSON schema in `elasticgraph-schema_definition/spec` should approach zero now that the JSON schema logic lives in `elasticgraph-json_ingestion`: - The graphql_schema, datastore_config, and runtime_metadata spec supports now run schemas without any extension modules, and the `json_schema` calls that existed only to satisfy the extension's scalar validation are gone. - The scalar `json_schema` requirement test (duplicated by the json_ingestion suite) is deleted, and the `long`/`unsigned_long` placeholder-inference tests that depend on JSON schema bounds moved to the json_ingestion suite (along with the built-in-scalar placeholder map, which differs with the extension loaded). - The reserved-type-name test now exercises the core `reserved_type_names` mechanism directly; the `ElasticGraphEventEnvelope` reservation is already covered by the json_ingestion suite. - `rake_tasks_spec` runs its synthetic schemas without the extension and no longer asserts on JSON schema artifacts (covered by json_ingestion's integration spec). A new short-diff test keeps `truncate_diff` fully covered. The tests that evaluate the repo's own `config/schema.rb` still load the extension, since that schema is a JSON ingestion application. The remaining mentions are the `define_schema` test-support seam (which exists for optional ingestion extensions) and JSON-the-format documentation text. --- .../schema_definition/json_schema_spec.rb | 21 +++ .../scalar_type_extension_spec.rb | 117 +++++++++++++- .../schema_definition/rake_tasks_spec.rb | 107 +++++-------- .../index_definition_spec_support.rb | 1 + .../mapping_customizations_spec.rb | 2 - .../graphql_schema/define_schema_spec.rb | 11 +- ...erived_graphql_type_customizations_spec.rb | 1 - .../graphql_schema_spec_support.rb | 2 +- .../graphql_schema/highlights_spec.rb | 2 - .../implements_shared_examples.rb | 25 --- .../graphql_schema/object_type_spec.rb | 4 +- .../graphql_schema/scalar_type_spec.rb | 20 +-- .../graphql_fields_by_name_spec.rb | 1 - .../object_types_by_name/pruning_spec.rb | 1 - .../runtime_metadata_support.rb | 3 +- .../scalar_types_by_name_spec.rb | 145 +++--------------- 16 files changed, 209 insertions(+), 254 deletions(-) diff --git a/elasticgraph-json_ingestion/spec/unit/elastic_graph/json_ingestion/schema_definition/json_schema_spec.rb b/elasticgraph-json_ingestion/spec/unit/elastic_graph/json_ingestion/schema_definition/json_schema_spec.rb index 4390f9890..1c964801d 100644 --- a/elasticgraph-json_ingestion/spec/unit/elastic_graph/json_ingestion/schema_definition/json_schema_spec.rb +++ b/elasticgraph-json_ingestion/spec/unit/elastic_graph/json_ingestion/schema_definition/json_schema_spec.rb @@ -3151,6 +3151,27 @@ def link_supertype_to_subtypes(interface_type, *subtype_names) expect(widget_schema.dig("properties", "undocumented_field")).not_to have_key("description") end + it "does not care if the interface and object fields have different JSON schema" do + json_schema = dump_schema do |schema| + schema.object_type "Thing" do |t| + t.implements "HasID" + t.field "id", "ID!" do |f| + f.json_schema maxLength: 40 + end + t.field "name", "String" + t.index "things" + end + + schema.interface_type "HasID" do |t| + t.field "id", "ID!" do |f| + f.json_schema maxLength: 30 + end + end + end + + expect(json_schema.dig("$defs", "Thing", "properties", "id", "allOf")).to include({"maxLength" => 40}) + end + def all_type_definitions_for(&schema_definition) dump_schema(&schema_definition).fetch("$defs") end diff --git a/elasticgraph-json_ingestion/spec/unit/elastic_graph/json_ingestion/schema_definition/schema_elements/scalar_type_extension_spec.rb b/elasticgraph-json_ingestion/spec/unit/elastic_graph/json_ingestion/schema_definition/schema_elements/scalar_type_extension_spec.rb index 01acd3dcf..e50dfeae3 100644 --- a/elasticgraph-json_ingestion/spec/unit/elastic_graph/json_ingestion/schema_definition/schema_elements/scalar_type_extension_spec.rb +++ b/elasticgraph-json_ingestion/spec/unit/elastic_graph/json_ingestion/schema_definition/schema_elements/scalar_type_extension_spec.rb @@ -84,12 +84,127 @@ module SchemaElements expect(grouping_missing_value_placeholder).to eq(nil) end + it "does not infer a placeholder for JSON-safe unsigned_long scalars with the default coercion adapter (which would not coerce floats back to integers)" do + grouping_missing_value_placeholder = grouping_missing_value_placeholder_for( + "unsigned_long", + type: "integer", + maximum: JSON_SAFE_LONG_MAX + ) + + expect(grouping_missing_value_placeholder).to eq(nil) + end + + it "does not infer a placeholder for unsigned_long scalars when no maximum is specified" do + grouping_missing_value_placeholder = grouping_missing_value_placeholder_for("unsigned_long", type: "integer") do |type| + type.coerce_with "ExampleScalarCoercionAdapter", defined_at: scalar_coercion_adapter_path + end + + expect(grouping_missing_value_placeholder).to eq(nil) + end + + it "infers a numeric missing-value placeholder for long scalars exactly at the JSON-safe boundaries with custom coercion" do + grouping_missing_value_placeholder = grouping_missing_value_placeholder_for( + "long", + type: "integer", + minimum: JSON_SAFE_LONG_MIN, + maximum: JSON_SAFE_LONG_MAX + ) do |type| + type.coerce_with "ExampleScalarCoercionAdapter", defined_at: scalar_coercion_adapter_path + end + + expect(grouping_missing_value_placeholder).to eq(MISSING_NUMERIC_PLACEHOLDER) + end + + it "does not infer a placeholder for JSON-safe long scalars with the default coercion adapter" do + grouping_missing_value_placeholder = grouping_missing_value_placeholder_for( + "long", + type: "integer", + minimum: JSON_SAFE_LONG_MIN, + maximum: JSON_SAFE_LONG_MAX + ) + + expect(grouping_missing_value_placeholder).to eq(nil) + end + + it "does not infer a placeholder for long scalars when the minimum is one below the JSON-safe range" do + grouping_missing_value_placeholder = grouping_missing_value_placeholder_for( + "long", + type: "integer", + minimum: JSON_SAFE_LONG_MIN - 1, + maximum: JSON_SAFE_LONG_MAX + ) do |type| + type.coerce_with "ExampleScalarCoercionAdapter", defined_at: scalar_coercion_adapter_path + end + + expect(grouping_missing_value_placeholder).to eq(nil) + end + + it "does not infer a placeholder for long scalars when the maximum is one above the JSON-safe range" do + grouping_missing_value_placeholder = grouping_missing_value_placeholder_for( + "long", + type: "integer", + minimum: JSON_SAFE_LONG_MIN, + maximum: JSON_SAFE_LONG_MAX + 1 + ) do |type| + type.coerce_with "ExampleScalarCoercionAdapter", defined_at: scalar_coercion_adapter_path + end + + expect(grouping_missing_value_placeholder).to eq(nil) + end + + it "does not infer a placeholder for long scalars when only one bound is specified (the other defaults to the LongString range)" do + only_min = grouping_missing_value_placeholder_for("long", type: "integer", minimum: 0) do |type| + type.coerce_with "ExampleScalarCoercionAdapter", defined_at: scalar_coercion_adapter_path + end + + only_max = grouping_missing_value_placeholder_for("long", type: "integer", maximum: 1000) do |type| + type.coerce_with "ExampleScalarCoercionAdapter", defined_at: scalar_coercion_adapter_path + end + + expect(only_min).to eq(nil) + expect(only_max).to eq(nil) + end + + it "does not infer a placeholder for long scalars when no bounds are specified" do + grouping_missing_value_placeholder = grouping_missing_value_placeholder_for("long", type: "integer") do |type| + type.coerce_with "ExampleScalarCoercionAdapter", defined_at: scalar_coercion_adapter_path + end + + expect(grouping_missing_value_placeholder).to eq(nil) + end + + it "has the expected placeholder for each built-in scalar type, including the JSON-safe-range-aware `JsonSafeLong` inference" do + results = define_schema(schema_element_name_form: "snake_case") { |schema| } + built_in_scalars = results.state.scalar_types_by_name.keys + scalar_types_by_name = results.runtime_metadata.scalar_types_by_name + + placeholders_by_scalar_type = built_in_scalars.to_h do |scalar_type| + [scalar_type, scalar_types_by_name.fetch(scalar_type).grouping_missing_value_placeholder] + end + + expect(placeholders_by_scalar_type).to eq({ + "Boolean" => nil, + "Cursor" => MISSING_STRING_PLACEHOLDER, + "Date" => nil, + "DateTime" => nil, + "Float" => MISSING_NUMERIC_PLACEHOLDER, + "ID" => MISSING_STRING_PLACEHOLDER, + "Int" => MISSING_NUMERIC_PLACEHOLDER, # GraphQL automatically coerces Int values + "JsonSafeLong" => MISSING_NUMERIC_PLACEHOLDER, # custom coercion adapter coerces floats back to integers + "LocalTime" => nil, + "LongString" => nil, # outside of the JSON safe range. + "String" => MISSING_STRING_PLACEHOLDER, + "TimeZone" => MISSING_STRING_PLACEHOLDER, + "Untyped" => MISSING_STRING_PLACEHOLDER + }) + end + def grouping_missing_value_placeholder_for(mapping_type, **json_schema_options) define_schema(schema_element_name_form: "snake_case") do |schema| schema.scalar_type "CustomScalar" do |type| type.mapping type: mapping_type type.json_schema(**json_schema_options) - yield type + yield type if block_given? end end.runtime_metadata.scalar_types_by_name.fetch("CustomScalar").grouping_missing_value_placeholder end diff --git a/elasticgraph-schema_definition/spec/integration/elastic_graph/schema_definition/rake_tasks_spec.rb b/elasticgraph-schema_definition/spec/integration/elastic_graph/schema_definition/rake_tasks_spec.rb index ef2703cde..892544da0 100644 --- a/elasticgraph-schema_definition/spec/integration/elastic_graph/schema_definition/rake_tasks_spec.rb +++ b/elasticgraph-schema_definition/spec/integration/elastic_graph/schema_definition/rake_tasks_spec.rb @@ -33,7 +33,7 @@ module SchemaDefinition describe "schema_artifacts:dump", :in_temp_dir do it "idempotently dumps all schema artifacts, and is able to check if they are current with `:check`" do - write_elastic_graph_schema_def_code(json_schema_version: 1) + write_elastic_graph_schema_def_code expect_all_artifacts_out_of_date_because_they_havent_been_dumped expect { @@ -41,8 +41,6 @@ module SchemaDefinition expect(output.lines).to include( a_string_including("Dumped", DATASTORE_CONFIG_FILE), a_string_including("Dumped", RUNTIME_METADATA_FILE), - a_string_including("Dumped", JSON_SCHEMAS_FILE), - a_string_including("Dumped", versioned_json_schema_file(1)), a_string_including("Dumped", GRAPHQL_SCHEMA_FILE) ) }.to change { read_artifact(DATASTORE_CONFIG_FILE) } @@ -54,17 +52,11 @@ module SchemaDefinition .and change { read_artifact(RUNTIME_METADATA_FILE) } .from(a_falsy_value) .to(a_string_including("script_id: update_ComponentDesigner_from_Component_").and(excluding("ruby/object"))) - .and change { read_artifact(JSON_SCHEMAS_FILE) } - .from(a_falsy_value) - .to(a_string_including("\n Component:", "\njson_schema_version: 1")) .and change { read_artifact(GRAPHQL_SCHEMA_FILE) } .from(a_falsy_value) .to(a_string_including("type Component {", "directive @fromExtensionModule")) - # Verify the data is dumped in Alphabetical order for consistency, and is pruned - # (Except for `EVENT_ENVELOPE_JSON_SCHEMA_NAME` -- it goes first). - definition_names = YAML.safe_load(read_artifact(JSON_SCHEMAS_FILE)).fetch("$defs").keys - expect(definition_names).to eq(%w[ElasticGraphEventEnvelope Component ElectricalPart ID MechanicalPart Size String]) + # Verify the data is dumped in Alphabetical order for consistency. expect(YAML.safe_load(read_artifact(DATASTORE_CONFIG_FILE)).fetch("indices").keys).to eq %w[ component_designers components electrical_parts mechanical_parts ] @@ -77,10 +69,9 @@ module SchemaDefinition expect(output.lines).to include(a_string_including("already up to date")) }.to maintain { read_artifact(DATASTORE_CONFIG_FILE) } .and maintain { read_artifact(RUNTIME_METADATA_FILE) } - .and maintain { read_artifact(JSON_SCHEMAS_FILE) } .and maintain { read_artifact(GRAPHQL_SCHEMA_FILE) } - write_elastic_graph_schema_def_code(component_suffix: "2", component_extras: "schema.deleted_type 'Component'", json_schema_version: 2) + write_elastic_graph_schema_def_code(component_suffix: "2") expect_out_of_date_artifacts_with_details(<<~EOS.strip) - component_designers: @@ -97,9 +88,6 @@ module SchemaDefinition expect(output.lines).to include( a_string_including("Dumped", DATASTORE_CONFIG_FILE), a_string_including("Dumped", RUNTIME_METADATA_FILE), - a_string_including("Dumped", JSON_SCHEMAS_FILE), - a_string_including("Dumped", versioned_json_schema_file(1)), - a_string_including("Dumped", versioned_json_schema_file(2)), a_string_including("Dumped", GRAPHQL_SCHEMA_FILE) ) }.to change { read_artifact(DATASTORE_CONFIG_FILE) } @@ -111,17 +99,26 @@ module SchemaDefinition .and change { read_artifact(RUNTIME_METADATA_FILE) } .from(a_string_including("script_id: update_ComponentDesigner_from_Component_")) .to(a_string_including("script_id: update_ComponentDesigner2_from_Component2_")) - .and change { read_artifact(JSON_SCHEMAS_FILE) } - .from(a_string_including("\n Component:", "\njson_schema_version: 1")) - .to(a_string_including("\n Component2:", "\njson_schema_version: 2").and(excluding("\n Component:"))) .and change { read_artifact(GRAPHQL_SCHEMA_FILE) } .from(a_string_including("type Component {")) .to(a_string_including("type Component2 {").and(excluding("Component "))) expect_up_to_date_artifacts + end + + it "shows the full diff for an out-of-date artifact when the diff is short" do + write_elastic_graph_schema_def_code + run_rake("schema_artifacts:dump") - delete_artifact versioned_json_schema_file(2) - expect_missing_versioned_json_schema_artifact "v2.yaml" + write_elastic_graph_schema_def_code(number_of_shards: 7) + + expect { + run_rake("schema_artifacts:check") + }.to abort_with { |error| + expect(error.message) + .to include("1. config/schema/artifacts/datastore_config.yaml (see [1] below for the diff)", "number_of_shards") + .and exclude("lines of the diff") + } end it "allows the derived GraphQL type name formats to be customized" do @@ -133,7 +130,7 @@ module SchemaDefinition block.call(line) end - write_elastic_graph_schema_def_code(json_schema_version: 1) + write_elastic_graph_schema_def_code run_rake("schema_artifacts:dump") # We strip the comment preamble so we can compare it with an SDL string that lacks it below. @@ -175,7 +172,7 @@ module SchemaDefinition end it "generates separate input vs output enums by default, but allows them to be the same if desired" do - write_elastic_graph_schema_def_code(json_schema_version: 1) + write_elastic_graph_schema_def_code run_rake("schema_artifacts:dump") expect(enum_types_in_dumped_graphql_schema).to contain_exactly( @@ -215,6 +212,7 @@ module SchemaDefinition output = run_rake( "schema_artifacts:dump", + extension_modules: [JSONIngestion::SchemaDefinition::APIExtension], type_name_overrides: overrides.merge({"Widgets" => "Unused"}), enum_value_overrides_by_type: { "PreColor" => {"GREAN" => "GREENISH", "MAGENTA" => "RED"}, @@ -265,7 +263,7 @@ module SchemaDefinition overrides = original_core_types.to_h { |name| [name, "Pre#{name}"] } - output = run_rake("schema_artifacts:dump", type_name_overrides: overrides) + output = run_rake("schema_artifacts:dump", extension_modules: [JSONIngestion::SchemaDefinition::APIExtension], type_name_overrides: overrides) expect(output).to exclude(does_not_match_warning_snippet) overriden_types = graphql_types_defined_in(read_artifact(GRAPHQL_SCHEMA_FILE)) @@ -291,7 +289,12 @@ module SchemaDefinition it "does not change the formatting of the dumped artifacts in unexpected ways" do config_dir = File.join(CommonSpecHelpers::REPO_ROOT, "config") - run_rake("schema_artifacts:dump", path_to_schema: File.join(config_dir, "schema.rb"), include_extension_module: false) + run_rake( + "schema_artifacts:dump", + path_to_schema: File.join(config_dir, "schema.rb"), + include_extension_module: false, + extension_modules: [JSONIngestion::SchemaDefinition::APIExtension] + ) # :nocov: -- some branches below depend on pass vs fail or local vs CI. # Exclude `data_warehouse.yaml` from the diff since it's generated by the warehouse extension, @@ -315,13 +318,13 @@ module SchemaDefinition end it "retains `extend schema` in the dumped SDL if ElasticGraph includes it in the generated SDL string" do - write_elastic_graph_schema_def_code(json_schema_version: 1, extra_sdl: "") + write_elastic_graph_schema_def_code(extra_sdl: "") run_rake("schema_artifacts:dump") # `extend` should not be added by default... expect(read_artifact(GRAPHQL_SCHEMA_FILE)).not_to include("extend") - write_elastic_graph_schema_def_code(json_schema_version: 1, extra_sdl: <<~EOS) + write_elastic_graph_schema_def_code(extra_sdl: <<~EOS) extend schema @customDirective @@ -419,7 +422,7 @@ def expect_successful_run_of(*shell_commands) }.to output(/Your Gemfile lists/).to_stderr_from_any_process end - def write_elastic_graph_schema_def_code(json_schema_version:, component_suffix: "", extra_sdl: "", component_extras: "") + def write_elastic_graph_schema_def_code(component_suffix: "", extra_sdl: "", component_extras: "", number_of_shards: 5) code = <<~EOS Thread.current[:eg_schema_load_count] = (Thread.current[:eg_schema_load_count] || 0) + 1 if Thread.current[:eg_schema_load_count] > 1 @@ -427,7 +430,6 @@ def write_elastic_graph_schema_def_code(json_schema_version:, component_suffix: end ElasticGraph.define_schema do |schema| - schema.json_schema_version #{json_schema_version} schema.enum_type "Size" do |t| t.values "SMALL", "MEDIUM", "LAGE" end @@ -460,7 +462,7 @@ def write_elastic_graph_schema_def_code(json_schema_version:, component_suffix: t.field "id", "ID!" t.field "name", "String!" t.field "designer_id", "ID" - t.index "components#{component_suffix}", number_of_shards: 5 + t.index "components#{component_suffix}", number_of_shards: #{number_of_shards} t.derive_indexed_type_fields "ComponentDesigner#{component_suffix}", from_id: "designer_id" do |derive| derive.append_only_set "designed_component_names", from: "name" @@ -483,9 +485,6 @@ def runtime_metadata_for_elastic_graph_schema_def_code(include_date_time_fields: end ElasticGraph.define_schema do |schema| - schema.json_schema_version 1 - schema.enforce_json_schema_version false - schema.object_type "MyType" do |t| t.field "id", "ID!" #{'t.field "timestamp", "DateTime"' if include_date_time_fields} @@ -506,7 +505,7 @@ def expect_up_to_date_artifacts output = run_rake("schema_artifacts:check") }.not_to raise_error - expect(output).to include(DATASTORE_CONFIG_FILE, JSON_SCHEMAS_FILE, "up to date") + expect(output).to include(DATASTORE_CONFIG_FILE, RUNTIME_METADATA_FILE, "up to date") end def expect_all_artifacts_out_of_date_because_they_havent_been_dumped @@ -514,25 +513,11 @@ def expect_all_artifacts_out_of_date_because_they_havent_been_dumped run_rake("schema_artifacts:check") }.to abort_with { |error| expect(error.message).to eq(<<~EOS.strip) - 5 schema artifact(s) are out of date. Run `bundle exec rake schema_artifacts:dump` to update the following artifact(s): + 3 schema artifact(s) are out of date. Run `bundle exec rake schema_artifacts:dump` to update the following artifact(s): 1. config/schema/artifacts/datastore_config.yaml (file does not exist) - 2. config/schema/artifacts/json_schemas.yaml (file does not exist) - 3. config/schema/artifacts/json_schemas_by_version/v1.yaml (file does not exist) - 4. config/schema/artifacts/runtime_metadata.yaml (file does not exist) - 5. config/schema/artifacts/schema.graphql (file does not exist) - EOS - } - end - - def expect_missing_versioned_json_schema_artifact(version_file) - expect { - run_rake("schema_artifacts:check") - }.to abort_with { |error| - expect(error.message).to eq(<<~EOS.strip) - 1 schema artifact(s) are out of date. Run `bundle exec rake schema_artifacts:dump` to update the following artifact(s): - - 1. config/schema/artifacts/json_schemas_by_version/#{version_file} (file does not exist) + 2. config/schema/artifacts/runtime_metadata.yaml (file does not exist) + 3. config/schema/artifacts/schema.graphql (file does not exist) EOS } end @@ -541,15 +526,12 @@ def expect_out_of_date_artifacts_with_details(example_diff, test_color: false) expect { run_rake("schema_artifacts:check", pretend_tty: test_color) }.to abort_with { |error| - expect(error.message.lines.first(8).join).to eq(<<~EOS) - 6 schema artifact(s) are out of date. Run `bundle exec rake schema_artifacts:dump` to update the following artifact(s): + expect(error.message.lines.first(5).join).to eq(<<~EOS) + 3 schema artifact(s) are out of date. Run `bundle exec rake schema_artifacts:dump` to update the following artifact(s): 1. config/schema/artifacts/datastore_config.yaml (see [1] below for the first 50 lines of the diff) - 2. config/schema/artifacts/json_schemas.yaml (see [2] below for the first 50 lines of the diff) - 3. config/schema/artifacts/json_schemas_by_version/v1.yaml (see [3] below for the diff) - 4. config/schema/artifacts/json_schemas_by_version/v2.yaml (file does not exist) - 5. config/schema/artifacts/runtime_metadata.yaml (see [4] below for the first 50 lines of the diff) - 6. config/schema/artifacts/schema.graphql (see [5] below for the first 50 lines of the diff) + 2. config/schema/artifacts/runtime_metadata.yaml (see [2] below for the first 50 lines of the diff) + 3. config/schema/artifacts/schema.graphql (see [3] below for the first 50 lines of the diff) EOS expect(error.message).to include(example_diff) @@ -560,14 +542,6 @@ def read_artifact(name) path = File.join("config", "schema", "artifacts", name) File.exist?(path) && File.read(path) end - - def delete_artifact(*name_parts) - ::File.delete(::File.join("config", "schema", "artifacts", *name_parts)) - end - - def versioned_json_schema_file(version) - ::File.join(JSON_SCHEMAS_BY_VERSION_DIRECTORY, "v#{version}.yaml") - end end def run_rake( @@ -575,6 +549,7 @@ def run_rake( pretend_tty: false, path_to_schema: "schema.rb", include_extension_module: true, + extension_modules: [], derived_type_name_formats: {}, type_name_overrides: {}, enum_value_overrides_by_type: {} @@ -598,7 +573,7 @@ def as_active_instance index_document_sizes: true, path_to_schema: path_to_schema, schema_artifacts_directory: "config/schema/artifacts", - extension_modules: [JSONIngestion::SchemaDefinition::APIExtension, extension_module].compact, + extension_modules: extension_modules + [extension_module].compact, derived_type_name_formats: derived_type_name_formats, type_name_overrides: type_name_overrides, enum_value_overrides_by_type: enum_value_overrides_by_type, diff --git a/elasticgraph-schema_definition/spec/unit/elastic_graph/schema_definition/datastore_config/index_definition_spec_support.rb b/elasticgraph-schema_definition/spec/unit/elastic_graph/schema_definition/datastore_config/index_definition_spec_support.rb index 2d574983f..d8a98eae2 100644 --- a/elasticgraph-schema_definition/spec/unit/elastic_graph/schema_definition/datastore_config/index_definition_spec_support.rb +++ b/elasticgraph-schema_definition/spec/unit/elastic_graph/schema_definition/datastore_config/index_definition_spec_support.rb @@ -17,6 +17,7 @@ def build_datastore_config(index_document_sizes: false, schema_element_name_form define_schema( index_document_sizes: index_document_sizes, schema_element_name_form: schema_element_name_form, + extension_modules: [], &schema_definition ).datastore_config end diff --git a/elasticgraph-schema_definition/spec/unit/elastic_graph/schema_definition/datastore_config/index_mappings/mapping_customizations_spec.rb b/elasticgraph-schema_definition/spec/unit/elastic_graph/schema_definition/datastore_config/index_mappings/mapping_customizations_spec.rb index 9f5392bd9..1cc6aebf4 100644 --- a/elasticgraph-schema_definition/spec/unit/elastic_graph/schema_definition/datastore_config/index_mappings/mapping_customizations_spec.rb +++ b/elasticgraph-schema_definition/spec/unit/elastic_graph/schema_definition/datastore_config/index_mappings/mapping_customizations_spec.rb @@ -16,7 +16,6 @@ module SchemaDefinition it "respects `mapping` customizations set on a field definition, allowing them to augment or replace the mapping of the base type" do mapping = index_mapping_for "my_type" do |s| s.scalar_type "MyText" do |t| - t.json_schema type: "string" t.mapping type: "text" end @@ -221,7 +220,6 @@ module SchemaDefinition end s.scalar_type "MyText" do |t| - t.json_schema type: "string" t.mapping type: "text" end end diff --git a/elasticgraph-schema_definition/spec/unit/elastic_graph/schema_definition/graphql_schema/define_schema_spec.rb b/elasticgraph-schema_definition/spec/unit/elastic_graph/schema_definition/graphql_schema/define_schema_spec.rb index 9ba13dd0c..7b2965845 100644 --- a/elasticgraph-schema_definition/spec/unit/elastic_graph/schema_definition/graphql_schema/define_schema_spec.rb +++ b/elasticgraph-schema_definition/spec/unit/elastic_graph/schema_definition/graphql_schema/define_schema_spec.rb @@ -7,6 +7,7 @@ # frozen_string_literal: true require "elastic_graph/errors" +require "elastic_graph/json_ingestion/schema_definition/api_extension" require "elastic_graph/spec_support/have_readable_to_s_and_inspect_output" require_relative "graphql_schema_spec_support" @@ -81,13 +82,14 @@ module SchemaDefinition ) end - it "rejects type names reserved by schema definition extensions" do + it "rejects type names that have been registered as reserved (as schema definition extensions do)" do expect { define_schema do |schema| - schema.object_type EVENT_ENVELOPE_JSON_SCHEMA_NAME + schema.state.reserved_type_names << "SomeReservedName" + schema.object_type "SomeReservedName" end }.to raise_error Errors::SchemaError, a_string_including( - "`#{EVENT_ENVELOPE_JSON_SCHEMA_NAME}` cannot be used as a schema type", + "`SomeReservedName` cannot be used as a schema type", "reserved name" ) end @@ -108,7 +110,7 @@ module SchemaDefinition it "allows test schemas to set the JSON schema version themselves" do # If the test support logic re-set the version it would fail with a "can only be set once" error. - result = define_schema do |schema| + result = define_schema(extension_modules: [JSONIngestion::SchemaDefinition::APIExtension]) do |schema| schema.json_schema_version 7 schema.object_type("Widget") do |t| @@ -184,7 +186,6 @@ module SchemaDefinition schema.scalar_type "MyScalar" do |t| expect(t).to have_readable_to_s_and_inspect_output.including("MyScalar") t.mapping type: "keyword" - t.json_schema type: "string" end schema.enum_type "Color" do |t| diff --git a/elasticgraph-schema_definition/spec/unit/elastic_graph/schema_definition/graphql_schema/derived_graphql_type_customizations_spec.rb b/elasticgraph-schema_definition/spec/unit/elastic_graph/schema_definition/graphql_schema/derived_graphql_type_customizations_spec.rb index f280fbced..7d93460de 100644 --- a/elasticgraph-schema_definition/spec/unit/elastic_graph/schema_definition/graphql_schema/derived_graphql_type_customizations_spec.rb +++ b/elasticgraph-schema_definition/spec/unit/elastic_graph/schema_definition/graphql_schema/derived_graphql_type_customizations_spec.rb @@ -170,7 +170,6 @@ module SchemaDefinition api.raw_sdl "directive @external on OBJECT" api.scalar_type "Url" do |t| - t.json_schema type: "string" t.mapping type: "keyword" t.customize_derived_types "UrlEdge", "UrlConnection" do |dt| diff --git a/elasticgraph-schema_definition/spec/unit/elastic_graph/schema_definition/graphql_schema/graphql_schema_spec_support.rb b/elasticgraph-schema_definition/spec/unit/elastic_graph/schema_definition/graphql_schema/graphql_schema_spec_support.rb index bca5064cc..2c393cafc 100644 --- a/elasticgraph-schema_definition/spec/unit/elastic_graph/schema_definition/graphql_schema/graphql_schema_spec_support.rb +++ b/elasticgraph-schema_definition/spec/unit/elastic_graph/schema_definition/graphql_schema/graphql_schema_spec_support.rb @@ -35,7 +35,7 @@ def raise_invalid_graphql_name_error_for(name) end def define_schema(**options, &block) - define_schema_with_schema_elements(schema_elements, **options, &block).graphql_schema_string + define_schema_with_schema_elements(schema_elements, extension_modules: [], **options, &block).graphql_schema_string end def correctly_cased(name) diff --git a/elasticgraph-schema_definition/spec/unit/elastic_graph/schema_definition/graphql_schema/highlights_spec.rb b/elasticgraph-schema_definition/spec/unit/elastic_graph/schema_definition/graphql_schema/highlights_spec.rb index 175879824..117bb5be2 100644 --- a/elasticgraph-schema_definition/spec/unit/elastic_graph/schema_definition/graphql_schema/highlights_spec.rb +++ b/elasticgraph-schema_definition/spec/unit/elastic_graph/schema_definition/graphql_schema/highlights_spec.rb @@ -59,12 +59,10 @@ module SchemaDefinition end api.scalar_type "CustomNumber" do |t| - t.json_schema type: "number" t.mapping type: "integer" end api.scalar_type "CustomKeyword" do |t| - t.json_schema type: "string" t.mapping type: "keyword" end diff --git a/elasticgraph-schema_definition/spec/unit/elastic_graph/schema_definition/graphql_schema/implements_shared_examples.rb b/elasticgraph-schema_definition/spec/unit/elastic_graph/schema_definition/graphql_schema/implements_shared_examples.rb index 14da85267..dde06ab27 100644 --- a/elasticgraph-schema_definition/spec/unit/elastic_graph/schema_definition/graphql_schema/implements_shared_examples.rb +++ b/elasticgraph-schema_definition/spec/unit/elastic_graph/schema_definition/graphql_schema/implements_shared_examples.rb @@ -258,31 +258,6 @@ def implemented_interfaces_from(sdl, type_name) EOS end - it "does not care if the interface and object fields have different JSON schema" do - result = define_schema do |schema| - schema.public_send ruby_definition_method, "Thing" do |t| - t.implements "HasID" - t.field "id", "ID!" do |f| - f.json_schema maxLength: 40 - end - t.field "name", "String" - end - - schema.interface_type "HasID" do |t| - t.field "id", "ID!" do |f| - f.json_schema maxLength: 30 - end - end - end - - expect(type_def_from(result, "Thing")).to eq(<<~EOS.strip) - #{graphql_definition_keyword} Thing implements HasID { - id: ID! - name: String - } - EOS - end - it "does not care if the interface and object fields have different index mappings" do result = define_schema do |schema| schema.public_send ruby_definition_method, "Thing" do |t| diff --git a/elasticgraph-schema_definition/spec/unit/elastic_graph/schema_definition/graphql_schema/object_type_spec.rb b/elasticgraph-schema_definition/spec/unit/elastic_graph/schema_definition/graphql_schema/object_type_spec.rb index ae7f85e21..18186e5f9 100644 --- a/elasticgraph-schema_definition/spec/unit/elastic_graph/schema_definition/graphql_schema/object_type_spec.rb +++ b/elasticgraph-schema_definition/spec/unit/elastic_graph/schema_definition/graphql_schema/object_type_spec.rb @@ -674,9 +674,7 @@ module SchemaDefinition result = object_type "Widget", include_docs: true do |t| t.documentation "A widget." t.field "id", "ID" - t.field "user_id", "ID" do |f| - f.json_schema nullable: false - end + t.field "user_id", "ID" t.index "widgets" do |i| i.route_with "user_id" diff --git a/elasticgraph-schema_definition/spec/unit/elastic_graph/schema_definition/graphql_schema/scalar_type_spec.rb b/elasticgraph-schema_definition/spec/unit/elastic_graph/schema_definition/graphql_schema/scalar_type_spec.rb index e8db9a3df..798bddf1d 100644 --- a/elasticgraph-schema_definition/spec/unit/elastic_graph/schema_definition/graphql_schema/scalar_type_spec.rb +++ b/elasticgraph-schema_definition/spec/unit/elastic_graph/schema_definition/graphql_schema/scalar_type_spec.rb @@ -17,7 +17,6 @@ module SchemaDefinition it "generates the SDL for a custom scalar type" do result = scalar_type "BigInt" do |t| t.mapping type: "long" - t.json_schema type: "integer" end expect(type_def_from(result, "BigInt")).to eq(<<~EOS.strip) @@ -28,23 +27,14 @@ module SchemaDefinition it "requires the `mapping` to be specified so we know how to index it in the datastore" do expect { scalar_type "BigInt" do |t| - t.json_schema type: "integer" + # Intentionally not calling `t.mapping`. end }.to raise_error Errors::SchemaError, a_string_including("BigInt", "lacks `mapping`") end - it "requires the `json_schema` to be specified so we know how it should be encoded in an ingested event" do - expect { - scalar_type "BigInt" do |t| - t.mapping type: "long" - end - }.to raise_error Errors::SchemaError, a_string_including("BigInt", "lacks `json_schema`") - end - it "requires a `type` be specified on the `mapping` since we can't guess what the mapping type should be" do expect { scalar_type "BigInt" do |t| - t.json_schema type: "integer" t.mapping null_value: 0 end }.to raise_error Errors::SchemaError, a_string_including("BigInt", "mapping", "type:") @@ -58,7 +48,6 @@ module SchemaDefinition schema.scalar_type "BigInt" do |t| t.mapping type: "long" - t.json_schema type: "integer" end end @@ -79,7 +68,6 @@ module SchemaDefinition schema.scalar_type "BigInt" do |t| t.mapping type: "long" - t.json_schema type: "integer" t.directive "meta", since_date: "2021-08-01" t.directive "meta", author: "John" end @@ -93,7 +81,6 @@ module SchemaDefinition it "allows documentation to be defined on the scalar" do result = scalar_type "BigInt" do |t| t.mapping type: "long" - t.json_schema type: "integer" t.documentation "A number that exceeds the normal `Int` max." end @@ -108,7 +95,6 @@ module SchemaDefinition it "defines a filter type with `any_of` and `equal_to_any_of` for a mapping type that can't efficiently support range queries" do result = scalar_type "FullText" do |t| t.mapping type: "text" - t.json_schema type: "string" end expect(filter_type_from(result, "FullText")).to eq(<<~EOS.strip) @@ -124,7 +110,6 @@ module SchemaDefinition it "defines a filter type with `any_of`, `equal_to_any_of`, and comparison operators for a numeric mapping type that can efficiently support range queries" do result = scalar_type "Short" do |t| t.mapping type: "short" - t.json_schema type: "integer" end expect(filter_type_from(result, "Short")).to eq(<<~EOS.strip) @@ -144,7 +129,6 @@ module SchemaDefinition it "defines a filter type with `any_of`, `equal_to_any_of`, and comparison operators for a date mapping type that can efficiently support range queries" do result = scalar_type "CalendarDate" do |t| t.mapping type: "date" - t.json_schema type: "string" end expect(filter_type_from(result, "CalendarDate")).to eq(<<~EOS.strip) @@ -164,7 +148,6 @@ module SchemaDefinition it "defines a `*ListFilterInput` type so that lists of the custom scalar type can be filtered on" do result = scalar_type "Short" do |t| t.mapping type: "short" - t.json_schema type: "integer" end expect(list_filter_type_from(result, "Short", include_docs: true)).to eq(<<~EOS.strip) @@ -218,7 +201,6 @@ module SchemaDefinition it "documents each filter field" do result = scalar_type "Byte" do |t| t.mapping type: "byte" - t.json_schema type: "integer" end expect(filter_type_from(result, "Byte", include_docs: true)).to eq(<<~EOS.strip) diff --git a/elasticgraph-schema_definition/spec/unit/elastic_graph/schema_definition/runtime_metadata/object_types_by_name/graphql_fields_by_name_spec.rb b/elasticgraph-schema_definition/spec/unit/elastic_graph/schema_definition/runtime_metadata/object_types_by_name/graphql_fields_by_name_spec.rb index 7844ba422..2997bf7d3 100644 --- a/elasticgraph-schema_definition/spec/unit/elastic_graph/schema_definition/runtime_metadata/object_types_by_name/graphql_fields_by_name_spec.rb +++ b/elasticgraph-schema_definition/spec/unit/elastic_graph/schema_definition/runtime_metadata/object_types_by_name/graphql_fields_by_name_spec.rb @@ -243,7 +243,6 @@ module SchemaDefinition schema.scalar_type "Duration" do |t| t.mapping type: "keyword" - t.json_schema type: "string" end schema.object_type "Options" do |t| diff --git a/elasticgraph-schema_definition/spec/unit/elastic_graph/schema_definition/runtime_metadata/object_types_by_name/pruning_spec.rb b/elasticgraph-schema_definition/spec/unit/elastic_graph/schema_definition/runtime_metadata/object_types_by_name/pruning_spec.rb index ba53dd6d5..522fe1b91 100644 --- a/elasticgraph-schema_definition/spec/unit/elastic_graph/schema_definition/runtime_metadata/object_types_by_name/pruning_spec.rb +++ b/elasticgraph-schema_definition/spec/unit/elastic_graph/schema_definition/runtime_metadata/object_types_by_name/pruning_spec.rb @@ -113,7 +113,6 @@ module SchemaDefinition s.scalar_type "CustomFrameworkScalar" do |t| t.mapping type: "keyword" - t.json_schema type: "string" t.graphql_only true end diff --git a/elasticgraph-schema_definition/spec/unit/elastic_graph/schema_definition/runtime_metadata/runtime_metadata_support.rb b/elasticgraph-schema_definition/spec/unit/elastic_graph/schema_definition/runtime_metadata/runtime_metadata_support.rb index 60a3f823a..c4c8bfb4e 100644 --- a/elasticgraph-schema_definition/spec/unit/elastic_graph/schema_definition/runtime_metadata/runtime_metadata_support.rb +++ b/elasticgraph-schema_definition/spec/unit/elastic_graph/schema_definition/runtime_metadata/runtime_metadata_support.rb @@ -6,7 +6,6 @@ # # frozen_string_literal: true -require "elastic_graph/json_ingestion/schema_definition/api_extension" require "elastic_graph/spec_support/schema_definition_helpers" require "elastic_graph/spec_support/runtime_metadata_support" @@ -19,7 +18,7 @@ module SchemaDefinition def define_schema(**options, &block) super( schema_element_name_form: "snake_case", - extension_modules: [JSONIngestion::SchemaDefinition::APIExtension], + extension_modules: [], **options, &block ) diff --git a/elasticgraph-schema_definition/spec/unit/elastic_graph/schema_definition/runtime_metadata/scalar_types_by_name_spec.rb b/elasticgraph-schema_definition/spec/unit/elastic_graph/schema_definition/runtime_metadata/scalar_types_by_name_spec.rb index 19c9707dd..9b3204339 100644 --- a/elasticgraph-schema_definition/spec/unit/elastic_graph/schema_definition/runtime_metadata/scalar_types_by_name_spec.rb +++ b/elasticgraph-schema_definition/spec/unit/elastic_graph/schema_definition/runtime_metadata/scalar_types_by_name_spec.rb @@ -21,7 +21,6 @@ module SchemaDefinition metadata = scalar_type_metadata_for "BigInt" do |s| s.scalar_type "BigInt" do |t| t.mapping type: "long" - t.json_schema type: "integer" t.coerce_with "ExampleScalarCoercionAdapter", defined_at: "support/example_extensions/scalar_coercion_adapter" end end @@ -36,7 +35,6 @@ module SchemaDefinition metadata = scalar_type_metadata_for "BigInt" do |s| s.scalar_type "BigInt" do |t| t.mapping type: "long" - t.json_schema type: "integer" t.prepare_for_indexing_with "ExampleIndexingPreparer", defined_at: "support/example_extensions/indexing_preparer" end end @@ -51,7 +49,6 @@ module SchemaDefinition define_schema do |s| s.scalar_type "BigInt" do |t| t.mapping type: "long" - t.json_schema type: "integer" expect { t.coerce_with "NotAValidConstant", defined_at: "support/example_extensions/scalar_coercion_adapter" @@ -64,7 +61,6 @@ module SchemaDefinition define_schema do |s| s.scalar_type "BigInt" do |t| t.mapping type: "long" - t.json_schema type: "integer" expect { t.prepare_for_indexing_with "NotAValidConstant", defined_at: "support/example_extensions/indexing_preparer" @@ -96,7 +92,7 @@ module SchemaDefinition describe "`grouping_missing_value_placeholder`" do it "can be set to a number" do - grouping_missing_value_placeholder = grouping_missing_value_placeholder_for("long", type: "integer") do |t| + grouping_missing_value_placeholder = grouping_missing_value_placeholder_for("long") do |t| t.grouping_missing_value_placeholder(-1) end @@ -104,7 +100,7 @@ module SchemaDefinition end it "can be set to a string" do - grouping_missing_value_placeholder = grouping_missing_value_placeholder_for("keyword", type: "string") do |t| + grouping_missing_value_placeholder = grouping_missing_value_placeholder_for("keyword") do |t| t.grouping_missing_value_placeholder "missing" end @@ -112,10 +108,10 @@ module SchemaDefinition end it "does not infer placeholder when placeholder is set to nil" do - grouping_missing_value_placeholder = grouping_missing_value_placeholder_for("keyword", type: "string") + grouping_missing_value_placeholder = grouping_missing_value_placeholder_for("keyword") expect(grouping_missing_value_placeholder).not_to be_nil - grouping_missing_value_placeholder = grouping_missing_value_placeholder_for("keyword", type: "string") do |t| + grouping_missing_value_placeholder = grouping_missing_value_placeholder_for("keyword") do |t| t.grouping_missing_value_placeholder nil end expect(grouping_missing_value_placeholder).to be_nil @@ -123,7 +119,7 @@ module SchemaDefinition it "raises an error when placeholder is not a String, Numeric, or nil" do expect { - grouping_missing_value_placeholder_for("keyword", type: "string") do |t| + grouping_missing_value_placeholder_for("keyword") do |t| t.grouping_missing_value_placeholder :symbol end }.to raise_error Errors::SchemaError, a_string_including( @@ -134,7 +130,7 @@ module SchemaDefinition it "raises an error when placeholder is an array" do expect { - grouping_missing_value_placeholder_for("keyword", type: "string") do |t| + grouping_missing_value_placeholder_for("keyword") do |t| t.grouping_missing_value_placeholder ["invalid"] end }.to raise_error Errors::SchemaError, a_string_including( @@ -145,7 +141,7 @@ module SchemaDefinition it "raises an error when placeholder is a hash" do expect { - grouping_missing_value_placeholder_for("keyword", type: "string") do |t| + grouping_missing_value_placeholder_for("keyword") do |t| t.grouping_missing_value_placeholder({key: "value"}) end }.to raise_error Errors::SchemaError, a_string_including( @@ -155,7 +151,7 @@ module SchemaDefinition end it "accepts integer values" do - grouping_missing_value_placeholder = grouping_missing_value_placeholder_for("long", type: "integer") do |t| + grouping_missing_value_placeholder = grouping_missing_value_placeholder_for("long") do |t| t.grouping_missing_value_placeholder 42 end @@ -163,7 +159,7 @@ module SchemaDefinition end it "accepts float values" do - grouping_missing_value_placeholder = grouping_missing_value_placeholder_for("double", type: "number") do |t| + grouping_missing_value_placeholder = grouping_missing_value_placeholder_for("double") do |t| t.grouping_missing_value_placeholder 3.14 end @@ -172,7 +168,7 @@ module SchemaDefinition float_types.each do |float_type| it "infers 'NaN' for float type #{float_type}" do - grouping_missing_value_placeholder = grouping_missing_value_placeholder_for(float_type, type: "number") + grouping_missing_value_placeholder = grouping_missing_value_placeholder_for(float_type) expect(grouping_missing_value_placeholder).to eq(MISSING_NUMERIC_PLACEHOLDER) end @@ -180,7 +176,7 @@ module SchemaDefinition string_types.each do |string_type| it "infers secure random string for string type #{string_type}" do - grouping_missing_value_placeholder = grouping_missing_value_placeholder_for(string_type, type: "string") + grouping_missing_value_placeholder = grouping_missing_value_placeholder_for(string_type) expect(grouping_missing_value_placeholder).to eq(MISSING_STRING_PLACEHOLDER) end @@ -188,13 +184,13 @@ module SchemaDefinition integer_types.grep_v(/long/).each do |int_type| it "does not infer placeholder for safe integer type #{int_type} with default coercion adapter" do - grouping_missing_value_placeholder = grouping_missing_value_placeholder_for(int_type, type: "integer") + grouping_missing_value_placeholder = grouping_missing_value_placeholder_for(int_type) expect(grouping_missing_value_placeholder).to be_nil end it "infers 'NaN' for safe integer type #{int_type} with custom coercion adapter" do - grouping_missing_value_placeholder = grouping_missing_value_placeholder_for(int_type, type: "integer") do |t| + grouping_missing_value_placeholder = grouping_missing_value_placeholder_for(int_type) do |t| t.coerce_with "ExampleScalarCoercionAdapter", defined_at: "support/example_extensions/scalar_coercion_adapter" end @@ -202,122 +198,22 @@ module SchemaDefinition end end - it "does not infer placeholder for long types with JSON-safe min/max range and default coercion adapter" do - grouping_missing_value_placeholder = grouping_missing_value_placeholder_for("long", type: "integer", minimum: JSON_SAFE_LONG_MIN, maximum: JSON_SAFE_LONG_MAX) - - expect(grouping_missing_value_placeholder).to be_nil - end - - it "infers 'NaN' for long types with JSON-safe min/max range and custom coercion adapter" do - grouping_missing_value_placeholder = grouping_missing_value_placeholder_for("long", type: "integer", minimum: JSON_SAFE_LONG_MIN, maximum: JSON_SAFE_LONG_MAX) do |t| - t.coerce_with "ExampleScalarCoercionAdapter", defined_at: "support/example_extensions/scalar_coercion_adapter" - end - - expect(grouping_missing_value_placeholder).to eq(MISSING_NUMERIC_PLACEHOLDER) - end - - it "does not infer a value for long types with max too large" do - grouping_missing_value_placeholder = grouping_missing_value_placeholder_for("long", type: "integer", minimum: -(2**53) + 1, maximum: (2**60) - 1) do |t| - t.coerce_with "ExampleScalarCoercionAdapter", defined_at: "support/example_extensions/scalar_coercion_adapter" - end - - expect(grouping_missing_value_placeholder).to be_nil - end - - it "does not infer placeholder for long types with min too small" do - grouping_missing_value_placeholder = grouping_missing_value_placeholder_for("long", type: "integer", minimum: -(2**60), maximum: (2**53) - 1) do |t| - t.coerce_with "ExampleScalarCoercionAdapter", defined_at: "support/example_extensions/scalar_coercion_adapter" - end - - expect(grouping_missing_value_placeholder).to be_nil - end - - it "does not infer placeholder for long types with only minimum specified" do - grouping_missing_value_placeholder = grouping_missing_value_placeholder_for("long", type: "integer", minimum: 0) do |t| - t.coerce_with "ExampleScalarCoercionAdapter", defined_at: "support/example_extensions/scalar_coercion_adapter" - end - - expect(grouping_missing_value_placeholder).to be_nil - end - - it "does not infer placeholder for long types with only maximum specified" do - grouping_missing_value_placeholder = grouping_missing_value_placeholder_for("long", type: "integer", maximum: 1000) do |t| + it "does not infer a placeholder for `long` types since core ElasticGraph cannot know their range is float-safe" do + grouping_missing_value_placeholder = grouping_missing_value_placeholder_for("long") do |t| t.coerce_with "ExampleScalarCoercionAdapter", defined_at: "support/example_extensions/scalar_coercion_adapter" end expect(grouping_missing_value_placeholder).to be_nil end - it "does not infer placeholder for long types without min/max specified" do - grouping_missing_value_placeholder = grouping_missing_value_placeholder_for("long", type: "integer") do |t| + it "does not infer a placeholder for `unsigned_long` types since core ElasticGraph cannot know their range is float-safe" do + grouping_missing_value_placeholder = grouping_missing_value_placeholder_for("unsigned_long") do |t| t.coerce_with "ExampleScalarCoercionAdapter", defined_at: "support/example_extensions/scalar_coercion_adapter" end expect(grouping_missing_value_placeholder).to be_nil end - it "does not infer placeholder for unsigned_long types with safe maximum and default coercion adapter" do - grouping_missing_value_placeholder = grouping_missing_value_placeholder_for("unsigned_long", type: "integer", maximum: (2**53) - 1) - - expect(grouping_missing_value_placeholder).to be_nil - end - - it "infers 'NaN' for unsigned_long types with safe maximum and custom coercion adapter" do - grouping_missing_value_placeholder = grouping_missing_value_placeholder_for("unsigned_long", type: "integer", maximum: (2**53) - 1) do |t| - t.coerce_with "ExampleScalarCoercionAdapter", defined_at: "support/example_extensions/scalar_coercion_adapter" - end - - expect(grouping_missing_value_placeholder).to eq(MISSING_NUMERIC_PLACEHOLDER) - end - - it "does not infer placeholder for unsigned_long types with unsafe maximum" do - grouping_missing_value_placeholder = grouping_missing_value_placeholder_for("unsigned_long", type: "integer", maximum: (2**60) - 1) do |t| - t.coerce_with "ExampleScalarCoercionAdapter", defined_at: "support/example_extensions/scalar_coercion_adapter" - end - - expect(grouping_missing_value_placeholder).to be_nil - end - - it "does not infer placeholder for unsigned_long types without maximum specified" do - grouping_missing_value_placeholder = grouping_missing_value_placeholder_for("unsigned_long", type: "integer") do |t| - t.coerce_with "ExampleScalarCoercionAdapter", defined_at: "support/example_extensions/scalar_coercion_adapter" - end - - expect(grouping_missing_value_placeholder).to be_nil - end - - describe "boundary conditions for JSON-safe long ranges" do - it "does not infer placeholder when exactly at safe boundaries with default coercion adapter" do - grouping_missing_value_placeholder = grouping_missing_value_placeholder_for("long", type: "integer", minimum: JSON_SAFE_LONG_MIN, maximum: JSON_SAFE_LONG_MAX) - - expect(grouping_missing_value_placeholder).to be_nil - end - - it "infers 'NaN' when exactly at safe boundaries with custom coercion adapter" do - grouping_missing_value_placeholder = grouping_missing_value_placeholder_for("long", type: "integer", minimum: JSON_SAFE_LONG_MIN, maximum: JSON_SAFE_LONG_MAX) do |t| - t.coerce_with "ExampleScalarCoercionAdapter", defined_at: "support/example_extensions/scalar_coercion_adapter" - end - - expect(grouping_missing_value_placeholder).to eq(MISSING_NUMERIC_PLACEHOLDER) - end - - it "does not infer placeholder when minimum is one below safe range" do - grouping_missing_value_placeholder = grouping_missing_value_placeholder_for("long", type: "integer", minimum: JSON_SAFE_LONG_MIN - 1, maximum: JSON_SAFE_LONG_MAX) do |t| - t.coerce_with "ExampleScalarCoercionAdapter", defined_at: "support/example_extensions/scalar_coercion_adapter" - end - - expect(grouping_missing_value_placeholder).to be_nil - end - - it "does not infer placeholder when maximum is one above safe range" do - grouping_missing_value_placeholder = grouping_missing_value_placeholder_for("long", type: "integer", minimum: JSON_SAFE_LONG_MIN, maximum: JSON_SAFE_LONG_MAX + 1) do |t| - t.coerce_with "ExampleScalarCoercionAdapter", defined_at: "support/example_extensions/scalar_coercion_adapter" - end - - expect(grouping_missing_value_placeholder).to be_nil - end - end - it "has expected value for all built-in scalar types" do results = define_schema built_in_scalars = results.state.scalar_types_by_name.keys @@ -335,20 +231,19 @@ module SchemaDefinition "Float" => MISSING_NUMERIC_PLACEHOLDER, "ID" => MISSING_STRING_PLACEHOLDER, "Int" => MISSING_NUMERIC_PLACEHOLDER, # GraphQL automatically coerces Int values - "JsonSafeLong" => MISSING_NUMERIC_PLACEHOLDER, # custom coercion adapter coerces floats back to integers + "JsonSafeLong" => nil, # the safe range is only known to JSON ingestion (which infers a placeholder) "LocalTime" => nil, - "LongString" => nil, # outside of the JSON safe range. + "LongString" => nil, # same as JsonSafeLong (and its range is outside the JSON safe range anyway) "String" => MISSING_STRING_PLACEHOLDER, "TimeZone" => MISSING_STRING_PLACEHOLDER, "Untyped" => MISSING_STRING_PLACEHOLDER }) end - def grouping_missing_value_placeholder_for(mapping_type, **json_schema) + def grouping_missing_value_placeholder_for(mapping_type) metadata = scalar_type_metadata_for "CustomScalar" do |s| s.scalar_type "CustomScalar" do |t| t.mapping type: mapping_type - t.json_schema(**json_schema) yield t if block_given? end end