diff --git a/app/controllers/forest_liana/actions_controller.rb b/app/controllers/forest_liana/actions_controller.rb index 955cd8dd..180aedc9 100644 --- a/app/controllers/forest_liana/actions_controller.rb +++ b/app/controllers/forest_liana/actions_controller.rb @@ -55,10 +55,20 @@ def handle_result(result, formatted_fields, action) # Apply result on fields (transform the object back to an array), preserve order. fields = action.fields.map do |field| updated_field = result[field[:field]] + # Reset `value` when not present in `enums` (which means `enums` has changed). - if updated_field[:enums].is_a?(Array) && !updated_field[:enums].include?(updated_field[:value]) - updated_field[:value] = nil + if updated_field[:enums].is_a?(Array) + # `value` can be an array if the type of fields is `[x]` + if updated_field[:type].is_a?(Array) && updated_field[:value].is_a?(Array) && !(updated_field[:value] - updated_field[:enums]).empty? + updated_field[:value] = nil + end + + # `value` can be any other value + if !updated_field[:type].is_a?(Array) && !updated_field[:enums].include?(updated_field[:value]) + updated_field[:value] = nil + end end + updated_field end diff --git a/spec/requests/actions_controller_spec.rb b/spec/requests/actions_controller_spec.rb index ba7dddee..53856eaf 100644 --- a/spec/requests/actions_controller_spec.rb +++ b/spec/requests/actions_controller_spec.rb @@ -35,6 +35,11 @@ type: 'Enum', enums: %w[a b c], } + multiple_enum = { + field: 'multipleEnum', + type: ['Enum'], + enums: %w[a b c], + } action_definition = { name: 'my_action', @@ -95,12 +100,28 @@ } } } + + multiple_enums_action_definition = { + name: 'multiple_enums_action', + fields: [foo, multiple_enum], + hooks: { + :change => { + 'foo' => -> (context) { + fields = context[:fields] + fields['multipleEnum'][:enums] = %w[c d z] + return fields + } + } + } + } + action = ForestLiana::Model::Action.new(action_definition) fail_action = ForestLiana::Model::Action.new(fail_action_definition) cheat_action = ForestLiana::Model::Action.new(cheat_action_definition) enums_action = ForestLiana::Model::Action.new(enums_action_definition) + multiple_enums_action = ForestLiana::Model::Action.new(multiple_enums_action_definition) island = ForestLiana.apimap.find {|collection| collection.name.to_s == ForestLiana.name_for(Island)} - island.actions = [action, fail_action, cheat_action, enums_action] + island.actions = [action, fail_action, cheat_action, enums_action, multiple_enums_action] describe 'call /load' do params = {recordIds: [1], collectionName: 'Island'} @@ -169,6 +190,33 @@ expect(JSON.parse(response.body)).to eq({'fields' => [expected_foo.stringify_keys, expected_enum.stringify_keys]}) end + it 'should not reset value when every enum values are in the enums definition' do + updated_multiple_enum = multiple_enum.clone.merge({:previousValue => nil, :value => %w[c]}) + p = {recordIds: [1], fields: [foo, updated_multiple_enum], collectionName: 'Island', changedField: 'foo'} + post '/forest/actions/multiple_enums_action/hooks/change', params: JSON.dump(p), headers: { 'CONTENT_TYPE' => 'application/json' } + expect(response.status).to eq(200) + + expected_multiple_enum = updated_multiple_enum.clone.merge({ :enums => %w[c d z], :widgetEdit => nil, :value => %w[c]}) + expected_multiple_enum.delete(:widget) + expected_foo = foo.clone.merge({ :widgetEdit => nil}) + expected_foo.delete(:widget) + + expect(JSON.parse(response.body)).to eq({'fields' => [expected_foo.stringify_keys, expected_multiple_enum.stringify_keys]}) + end + + it 'should reset value when one of the enum values is not in the enums definition' do + wrongly_updated_multiple_enum = multiple_enum.clone.merge({:previousValue => nil, :value => %w[a b]}) + p = {recordIds: [1], fields: [foo, wrongly_updated_multiple_enum], collectionName: 'Island', changedField: 'foo'} + post '/forest/actions/multiple_enums_action/hooks/change', params: JSON.dump(p), headers: { 'CONTENT_TYPE' => 'application/json' } + expect(response.status).to eq(200) + + expected_multiple_enum = wrongly_updated_multiple_enum.clone.merge({ :enums => %w[c d z], :widgetEdit => nil, :value => nil }) + expected_multiple_enum.delete(:widget) + expected_foo = foo.clone.merge({ :widgetEdit => nil}) + expected_foo.delete(:widget) + + expect(JSON.parse(response.body)).to eq({'fields' => [expected_foo.stringify_keys, expected_multiple_enum.stringify_keys]}) + end end end end