Skip to content

Commit

Permalink
Improve integration mapping chain resolution (#526)
Browse files Browse the repository at this point in the history
  • Loading branch information
danielpgross authored Jan 10, 2025
2 parents aa030e0 + 71f2488 commit 3ace3f2
Show file tree
Hide file tree
Showing 2 changed files with 166 additions and 14 deletions.
28 changes: 16 additions & 12 deletions dev/lib/product_taxonomy/models/integration_version.rb
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,9 @@ def load_all_from_source(current_shopify_version: nil, base_path: INTEGRATIONS_P
#
# @param versions [Array<IntegrationVersion>] The versions to resolve, ordered from oldest to newest.
def resolve_to_shopify_mappings_chain(versions)
# Resolve newest version against current taxonomy
versions.last.resolve_to_shopify_mappings(nil)

# Resolve each older version against the one following it
versions.each_cons(2).reverse_each do |previous, next_version|
previous.resolve_to_shopify_mappings(next_version)
versions.reverse.each_with_object([]) do |version, resolved_versions|
version.resolve_to_shopify_mappings(resolved_versions)
resolved_versions.prepend(version)
end
end

Expand Down Expand Up @@ -177,16 +174,23 @@ def generate_distribution(output_path:, direction:)
)
end

# Resolve the output categories of to_shopify mappings to the next version of the Shopify taxonomy.
# Resolve the output categories of to_shopify mappings to the current version of the Shopify taxonomy, taking into
# any mappings from later versions.
#
# @param next_integration_version [IntegrationVersion | nil] The IntegrationVersion defining mappings to the next
# newer version of the Shopify taxonomy. If nil, the latest version of the Shopify taxonomy is used.
def resolve_to_shopify_mappings(next_integration_version)
# @param next_integration_versions [Array<IntegrationVersion>] An array of Shopify integration versions coming
# after the current version.
def resolve_to_shopify_mappings(next_integration_versions)
@to_shopify_mappings.each do |mapping|
newer_mapping = next_integration_version&.to_shopify_mappings&.find do
_1.input_category["id"] == mapping.output_category
newer_mapping = next_integration_versions.flat_map(&:to_shopify_mappings).find do |mapping_rule|
mapping_rule.input_category["id"] == mapping.output_category
end
mapping.output_category = newer_mapping&.output_category || Category.find_by(id: mapping.output_category)

next unless mapping.output_category.nil?

raise ArgumentError, "Failed to resolve Shopify mapping: " \
"\"#{mapping.input_category["id"]}\" to \"#{mapping.output_category}\" " \
"(input version: #{version})"
end
end

Expand Down
152 changes: 150 additions & 2 deletions dev/test/models/integration_version_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class IntegrationVersionTest < TestCase
integration_path: File.expand_path("integrations/shopify/2020-01", DATA_PATH),
current_shopify_version: @current_shopify_version,
)
@shopify_integration.resolve_to_shopify_mappings(nil) # Resolve against current version
@shopify_integration.resolve_to_shopify_mappings([]) # Resolve against current version
@external_integration = IntegrationVersion.load_from_source(
integration_path: File.expand_path("integrations/foocommerce/1.0.0", DATA_PATH),
current_shopify_version: @current_shopify_version,
Expand Down Expand Up @@ -236,7 +236,7 @@ class IntegrationVersionTest < TestCase
end

test "unmapped_external_category_ids returns IDs of external categories not mapped from the Shopify taxonomy" do
external_category1 = { "id" => "1", "full_name" => "External category 1" }
external_category1 = category_hash("1")
from_shopify_mappings = [
MappingRule.new(
input_category: Category.new(id: "aa", name: "aa"),
Expand All @@ -257,5 +257,153 @@ class IntegrationVersionTest < TestCase

assert_equal ["2", "3"], integration_version.unmapped_external_category_ids
end

test "resolve_to_shopify_mappings resolves mappings to the latest version of the Shopify taxonomy" do
mapping = MappingRule.new(input_category: category_hash("aa-1"), output_category: "aa-2")
integration_version = IntegrationVersion.new(
name: "shopify",
version: "2020-01",
to_shopify_mappings: [mapping],
full_names_by_id: {},
)
integration_version.resolve_to_shopify_mappings([])
assert_equal "gid://shopify/TaxonomyCategory/aa-2", mapping.output_category.gid
end

test "resolve_to_shopify_mappings raises an error if a mapping cannot be resolved" do
mapping = MappingRule.new(input_category: category_hash("aa-1"), output_category: "invalid")
integration_version = IntegrationVersion.new(
name: "shopify",
version: "2020-01",
to_shopify_mappings: [mapping],
full_names_by_id: {},
)
assert_raises(ArgumentError) { integration_version.resolve_to_shopify_mappings([]) }
end

test "IntegrationVersion.resolve_to_shopify_mappings_chain resolves mappings to the current version of the Shopify taxonomy" do
version = IntegrationVersion.new(
name: "shopify",
version: "2020-01",
to_shopify_mappings: [MappingRule.new(input_category: category_hash("aa-1"), output_category: "aa-2")],
full_names_by_id: {},
)
IntegrationVersion.resolve_to_shopify_mappings_chain([version])
assert_equal "gid://shopify/TaxonomyCategory/aa-2", version.to_shopify_mappings[0].output_category.gid
end

test "IntegrationVersion.resolve_to_shopify_mappings_chain resolves mappings through two versions without chained mappings" do
versions = [
IntegrationVersion.new(
name: "shopify",
version: "2020-01",
to_shopify_mappings: [MappingRule.new(input_category: category_hash("aa-1"), output_category: "aa-2")],
full_names_by_id: {},
),
IntegrationVersion.new(
name: "shopify",
version: "2021-01",
to_shopify_mappings: [MappingRule.new(input_category: category_hash("bb-1"), output_category: "aa-1")],
full_names_by_id: {},
),
]
IntegrationVersion.resolve_to_shopify_mappings_chain(versions)
assert_equal "gid://shopify/TaxonomyCategory/aa-2", versions[0].to_shopify_mappings[0].output_category.gid
assert_equal "gid://shopify/TaxonomyCategory/aa-1", versions[1].to_shopify_mappings[0].output_category.gid
end

test "IntegrationVersion.resolve_to_shopify_mappings_chain resolves mappings through two versions with chained mappings" do
versions = [
IntegrationVersion.new(
name: "shopify",
version: "2020-01",
to_shopify_mappings: [MappingRule.new(input_category: category_hash("aa-1"), output_category: "aa-2")],
full_names_by_id: {},
),
IntegrationVersion.new(
name: "shopify",
version: "2021-01",
to_shopify_mappings: [MappingRule.new(input_category: category_hash("aa-2"), output_category: "aa-3")],
full_names_by_id: {},
),
]
IntegrationVersion.resolve_to_shopify_mappings_chain(versions)
assert_equal "gid://shopify/TaxonomyCategory/aa-3", versions[0].to_shopify_mappings[0].output_category.gid
assert_equal "gid://shopify/TaxonomyCategory/aa-3", versions[1].to_shopify_mappings[0].output_category.gid
end

test "IntegrationVersion.resolve_to_shopify_mappings_chain resolves mappings through four versions with non-consecutive chained mappings" do
versions = [
IntegrationVersion.new(
name: "shopify",
version: "2020-01",
to_shopify_mappings: [MappingRule.new(input_category: category_hash("aa-1"), output_category: "aa-2")],
full_names_by_id: {},
),
IntegrationVersion.new(
name: "shopify",
version: "2021-01",
to_shopify_mappings: [],
full_names_by_id: {},
),
IntegrationVersion.new(
name: "shopify",
version: "2022-01",
to_shopify_mappings: [MappingRule.new(input_category: category_hash("aa-2"), output_category: "aa-3")],
full_names_by_id: {},
),
IntegrationVersion.new(
name: "shopify",
version: "2023-01",
to_shopify_mappings: [],
full_names_by_id: {},
),
]
IntegrationVersion.resolve_to_shopify_mappings_chain(versions)
assert_equal "gid://shopify/TaxonomyCategory/aa-3", versions[0].to_shopify_mappings[0].output_category.gid
assert_equal "gid://shopify/TaxonomyCategory/aa-3", versions[2].to_shopify_mappings[0].output_category.gid
end

test "IntegrationVersion.resolve_to_shopify_mappings_chain resolves mappings through four versions with a mix of chained and non-chained mappings" do
versions = [
IntegrationVersion.new(
name: "shopify",
version: "2020-01",
to_shopify_mappings: [
MappingRule.new(input_category: category_hash("aa-1"), output_category: "aa-2"),
MappingRule.new(input_category: category_hash("bb-1"), output_category: "aa-1"),
],
full_names_by_id: {},
),
IntegrationVersion.new(
name: "shopify",
version: "2021-01",
to_shopify_mappings: [MappingRule.new(input_category: category_hash("cc-1"), output_category: "aa-1")],
full_names_by_id: {},
),
IntegrationVersion.new(
name: "shopify",
version: "2022-01",
to_shopify_mappings: [MappingRule.new(input_category: category_hash("aa-2"), output_category: "aa-3")],
full_names_by_id: {},
),
IntegrationVersion.new(
name: "shopify",
version: "2023-01",
to_shopify_mappings: [MappingRule.new(input_category: category_hash("dd-1"), output_category: "aa-2")],
full_names_by_id: {},
),
]
IntegrationVersion.resolve_to_shopify_mappings_chain(versions)
assert_equal "gid://shopify/TaxonomyCategory/aa-3", versions[0].to_shopify_mappings[0].output_category.gid
assert_equal "gid://shopify/TaxonomyCategory/aa-1", versions[0].to_shopify_mappings[1].output_category.gid
assert_equal "gid://shopify/TaxonomyCategory/aa-1", versions[1].to_shopify_mappings[0].output_category.gid
assert_equal "gid://shopify/TaxonomyCategory/aa-3", versions[2].to_shopify_mappings[0].output_category.gid
assert_equal "gid://shopify/TaxonomyCategory/aa-2", versions[3].to_shopify_mappings[0].output_category.gid
end

def category_hash(id)
{ "id" => id, "full_name" => "Category #{id}" }
end
end
end

0 comments on commit 3ace3f2

Please sign in to comment.