forest_liana 7.0.0.beta.1 → 7.0.0.beta.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 69b23785cf391fb245efbf6488e58fb19bbbc010e9dac0a91574412684e89129
4
- data.tar.gz: 26d9dd7b466009b8a09182dec02778b729e58b83c7b717811c45dca5ce6cc032
3
+ metadata.gz: 6be4888e921b11142c5bc7774e6a0c9ce9a91b7e0b8ceb8a812cff8e297b540a
4
+ data.tar.gz: '043584e75c96d49b34a4ab6ec0e0f0315700eb86a7d061fb03de66c095840b1c'
5
5
  SHA512:
6
- metadata.gz: e216bb8280e6adc87f2ab5f4c0d1a2937306ba1237aedcc9b80375a742227bcdf2187e74b573691324f55d9ef13843b397c25348d442a3e211eda2d8c20cb06c
7
- data.tar.gz: a3e736ae280744d93d65f9592ff9b9475f1f2b22b24790ee37b202ad361f0f192ff0a2bf87dd2669327492b24d2afee3000130af925d38788879512e086da24e
6
+ metadata.gz: bfc23dfba08023225f17e44860caf95dc2fe041bcf81a1d61651ee96cea59563aa2c97ee6a1bcdc2e38e2e56a0f9c7c5e144b64583286af70864ec4d636a5795
7
+ data.tar.gz: 2cc2bf17cc1a235264db9981e33e99b22c23468514bf136e3379523020ca1efd906b792b46c45b6893f0edb279d8845c79e2e14ee8821ee47db6fc87d4992692
@@ -27,34 +27,45 @@ module ForestLiana
27
27
  end
28
28
 
29
29
  def get_smart_action_load_ctx(fields)
30
- fields = fields.reduce({}) do |p, c|
31
- ForestLiana::WidgetsHelper.set_field_widget(c)
32
- p.update(c[:field] => c.merge!(value: nil))
30
+ fields = fields.map do |field|
31
+ ForestLiana::WidgetsHelper.set_field_widget(field)
32
+ field[:value] = nil unless field[:value]
33
+ field
33
34
  end
34
35
  {:record => get_record, :fields => fields}
35
36
  end
36
37
 
37
- def get_smart_action_change_ctx(fields)
38
- fields = fields.reduce({}) do |p, c|
39
- field = c.permit!.to_h.symbolize_keys
38
+ def get_smart_action_change_ctx(fields, field_changed)
39
+ found_field_changed = fields.find{|field| field[:field] == field_changed}
40
+ fields = fields.map do |field|
41
+ field = field.permit!.to_h.symbolize_keys
40
42
  ForestLiana::WidgetsHelper.set_field_widget(field)
41
- p.update(c[:field] => field)
43
+ field
42
44
  end
43
- {:record => get_record, :fields => fields}
45
+ {:record => get_record, :field_changed => found_field_changed, :fields => fields}
44
46
  end
45
47
 
46
- def handle_result(result, formatted_fields, action)
47
- if result.nil? || !result.is_a?(Hash)
48
- return render status: 500, json: { error: 'Error in smart action load hook: hook must return an object' }
48
+ def handle_result(result, action)
49
+ if result.nil? || !result.is_a?(Array)
50
+ return render status: 500, json: { error: 'Error in smart action load hook: hook must return an array of fields' }
49
51
  end
50
- is_same_data_structure = ForestLiana::IsSameDataStructureHelper::Analyser.new(formatted_fields, result, 1)
51
- unless is_same_data_structure.perform
52
- return render status: 500, json: { error: 'Error in smart action hook: fields must be unchanged (no addition nor deletion allowed)' }
52
+
53
+ # Validate that the fields are well formed.
54
+ begin
55
+ # action.hooks[:change] is a hashmap here
56
+ # to do the validation, only the hook names are require
57
+ change_hooks_name = action.hooks[:change].nil? ? nil : action.hooks[:change].keys
58
+ ForestLiana::SmartActionFieldValidator.validate_smart_action_fields(result, action.name, change_hooks_name)
59
+ rescue ForestLiana::Errors::SmartActionInvalidFieldError => invalid_field_error
60
+ FOREST_LOGGER.warn invalid_field_error.message
61
+ rescue ForestLiana::Errors::SmartActionInvalidFieldHookError => invalid_hook_error
62
+ FOREST_LOGGER.error invalid_hook_error.message
63
+ return render status: 500, json: { error: invalid_hook_error.message }
53
64
  end
54
65
 
55
66
  # Apply result on fields (transform the object back to an array), preserve order.
56
- fields = action.fields.map do |field|
57
- updated_field = result[field[:field]]
67
+ fields = result.map do |field|
68
+ updated_field = result.find{|f| f[:field] == field[:field]}
58
69
 
59
70
  # Reset `value` when not present in `enums` (which means `enums` has changed).
60
71
  if updated_field[:enums].is_a?(Array)
@@ -72,7 +83,7 @@ module ForestLiana
72
83
  updated_field
73
84
  end
74
85
 
75
- render serializer: nil, json: { fields: fields}, status: :ok
86
+ render serializer: nil, json: { fields: fields }, status: :ok
76
87
  end
77
88
 
78
89
  def load
@@ -81,14 +92,13 @@ module ForestLiana
81
92
  if !action
82
93
  render status: 500, json: {error: 'Error in smart action load hook: cannot retrieve action from collection'}
83
94
  else
84
- # Transform fields from array to an object to ease usage in hook, adds null value.
95
+ # Get the smart action hook load context
85
96
  context = get_smart_action_load_ctx(action.fields)
86
- formatted_fields = context[:fields].clone # clone for following test on is_same_data_structure
87
97
 
88
98
  # Call the user-defined load hook.
89
99
  result = action.hooks[:load].(context)
90
100
 
91
- handle_result(result, formatted_fields, action)
101
+ handle_result(result, action)
92
102
  end
93
103
  end
94
104
 
@@ -96,17 +106,22 @@ module ForestLiana
96
106
  action = get_action(params[:collectionName])
97
107
 
98
108
  if !action
99
- render status: 500, json: {error: 'Error in smart action change hook: cannot retrieve action from collection'}
100
- else
101
- # Transform fields from array to an object to ease usage in hook.
102
- context = get_smart_action_change_ctx(params[:fields])
103
- formatted_fields = context[:fields].clone # clone for following test on is_same_data_structure
109
+ return render status: 500, json: {error: 'Error in smart action change hook: cannot retrieve action from collection'}
110
+ elsif params[:fields].nil?
111
+ return render status: 500, json: {error: 'Error in smart action change hook: fields params is mandatory'}
112
+ elsif !params[:fields].is_a?(Array)
113
+ return render status: 500, json: {error: 'Error in smart action change hook: fields params must be an array'}
114
+ end
104
115
 
105
- # Call the user-defined change hook.
106
- result = action.hooks[:change][params[:changedField]].(context)
116
+ # Get the smart action hook change context
117
+ context = get_smart_action_change_ctx(params[:fields], params[:changedField])
107
118
 
108
- handle_result(result, formatted_fields, action)
109
- end
119
+ field_changed_hook = context[:field_changed][:hook]
120
+
121
+ # Call the user-defined change hook.
122
+ result = action.hooks[:change][field_changed_hook].(context)
123
+
124
+ handle_result(result, action)
110
125
  end
111
126
  end
112
127
  end
@@ -52,6 +52,7 @@ module ForestLiana
52
52
  'description',
53
53
  'position',
54
54
  'widget',
55
+ 'hook',
55
56
  ]
56
57
  KEYS_SEGMENT = ['name']
57
58
 
@@ -0,0 +1,49 @@
1
+ module ForestLiana
2
+ class SmartActionFieldValidator
3
+
4
+ @@accepted_primitive_field_type = [
5
+ 'String',
6
+ 'Number',
7
+ 'Date',
8
+ 'Boolean',
9
+ 'File',
10
+ 'Enum',
11
+ 'Json',
12
+ 'Dateonly',
13
+ ]
14
+
15
+ @@accepted_array_field_type = [
16
+ 'String',
17
+ 'Number',
18
+ 'Date',
19
+ 'boolean',
20
+ 'File',
21
+ 'Enum',
22
+ ]
23
+
24
+ def self.validate_field(field, action_name)
25
+ raise ForestLiana::Errors::SmartActionInvalidFieldError.new(action_name, nil, "The field attribute must be defined") if !field || field[:field].nil?
26
+ raise ForestLiana::Errors::SmartActionInvalidFieldError.new(action_name, nil, "The field attribute must be a string.") if !field[:field].is_a?(String)
27
+ raise ForestLiana::Errors::SmartActionInvalidFieldError.new(action_name, field[:field], "The description attribute must be a string.") if field[:description] && !field[:description].is_a?(String)
28
+ raise ForestLiana::Errors::SmartActionInvalidFieldError.new(action_name, field[:field], "The enums attribute must be an array.") if field[:enums] && !field[:enums].is_a?(Array)
29
+ raise ForestLiana::Errors::SmartActionInvalidFieldError.new(action_name, field[:field], "The reference attribute must be a string.") if field[:reference] && !field[:reference].is_a?(String)
30
+
31
+ is_type_valid = field[:type].is_a?(Array) ?
32
+ @@accepted_array_field_type.include?(field[:type][0]) :
33
+ @@accepted_primitive_field_type.include?(field[:type])
34
+
35
+ raise ForestLiana::Errors::SmartActionInvalidFieldError.new(action_name, field[:field], "The type attribute must be a valid type. See the documentation for more information. https://docs.forestadmin.com/documentation/reference-guide/fields/create-and-manage-smart-fields#available-field-options.") if !is_type_valid
36
+ end
37
+
38
+ def self.validate_field_change_hook(field, action_name, hooks)
39
+ raise ForestLiana::Errors::SmartActionInvalidFieldHookError.new(action_name, field[:field], field[:hook]) if field[:hook] && !hooks.find{|hook| hook == field[:hook]}
40
+ end
41
+
42
+ def self.validate_smart_action_fields(fields, action_name, change_hooks)
43
+ fields.map{|field|
44
+ self.validate_field(field.symbolize_keys, action_name)
45
+ self.validate_field_change_hook(field.symbolize_keys, action_name, change_hooks) if change_hooks
46
+ }
47
+ end
48
+ end
49
+ end
@@ -13,6 +13,23 @@ module ForestLiana
13
13
  end
14
14
  end
15
15
 
16
+ class SmartActionInvalidFieldError < StandardError
17
+ def initialize(action_name=nil, field_name=nil, message=nil)
18
+ error_message = ""
19
+ error_message << "Error while parsing action \"#{action_name}\"" if !action_name.nil?
20
+ error_message << " on field \"#{field_name}\"" if !field_name.nil?
21
+ error_message << ": " if !field_name.nil? || !action_name.nil?
22
+ error_message << message if !message.nil?
23
+ super(error_message)
24
+ end
25
+ end
26
+
27
+ class SmartActionInvalidFieldHookError < StandardError
28
+ def initialize(action_name=nil, field_name=nil, hook_name=nil)
29
+ super("The hook \"#{hook_name}\" of \"#{field_name}\" field on the smart action \"#{action_name}\" is not defined.")
30
+ end
31
+ end
32
+
16
33
  class ExpectedError < StandardError
17
34
  attr_reader :error_code, :status, :message, :name
18
35
 
@@ -60,7 +60,7 @@ module ForestLiana
60
60
  a = get_action(c, action['name'])
61
61
  load = !a.hooks.nil? && a.hooks.key?(:load) && a.hooks[:load].is_a?(Proc)
62
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}
63
+ action['hooks'] = {'load' => load, 'change' => change}
64
64
  end
65
65
  end
66
66
  end
@@ -63,6 +63,7 @@ module ForestLiana
63
63
  'description',
64
64
  'position',
65
65
  'widget',
66
+ 'hook',
66
67
  ]
67
68
  KEYS_SEGMENT = ['name']
68
69
 
@@ -96,6 +97,13 @@ module ForestLiana
96
97
  end
97
98
 
98
99
  collection['actions'] = collection['actions'].map do |action|
100
+ begin
101
+ SmartActionFieldValidator.validate_smart_action_fields(action['fields'], action['name'], action['hooks']['change'])
102
+ rescue ForestLiana::Errors::SmartActionInvalidFieldError => invalid_field_error
103
+ FOREST_LOGGER.warn invalid_field_error.message
104
+ rescue ForestLiana::Errors::SmartActionInvalidFieldHookError => invalid_hook_error
105
+ FOREST_LOGGER.error invalid_hook_error.message
106
+ end
99
107
  action['fields'] = action['fields'].map { |field| field.slice(*KEYS_ACTION_FIELD) }
100
108
  action.slice(*KEYS_ACTION)
101
109
  end
@@ -1,3 +1,3 @@
1
1
  module ForestLiana
2
- VERSION = "7.0.0.beta.1"
2
+ VERSION = "7.0.0.beta.2"
3
3
  end
@@ -0,0 +1,94 @@
1
+ module ForestLiana
2
+ describe SchemaFileUpdater do
3
+ describe "initialize" do
4
+ describe "without any collections nor meta" do
5
+ it "should set collections as an empty array and meta as an empty object" do
6
+ schema_file_updater = ForestLiana::SchemaFileUpdater.new("test.txt", [], {})
7
+ expect(schema_file_updater.instance_variable_get(:@collections)).to eq([])
8
+ expect(schema_file_updater.instance_variable_get(:@meta)).to eq({})
9
+ end
10
+ end
11
+
12
+ describe "with a given collection" do
13
+ describe "when the collection has a smart action action" do
14
+ it "should save the smart action" do
15
+ collections = [{
16
+ "fields" => [],
17
+ "actions" => [{
18
+ "fields" => [],
19
+ "name" => "test",
20
+ "hooks" => {
21
+ "change" => []
22
+ }
23
+ }],
24
+ "segments" => []
25
+ }]
26
+ schema_file_updater = ForestLiana::SchemaFileUpdater.new("test.txt", collections, {})
27
+ expect(schema_file_updater.instance_variable_get(:@collections))
28
+ .to eq(collections)
29
+ end
30
+
31
+ describe "when a smart action field is malformed" do
32
+ it "should display a warning message" do
33
+ collections = [{
34
+ "fields" => [],
35
+ "actions" => [{
36
+ "fields" => [{}],
37
+ "name" => "test",
38
+ "hooks" => {
39
+ "change" => []
40
+ }
41
+ }],
42
+ "segments" => []
43
+ }]
44
+ allow(FOREST_LOGGER).to receive(:warn)
45
+ schema_file_updater = ForestLiana::SchemaFileUpdater.new("test.txt", collections, {})
46
+ expect(FOREST_LOGGER).to have_received(:warn).with('Error while parsing action "test": The field attribute must be defined')
47
+ end
48
+ end
49
+
50
+ describe "when a smart action change field hook does not exist" do
51
+ it "should display an error message" do
52
+ collections = [{
53
+ "fields" => [],
54
+ "actions" => [{
55
+ "fields" => [{
56
+ "field" => "testField",
57
+ "hook" => "undefinedHook",
58
+ "type" => "String",
59
+ }],
60
+ "name" => "test",
61
+ "hooks" => {
62
+ "change" => []
63
+ }
64
+ }],
65
+ "segments" => []
66
+ }]
67
+
68
+ allow(FOREST_LOGGER).to receive(:error)
69
+ schema_file_updater = ForestLiana::SchemaFileUpdater.new("test.txt", collections, {})
70
+ expect(FOREST_LOGGER).to have_received(:error).with('The hook "undefinedHook" of "testField" field on the smart action "test" is not defined.')
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
76
+
77
+ describe "perform" do
78
+ it "should call file puts with pretty printed data" do
79
+ file = instance_double(File, read: "stubbed read")
80
+
81
+ allow(File).to receive(:open).with("test.txt", "w") { |&block| block.call(file) }
82
+
83
+ schema_file_updater = ForestLiana::SchemaFileUpdater.new("test.txt", [], {})
84
+ expected_result = schema_file_updater.pretty_print({
85
+ "collections" => [],
86
+ "meta" => {}
87
+ })
88
+
89
+ expect(file).to receive(:puts).with(expected_result)
90
+ schema_file_updater.perform
91
+ end
92
+ end
93
+ end
94
+ end
@@ -30,6 +30,7 @@ describe 'Requesting Actions routes', :type => :request do
30
30
  reference: nil,
31
31
  description: nil,
32
32
  widget: nil,
33
+ hook: 'on_foo_changed'
33
34
  }
34
35
  enum = {
35
36
  field: 'enum',
@@ -50,10 +51,10 @@ describe 'Requesting Actions routes', :type => :request do
50
51
  context[:fields]
51
52
  },
52
53
  :change => {
53
- 'foo' => -> (context) {
54
- fields = context[:fields]
55
- fields['foo'][:value] = 'baz'
56
- return fields
54
+ 'on_foo_changed' => -> (context) {
55
+ foo = context[:fields].find{|field| field[:field] == 'foo'}
56
+ foo[:value] = 'baz'
57
+ context[:fields]
57
58
  }
58
59
  }
59
60
  }
@@ -66,7 +67,7 @@ describe 'Requesting Actions routes', :type => :request do
66
67
  1
67
68
  },
68
69
  :change => {
69
- 'foo' => -> (context) {
70
+ 'on_foo_changed' => -> (context) {
70
71
  1
71
72
  }
72
73
  }
@@ -77,11 +78,10 @@ describe 'Requesting Actions routes', :type => :request do
77
78
  fields: [foo],
78
79
  hooks: {
79
80
  :load => -> (context) {
80
- context[:fields]['baz'] = foo.clone.update({field: 'baz'})
81
- context[:fields]
81
+ {}
82
82
  },
83
83
  :change => {
84
- 'foo' => -> (context) {
84
+ 'on_foo_changed' => -> (context) {
85
85
  context[:fields]['baz'] = foo.clone.update({field: 'baz'})
86
86
  context[:fields]
87
87
  }
@@ -93,10 +93,11 @@ describe 'Requesting Actions routes', :type => :request do
93
93
  fields: [foo, enum],
94
94
  hooks: {
95
95
  :change => {
96
- 'foo' => -> (context) {
96
+ 'on_foo_changed' => -> (context) {
97
97
  fields = context[:fields]
98
- fields['enum'][:enums] = %w[c d e]
99
- return fields
98
+ enum_field = fields.find{|field| field[:field] == 'enum'}
99
+ enum_field[:enums] = %w[c d e]
100
+ fields
100
101
  }
101
102
  }
102
103
  }
@@ -107,10 +108,11 @@ describe 'Requesting Actions routes', :type => :request do
107
108
  fields: [foo, multiple_enum],
108
109
  hooks: {
109
110
  :change => {
110
- 'foo' => -> (context) {
111
+ 'on_foo_changed' => -> (context) {
111
112
  fields = context[:fields]
112
- fields['multipleEnum'][:enums] = %w[c d z]
113
- return fields
113
+ enum_field = fields.find{|field| field[:field] == 'multipleEnum'}
114
+ enum_field[:enums] = %w[c d z]
115
+ fields
114
116
  }
115
117
  }
116
118
  }
@@ -136,16 +138,19 @@ describe 'Requesting Actions routes', :type => :request do
136
138
  it 'should respond 500 with bad params' do
137
139
  post '/forest/actions/my_action/hooks/load', params: {}
138
140
  expect(response.status).to eq(500)
141
+ expect(JSON.parse(response.body)).to eq({'error' => 'Error in smart action load hook: cannot retrieve action from collection'})
139
142
  end
140
143
 
141
144
  it 'should respond 500 with bad hook result type' do
142
145
  post '/forest/actions/fail_action/hooks/load', params: JSON.dump(params), headers: { 'CONTENT_TYPE' => 'application/json' }
143
146
  expect(response.status).to eq(500)
147
+ expect(JSON.parse(response.body)).to eq({'error' => 'Error in smart action load hook: hook must return an array of fields'})
144
148
  end
145
149
 
146
150
  it 'should respond 500 with bad hook result data structure' do
147
151
  post '/forest/actions/cheat_action/hooks/load', params: JSON.dump(params), headers: { 'CONTENT_TYPE' => 'application/json' }
148
152
  expect(response.status).to eq(500)
153
+ expect(JSON.parse(response.body)).to eq({'error' => 'Error in smart action load hook: hook must return an array of fields'})
149
154
  end
150
155
  end
151
156
 
@@ -163,18 +168,15 @@ describe 'Requesting Actions routes', :type => :request do
163
168
  end
164
169
 
165
170
  it 'should respond 500 with bad params' do
166
- post '/forest/actions/my_action/hooks/change', params: {}
171
+ post '/forest/actions/my_action/hooks/change', params: JSON.dump({collectionName: 'Island'}), headers: { 'CONTENT_TYPE' => 'application/json' }
167
172
  expect(response.status).to eq(500)
173
+ expect(JSON.parse(response.body)).to eq({'error' => 'Error in smart action change hook: fields params is mandatory'})
168
174
  end
169
175
 
170
176
  it 'should respond 500 with bad hook result type' do
171
177
  post '/forest/actions/fail_action/hooks/change', params: JSON.dump(params), headers: { 'CONTENT_TYPE' => 'application/json' }
172
178
  expect(response.status).to eq(500)
173
- end
174
-
175
- it 'should respond 500 with bad hook result data structure' do
176
- post '/forest/actions/cheat_action/hooks/change', params: JSON.dump(params), headers: { 'CONTENT_TYPE' => 'application/json' }
177
- expect(response.status).to eq(500)
179
+ expect(JSON.parse(response.body)).to eq({'error' => 'Error in smart action load hook: hook must return an array of fields'})
178
180
  end
179
181
 
180
182
  it 'should reset value when enums has changed' do
@@ -0,0 +1,70 @@
1
+ module ForestLiana
2
+ describe SmartActionFieldValidator do
3
+ describe "self.validate_field" do
4
+ it "should raise an SmartActionInvalidFieldError with nil field" do
5
+ expect { SmartActionFieldValidator.validate_field(nil, "actionName") }.to raise_error(ForestLiana::Errors::SmartActionInvalidFieldError, 'Error while parsing action "actionName": The field attribute must be defined')
6
+ end
7
+
8
+ it "should raise an SmartActionInvalidFieldError with a field that is not a string" do
9
+ expect { SmartActionFieldValidator.validate_field({
10
+ :field => 5
11
+ }, "actionName") }.to raise_error(ForestLiana::Errors::SmartActionInvalidFieldError, 'Error while parsing action "actionName": The field attribute must be a string.')
12
+ end
13
+
14
+ it "should raise an SmartActionInvalidFieldError with description that is not a string" do
15
+ expect { SmartActionFieldValidator.validate_field({
16
+ :field => "field",
17
+ :description => 5
18
+ }, "actionName") }.to raise_error(ForestLiana::Errors::SmartActionInvalidFieldError, 'Error while parsing action "actionName" on field "field": The description attribute must be a string.')
19
+ end
20
+
21
+ it "should raise an SmartActionInvalidFieldError with an enums that is not an array" do
22
+ expect { SmartActionFieldValidator.validate_field({
23
+ :field => "field",
24
+ :enums => "NotAnArray"
25
+ }, "actionName") }.to raise_error(ForestLiana::Errors::SmartActionInvalidFieldError, 'Error while parsing action "actionName" on field "field": The enums attribute must be an array.')
26
+ end
27
+
28
+ it "should raise an SmartActionInvalidFieldError with a reference that is not a string" do
29
+ expect { SmartActionFieldValidator.validate_field({
30
+ :field => "field",
31
+ :type => "String",
32
+ :reference => 5
33
+ }, "actionName") }.to raise_error(ForestLiana::Errors::SmartActionInvalidFieldError, 'Error while parsing action "actionName" on field "field": The reference attribute must be a string.')
34
+ end
35
+
36
+ it "should raise an SmartActionInvalidFieldError with an invalid type" do
37
+ expect { SmartActionFieldValidator.validate_field({
38
+ :field => "field",
39
+ :type => "AbsolutelyNotAValidType"
40
+ }, "actionName") }.to raise_error(ForestLiana::Errors::SmartActionInvalidFieldError, 'Error while parsing action "actionName" on field "field": The type attribute must be a valid type. See the documentation for more information. https://docs.forestadmin.com/documentation/reference-guide/fields/create-and-manage-smart-fields#available-field-options.')
41
+ end
42
+
43
+ it "should not raise any error when everything is configured correctly" do
44
+ expect { SmartActionFieldValidator.validate_field({
45
+ :field => "field",
46
+ :type => "String",
47
+ :description => "field description"
48
+ }, "actionName") }.not_to raise_error
49
+ end
50
+ end
51
+
52
+ describe "self.validate_field_change_hook" do
53
+ it "should raise an SmartActionInvalidFieldHookError with an invalid type" do
54
+ expect { SmartActionFieldValidator.validate_field_change_hook({
55
+ :field => "field",
56
+ :type => "AbsolutelyNotAValidType",
57
+ :hook => "hookThatDoesNotExist"
58
+ }, "actionName", []) }.to raise_error(ForestLiana::Errors::SmartActionInvalidFieldHookError)
59
+ end
60
+
61
+ it "should not raise any error when everything is configured correctly" do
62
+ expect { SmartActionFieldValidator.validate_field_change_hook({
63
+ :field => "field",
64
+ :type => "AbsolutelyNotAValidType",
65
+ :hook => "on_field_changed"
66
+ }, "actionName", ["on_field_changed"]) }.not_to raise_error
67
+ end
68
+ end
69
+ end
70
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: forest_liana
3
3
  version: !ruby/object:Gem::Version
4
- version: 7.0.0.beta.1
4
+ version: 7.0.0.beta.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sandro Munda
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-06-01 00:00:00.000000000 Z
11
+ date: 2021-06-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -225,7 +225,6 @@ files:
225
225
  - app/helpers/forest_liana/adapter_helper.rb
226
226
  - app/helpers/forest_liana/application_helper.rb
227
227
  - app/helpers/forest_liana/decoration_helper.rb
228
- - app/helpers/forest_liana/is_same_data_structure_helper.rb
229
228
  - app/helpers/forest_liana/query_helper.rb
230
229
  - app/helpers/forest_liana/schema_helper.rb
231
230
  - app/helpers/forest_liana/widgets_helper.rb
@@ -283,6 +282,7 @@ files:
283
282
  - app/services/forest_liana/schema_utils.rb
284
283
  - app/services/forest_liana/scope_validator.rb
285
284
  - app/services/forest_liana/search_query_builder.rb
285
+ - app/services/forest_liana/smart_action_field_validator.rb
286
286
  - app/services/forest_liana/stat_getter.rb
287
287
  - app/services/forest_liana/stripe_base_getter.rb
288
288
  - app/services/forest_liana/stripe_invoice_getter.rb
@@ -368,9 +368,9 @@ files:
368
368
  - spec/dummy/db/schema.rb
369
369
  - spec/dummy/lib/forest_liana/collections/location.rb
370
370
  - spec/dummy/lib/forest_liana/collections/user.rb
371
- - spec/helpers/forest_liana/is_same_data_structure_helper_spec.rb
372
371
  - spec/helpers/forest_liana/query_helper_spec.rb
373
372
  - spec/helpers/forest_liana/schema_helper_spec.rb
373
+ - spec/lib/forest_liana/schema_file_updater_spec.rb
374
374
  - spec/rails_helper.rb
375
375
  - spec/requests/actions_controller_spec.rb
376
376
  - spec/requests/authentications_spec.rb
@@ -387,6 +387,7 @@ files:
387
387
  - spec/services/forest_liana/permissions_getter_spec.rb
388
388
  - spec/services/forest_liana/resources_getter_spec.rb
389
389
  - spec/services/forest_liana/schema_adapter_spec.rb
390
+ - spec/services/forest_liana/smart_action_field_validator_spec.rb
390
391
  - spec/spec_helper.rb
391
392
  - test/dummy/README.rdoc
392
393
  - test/dummy/Rakefile
@@ -603,13 +604,13 @@ test_files:
603
604
  - spec/services/forest_liana/permissions_checker_acl_enabled_spec.rb
604
605
  - spec/services/forest_liana/filters_parser_spec.rb
605
606
  - spec/services/forest_liana/schema_adapter_spec.rb
607
+ - spec/services/forest_liana/smart_action_field_validator_spec.rb
606
608
  - spec/services/forest_liana/line_stat_getter_spec.rb
607
609
  - spec/services/forest_liana/permissions_formatter_spec.rb
608
610
  - spec/services/forest_liana/permissions_checker_live_queries_spec.rb
609
611
  - spec/services/forest_liana/apimap_sorter_spec.rb
610
612
  - spec/services/forest_liana/permissions_checker_acl_disabled_spec.rb
611
613
  - spec/config/initializers/logger_spec.rb
612
- - spec/helpers/forest_liana/is_same_data_structure_helper_spec.rb
613
614
  - spec/helpers/forest_liana/schema_helper_spec.rb
614
615
  - spec/helpers/forest_liana/query_helper_spec.rb
615
616
  - spec/dummy/db/schema.rb
@@ -663,6 +664,7 @@ test_files:
663
664
  - spec/dummy/app/models/location.rb
664
665
  - spec/dummy/app/models/island.rb
665
666
  - spec/dummy/app/models/reference.rb
667
+ - spec/lib/forest_liana/schema_file_updater_spec.rb
666
668
  - spec/rails_helper.rb
667
669
  - spec/requests/stats_spec.rb
668
670
  - spec/requests/resources_spec.rb
@@ -1,44 +0,0 @@
1
- require 'set'
2
-
3
- module ForestLiana
4
- module IsSameDataStructureHelper
5
- class Analyser
6
- def initialize(object, other, deep = 0)
7
- @object = object
8
- @other = other
9
- @deep = deep
10
- end
11
-
12
- def are_objects(object, other)
13
- object && other && object.is_a?(Hash) && other.is_a?(Hash)
14
- end
15
-
16
- def check_keys(object, other, step = 0)
17
- unless are_objects(object, other)
18
- return false
19
- end
20
-
21
- object_keys = object.keys
22
- other_keys = other.keys
23
-
24
- if object_keys.length != other_keys.length
25
- return false
26
- end
27
-
28
- object_keys_set = object_keys.to_set
29
- other_keys.each { |key|
30
- if !object_keys_set.member?(key) || (step + 1 <= @deep && !check_keys(object[key], other[key], step + 1))
31
- return false
32
- end
33
- }
34
-
35
- return true
36
- end
37
-
38
- def perform
39
- check_keys(@object, @other)
40
- end
41
- end
42
- end
43
- end
44
-
@@ -1,87 +0,0 @@
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