forest_liana 5.2.3 → 5.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/app/controllers/forest_liana/actions_controller.rb +95 -0
- data/app/controllers/forest_liana/resources_controller.rb +14 -17
- data/app/controllers/forest_liana/smart_actions_controller.rb +10 -5
- data/app/helpers/forest_liana/is_same_data_structure_helper.rb +44 -0
- data/app/helpers/forest_liana/widgets_helper.rb +59 -0
- data/app/models/forest_liana/model/action.rb +2 -1
- data/app/services/forest_liana/apimap_sorter.rb +1 -0
- data/app/services/forest_liana/permissions_checker.rb +118 -56
- data/app/services/forest_liana/permissions_formatter.rb +52 -0
- data/app/services/forest_liana/permissions_getter.rb +52 -17
- data/app/services/forest_liana/resources_getter.rb +3 -3
- data/app/services/forest_liana/scope_validator.rb +8 -7
- data/app/services/forest_liana/utils/beta_schema_utils.rb +13 -0
- data/config/routes.rb +2 -0
- data/lib/forest_liana/bootstrapper.rb +19 -0
- data/lib/forest_liana/schema_file_updater.rb +1 -0
- data/lib/forest_liana/version.rb +1 -1
- data/spec/helpers/forest_liana/is_same_data_structure_helper_spec.rb +87 -0
- data/spec/requests/actions_controller_spec.rb +174 -0
- data/spec/services/forest_liana/apimap_sorter_spec.rb +6 -4
- data/spec/services/forest_liana/permissions_checker_acl_disabled_spec.rb +711 -0
- data/spec/services/forest_liana/permissions_checker_acl_enabled_spec.rb +831 -0
- data/spec/services/forest_liana/permissions_formatter_spec.rb +222 -0
- data/spec/services/forest_liana/permissions_getter_spec.rb +82 -0
- data/spec/services/forest_liana/schema_adapter_spec.rb +1 -1
- data/spec/spec_helper.rb +3 -0
- metadata +18 -2
@@ -0,0 +1,52 @@
|
|
1
|
+
module ForestLiana
|
2
|
+
class PermissionsFormatter
|
3
|
+
class << PermissionsFormatter
|
4
|
+
# Convert old format permissions to unify PermissionsGetter code
|
5
|
+
def convert_to_new_format(permissions, rendering_id)
|
6
|
+
permissions_new_format = Hash.new
|
7
|
+
permissions_new_format['collections'] = Hash.new
|
8
|
+
permissions_new_format['renderings'] = Hash.new
|
9
|
+
permissions_new_format['renderings'][rendering_id] = Hash.new
|
10
|
+
permissions.keys.each { |collection_name|
|
11
|
+
permissions_new_format['collections'][collection_name] = {
|
12
|
+
'collection' => convert_collection_permissions_to_new_format(permissions[collection_name]['collection']),
|
13
|
+
'actions' => convert_actions_permissions_to_new_format(permissions[collection_name]['actions'])
|
14
|
+
}
|
15
|
+
|
16
|
+
permissions_new_format['renderings'][rendering_id][collection_name] = { 'scope' => permissions[collection_name]['scope'] }
|
17
|
+
}
|
18
|
+
|
19
|
+
permissions_new_format
|
20
|
+
end
|
21
|
+
|
22
|
+
def convert_collection_permissions_to_new_format(collection_permissions)
|
23
|
+
{
|
24
|
+
'browseEnabled' => collection_permissions['list'] || collection_permissions['searchToEdit'],
|
25
|
+
'readEnabled' => collection_permissions['show'],
|
26
|
+
'addEnabled' => collection_permissions['create'],
|
27
|
+
'editEnabled' => collection_permissions['update'],
|
28
|
+
'deleteEnabled' => collection_permissions['delete'],
|
29
|
+
'exportEnabled' => collection_permissions['export']
|
30
|
+
}
|
31
|
+
end
|
32
|
+
|
33
|
+
def convert_actions_permissions_to_new_format(actions_permissions)
|
34
|
+
return nil unless actions_permissions
|
35
|
+
|
36
|
+
actions_permissions_new_format = Hash.new
|
37
|
+
|
38
|
+
actions_permissions.keys.each { |action_name|
|
39
|
+
allowed = actions_permissions[action_name]['allowed']
|
40
|
+
users = actions_permissions[action_name]['users']
|
41
|
+
|
42
|
+
actions_permissions_new_format[action_name] = Hash.new
|
43
|
+
actions_permissions_new_format[action_name] = {
|
44
|
+
'triggerEnabled' => allowed && (users.nil? || users)
|
45
|
+
}
|
46
|
+
}
|
47
|
+
|
48
|
+
actions_permissions_new_format
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -1,25 +1,60 @@
|
|
1
1
|
module ForestLiana
|
2
2
|
class PermissionsGetter
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
3
|
+
class << PermissionsGetter
|
4
|
+
def get_permissions_api_route
|
5
|
+
'/liana/v3/permissions'
|
6
|
+
end
|
7
|
+
|
8
|
+
# Permission format example:
|
9
|
+
# collections => {
|
10
|
+
# {model_name} => {
|
11
|
+
# collection => {
|
12
|
+
# browseEnabled => true,
|
13
|
+
# readEnabled => true,
|
14
|
+
# editEnabled => true,
|
15
|
+
# addEnabled => true,
|
16
|
+
# deleteEnabled => true,
|
17
|
+
# exportEnabled => true,
|
18
|
+
# },
|
19
|
+
# actions => {
|
20
|
+
# {action_name} => {
|
21
|
+
# triggerEnabled => true,
|
22
|
+
# },
|
23
|
+
# },
|
24
|
+
# },
|
25
|
+
# },
|
26
|
+
# rederings => {
|
27
|
+
# {rendering_id} => {
|
28
|
+
# {collection_id} => {
|
29
|
+
# scope => {
|
30
|
+
# dynamicScopesValues => {},
|
31
|
+
# filter => {}
|
32
|
+
# }
|
33
|
+
# }
|
34
|
+
# }
|
35
|
+
# }
|
36
|
+
# }
|
37
|
+
# With `rendering_specific_only` this returns only the permissions related data specific to the provided rendering
|
38
|
+
# For now this only includes scopes
|
39
|
+
def get_permissions_for_rendering(rendering_id, rendering_specific_only: false)
|
40
|
+
begin
|
41
|
+
query_parameters = { 'renderingId' => rendering_id }
|
42
|
+
query_parameters['renderingSpecificOnly'] = rendering_specific_only if rendering_specific_only
|
7
43
|
|
8
|
-
|
9
|
-
|
10
|
-
query_parameters = { 'renderingId' => @rendering_id }
|
11
|
-
response = ForestLiana::ForestApiRequester.get(@route, query: query_parameters)
|
44
|
+
api_route = get_permissions_api_route
|
45
|
+
response = ForestLiana::ForestApiRequester.get(api_route, query: query_parameters)
|
12
46
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
47
|
+
if response.is_a?(Net::HTTPOK)
|
48
|
+
JSON.parse(response.body)
|
49
|
+
else
|
50
|
+
raise "Forest API returned an #{ForestLiana::Errors::HTTPErrorHelper.format(response)}"
|
51
|
+
end
|
52
|
+
rescue => exception
|
53
|
+
FOREST_LOGGER.error 'Cannot retrieve the permissions from the Forest server.'
|
54
|
+
FOREST_LOGGER.error 'Which was caused by:'
|
55
|
+
ForestLiana::Errors::ExceptionHelper.recursively_print(exception, margin: ' ', is_error: true)
|
56
|
+
nil
|
17
57
|
end
|
18
|
-
rescue => exception
|
19
|
-
FOREST_LOGGER.error 'Cannot retrieve the permissions from the Forest server.'
|
20
|
-
FOREST_LOGGER.error 'Which was caused by:'
|
21
|
-
ForestLiana::Errors::ExceptionHelper.recursively_print(exception, margin: ' ', is_error: true)
|
22
|
-
nil
|
23
58
|
end
|
24
59
|
end
|
25
60
|
end
|
@@ -12,11 +12,11 @@ module ForestLiana
|
|
12
12
|
@collection = get_collection(@collection_name)
|
13
13
|
@fields_to_serialize = get_fields_to_serialize
|
14
14
|
@field_names_requested = field_names_requested
|
15
|
-
get_segment
|
16
|
-
compute_includes
|
15
|
+
get_segment
|
16
|
+
compute_includes
|
17
17
|
@search_query_builder = SearchQueryBuilder.new(@params, @includes, @collection)
|
18
18
|
|
19
|
-
prepare_query
|
19
|
+
prepare_query
|
20
20
|
end
|
21
21
|
|
22
22
|
def self.get_ids_from_request(params)
|
@@ -32,9 +32,10 @@ module ForestLiana
|
|
32
32
|
def compute_condition_filters_from_scope(user_id)
|
33
33
|
computed_condition_filters = @scope_filters.clone
|
34
34
|
computed_condition_filters['conditions'].each do |condition|
|
35
|
-
if condition.include?('value') &&
|
36
|
-
!condition['value'].nil? &&
|
37
|
-
condition['value'].
|
35
|
+
if condition.include?('value') &&
|
36
|
+
!condition['value'].nil? &&
|
37
|
+
condition['value'].instance_of?(String) &&
|
38
|
+
condition['value'].start_with?('$') &&
|
38
39
|
@users_variable_values.include?(user_id)
|
39
40
|
condition['value'] = @users_variable_values[user_id][condition['value']]
|
40
41
|
end
|
@@ -51,9 +52,9 @@ module ForestLiana
|
|
51
52
|
ensure_valid_aggregation(node)
|
52
53
|
|
53
54
|
return is_scope_condition?(node) unless node['aggregator']
|
54
|
-
|
55
|
+
|
55
56
|
# NOTICE: Remove conditions that are not from the scope
|
56
|
-
filtered_conditions = node['conditions'].map { |condition|
|
57
|
+
filtered_conditions = node['conditions'].map { |condition|
|
57
58
|
search_scope_aggregation(condition)
|
58
59
|
}.select { |condition|
|
59
60
|
condition
|
@@ -61,7 +62,7 @@ module ForestLiana
|
|
61
62
|
|
62
63
|
# NOTICE: If there is only one condition filter left and its current aggregator is
|
63
64
|
# an "and", this condition filter is the searched scope
|
64
|
-
if (filtered_conditions.length == 1 &&
|
65
|
+
if (filtered_conditions.length == 1 &&
|
65
66
|
filtered_conditions.first.is_a?(Hash) &&
|
66
67
|
filtered_conditions.first.include?(:aggregator) &&
|
67
68
|
node['aggregator'] == 'and')
|
@@ -70,7 +71,7 @@ module ForestLiana
|
|
70
71
|
|
71
72
|
# NOTICE: Otherwise, validate if the current node is the scope and return nil
|
72
73
|
# if it's not
|
73
|
-
return (filtered_conditions.length == @scope_filters['conditions'].length &&
|
74
|
+
return (filtered_conditions.length == @scope_filters['conditions'].length &&
|
74
75
|
node['aggregator'] == @scope_filters['aggregator']) ?
|
75
76
|
{ aggregator: node['aggregator'], conditions: filtered_conditions } :
|
76
77
|
nil
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module ForestLiana
|
2
|
+
module Utils
|
3
|
+
class BetaSchemaUtils
|
4
|
+
def self.find_action_from_endpoint(collection_name, endpoint, http_method)
|
5
|
+
collection = ForestLiana.apimap.find { |collection| collection.name.to_s == collection_name }
|
6
|
+
|
7
|
+
return nil unless collection
|
8
|
+
|
9
|
+
collection.actions.find { |action| action.endpoint == endpoint && action.http_method == http_method }
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
data/config/routes.rb
CHANGED
@@ -38,6 +38,14 @@ module ForestLiana
|
|
38
38
|
|
39
39
|
private
|
40
40
|
|
41
|
+
def get_collection(collection_name)
|
42
|
+
ForestLiana.apimap.find { |collection| collection.name.to_s == collection_name }
|
43
|
+
end
|
44
|
+
|
45
|
+
def get_action(collection, action_name)
|
46
|
+
collection.actions.find {|action| action.name == action_name}
|
47
|
+
end
|
48
|
+
|
41
49
|
def generate_apimap
|
42
50
|
create_apimap
|
43
51
|
require_lib_forest_liana
|
@@ -45,6 +53,17 @@ module ForestLiana
|
|
45
53
|
|
46
54
|
if Rails.env.development?
|
47
55
|
@collections_sent = ForestLiana.apimap.as_json
|
56
|
+
|
57
|
+
@collections_sent.each do |collection|
|
58
|
+
collection['actions'].each do |action|
|
59
|
+
c = get_collection(collection['name'])
|
60
|
+
a = get_action(c, action['name'])
|
61
|
+
load = !a.hooks.nil? && a.hooks.key?(:load) && a.hooks[:load].is_a?(Proc)
|
62
|
+
change = !a.hooks.nil? && a.hooks.key?(:change) && a.hooks[:change].is_a?(Hash) ? a.hooks[:change].keys : []
|
63
|
+
action['hooks'] = {:load => load, :change => change}
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
48
67
|
@meta_sent = ForestLiana.meta
|
49
68
|
SchemaFileUpdater.new(SCHEMA_FILENAME, @collections_sent, @meta_sent).perform()
|
50
69
|
else
|
data/lib/forest_liana/version.rb
CHANGED
@@ -0,0 +1,87 @@
|
|
1
|
+
module ForestLiana
|
2
|
+
context 'IsSameDataStructure class' do
|
3
|
+
it 'should: be valid with simple data' do
|
4
|
+
object = {:a => 'a', :b => 'b'}
|
5
|
+
other = {:a => 'a', :b => 'b'}
|
6
|
+
result = IsSameDataStructureHelper::Analyser.new(object, other).perform
|
7
|
+
expect(result).to be true
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'should: be invalid with simple data' do
|
11
|
+
object = {:a => 'a', :b => 'b'}
|
12
|
+
other = {:a => 'a', :c => 'c'}
|
13
|
+
result = IsSameDataStructureHelper::Analyser.new(object, other).perform
|
14
|
+
expect(result).to be false
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'should: be invalid with not same hash' do
|
18
|
+
object = {:a => 'a', :b => 'b'}
|
19
|
+
other = {:a => 'a', :b => 'b', :c => 'c'}
|
20
|
+
result = IsSameDataStructureHelper::Analyser.new(object, other).perform
|
21
|
+
expect(result).to be false
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'should: be invalid with nil' do
|
25
|
+
object = nil
|
26
|
+
other = {:a => 'a', :b => 'b', :c => 'c'}
|
27
|
+
result = IsSameDataStructureHelper::Analyser.new(object, other).perform
|
28
|
+
expect(result).to be false
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'should: be invalid with not hash' do
|
32
|
+
object = nil
|
33
|
+
other = {:a => 'a', :b => 'b', :c => 'c'}
|
34
|
+
result = IsSameDataStructureHelper::Analyser.new(object, other).perform
|
35
|
+
expect(result).to be false
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'should: be invalid with integer' do
|
39
|
+
object = 1
|
40
|
+
other = {:a => 'a', :b => 'b', :c => 'c'}
|
41
|
+
result = IsSameDataStructureHelper::Analyser.new(object, other).perform
|
42
|
+
expect(result).to be false
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'should: be invalid with string' do
|
46
|
+
object = 'a'
|
47
|
+
other = {:a => 'a', :b => 'b', :c => 'c'}
|
48
|
+
result = IsSameDataStructureHelper::Analyser.new(object, other).perform
|
49
|
+
expect(result).to be false
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'should: be valid with depth 1' do
|
53
|
+
object = {:a => {:c => 'c'}, :b => {:d => 'd'}}
|
54
|
+
other = {:a => {:c => 'c'}, :b => {:d => 'd'}}
|
55
|
+
result = IsSameDataStructureHelper::Analyser.new(object, other, 1).perform
|
56
|
+
expect(result).to be true
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'should: be invalid with depth 1' do
|
60
|
+
object = {:a => {:c => 'c'}, :b => {:d => 'd'}}
|
61
|
+
other = {:a => {:c => 'c'}, :b => {:e => 'e'}}
|
62
|
+
result = IsSameDataStructureHelper::Analyser.new(object, other, 1).perform
|
63
|
+
expect(result).to be false
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'should: be invalid with depth 1 and nil' do
|
67
|
+
object = {:a => {:c => 'c'}, :b => {:d => 'd'}}
|
68
|
+
other = {:a => {:c => 'c'}, :b => nil}
|
69
|
+
result = IsSameDataStructureHelper::Analyser.new(object, other, 1).perform
|
70
|
+
expect(result).to be false
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'should: be invalid with depth 1 and integer' do
|
74
|
+
object = {:a => {:c => 'c'}, :b => {:d => 'd'}}
|
75
|
+
other = {:a => {:c => 'c'}, :b => 1}
|
76
|
+
result = IsSameDataStructureHelper::Analyser.new(object, other, 1).perform
|
77
|
+
expect(result).to be false
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'should: be invalid with depth 1 and string' do
|
81
|
+
object = {:a => {:c => 'c'}, :b => {:d => 'd'}}
|
82
|
+
other = {:a => {:c => 'c'}, :b => 'b'}
|
83
|
+
result = IsSameDataStructureHelper::Analyser.new(object, other, 1).perform
|
84
|
+
expect(result).to be false
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,174 @@
|
|
1
|
+
require 'rails_helper'
|
2
|
+
|
3
|
+
describe 'Requesting Actions routes', :type => :request do
|
4
|
+
before(:each) do
|
5
|
+
allow(ForestLiana::IpWhitelist).to receive(:is_ip_whitelist_retrieved) { true }
|
6
|
+
allow(ForestLiana::IpWhitelist).to receive(:is_ip_valid) { true }
|
7
|
+
Island.create(name: 'Corsica')
|
8
|
+
end
|
9
|
+
|
10
|
+
after(:each) do
|
11
|
+
Island.destroy_all
|
12
|
+
end
|
13
|
+
|
14
|
+
describe 'call /values' do
|
15
|
+
it 'should respond 200' do
|
16
|
+
post '/forest/actions/foo/values', {}
|
17
|
+
expect(response.status).to eq(200)
|
18
|
+
expect(response.body).to be {}
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe 'hooks' do
|
23
|
+
foo = {
|
24
|
+
field: 'foo',
|
25
|
+
type: 'String',
|
26
|
+
default_value: nil,
|
27
|
+
enums: nil,
|
28
|
+
is_required: false,
|
29
|
+
reference: nil,
|
30
|
+
description: nil,
|
31
|
+
widget: nil,
|
32
|
+
}
|
33
|
+
enum = {
|
34
|
+
field: 'enum',
|
35
|
+
type: 'Enum',
|
36
|
+
enums: %w[a b c],
|
37
|
+
}
|
38
|
+
|
39
|
+
action_definition = {
|
40
|
+
name: 'my_action',
|
41
|
+
fields: [foo],
|
42
|
+
hooks: {
|
43
|
+
:load => -> (context) {
|
44
|
+
context[:fields]
|
45
|
+
},
|
46
|
+
:change => {
|
47
|
+
'foo' => -> (context) {
|
48
|
+
fields = context[:fields]
|
49
|
+
fields['foo'][:value] = 'baz'
|
50
|
+
return fields
|
51
|
+
}
|
52
|
+
}
|
53
|
+
}
|
54
|
+
}
|
55
|
+
fail_action_definition = {
|
56
|
+
name: 'fail_action',
|
57
|
+
fields: [foo],
|
58
|
+
hooks: {
|
59
|
+
:load => -> (context) {
|
60
|
+
1
|
61
|
+
},
|
62
|
+
:change => {
|
63
|
+
'foo' => -> (context) {
|
64
|
+
1
|
65
|
+
}
|
66
|
+
}
|
67
|
+
}
|
68
|
+
}
|
69
|
+
cheat_action_definition = {
|
70
|
+
name: 'cheat_action',
|
71
|
+
fields: [foo],
|
72
|
+
hooks: {
|
73
|
+
:load => -> (context) {
|
74
|
+
context[:fields]['baz'] = foo.clone.update({field: 'baz'})
|
75
|
+
context[:fields]
|
76
|
+
},
|
77
|
+
:change => {
|
78
|
+
'foo' => -> (context) {
|
79
|
+
context[:fields]['baz'] = foo.clone.update({field: 'baz'})
|
80
|
+
context[:fields]
|
81
|
+
}
|
82
|
+
}
|
83
|
+
}
|
84
|
+
}
|
85
|
+
enums_action_definition = {
|
86
|
+
name: 'enums_action',
|
87
|
+
fields: [foo, enum],
|
88
|
+
hooks: {
|
89
|
+
:change => {
|
90
|
+
'foo' => -> (context) {
|
91
|
+
fields = context[:fields]
|
92
|
+
fields['enum'][:enums] = %w[c d e]
|
93
|
+
return fields
|
94
|
+
}
|
95
|
+
}
|
96
|
+
}
|
97
|
+
}
|
98
|
+
action = ForestLiana::Model::Action.new(action_definition)
|
99
|
+
fail_action = ForestLiana::Model::Action.new(fail_action_definition)
|
100
|
+
cheat_action = ForestLiana::Model::Action.new(cheat_action_definition)
|
101
|
+
enums_action = ForestLiana::Model::Action.new(enums_action_definition)
|
102
|
+
island = ForestLiana.apimap.find {|collection| collection.name.to_s == ForestLiana.name_for(Island)}
|
103
|
+
island.actions = [action, fail_action, cheat_action, enums_action]
|
104
|
+
|
105
|
+
describe 'call /load' do
|
106
|
+
params = {recordIds: [1], collectionName: 'Island'}
|
107
|
+
|
108
|
+
it 'should respond 200' do
|
109
|
+
post '/forest/actions/my_action/hooks/load', JSON.dump(params), 'CONTENT_TYPE' => 'application/json'
|
110
|
+
expect(response.status).to eq(200)
|
111
|
+
expect(JSON.parse(response.body)).to eq({'fields' => [foo.merge({:value => nil}).stringify_keys]})
|
112
|
+
end
|
113
|
+
|
114
|
+
it 'should respond 500 with bad params' do
|
115
|
+
post '/forest/actions/my_action/hooks/load', {}
|
116
|
+
expect(response.status).to eq(500)
|
117
|
+
end
|
118
|
+
|
119
|
+
it 'should respond 500 with bad hook result type' do
|
120
|
+
post '/forest/actions/fail_action/hooks/load', JSON.dump(params), 'CONTENT_TYPE' => 'application/json'
|
121
|
+
expect(response.status).to eq(500)
|
122
|
+
end
|
123
|
+
|
124
|
+
it 'should respond 500 with bad hook result data structure' do
|
125
|
+
post '/forest/actions/cheat_action/hooks/load', JSON.dump(params), 'CONTENT_TYPE' => 'application/json'
|
126
|
+
expect(response.status).to eq(500)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
describe 'call /change' do
|
131
|
+
updated_foo = foo.clone.merge({:previousValue => nil, :value => 'bar'})
|
132
|
+
params = {recordIds: [1], fields: [updated_foo], collectionName: 'Island', changedField: 'foo'}
|
133
|
+
|
134
|
+
it 'should respond 200' do
|
135
|
+
post '/forest/actions/my_action/hooks/change', JSON.dump(params), 'CONTENT_TYPE' => 'application/json'
|
136
|
+
expect(response.status).to eq(200)
|
137
|
+
expected = updated_foo.clone.merge({:value => 'baz'})
|
138
|
+
expected[:widgetEdit] = nil
|
139
|
+
expected.delete(:widget)
|
140
|
+
expect(JSON.parse(response.body)).to eq({'fields' => [expected.stringify_keys]})
|
141
|
+
end
|
142
|
+
|
143
|
+
it 'should respond 500 with bad params' do
|
144
|
+
post '/forest/actions/my_action/hooks/change', {}
|
145
|
+
expect(response.status).to eq(500)
|
146
|
+
end
|
147
|
+
|
148
|
+
it 'should respond 500 with bad hook result type' do
|
149
|
+
post '/forest/actions/fail_action/hooks/change', JSON.dump(params), 'CONTENT_TYPE' => 'application/json'
|
150
|
+
expect(response.status).to eq(500)
|
151
|
+
end
|
152
|
+
|
153
|
+
it 'should respond 500 with bad hook result data structure' do
|
154
|
+
post '/forest/actions/cheat_action/hooks/change', JSON.dump(params), 'CONTENT_TYPE' => 'application/json'
|
155
|
+
expect(response.status).to eq(500)
|
156
|
+
end
|
157
|
+
|
158
|
+
it 'should reset value when enums has changed' do
|
159
|
+
updated_enum = enum.clone.merge({:previousValue => nil, :value => 'a'}) # set value to a
|
160
|
+
p = {recordIds: [1], fields: [updated_foo, updated_enum], collectionName: 'Island', changedField: 'foo'}
|
161
|
+
post '/forest/actions/enums_action/hooks/change', JSON.dump(p), 'CONTENT_TYPE' => 'application/json'
|
162
|
+
expect(response.status).to eq(200)
|
163
|
+
|
164
|
+
expected_enum = updated_enum.clone.merge({ :enums => %w[c d e], :value => nil, :widgetEdit => nil})
|
165
|
+
expected_enum.delete(:widget)
|
166
|
+
expected_foo = updated_foo.clone.merge({ :widgetEdit => nil})
|
167
|
+
expected_foo.delete(:widget)
|
168
|
+
|
169
|
+
expect(JSON.parse(response.body)).to eq({'fields' => [expected_foo.stringify_keys, expected_enum.stringify_keys]})
|
170
|
+
end
|
171
|
+
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|