forest_liana 5.3.3 → 5.4.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/forest_liana/actions_controller.rb +12 -2
  3. data/app/controllers/forest_liana/resources_controller.rb +14 -17
  4. data/app/controllers/forest_liana/smart_actions_controller.rb +10 -5
  5. data/app/serializers/forest_liana/stripe_invoice_serializer.rb +5 -5
  6. data/app/services/forest_liana/permissions_checker.rb +118 -56
  7. data/app/services/forest_liana/permissions_formatter.rb +52 -0
  8. data/app/services/forest_liana/permissions_getter.rb +52 -17
  9. data/app/services/forest_liana/resource_creator.rb +1 -1
  10. data/app/services/forest_liana/resource_updater.rb +3 -3
  11. data/app/services/forest_liana/schema_utils.rb +8 -3
  12. data/app/services/forest_liana/scope_validator.rb +8 -7
  13. data/app/services/forest_liana/stripe_invoice_getter.rb +1 -1
  14. data/app/services/forest_liana/stripe_invoices_getter.rb +1 -1
  15. data/app/services/forest_liana/stripe_source_getter.rb +1 -1
  16. data/app/services/forest_liana/stripe_sources_getter.rb +1 -1
  17. data/app/services/forest_liana/utils/beta_schema_utils.rb +13 -0
  18. data/lib/forest_liana/bootstrapper.rb +5 -5
  19. data/lib/forest_liana/version.rb +1 -1
  20. data/spec/dummy/app/assets/config/manifest.js +1 -0
  21. data/spec/dummy/config/application.rb +1 -1
  22. data/spec/dummy/db/migrate/20190226172951_create_user.rb +1 -1
  23. data/spec/dummy/db/migrate/20190226173051_create_isle.rb +1 -1
  24. data/spec/dummy/db/migrate/20190226174951_create_tree.rb +1 -1
  25. data/spec/dummy/db/migrate/20190716130830_add_age_to_tree.rb +1 -1
  26. data/spec/dummy/db/migrate/20190716135241_add_type_to_user.rb +1 -1
  27. data/spec/dummy/db/schema.rb +18 -20
  28. data/spec/requests/actions_controller_spec.rb +59 -11
  29. data/spec/requests/resources_spec.rb +4 -4
  30. data/spec/services/forest_liana/permissions_checker_acl_disabled_spec.rb +711 -0
  31. data/spec/services/forest_liana/permissions_checker_acl_enabled_spec.rb +831 -0
  32. data/spec/services/forest_liana/permissions_formatter_spec.rb +222 -0
  33. data/spec/services/forest_liana/permissions_getter_spec.rb +82 -0
  34. data/spec/spec_helper.rb +3 -0
  35. data/test/dummy/app/assets/config/manifest.js +1 -0
  36. data/test/dummy/config/application.rb +1 -1
  37. data/test/dummy/db/migrate/20150608130516_create_date_field.rb +1 -1
  38. data/test/dummy/db/migrate/20150608131430_create_integer_field.rb +1 -1
  39. data/test/dummy/db/migrate/20150608131603_create_decimal_field.rb +1 -1
  40. data/test/dummy/db/migrate/20150608131610_create_float_field.rb +1 -1
  41. data/test/dummy/db/migrate/20150608132159_create_boolean_field.rb +1 -1
  42. data/test/dummy/db/migrate/20150608132621_create_string_field.rb +1 -1
  43. data/test/dummy/db/migrate/20150608133038_create_belongs_to_field.rb +1 -1
  44. data/test/dummy/db/migrate/20150608133044_create_has_one_field.rb +1 -1
  45. data/test/dummy/db/migrate/20150608150016_create_has_many_field.rb +1 -1
  46. data/test/dummy/db/migrate/20150609114636_create_belongs_to_class_name_field.rb +1 -1
  47. data/test/dummy/db/migrate/20150612112520_create_has_and_belongs_to_many_field.rb +1 -1
  48. data/test/dummy/db/migrate/20150616150629_create_polymorphic_field.rb +1 -1
  49. data/test/dummy/db/migrate/20150623115554_create_has_many_class_name_field.rb +1 -1
  50. data/test/dummy/db/migrate/20150814081918_create_has_many_through_field.rb +1 -1
  51. data/test/dummy/db/migrate/20160627172810_create_owner.rb +1 -1
  52. data/test/dummy/db/migrate/20160627172951_create_tree.rb +1 -1
  53. data/test/dummy/db/migrate/20160628173505_add_timestamps.rb +1 -1
  54. data/test/dummy/db/migrate/20170614141921_create_serialize_field.rb +1 -1
  55. data/test/dummy/db/migrate/20181111162121_create_references_table.rb +1 -1
  56. data/test/services/forest_liana/resources_getter_test.rb +1 -1
  57. metadata +119 -105
@@ -1,25 +1,60 @@
1
1
  module ForestLiana
2
2
  class PermissionsGetter
3
- def initialize(rendering_id)
4
- @route = "/liana/v2/permissions"
5
- @rendering_id = rendering_id
6
- end
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
- def perform
9
- begin
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
- if response.is_a?(Net::HTTPOK)
14
- JSON.parse(response.body)
15
- else
16
- raise "Forest API returned an #{ForestLiana::Errors::HTTPErrorHelper.format(response)}"
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
@@ -53,7 +53,7 @@ module ForestLiana
53
53
  end
54
54
 
55
55
  def has_strong_parameter
56
- Rails::VERSION::MAJOR > 5 || @resource.instance_method(:update_attributes!).arity == 1
56
+ Rails::VERSION::MAJOR > 5 || @resource.instance_method(:update!).arity == 1
57
57
  end
58
58
  end
59
59
  end
@@ -14,9 +14,9 @@ module ForestLiana
14
14
  @record = @resource.find(@params[:id])
15
15
 
16
16
  if has_strong_parameter
17
- @record.update_attributes(resource_params)
17
+ @record.update(resource_params)
18
18
  else
19
- @record.update_attributes(resource_params, without_protection: true)
19
+ @record.update(resource_params, without_protection: true)
20
20
  end
21
21
  rescue ActiveRecord::StatementInvalid => exception
22
22
  # NOTICE: SQL request cannot be executed properly
@@ -33,7 +33,7 @@ module ForestLiana
33
33
  end
34
34
 
35
35
  def has_strong_parameter
36
- Rails::VERSION::MAJOR > 5 || @resource.instance_method(:update_attributes!).arity == 1
36
+ Rails::VERSION::MAJOR > 5 || @resource.instance_method(:update!).arity == 1
37
37
  end
38
38
  end
39
39
  end
@@ -2,9 +2,14 @@ module ForestLiana
2
2
  class SchemaUtils
3
3
 
4
4
  def self.associations(active_record_class)
5
- active_record_class
6
- .reflect_on_all_associations
7
- .select { |association| !polymorphic?(association) && !is_active_type?(association.klass) }
5
+ active_record_class.reflect_on_all_associations.select do |association|
6
+ begin
7
+ !polymorphic?(association) && !is_active_type?(association.klass)
8
+ rescue
9
+ FOREST_LOGGER.warn "Unknown association #{association.name} on class #{active_record_class.name}"
10
+ false
11
+ end
12
+ end
8
13
  end
9
14
 
10
15
  def self.one_associations(active_record_class)
@@ -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'].start_with?('$') &&
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
@@ -11,7 +11,7 @@ module ForestLiana
11
11
  query = {}
12
12
  @record = ::Stripe::Invoice.retrieve(@params[:invoice_id])
13
13
 
14
- @record.date = Time.at(@record.date).to_datetime
14
+ @record.due_date = Time.at(@record.due_date).to_datetime unless @record.due_date.nil?
15
15
  @record.period_start = Time.at(@record.period_start).to_datetime
16
16
  @record.period_end = Time.at(@record.period_end).to_datetime
17
17
  @record.subtotal /= 100.00
@@ -32,7 +32,7 @@ module ForestLiana
32
32
  end
33
33
 
34
34
  @records = @invoices.data.map do |d|
35
- d.date = Time.at(d.date).to_datetime
35
+ d.date = Time.at(d.created).to_datetime
36
36
  d.period_start = Time.at(d.period_start).to_datetime
37
37
  d.period_end = Time.at(d.period_end).to_datetime
38
38
  d.subtotal /= 100.00
@@ -12,7 +12,7 @@ module ForestLiana
12
12
  customer = resource[field]
13
13
 
14
14
  @record = ::Stripe::Customer
15
- .retrieve(customer)
15
+ .retrieve({ id: customer, expand: ['sources'] })
16
16
  .sources.retrieve(@params[:objectId])
17
17
 
18
18
  query = {}
@@ -32,7 +32,7 @@ module ForestLiana
32
32
 
33
33
  def fetch_bank_accounts(customer, params)
34
34
  begin
35
- @cards = ::Stripe::Customer.retrieve(customer).sources.list(params)
35
+ @cards = ::Stripe::Customer.retrieve({ id: customer, expand: ['sources'] }).sources.list(params)
36
36
  if @cards.blank?
37
37
  @records = []
38
38
  return
@@ -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
@@ -430,19 +430,19 @@ module ForestLiana
430
430
  fields: [
431
431
  { field: :id, type: 'String', is_filterable: false },
432
432
  { field: :amount_due, type: 'Number', is_filterable: false },
433
+ { field: :amount_paid, type: 'Number', is_filterable: false },
434
+ { field: :amount_remaining, type: 'Number', is_filterable: false },
435
+ { field: :application_fee_amount, type: 'Number', is_filterable: false },
433
436
  { field: :attempt_count, type: 'Number', is_filterable: false },
434
437
  { field: :attempted, type: 'Boolean', is_filterable: false },
435
- { field: :closed, type: 'Boolean', is_filterable: false },
436
438
  { field: :currency, type: 'String', is_filterable: false },
437
- { field: :date, type: 'Date', is_filterable: false },
438
- { field: :forgiven, type: 'Boolean', is_filterable: false },
439
+ { field: :due_date, type: 'Date', is_filterable: false },
439
440
  { field: :period_start, type: 'Date', is_filterable: false },
440
441
  { field: :period_end, type: 'Date', is_filterable: false },
442
+ { field: :status, type: 'String', enums: ['draft', 'open', 'paid', 'uncollectible', 'void'], is_filterable: false },
441
443
  { field: :subtotal, type: 'Number', is_filterable: false },
442
444
  { field: :total, type: 'Number', is_filterable: false },
443
- { field: :application_fee, type: 'Number', is_filterable: false },
444
445
  { field: :tax, type: 'Number', is_filterable: false },
445
- { field: :tax_percent, type: 'Number', is_filterable: false },
446
446
  {
447
447
  field: :customer,
448
448
  type: 'String',
@@ -1,3 +1,3 @@
1
1
  module ForestLiana
2
- VERSION = "5.3.3"
2
+ VERSION = "5.4.4"
3
3
  end
@@ -0,0 +1 @@
1
+ {}
@@ -20,7 +20,7 @@ module Dummy
20
20
  # config.i18n.default_locale = :de
21
21
 
22
22
  # Do not swallow errors in after_commit/after_rollback callbacks.
23
- config.active_record.raise_in_transactional_callbacks = true
23
+ # config.active_record.raise_in_transactional_callbacks = true
24
24
  end
25
25
  end
26
26
 
@@ -1,4 +1,4 @@
1
- class CreateUser < ActiveRecord::Migration
1
+ class CreateUser < ActiveRecord::Migration[4.2]
2
2
  def change
3
3
  create_table :users do |t|
4
4
  t.string :name
@@ -1,4 +1,4 @@
1
- class CreateIsle < ActiveRecord::Migration
1
+ class CreateIsle < ActiveRecord::Migration[4.2]
2
2
  def change
3
3
  create_table :isle do |t|
4
4
  t.string :name
@@ -1,4 +1,4 @@
1
- class CreateTree < ActiveRecord::Migration
1
+ class CreateTree < ActiveRecord::Migration[4.2]
2
2
  def change
3
3
  create_table :trees do |t|
4
4
  t.string :name
@@ -1,4 +1,4 @@
1
- class AddAgeToTree < ActiveRecord::Migration
1
+ class AddAgeToTree < ActiveRecord::Migration[4.2]
2
2
  def up
3
3
  add_column :trees, :age, :integer
4
4
  end
@@ -1,4 +1,4 @@
1
- class AddTypeToUser < ActiveRecord::Migration
1
+ class AddTypeToUser < ActiveRecord::Migration[4.2]
2
2
  def up
3
3
  add_column :users, :title, :integer
4
4
  end
@@ -1,44 +1,42 @@
1
- # encoding: UTF-8
2
1
  # This file is auto-generated from the current state of the database. Instead
3
2
  # of editing this file, please use the migrations feature of Active Record to
4
3
  # incrementally modify your database, and then regenerate this schema definition.
5
4
  #
6
- # Note that this schema.rb definition is the authoritative source for your
7
- # database schema. If you need to create the application database on another
8
- # system, you should be using db:schema:load, not running all the migrations
9
- # from scratch. The latter is a flawed and unsustainable approach (the more migrations
10
- # you'll amass, the slower it'll run and the greater likelihood for issues).
5
+ # This file is the source Rails uses to define your schema when running `rails
6
+ # db:schema:load`. When creating a new database, `rails db:schema:load` tends to
7
+ # be faster and is potentially less error prone than running all of your
8
+ # migrations from scratch. Old migrations may fail to apply correctly if those
9
+ # migrations use external dependencies or application code.
11
10
  #
12
11
  # It's strongly recommended that you check this file into your version control system.
13
12
 
14
- ActiveRecord::Schema.define(version: 20190716135241) do
13
+ ActiveRecord::Schema.define(version: 2019_07_16_135241) do
15
14
 
16
15
  create_table "isle", force: :cascade do |t|
17
- t.string "name"
18
- t.binary "map"
16
+ t.string "name"
17
+ t.binary "map"
19
18
  t.datetime "created_at"
20
19
  t.datetime "updated_at"
21
20
  end
22
21
 
23
22
  create_table "trees", force: :cascade do |t|
24
- t.string "name"
25
- t.integer "owner_id"
26
- t.integer "cutter_id"
27
- t.integer "island_id"
23
+ t.string "name"
24
+ t.integer "owner_id"
25
+ t.integer "cutter_id"
26
+ t.integer "island_id"
28
27
  t.datetime "created_at"
29
28
  t.datetime "updated_at"
30
- t.integer "age"
29
+ t.integer "age"
30
+ t.index ["cutter_id"], name: "index_trees_on_cutter_id"
31
+ t.index ["island_id"], name: "index_trees_on_island_id"
32
+ t.index ["owner_id"], name: "index_trees_on_owner_id"
31
33
  end
32
34
 
33
- add_index "trees", ["cutter_id"], name: "index_trees_on_cutter_id"
34
- add_index "trees", ["island_id"], name: "index_trees_on_island_id"
35
- add_index "trees", ["owner_id"], name: "index_trees_on_owner_id"
36
-
37
35
  create_table "users", force: :cascade do |t|
38
- t.string "name"
36
+ t.string "name"
39
37
  t.datetime "created_at"
40
38
  t.datetime "updated_at"
41
- t.integer "title"
39
+ t.integer "title"
42
40
  end
43
41
 
44
42
  end
@@ -35,6 +35,11 @@ describe 'Requesting Actions routes', :type => :request do
35
35
  type: 'Enum',
36
36
  enums: %w[a b c],
37
37
  }
38
+ multiple_enum = {
39
+ field: 'multipleEnum',
40
+ type: ['Enum'],
41
+ enums: %w[a b c],
42
+ }
38
43
 
39
44
  action_definition = {
40
45
  name: 'my_action',
@@ -95,34 +100,50 @@ describe 'Requesting Actions routes', :type => :request do
95
100
  }
96
101
  }
97
102
  }
103
+
104
+ multiple_enums_action_definition = {
105
+ name: 'multiple_enums_action',
106
+ fields: [foo, multiple_enum],
107
+ hooks: {
108
+ :change => {
109
+ 'foo' => -> (context) {
110
+ fields = context[:fields]
111
+ fields['multipleEnum'][:enums] = %w[c d z]
112
+ return fields
113
+ }
114
+ }
115
+ }
116
+ }
117
+
98
118
  action = ForestLiana::Model::Action.new(action_definition)
99
119
  fail_action = ForestLiana::Model::Action.new(fail_action_definition)
100
120
  cheat_action = ForestLiana::Model::Action.new(cheat_action_definition)
101
121
  enums_action = ForestLiana::Model::Action.new(enums_action_definition)
122
+ multiple_enums_action = ForestLiana::Model::Action.new(multiple_enums_action_definition)
102
123
  island = ForestLiana.apimap.find {|collection| collection.name.to_s == ForestLiana.name_for(Island)}
103
- island.actions = [action, fail_action, cheat_action, enums_action]
124
+ island.actions = [action, fail_action, cheat_action, enums_action, multiple_enums_action]
104
125
 
105
126
  describe 'call /load' do
106
127
  params = {recordIds: [1], collectionName: 'Island'}
107
128
 
108
129
  it 'should respond 200' do
109
- post '/forest/actions/my_action/hooks/load', JSON.dump(params), 'CONTENT_TYPE' => 'application/json'
130
+ post '/forest/actions/my_action/hooks/load', params: JSON.dump(params), headers: { 'CONTENT_TYPE' => 'application/json' }
110
131
  expect(response.status).to eq(200)
111
132
  expect(JSON.parse(response.body)).to eq({'fields' => [foo.merge({:value => nil}).stringify_keys]})
112
133
  end
113
134
 
114
135
  it 'should respond 500 with bad params' do
115
- post '/forest/actions/my_action/hooks/load', {}
136
+ post '/forest/actions/my_action/hooks/load', params: {}
116
137
  expect(response.status).to eq(500)
117
138
  end
118
139
 
119
140
  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'
141
+ post '/forest/actions/fail_action/hooks/load', params: JSON.dump(params), headers: { 'CONTENT_TYPE' => 'application/json' }
121
142
  expect(response.status).to eq(500)
122
143
  end
123
144
 
124
145
  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'
146
+ post '/forest/actions/cheat_action/hooks/load', params: JSON.dump(params), headers: { 'CONTENT_TYPE' => 'application/json' }
126
147
  expect(response.status).to eq(500)
127
148
  end
128
149
  end
@@ -132,7 +153,7 @@ describe 'Requesting Actions routes', :type => :request do
132
153
  params = {recordIds: [1], fields: [updated_foo], collectionName: 'Island', changedField: 'foo'}
133
154
 
134
155
  it 'should respond 200' do
135
- post '/forest/actions/my_action/hooks/change', JSON.dump(params), 'CONTENT_TYPE' => 'application/json'
156
+ post '/forest/actions/my_action/hooks/change', params: JSON.dump(params), headers: { 'CONTENT_TYPE' => 'application/json' }
136
157
  expect(response.status).to eq(200)
137
158
  expected = updated_foo.clone.merge({:value => 'baz'})
138
159
  expected[:widgetEdit] = nil
@@ -141,24 +162,24 @@ describe 'Requesting Actions routes', :type => :request do
141
162
  end
142
163
 
143
164
  it 'should respond 500 with bad params' do
144
- post '/forest/actions/my_action/hooks/change', {}
165
+ post '/forest/actions/my_action/hooks/change', params: {}
145
166
  expect(response.status).to eq(500)
146
167
  end
147
168
 
148
169
  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'
170
+ post '/forest/actions/fail_action/hooks/change', params: JSON.dump(params), headers: { 'CONTENT_TYPE' => 'application/json' }
150
171
  expect(response.status).to eq(500)
151
172
  end
152
173
 
153
174
  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'
175
+ post '/forest/actions/cheat_action/hooks/change', params: JSON.dump(params), headers: { 'CONTENT_TYPE' => 'application/json' }
155
176
  expect(response.status).to eq(500)
156
177
  end
157
178
 
158
179
  it 'should reset value when enums has changed' do
159
180
  updated_enum = enum.clone.merge({:previousValue => nil, :value => 'a'}) # set value to a
160
181
  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'
182
+ post '/forest/actions/enums_action/hooks/change', params: JSON.dump(p), headers: { 'CONTENT_TYPE' => 'application/json' }
162
183
  expect(response.status).to eq(200)
163
184
 
164
185
  expected_enum = updated_enum.clone.merge({ :enums => %w[c d e], :value => nil, :widgetEdit => nil})
@@ -169,6 +190,33 @@ describe 'Requesting Actions routes', :type => :request do
169
190
  expect(JSON.parse(response.body)).to eq({'fields' => [expected_foo.stringify_keys, expected_enum.stringify_keys]})
170
191
  end
171
192
 
193
+ it 'should not reset value when every enum values are in the enums definition' do
194
+ updated_multiple_enum = multiple_enum.clone.merge({:previousValue => nil, :value => %w[c]})
195
+ p = {recordIds: [1], fields: [foo, updated_multiple_enum], collectionName: 'Island', changedField: 'foo'}
196
+ post '/forest/actions/multiple_enums_action/hooks/change', params: JSON.dump(p), headers: { 'CONTENT_TYPE' => 'application/json' }
197
+ expect(response.status).to eq(200)
198
+
199
+ expected_multiple_enum = updated_multiple_enum.clone.merge({ :enums => %w[c d z], :widgetEdit => nil, :value => %w[c]})
200
+ expected_multiple_enum.delete(:widget)
201
+ expected_foo = foo.clone.merge({ :widgetEdit => nil})
202
+ expected_foo.delete(:widget)
203
+
204
+ expect(JSON.parse(response.body)).to eq({'fields' => [expected_foo.stringify_keys, expected_multiple_enum.stringify_keys]})
205
+ end
206
+
207
+ it 'should reset value when one of the enum values is not in the enums definition' do
208
+ wrongly_updated_multiple_enum = multiple_enum.clone.merge({:previousValue => nil, :value => %w[a b]})
209
+ p = {recordIds: [1], fields: [foo, wrongly_updated_multiple_enum], collectionName: 'Island', changedField: 'foo'}
210
+ post '/forest/actions/multiple_enums_action/hooks/change', params: JSON.dump(p), headers: { 'CONTENT_TYPE' => 'application/json' }
211
+ expect(response.status).to eq(200)
212
+
213
+ expected_multiple_enum = wrongly_updated_multiple_enum.clone.merge({ :enums => %w[c d z], :widgetEdit => nil, :value => nil })
214
+ expected_multiple_enum.delete(:widget)
215
+ expected_foo = foo.clone.merge({ :widgetEdit => nil})
216
+ expected_foo.delete(:widget)
217
+
218
+ expect(JSON.parse(response.body)).to eq({'fields' => [expected_foo.stringify_keys, expected_multiple_enum.stringify_keys]})
219
+ end
172
220
  end
173
221
  end
174
- end
222
+ end