Module: JSONAPI::Testing::StiHelpers

Defined in:
lib/json_api/testing/sti_helpers.rb

Overview

Helper methods for testing STI (Single Table Inheritance) resources in JSON:API responses.

These helpers simplify testing that STI subtypes are correctly serialized and included in JSON:API responses.

Usage in request specs:

it "includes user messages", :aggregate_failures do
  get conversation_path(conversation), params: { include: "messages" }, as: :jsonapi
  expect_sti_types_in_included(expected_subtypes: ["user_messages"])
  expect_sti_resources_included(sti_type: "user_messages", expected_ids: [message.id])
end

Instance Method Summary collapse

Instance Method Details

#expect_sti_resources_in_data(sti_type:, expected_ids:) ⇒ void

This method returns an undefined value.

Verify that specific STI resources are present in data by ID.

Examples:

Verify specific messages are in data

expect_sti_resources_in_data(
  sti_type: "user_messages",
  expected_ids: [message1.id, message2.id]
)

Parameters:

  • sti_type (String, Symbol)

    The STI subtype

  • expected_ids (Array<Integer, String>)

    Expected resource IDs



131
132
133
134
135
136
137
138
# File 'lib/json_api/testing/sti_helpers.rb', line 131

def expect_sti_resources_in_data(sti_type:, expected_ids:)
  resources = find_sti_resources_in_data(sti_type)
  actual_ids = resources.map { |r| r["id"] }
  expected_ids_str = expected_ids.map(&:to_s)

  expect(actual_ids).to match_array(expected_ids_str),
                        "Expected #{sti_type} resources with IDs #{expected_ids_str}, got: #{actual_ids}"
end

#expect_sti_resources_included(sti_type:, expected_ids:) ⇒ void

This method returns an undefined value.

Verify that specific STI resources are included by ID.

Examples:

Verify specific messages are included

expect_sti_resources_included(
  sti_type: "user_messages",
  expected_ids: [message1.id, message2.id]
)

Parameters:

  • sti_type (String, Symbol)

    The STI subtype

  • expected_ids (Array<Integer, String>)

    Expected resource IDs



71
72
73
74
75
76
77
78
# File 'lib/json_api/testing/sti_helpers.rb', line 71

def expect_sti_resources_included(sti_type:, expected_ids:)
  resources = find_sti_resources_in_included(sti_type)
  actual_ids = resources.map { |r| r["id"] }
  expected_ids_str = expected_ids.map(&:to_s)

  expect(actual_ids).to match_array(expected_ids_str),
                        "Expected #{sti_type} resources with IDs #{expected_ids_str}, got: #{actual_ids}"
end

#expect_sti_types_in_data(expected_subtypes:, exclude_base_type: nil) ⇒ void

This method returns an undefined value.

Verify STI types in data array (not included).

Examples:

Verify data contains correct STI types

expect_sti_types_in_data(
  expected_subtypes: ["user_messages", "ai_messages"],
  exclude_base_type: "messages"
)

Parameters:

  • expected_subtypes (Array<String, Symbol>)

    Expected STI subtype names

  • exclude_base_type (String, Symbol, nil) (defaults to: nil)

    Base type that should NOT be present (optional)



91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/json_api/testing/sti_helpers.rb', line 91

def expect_sti_types_in_data(expected_subtypes:, exclude_base_type: nil)
  data = response.parsed_body["data"]
  data = [data] unless data.is_a?(Array)
  types = data.pluck("type").uniq

  expected_subtypes.each do |subtype|
    expect(types).to include(subtype.to_s),
                     "Expected data to contain STI subtype '#{subtype}', got: #{types}"
  end

  return if exclude_base_type.blank?

  expect(types).not_to include(exclude_base_type.to_s),
                       "Expected data NOT to contain base type '#{exclude_base_type}', but it did"
end

#expect_sti_types_in_included(expected_subtypes:, exclude_base_type: nil) ⇒ void

This method returns an undefined value.

Verify that included resources contain expected STI subtypes.

Examples:

Verify subtypes are present

expect_sti_types_in_included(expected_subtypes: ["user_messages", "ai_messages"])

Verify subtypes and exclude base type

expect_sti_types_in_included(
  expected_subtypes: ["user_messages"],
  exclude_base_type: "messages"
)

Parameters:

  • expected_subtypes (Array<String, Symbol>)

    Expected STI subtype names

  • exclude_base_type (String, Symbol, nil) (defaults to: nil)

    Base type that should NOT be present (optional)



32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/json_api/testing/sti_helpers.rb', line 32

def expect_sti_types_in_included(expected_subtypes:, exclude_base_type: nil)
  included = response.parsed_body["included"] || []
  included_types = included.pluck("type").uniq

  expected_subtypes.each do |subtype|
    expect(included_types).to include(subtype.to_s),
                              "Expected included to contain STI type '#{subtype}', got: #{included_types}"
  end

  return if exclude_base_type.blank?

  expect(included_types).not_to include(exclude_base_type.to_s),
                                "Expected included NOT to contain base type '#{exclude_base_type}', but it did"
end

#find_sti_resources_in_data(sti_type) ⇒ Array<Hash>

Find all resources of a specific STI type in the data array.

Examples:

Find all user messages in data

messages = find_sti_resources_in_data("user_messages")

Parameters:

  • sti_type (String, Symbol)

    The STI subtype to find

Returns:

  • (Array<Hash>)

    Array of resource objects matching the STI type



114
115
116
117
118
# File 'lib/json_api/testing/sti_helpers.rb', line 114

def find_sti_resources_in_data(sti_type)
  data = response.parsed_body["data"]
  data = [data] unless data.is_a?(Array)
  data.select { |item| item["type"] == sti_type.to_s }
end

#find_sti_resources_in_included(sti_type) ⇒ Array<Hash>

Find all resources of a specific STI type in the included array.

Examples:

Find all user messages in included

messages = find_sti_resources_in_included("user_messages")
expect(messages.first["attributes"]["content"]).to eq("Hello")

Parameters:

  • sti_type (String, Symbol)

    The STI subtype to find

Returns:

  • (Array<Hash>)

    Array of resource objects matching the STI type



55
56
57
58
# File 'lib/json_api/testing/sti_helpers.rb', line 55

def find_sti_resources_in_included(sti_type)
  included = response.parsed_body["included"] || []
  included.select { |item| item["type"] == sti_type.to_s }
end