iknow_view_models 3.1.6 → 3.2.2
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/.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))
|