Skip to content

Commit 58fe974

Browse files
Refactor:Add deep nested placeholder validation for custom objects v2
- Recursively scan objects, fields, and triggers for setting placeholders in nested structures like metadata, custom_field_options, actions, and conditions
1 parent 0c9b2cd commit 58fe974

File tree

2 files changed

+110
-49
lines changed

2 files changed

+110
-49
lines changed

lib/zendesk_apps_support/validations/custom_objects_v2/schema_validator.rb

Lines changed: 55 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -134,14 +134,8 @@ def validate_objects_placeholder_values(objects)
134134
end
135135

136136
def validate_object_placeholder_values(object, object_identifier)
137-
object.select { |_, value| contains_setting_placeholder?(value) }.map do |property_name, property_value|
138-
ValidationError.new(
139-
:cov2_object_setting_placeholder_not_allowed,
140-
object_key: safe_value(object_identifier),
141-
property_name:,
142-
property_value:
143-
)
144-
end
137+
context_info = { type: :object, object_key: safe_value(object_identifier) }
138+
scan_for_placeholders(object, context_info)
145139
end
146140

147141
def validate_fields_placeholder_values(object_fields)
@@ -152,15 +146,12 @@ def validate_fields_placeholder_values(object_fields)
152146
end
153147

154148
def validate_field_placeholder_values(field, field_identifier, object_identifier)
155-
field.select { |_, value| contains_setting_placeholder?(value) }.map do |property_name, property_value|
156-
ValidationError.new(
157-
:cov2_field_setting_placeholder_not_allowed,
158-
field_key: safe_value(field_identifier),
159-
object_key: safe_value(object_identifier),
160-
property_name:,
161-
property_value:
162-
)
163-
end
149+
context_info = {
150+
type: :object_field,
151+
field_key: safe_value(field_identifier),
152+
object_key: safe_value(object_identifier)
153+
}
154+
scan_for_placeholders(field, context_info)
164155
end
165156

166157
def validate_triggers_placeholder_values(object_triggers)
@@ -171,21 +162,55 @@ def validate_triggers_placeholder_values(object_triggers)
171162
end
172163

173164
def validate_trigger_placeholder_values(trigger, trigger_identifier, object_identifier)
174-
placeholder_restricted_keys = %w[key object_key title]
175-
176-
placeholder_restricted_keys.filter_map do |key|
177-
value = trigger[key]
178-
next unless value.is_a?(String) && contains_setting_placeholder?(value)
179-
180-
ValidationError.new(
181-
:cov2_trigger_setting_placeholder_not_allowed,
182-
trigger_key: safe_value(trigger_identifier),
183-
object_key: safe_value(object_identifier),
184-
property_name: key,
185-
property_value: value
186-
)
165+
context_info = {
166+
type: :object_trigger,
167+
trigger_key: safe_value(trigger_identifier),
168+
object_key: safe_value(object_identifier)
169+
}
170+
scan_for_placeholders(trigger, context_info)
171+
end
172+
173+
def scan_for_placeholders(data, context_info)
174+
case data
175+
when Hash
176+
scan_hash_for_placeholders(data, context_info)
177+
when Array
178+
scan_array_for_placeholders(data, context_info)
179+
else
180+
[]
181+
end
182+
end
183+
184+
def scan_hash_for_placeholders(hash, context_info)
185+
hash.flat_map do |property_name, property_value|
186+
if property_value.is_a?(String) && contains_setting_placeholder?(property_value)
187+
[create_placeholder_error(property_name, property_value, context_info)]
188+
elsif property_value.is_a?(Hash) || property_value.is_a?(Array)
189+
scan_for_placeholders(property_value, context_info)
190+
else
191+
[]
192+
end
193+
end
194+
end
195+
196+
def scan_array_for_placeholders(array, context_info)
197+
array.flat_map do |item|
198+
scan_for_placeholders(item, context_info)
187199
end
188200
end
201+
202+
def create_placeholder_error(property_name, property_value, context_info)
203+
error_type_map = {
204+
object: :cov2_object_setting_placeholder_not_allowed,
205+
object_field: :cov2_field_setting_placeholder_not_allowed,
206+
object_trigger: :cov2_trigger_setting_placeholder_not_allowed
207+
}
208+
209+
error_type = error_type_map[context_info[:type]]
210+
211+
ValidationError.new(error_type, **context_info.except(:type), property_name: property_name,
212+
property_value: property_value)
213+
end
189214
end
190215
end
191216
end

spec/validations/custom_objects_v2/schema_validator_spec.rb

Lines changed: 55 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -104,15 +104,18 @@
104104
'objects' => [
105105
{
106106
'key' => 'object_1',
107-
'title' => '{{ setting.object_title }}',
107+
'title' => 'Object 1',
108108
'title_pluralized' => 'Objects 1',
109-
'include_in_list_view' => true
109+
'include_in_list_view' => true,
110+
'metadata' => {
111+
'description' => '{{ setting.nested_description }}'
112+
}
110113
}
111114
],
112115
'object_fields' => [],
113116
'object_triggers' => []
114117
},
115-
description: 'object contains setting placeholder in value'
118+
description: 'object contains setting placeholder'
116119
},
117120
{
118121
error: :cov2_field_setting_placeholder_not_allowed,
@@ -126,16 +129,19 @@
126129
}
127130
],
128131
'object_fields' => [
129-
{
130-
'key' => 'field_1',
131-
'title' => '{{ setting.field_title }}',
132-
'type' => 'text',
133-
'object_key' => 'object_1'
134-
}
135-
],
132+
{
133+
'key' => 'field_1',
134+
'title' => 'Field 1',
135+
'type' => 'dropdown',
136+
'object_key' => 'object_1',
137+
'custom_field_options' => [
138+
{ 'name' => 'Option 1', 'value' => '{{ setting.option_value }}' }
139+
]
140+
}
141+
],
136142
'object_triggers' => []
137143
},
138-
description: 'field contains setting placeholder in value'
144+
description: 'field contains setting placeholder'
139145
},
140146
{
141147
error: :cov2_trigger_setting_placeholder_not_allowed,
@@ -150,16 +156,46 @@
150156
],
151157
'object_fields' => [],
152158
'object_triggers' => [
159+
{
160+
'key' => 'trigger_1',
161+
'object_key' => 'object_1',
162+
'title' => 'Trigger 1',
163+
'actions' => [
164+
{ 'field' => 'status', 'value' => '{{ setting.action_value }}' }
165+
],
166+
'conditions' => { 'all' => [{ 'field' => 'status', 'operator' => 'is', 'value' => 'open' }] }
167+
}
168+
]
169+
},
170+
description: 'trigger contains setting placeholder in actions array'
171+
},
153172
{
154-
'key' => 'trigger_1',
155-
'object_key' => 'object_1',
156-
'title' => '{{ setting.trigger_title }}',
157-
'actions' => [{ 'field' => 'status', 'value' => 'resolved' }],
158-
'conditions' => { 'all' => [{ 'field' => 'status', 'operator' => 'is', 'value' => 'open' }] }
159-
}
160-
]
173+
error: :cov2_trigger_setting_placeholder_not_allowed,
174+
requirements: {
175+
'objects' => [
176+
{
177+
'key' => 'object_1',
178+
'title' => 'Object 1',
179+
'title_pluralized' => 'Objects 1',
180+
'include_in_list_view' => true
181+
}
182+
],
183+
'object_fields' => [],
184+
'object_triggers' => [
185+
{
186+
'key' => 'trigger_1',
187+
'object_key' => 'object_1',
188+
'title' => 'Trigger 1',
189+
'actions' => [{ 'field' => 'status', 'value' => 'resolved' }],
190+
'conditions' => {
191+
'all' => [
192+
{ 'field' => 'status', 'operator' => 'is', 'value' => '{{ setting.condition_value }}' }
193+
]
194+
}
195+
}
196+
]
161197
},
162-
description: 'trigger contains setting placeholder in title'
198+
description: 'trigger contains setting placeholder in conditions'
163199
}
164200
].each do |test_case|
165201
context "when #{test_case[:description]}" do

0 commit comments

Comments
 (0)