iknow_view_models 3.1.6 → 3.2.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.circleci/config.yml +6 -6
- data/.rubocop.yml +18 -0
- data/Appraisals +6 -6
- data/Gemfile +6 -2
- data/Rakefile +5 -5
- data/gemfiles/rails_5_2.gemfile +5 -5
- data/gemfiles/rails_6_0.gemfile +9 -0
- data/iknow_view_models.gemspec +40 -38
- data/lib/iknow_view_models.rb +9 -7
- data/lib/iknow_view_models/version.rb +1 -1
- data/lib/view_model.rb +31 -17
- data/lib/view_model/access_control.rb +5 -2
- data/lib/view_model/access_control/composed.rb +10 -9
- data/lib/view_model/access_control/open.rb +2 -0
- data/lib/view_model/access_control/read_only.rb +2 -0
- data/lib/view_model/access_control/tree.rb +11 -6
- data/lib/view_model/access_control_error.rb +4 -1
- data/lib/view_model/active_record.rb +13 -12
- data/lib/view_model/active_record/association_data.rb +3 -2
- data/lib/view_model/active_record/association_manipulation.rb +6 -4
- data/lib/view_model/active_record/cache.rb +114 -34
- data/lib/view_model/active_record/cache/cacheable_view.rb +2 -2
- data/lib/view_model/active_record/collection_nested_controller.rb +3 -3
- data/lib/view_model/active_record/controller.rb +68 -1
- data/lib/view_model/active_record/controller_base.rb +4 -1
- data/lib/view_model/active_record/nested_controller_base.rb +1 -0
- data/lib/view_model/active_record/update_context.rb +8 -6
- data/lib/view_model/active_record/update_data.rb +32 -30
- data/lib/view_model/active_record/update_operation.rb +17 -13
- data/lib/view_model/active_record/visitor.rb +0 -1
- data/lib/view_model/after_transaction_runner.rb +2 -2
- data/lib/view_model/callbacks.rb +3 -1
- data/lib/view_model/controller.rb +13 -3
- data/lib/view_model/deserialization_error.rb +15 -12
- data/lib/view_model/error.rb +12 -10
- data/lib/view_model/error_view.rb +3 -1
- data/lib/view_model/migratable_view.rb +78 -0
- data/lib/view_model/migration.rb +48 -0
- data/lib/view_model/migration/no_path_error.rb +26 -0
- data/lib/view_model/migration/one_way_error.rb +24 -0
- data/lib/view_model/migration/unspecified_version_error.rb +24 -0
- data/lib/view_model/migrator.rb +108 -0
- data/lib/view_model/record.rb +15 -14
- data/lib/view_model/reference.rb +3 -1
- data/lib/view_model/references.rb +8 -5
- data/lib/view_model/registry.rb +1 -1
- data/lib/view_model/schemas.rb +9 -4
- data/lib/view_model/serialization_error.rb +4 -1
- data/lib/view_model/serialize_context.rb +4 -4
- data/lib/view_model/test_helpers.rb +8 -3
- data/lib/view_model/test_helpers/arvm_builder.rb +21 -15
- data/lib/view_model/traversal_context.rb +2 -1
- data/nix/dependencies.nix +5 -0
- data/nix/gem/generate.rb +2 -1
- data/shell.nix +8 -3
- data/test/.rubocop.yml +14 -0
- data/test/helpers/arvm_test_models.rb +12 -9
- data/test/helpers/arvm_test_utilities.rb +5 -3
- data/test/helpers/controller_test_helpers.rb +55 -32
- data/test/helpers/match_enumerator.rb +1 -0
- data/test/helpers/query_logging.rb +2 -1
- data/test/helpers/test_access_control.rb +5 -3
- data/test/helpers/viewmodel_spec_helpers.rb +88 -22
- data/test/unit/view_model/access_control_test.rb +144 -144
- data/test/unit/view_model/active_record/alias_test.rb +15 -13
- data/test/unit/view_model/active_record/belongs_to_test.rb +40 -39
- data/test/unit/view_model/active_record/cache_test.rb +68 -31
- data/test/unit/view_model/active_record/cloner_test.rb +67 -63
- data/test/unit/view_model/active_record/controller_test.rb +113 -65
- data/test/unit/view_model/active_record/counter_test.rb +10 -9
- data/test/unit/view_model/active_record/customization_test.rb +59 -58
- data/test/unit/view_model/active_record/has_many_test.rb +112 -111
- data/test/unit/view_model/active_record/has_many_through_poly_test.rb +15 -14
- data/test/unit/view_model/active_record/has_many_through_test.rb +33 -38
- data/test/unit/view_model/active_record/has_one_test.rb +37 -36
- data/test/unit/view_model/active_record/migration_test.rb +161 -0
- data/test/unit/view_model/active_record/namespacing_test.rb +19 -17
- data/test/unit/view_model/active_record/poly_test.rb +44 -45
- data/test/unit/view_model/active_record/shared_test.rb +30 -28
- data/test/unit/view_model/active_record/version_test.rb +9 -7
- data/test/unit/view_model/active_record_test.rb +72 -72
- data/test/unit/view_model/callbacks_test.rb +19 -15
- data/test/unit/view_model/controller_test.rb +4 -2
- data/test/unit/view_model/record_test.rb +92 -97
- data/test/unit/view_model/traversal_context_test.rb +4 -5
- data/test/unit/view_model_test.rb +18 -16
- metadata +36 -12
- data/.travis.yml +0 -31
- data/appveyor.yml +0 -22
- data/gemfiles/rails_6_0_beta.gemfile +0 -9
@@ -1,15 +1,15 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative
|
4
|
-
require_relative
|
5
|
-
require_relative '../../helpers/viewmodel_spec_helpers
|
3
|
+
require_relative '../../helpers/arvm_test_utilities'
|
4
|
+
require_relative '../../helpers/arvm_test_models'
|
5
|
+
require_relative '../../helpers/viewmodel_spec_helpers'
|
6
6
|
|
7
|
-
require
|
7
|
+
require 'minitest/autorun'
|
8
8
|
require 'minitest/unit'
|
9
9
|
|
10
10
|
require 'rspec/expectations/minitest_integration'
|
11
11
|
|
12
|
-
require
|
12
|
+
require 'view_model/active_record'
|
13
13
|
|
14
14
|
class ViewModel::AccessControlTest < ActiveSupport::TestCase
|
15
15
|
include ARVMTestUtilities
|
@@ -55,103 +55,103 @@ class ViewModel::AccessControlTest < ActiveSupport::TestCase
|
|
55
55
|
end
|
56
56
|
|
57
57
|
def test_visible_if
|
58
|
-
TestAccessControl.visible_if!(
|
59
|
-
view.car ==
|
58
|
+
TestAccessControl.visible_if!('car is visible1') do
|
59
|
+
view.car == 'visible1'
|
60
60
|
end
|
61
61
|
|
62
|
-
TestAccessControl.visible_if!(
|
63
|
-
view.car ==
|
62
|
+
TestAccessControl.visible_if!('car is visible2') do
|
63
|
+
view.car == 'visible2'
|
64
64
|
end
|
65
65
|
|
66
|
-
assert_serializes(ListView, List.create!(car:
|
67
|
-
assert_serializes(ListView, List.create!(car:
|
68
|
-
ex = refute_serializes(ListView, List.create!(car:
|
66
|
+
assert_serializes(ListView, List.create!(car: 'visible1'))
|
67
|
+
assert_serializes(ListView, List.create!(car: 'visible2'))
|
68
|
+
ex = refute_serializes(ListView, List.create!(car: 'bad'), /none of the possible/)
|
69
69
|
assert_equal(2, ex.reasons.count)
|
70
70
|
end
|
71
71
|
|
72
72
|
def test_visible_unless
|
73
|
-
TestAccessControl.visible_if!(
|
73
|
+
TestAccessControl.visible_if!('always') { true }
|
74
74
|
|
75
|
-
TestAccessControl.visible_unless!(
|
76
|
-
view.car ==
|
75
|
+
TestAccessControl.visible_unless!('car is invisible') do
|
76
|
+
view.car == 'invisible'
|
77
77
|
end
|
78
78
|
|
79
|
-
assert_serializes(ListView, List.create!(car:
|
80
|
-
refute_serializes(ListView, List.create!(car:
|
79
|
+
assert_serializes(ListView, List.create!(car: 'ok'))
|
80
|
+
refute_serializes(ListView, List.create!(car: 'invisible'), /not permitted.*car is invisible/)
|
81
81
|
end
|
82
82
|
|
83
83
|
def test_editable_if
|
84
|
-
TestAccessControl.visible_if!(
|
84
|
+
TestAccessControl.visible_if!('always') { true }
|
85
85
|
|
86
|
-
TestAccessControl.editable_if!(
|
87
|
-
view.car ==
|
86
|
+
TestAccessControl.editable_if!('car is editable1') do
|
87
|
+
view.car == 'editable1'
|
88
88
|
end
|
89
89
|
|
90
|
-
TestAccessControl.editable_if!(
|
91
|
-
view.car ==
|
90
|
+
TestAccessControl.editable_if!('car is editable2') do
|
91
|
+
view.car == 'editable2'
|
92
92
|
end
|
93
93
|
|
94
|
-
assert_deserializes(ListView, List.create!(car:
|
95
|
-
assert_deserializes(ListView, List.create!(car:
|
96
|
-
assert_deserializes(ListView, List.create!(car:
|
97
|
-
refute_deserializes(ListView, List.create!(car:
|
94
|
+
assert_deserializes(ListView, List.create!(car: 'editable1')) { |v, _| v['car'] = 'unchecked' }
|
95
|
+
assert_deserializes(ListView, List.create!(car: 'editable2')) { |v, _| v['car'] = 'unchecked' }
|
96
|
+
assert_deserializes(ListView, List.create!(car: 'forbidden')) { |v, _| v['car'] = 'forbidden' } # no change so permitted
|
97
|
+
refute_deserializes(ListView, List.create!(car: 'forbidden'), /none of the possible/) { |v, _| v['car'] = 'unchecked' }
|
98
98
|
end
|
99
99
|
|
100
100
|
def test_editable_unless
|
101
|
-
TestAccessControl.visible_if!(
|
102
|
-
TestAccessControl.editable_if!(
|
101
|
+
TestAccessControl.visible_if!('always') { true }
|
102
|
+
TestAccessControl.editable_if!('always') { true }
|
103
103
|
|
104
|
-
TestAccessControl.editable_unless!(
|
105
|
-
view.car ==
|
104
|
+
TestAccessControl.editable_unless!('car is uneditable') do
|
105
|
+
view.car == 'uneditable'
|
106
106
|
end
|
107
107
|
|
108
|
-
assert_deserializes(ListView, List.create!(car:
|
109
|
-
assert_deserializes(ListView, List.create!(car:
|
110
|
-
refute_deserializes(ListView, List.create!(car:
|
108
|
+
assert_deserializes(ListView, List.create!(car: 'ok')) { |v, _| v['car'] = 'unchecked' }
|
109
|
+
assert_deserializes(ListView, List.create!(car: 'uneditable')) { |v, _| v['car'] = 'uneditable' } # no change so permitted
|
110
|
+
refute_deserializes(ListView, List.create!(car: 'uneditable'), /car is uneditable/) { |v, _| v['car'] = 'unchecked' }
|
111
111
|
end
|
112
112
|
|
113
113
|
def test_edit_valid_if
|
114
|
-
TestAccessControl.visible_if!(
|
114
|
+
TestAccessControl.visible_if!('always') { true }
|
115
115
|
|
116
|
-
TestAccessControl.edit_valid_if!(
|
117
|
-
view.car ==
|
116
|
+
TestAccessControl.edit_valid_if!('car is validedit') do
|
117
|
+
view.car == 'validedit'
|
118
118
|
end
|
119
119
|
|
120
|
-
assert_deserializes(ListView, List.create!(car:
|
121
|
-
assert_deserializes(ListView, List.create!(car:
|
122
|
-
refute_deserializes(ListView, List.create!(car:
|
120
|
+
assert_deserializes(ListView, List.create!(car: 'unchecked')) { |v, _| v['car'] = 'validedit' }
|
121
|
+
assert_deserializes(ListView, List.create!(car: 'unmodified')) { |v, _| v['car'] = 'unmodified' } # no change so permitted
|
122
|
+
refute_deserializes(ListView, List.create!(car: 'unchecked'), /none of the possible/) { |v, _| v['car'] = 'bad' }
|
123
123
|
end
|
124
124
|
|
125
125
|
def test_edit_valid_unless
|
126
|
-
TestAccessControl.visible_if!(
|
127
|
-
TestAccessControl.edit_valid_if!(
|
128
|
-
TestAccessControl.edit_valid_unless!(
|
129
|
-
view.car ==
|
126
|
+
TestAccessControl.visible_if!('always') { true }
|
127
|
+
TestAccessControl.edit_valid_if!('always') { true }
|
128
|
+
TestAccessControl.edit_valid_unless!('car is invalidedit') do
|
129
|
+
view.car == 'invalidedit'
|
130
130
|
end
|
131
131
|
|
132
|
-
assert_deserializes(ListView, List.create!(car:
|
133
|
-
assert_deserializes(ListView, List.create!(car:
|
134
|
-
refute_deserializes(ListView, List.create!(car:
|
132
|
+
assert_deserializes(ListView, List.create!(car: 'unchecked')) { |v, _| v['car'] = 'ok' }
|
133
|
+
assert_deserializes(ListView, List.create!(car: 'invalidedit')) { |v, _| v['car'] = 'invalidedit' }
|
134
|
+
refute_deserializes(ListView, List.create!(car: 'unchecked'), /car is invalidedit/) { |v, _| v['car'] = 'invalidedit' }
|
135
135
|
end
|
136
136
|
|
137
137
|
def test_editable_and_edit_valid
|
138
|
-
TestAccessControl.visible_if!(
|
138
|
+
TestAccessControl.visible_if!('always') { true }
|
139
139
|
|
140
|
-
TestAccessControl.editable_if!(
|
141
|
-
view.car ==
|
140
|
+
TestAccessControl.editable_if!('original car permits') do
|
141
|
+
view.car == 'permitoriginal'
|
142
142
|
end
|
143
143
|
|
144
|
-
TestAccessControl.edit_valid_if!(
|
145
|
-
view.car ==
|
144
|
+
TestAccessControl.edit_valid_if!('resulting car permits') do
|
145
|
+
view.car == 'permitresult'
|
146
146
|
end
|
147
147
|
|
148
148
|
# at least one valid
|
149
|
-
assert_deserializes(ListView, List.create!(car:
|
150
|
-
assert_deserializes(ListView, List.create!(car:
|
151
|
-
assert_deserializes(ListView, List.create!(car:
|
149
|
+
assert_deserializes(ListView, List.create!(car: 'permitoriginal')) { |v, _| v['car'] = 'permitresult' }
|
150
|
+
assert_deserializes(ListView, List.create!(car: 'badoriginal')) { |v, _| v['car'] = 'permitresult' }
|
151
|
+
assert_deserializes(ListView, List.create!(car: 'permitoriginal')) { |v, _| v['car'] = 'badresult' }
|
152
152
|
|
153
153
|
# no valid
|
154
|
-
ex = refute_deserializes(ListView, List.create!(car:
|
154
|
+
ex = refute_deserializes(ListView, List.create!(car: 'badoriginal'), /none of the possible/) { |v, _| v['car'] = 'badresult' }
|
155
155
|
|
156
156
|
assert_equal(2, ex.reasons.count)
|
157
157
|
end
|
@@ -160,14 +160,14 @@ class ViewModel::AccessControlTest < ActiveSupport::TestCase
|
|
160
160
|
child_access_control = Class.new(ViewModel::AccessControl::Composed)
|
161
161
|
child_access_control.include_from(TestAccessControl)
|
162
162
|
|
163
|
-
TestAccessControl.visible_if!(
|
164
|
-
child_access_control.visible_if!(
|
163
|
+
TestAccessControl.visible_if!('car is ancestor') { view.car == 'ancestor' }
|
164
|
+
child_access_control.visible_if!('car is descendent') { view.car == 'descendent' }
|
165
165
|
|
166
166
|
s_ctx = ListView.new_serialize_context(access_control: child_access_control.new)
|
167
167
|
|
168
|
-
assert_serializes(ListView, List.create!(car:
|
169
|
-
assert_serializes(ListView, List.create!(car:
|
170
|
-
ex = refute_serializes(ListView, List.create!(car:
|
168
|
+
assert_serializes(ListView, List.create!(car: 'ancestor'), serialize_context: s_ctx)
|
169
|
+
assert_serializes(ListView, List.create!(car: 'descendent'), serialize_context: s_ctx)
|
170
|
+
ex = refute_serializes(ListView, List.create!(car: 'foreigner'), serialize_context: s_ctx)
|
171
171
|
assert_equal(2, ex.reasons.count)
|
172
172
|
end
|
173
173
|
end
|
@@ -243,7 +243,7 @@ class ViewModel::AccessControlTest < ActiveSupport::TestCase
|
|
243
243
|
|
244
244
|
child = root[attr]
|
245
245
|
|
246
|
-
if (child_ref = child[
|
246
|
+
if (child_ref = child['_ref'])
|
247
247
|
child = refs[child_ref]
|
248
248
|
end
|
249
249
|
|
@@ -255,189 +255,189 @@ class ViewModel::AccessControlTest < ActiveSupport::TestCase
|
|
255
255
|
end
|
256
256
|
|
257
257
|
def test_visibility_from_root
|
258
|
-
TestAccessControl.view
|
259
|
-
visible_if!(
|
258
|
+
TestAccessControl.view 'Tree1' do
|
259
|
+
visible_if!('true') { true }
|
260
260
|
|
261
|
-
root_children_visible_if!(
|
262
|
-
view.val ==
|
261
|
+
root_children_visible_if!('root children visible') do
|
262
|
+
view.val == 'rule:visible_children'
|
263
263
|
end
|
264
264
|
end
|
265
265
|
|
266
|
-
refute_serializes(Tree1View, make_tree(
|
267
|
-
assert_serializes(Tree1View, make_tree(
|
266
|
+
refute_serializes(Tree1View, make_tree('arbitrary parent', 'invisible child'))
|
267
|
+
assert_serializes(Tree1View, make_tree('rule:visible_children', 'visible child'))
|
268
268
|
|
269
269
|
# nested root
|
270
|
-
refute_serializes(Tree1View, make_tree(
|
271
|
-
assert_serializes(Tree1View, make_tree(
|
270
|
+
refute_serializes(Tree1View, make_tree('rule:visible_children', 'visible child', 'arbitrary parent', 'invisible child'))
|
271
|
+
assert_serializes(Tree1View, make_tree('rule:visible_children', 'visible child', 'rule:visible_children', 'visible child'))
|
272
272
|
end
|
273
273
|
|
274
274
|
def test_visibility_veto_from_root
|
275
|
-
TestAccessControl.view
|
276
|
-
root_children_visible_unless!(
|
277
|
-
view.val ==
|
275
|
+
TestAccessControl.view 'Tree1' do
|
276
|
+
root_children_visible_unless!('root children invisible') do
|
277
|
+
view.val == 'rule:invisible_children'
|
278
278
|
end
|
279
279
|
end
|
280
280
|
|
281
281
|
TestAccessControl.always do
|
282
|
-
visible_if!(
|
282
|
+
visible_if!('true') { true }
|
283
283
|
end
|
284
284
|
|
285
|
-
assert_serializes(Tree1View, make_tree(
|
286
|
-
refute_serializes(Tree1View, make_tree(
|
285
|
+
assert_serializes(Tree1View, make_tree('arbitrary parent', 'visible child'))
|
286
|
+
refute_serializes(Tree1View, make_tree('rule:invisible_children', 'invisible child'))
|
287
287
|
|
288
288
|
# nested root
|
289
|
-
assert_serializes(Tree1View, make_tree(
|
290
|
-
refute_serializes(Tree1View, make_tree(
|
289
|
+
assert_serializes(Tree1View, make_tree('arbitrary parent', 'visible child', 'arbitrary nested parent', 'visible child'))
|
290
|
+
refute_serializes(Tree1View, make_tree('arbitrary parent', 'visible child', 'rule:invisible_children', 'invisible child'))
|
291
291
|
end
|
292
292
|
|
293
293
|
def test_editability_from_root
|
294
294
|
TestAccessControl.always do
|
295
|
-
visible_if!(
|
295
|
+
visible_if!('always') { true }
|
296
296
|
end
|
297
297
|
|
298
|
-
TestAccessControl.view
|
299
|
-
editable_if!(
|
298
|
+
TestAccessControl.view 'Tree1' do
|
299
|
+
editable_if!('true') { true }
|
300
300
|
|
301
|
-
root_children_editable_if!(
|
302
|
-
view.val ==
|
301
|
+
root_children_editable_if!('root children editable') do
|
302
|
+
view.val == 'rule:editable_children'
|
303
303
|
end
|
304
304
|
end
|
305
305
|
|
306
|
-
refute_deserializes(Tree1View, make_tree(
|
307
|
-
dig_tree(v, r,
|
306
|
+
refute_deserializes(Tree1View, make_tree('arbitrary parent', 'uneditable child')) { |v, r|
|
307
|
+
dig_tree(v, r, 'tree2')['val'] = 'change'
|
308
308
|
}
|
309
309
|
|
310
|
-
assert_deserializes(Tree1View, make_tree(
|
311
|
-
dig_tree(v, r,
|
310
|
+
assert_deserializes(Tree1View, make_tree('rule:editable_children', 'editable child')) { |v, r|
|
311
|
+
dig_tree(v, r, 'tree2')['val'] = 'change'
|
312
312
|
}
|
313
313
|
|
314
314
|
# nested root
|
315
|
-
refute_deserializes(Tree1View, make_tree(
|
316
|
-
dig_tree(v, r,
|
315
|
+
refute_deserializes(Tree1View, make_tree('rule:editable_children', 'editable child', 'arbitrary parent', 'uneditable child')) { |v, r|
|
316
|
+
dig_tree(v, r, 'tree2', 'tree1', 'tree2')['val'] = 'change'
|
317
317
|
}
|
318
318
|
|
319
|
-
assert_deserializes(Tree1View, make_tree(
|
320
|
-
dig_tree(v, r,
|
319
|
+
assert_deserializes(Tree1View, make_tree('arbitrary parent', 'uneditable child', 'rule:editable_children', 'editable child')) { |v, r|
|
320
|
+
dig_tree(v, r, 'tree2', 'tree1', 'tree2')['val'] = 'change'
|
321
321
|
}
|
322
322
|
end
|
323
323
|
|
324
324
|
def test_editability_veto_from_root
|
325
325
|
TestAccessControl.always do
|
326
|
-
visible_if!(
|
327
|
-
editable_if!(
|
326
|
+
visible_if!('always') { true }
|
327
|
+
editable_if!('always') { true }
|
328
328
|
end
|
329
329
|
|
330
|
-
TestAccessControl.view
|
331
|
-
root_children_editable_unless!(
|
332
|
-
view.val ==
|
330
|
+
TestAccessControl.view 'Tree1' do
|
331
|
+
root_children_editable_unless!('root children uneditable') do
|
332
|
+
view.val == 'rule:uneditable_children'
|
333
333
|
end
|
334
334
|
end
|
335
335
|
|
336
|
-
refute_deserializes(Tree1View, make_tree(
|
337
|
-
dig_tree(v, r,
|
336
|
+
refute_deserializes(Tree1View, make_tree('rule:uneditable_children', 'uneditable child')) { |v, r|
|
337
|
+
dig_tree(v, r, 'tree2')['val'] = 'change'
|
338
338
|
}
|
339
339
|
|
340
|
-
assert_deserializes(Tree1View, make_tree(
|
341
|
-
dig_tree(v, r,
|
340
|
+
assert_deserializes(Tree1View, make_tree('arbitrary parent', 'editable child')) { |v, r|
|
341
|
+
dig_tree(v, r, 'tree2')['val'] = 'change'
|
342
342
|
}
|
343
343
|
|
344
344
|
# nested root
|
345
|
-
refute_deserializes(Tree1View, make_tree(
|
346
|
-
dig_tree(v, r,
|
345
|
+
refute_deserializes(Tree1View, make_tree('arbitrary parent', 'editable child', 'rule:uneditable_children', 'uneditable child')) { |v, r|
|
346
|
+
dig_tree(v, r, 'tree2', 'tree1', 'tree2')['val'] = 'change'
|
347
347
|
}
|
348
348
|
|
349
|
-
assert_deserializes(Tree1View, make_tree(
|
350
|
-
dig_tree(v, r,
|
349
|
+
assert_deserializes(Tree1View, make_tree('rule:uneditable_children', 'uneditable child', 'arbitrary parent', 'editable child')) { |v, r|
|
350
|
+
dig_tree(v, r, 'tree2', 'tree1', 'tree2')['val'] = 'change'
|
351
351
|
}
|
352
352
|
end
|
353
353
|
|
354
354
|
def test_type_independence
|
355
|
-
TestAccessControl.view
|
356
|
-
visible_if!(
|
357
|
-
view.val ==
|
355
|
+
TestAccessControl.view 'Tree1' do
|
356
|
+
visible_if!('tree1 visible') do
|
357
|
+
view.val == 'tree1visible'
|
358
358
|
end
|
359
359
|
end
|
360
360
|
|
361
|
-
TestAccessControl.view
|
362
|
-
visible_if!(
|
363
|
-
view.val ==
|
361
|
+
TestAccessControl.view 'Tree2' do
|
362
|
+
visible_if!('tree2 visible') do
|
363
|
+
view.val == 'tree2visible'
|
364
364
|
end
|
365
365
|
end
|
366
366
|
|
367
|
-
refute_serializes(Tree1View, make_tree(
|
368
|
-
assert_serializes(Tree1View, make_tree(
|
369
|
-
refute_serializes(Tree1View, make_tree(
|
367
|
+
refute_serializes(Tree1View, make_tree('tree1invisible', 'tree2visible'))
|
368
|
+
assert_serializes(Tree1View, make_tree('tree1visible', 'tree2visible'))
|
369
|
+
refute_serializes(Tree1View, make_tree('tree1visible', 'tree2invisible'))
|
370
370
|
end
|
371
371
|
|
372
372
|
def test_visibility_always_composition
|
373
|
-
TestAccessControl.view
|
374
|
-
visible_if!(
|
375
|
-
view.val ==
|
373
|
+
TestAccessControl.view 'Tree1' do
|
374
|
+
visible_if!('tree1 visible') do
|
375
|
+
view.val == 'tree1visible'
|
376
376
|
end
|
377
377
|
end
|
378
378
|
|
379
379
|
TestAccessControl.always do
|
380
|
-
visible_if!(
|
381
|
-
view.val ==
|
380
|
+
visible_if!('tree2 visible') do
|
381
|
+
view.val == 'alwaysvisible'
|
382
382
|
end
|
383
383
|
end
|
384
384
|
|
385
|
-
refute_serializes(Tree1View, Tree1.create(val:
|
386
|
-
assert_serializes(Tree1View, Tree1.create(val:
|
387
|
-
assert_serializes(Tree1View, Tree1.create(val:
|
385
|
+
refute_serializes(Tree1View, Tree1.create(val: 'bad'))
|
386
|
+
assert_serializes(Tree1View, Tree1.create(val: 'tree1visible'))
|
387
|
+
assert_serializes(Tree1View, Tree1.create(val: 'alwaysvisible'))
|
388
388
|
end
|
389
389
|
|
390
390
|
def test_editability_always_composition
|
391
|
-
TestAccessControl.view
|
392
|
-
editable_if!(
|
393
|
-
edit_valid_if!(
|
391
|
+
TestAccessControl.view 'Tree1' do
|
392
|
+
editable_if!('editable1') { view.val == 'editable1' }
|
393
|
+
edit_valid_if!('editvalid1') { view.val == 'editvalid1' }
|
394
394
|
end
|
395
395
|
|
396
396
|
TestAccessControl.always do
|
397
|
-
editable_if!(
|
398
|
-
edit_valid_if!(
|
397
|
+
editable_if!('editable2') { view.val == 'editable2' }
|
398
|
+
edit_valid_if!('editvalid2') { view.val == 'editvalid2' }
|
399
399
|
|
400
|
-
visible_if!(
|
400
|
+
visible_if!('always') { true }
|
401
401
|
end
|
402
402
|
|
403
|
-
refute_deserializes(Tree1View, Tree1.create!(val:
|
403
|
+
refute_deserializes(Tree1View, Tree1.create!(val: 'bad')) { |v, _| v['val'] = 'alsobad' }
|
404
404
|
|
405
|
-
assert_deserializes(Tree1View, Tree1.create!(val:
|
406
|
-
assert_deserializes(Tree1View, Tree1.create!(val:
|
405
|
+
assert_deserializes(Tree1View, Tree1.create!(val: 'editable1')) { |v, _| v['val'] = 'unchecked' }
|
406
|
+
assert_deserializes(Tree1View, Tree1.create!(val: 'editable2')) { |v, _| v['val'] = 'unchecked' }
|
407
407
|
|
408
|
-
assert_deserializes(Tree1View, Tree1.create!(val:
|
409
|
-
assert_deserializes(Tree1View, Tree1.create!(val:
|
408
|
+
assert_deserializes(Tree1View, Tree1.create!(val: 'unchecked')) { |v, _| v['val'] = 'editvalid1' }
|
409
|
+
assert_deserializes(Tree1View, Tree1.create!(val: 'unchecked')) { |v, _| v['val'] = 'editvalid2' }
|
410
410
|
end
|
411
411
|
|
412
412
|
def test_ancestry
|
413
|
-
TestAccessControl.view
|
414
|
-
visible_if!(
|
413
|
+
TestAccessControl.view 'Tree1' do
|
414
|
+
visible_if!('parent tree1') { view.val == 'parenttree1' }
|
415
415
|
end
|
416
416
|
|
417
417
|
TestAccessControl.always do
|
418
|
-
visible_if!(
|
418
|
+
visible_if!('parent always') { view.val == 'parentalways' }
|
419
419
|
end
|
420
420
|
|
421
421
|
# Child must be set up after parent is fully defined
|
422
422
|
child_access_control = Class.new(ViewModel::AccessControl::Tree)
|
423
423
|
child_access_control.include_from(TestAccessControl)
|
424
424
|
|
425
|
-
child_access_control.view
|
426
|
-
visible_if!(
|
425
|
+
child_access_control.view 'Tree1' do
|
426
|
+
visible_if!('child tree1') { view.val == 'childtree1' }
|
427
427
|
end
|
428
428
|
|
429
429
|
child_access_control.always do
|
430
|
-
visible_if!(
|
430
|
+
visible_if!('child always') { view.val == 'childalways' }
|
431
431
|
end
|
432
432
|
|
433
433
|
s_ctx = Tree1View.new_serialize_context(access_control: child_access_control.new)
|
434
434
|
|
435
|
-
refute_serializes(Tree1View, Tree1.create!(val:
|
435
|
+
refute_serializes(Tree1View, Tree1.create!(val: 'bad'), serialize_context: s_ctx)
|
436
436
|
|
437
|
-
assert_serializes(Tree1View, Tree1.create!(val:
|
438
|
-
assert_serializes(Tree1View, Tree1.create!(val:
|
439
|
-
assert_serializes(Tree1View, Tree1.create!(val:
|
440
|
-
assert_serializes(Tree1View, Tree1.create!(val:
|
437
|
+
assert_serializes(Tree1View, Tree1.create!(val: 'parenttree1'), serialize_context: s_ctx)
|
438
|
+
assert_serializes(Tree1View, Tree1.create!(val: 'parentalways'), serialize_context: s_ctx)
|
439
|
+
assert_serializes(Tree1View, Tree1.create!(val: 'childtree1'), serialize_context: s_ctx)
|
440
|
+
assert_serializes(Tree1View, Tree1.create!(val: 'childalways'), serialize_context: s_ctx)
|
441
441
|
end
|
442
442
|
end
|
443
443
|
|
@@ -574,7 +574,7 @@ class ViewModel::AccessControlTest < ActiveSupport::TestCase
|
|
574
574
|
model_class.new(
|
575
575
|
name: 'a',
|
576
576
|
children: [child_model_class.new(name: 'x', position: 1),
|
577
|
-
child_model_class.new(name: 'y', position: 2)])
|
577
|
+
child_model_class.new(name: 'y', position: 2),])
|
578
578
|
end
|
579
579
|
|
580
580
|
it 'records new children' do
|
@@ -619,7 +619,7 @@ class ViewModel::AccessControlTest < ActiveSupport::TestCase
|
|
619
619
|
|
620
620
|
new_child = vm.children.detect { |c| c.name == 'b' }
|
621
621
|
c_changes = ctx.valid_edit_changes(new_child.to_reference)
|
622
|
-
assert_changes_match(c_changes, n:true, att: ['name'])
|
622
|
+
assert_changes_match(c_changes, n: true, att: ['name'])
|
623
623
|
|
624
624
|
oc_changes = ctx.valid_edit_changes(
|
625
625
|
ViewModel::Reference.new(child_viewmodel_class, replaced_child.id))
|