scimitar 2.7.0 → 2.7.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -81,6 +81,102 @@ RSpec.describe Scimitar::Resources::Mixin do
81
81
  include Scimitar::Resources::Mixin
82
82
  end
83
83
 
84
+ # A simple schema containing two attributes that looks very like complex
85
+ # type "name", except shorter and with "familyName" never returned.
86
+ #
87
+ NestedReturnedNeverTestNameSchema = Class.new(Scimitar::Schema::Base) do
88
+ def self.id
89
+ 'nested-returned-never-name-id'
90
+ end
91
+
92
+ def self.scim_attributes
93
+ @scim_attributes ||= [
94
+ Scimitar::Schema::Attribute.new(name: 'familyName', type: 'string', required: true, returned: 'never'),
95
+ Scimitar::Schema::Attribute.new(name: 'givenName', type: 'string', required: true)
96
+ ]
97
+ end
98
+ end
99
+
100
+ # A complex type that uses the above schema, giving us the ability to define
101
+ # an attribute using this complex type, with therefore the *nested* attribute
102
+ # "familyName" being never returned.
103
+ #
104
+ NestedReturnedNeverTestNameType = Class.new(Scimitar::ComplexTypes::Base) do
105
+ set_schema NestedReturnedNeverTestNameSchema
106
+ end
107
+
108
+ # A test schema that uses the above type, the standard name type (but that
109
+ # *entire* top-level attribute is never returned) and a simple String item.
110
+ #
111
+ NestedReturnedNeverTestSchema = Class.new(Scimitar::Schema::Base) do
112
+ def self.id
113
+ 'nested-returned-never-id'
114
+ end
115
+
116
+ def self.scim_attributes
117
+ [
118
+ Scimitar::Schema::Attribute.new(
119
+ name: 'name', complexType: NestedReturnedNeverTestNameType
120
+ ),
121
+ Scimitar::Schema::Attribute.new(
122
+ name: 'privateName', complexType: Scimitar::ComplexTypes::Name, returned: 'never'
123
+ ),
124
+ Scimitar::Schema::Attribute.new(
125
+ name: 'simpleName', type: 'string'
126
+ )
127
+ ]
128
+ end
129
+ end
130
+
131
+ # Define a resource that is based upon the above schema.
132
+ #
133
+ NestedReturnedNeverTestResourse = Class.new(Scimitar::Resources::Base) do
134
+ set_schema NestedReturnedNeverTestSchema
135
+ end
136
+
137
+ # Create a testable model that is our internal representation of the above
138
+ # resource.
139
+ #
140
+ class NestedReturnedNeverTest
141
+ include ActiveModel::Model
142
+
143
+ def self.scim_resource_type
144
+ return NestedReturnedNeverTestResourse
145
+ end
146
+
147
+ attr_accessor :given_name,
148
+ :last_name,
149
+ :private_given_name,
150
+ :private_last_name,
151
+ :simple_name
152
+
153
+ def self.scim_attributes_map
154
+ return {
155
+ name: {
156
+ givenName: :given_name,
157
+ familyName: :last_name
158
+ },
159
+
160
+ privateName: {
161
+ givenName: :private_given_name,
162
+ familyName: :private_last_name
163
+ },
164
+
165
+ simpleName: :simple_name
166
+ }
167
+ end
168
+
169
+ def self.scim_mutable_attributes
170
+ return nil
171
+ end
172
+
173
+ def self.scim_queryable_attributes
174
+ return nil
175
+ end
176
+
177
+ include Scimitar::Resources::Mixin
178
+ end
179
+
84
180
  # ===========================================================================
85
181
  # Errant class definitions
86
182
  # ===========================================================================
@@ -362,6 +458,30 @@ RSpec.describe Scimitar::Resources::Mixin do
362
458
  end # "context 'using dynamic lists' do"
363
459
  end # "context 'with arrays' do"
364
460
 
461
+ context 'with "returned: \'never\' fields' do
462
+ it 'hides appropriate top-level and nested attributes' do
463
+ instance = NestedReturnedNeverTest.new(
464
+ given_name: 'One',
465
+ last_name: 'Two',
466
+ private_given_name: 'Three',
467
+ private_last_name: 'Four',
468
+ simple_name: 'Five'
469
+ )
470
+
471
+ scim = instance.to_scim(location: 'https://test.com/never_retutrned_test')
472
+ json = scim.to_json()
473
+ hash = JSON.parse(json)
474
+
475
+ expect(hash).to eql({
476
+ 'name' => { 'givenName' => 'One' },
477
+ 'simpleName' => 'Five',
478
+
479
+ 'meta' => {'location'=>'https://test.com/never_retutrned_test', 'resourceType'=>'NestedReturnedNeverTestResourse'},
480
+ 'schemas' => ['nested-returned-never-id']
481
+ })
482
+ end
483
+ end # "context 'with "returned: \'never\' fields' do"
484
+
365
485
  context 'with bad definitions' do
366
486
  it 'complains about non-Hash entries in mapping Arrays' do
367
487
  expect(StaticMapTest).to receive(:scim_attributes_map).and_return({
@@ -702,7 +822,8 @@ RSpec.describe Scimitar::Resources::Mixin do
702
822
  nature: 'add',
703
823
  path: path,
704
824
  value: 'foo',
705
- altering_hash: scim_hash
825
+ altering_hash: scim_hash,
826
+ with_attr_map: { userName: :user_name }
706
827
  )
707
828
 
708
829
  expect(scim_hash['userName']).to eql('foo')
@@ -717,7 +838,8 @@ RSpec.describe Scimitar::Resources::Mixin do
717
838
  nature: 'add',
718
839
  path: path,
719
840
  value: 'Baz',
720
- altering_hash: scim_hash
841
+ altering_hash: scim_hash,
842
+ with_attr_map: { name: { givenName: :first_name, familyName: :last_name } }
721
843
  )
722
844
 
723
845
  expect(scim_hash['name']['givenName' ]).to eql('Baz')
@@ -733,7 +855,8 @@ RSpec.describe Scimitar::Resources::Mixin do
733
855
  nature: 'add',
734
856
  path: path,
735
857
  value: 'OTHERORG',
736
- altering_hash: scim_hash
858
+ altering_hash: scim_hash,
859
+ with_attr_map: { organization: :org_name }
737
860
  )
738
861
 
739
862
  expect(scim_hash['urn:ietf:params:scim:schemas:extension:enterprise:2.0:User']['organization' ]).to eql('OTHERORG')
@@ -763,7 +886,13 @@ RSpec.describe Scimitar::Resources::Mixin do
763
886
  nature: 'add',
764
887
  path: path,
765
888
  value: 'added_over_original@test.com',
766
- altering_hash: scim_hash
889
+ altering_hash: scim_hash,
890
+ with_attr_map: {
891
+ emails: [
892
+ { match: 'type', with: 'home', using: { value: :home_email, primary: true } },
893
+ { match: 'type', with: 'work', using: { value: :work_email } },
894
+ ]
895
+ }
767
896
  )
768
897
 
769
898
  expect(scim_hash['emails'][0]['value']).to eql('home@test.com')
@@ -789,7 +918,13 @@ RSpec.describe Scimitar::Resources::Mixin do
789
918
  nature: 'add',
790
919
  path: path,
791
920
  value: 'added_over_original@test.com',
792
- altering_hash: scim_hash
921
+ altering_hash: scim_hash,
922
+ with_attr_map: {
923
+ emails: [
924
+ { match: 'type', with: 'home', using: { value: :home_email, primary: true } },
925
+ { match: 'type', with: 'work', using: { value: :work_email } },
926
+ ]
927
+ }
793
928
  )
794
929
 
795
930
  expect(scim_hash['emails'][0]['value']).to eql('home@test.com')
@@ -816,7 +951,13 @@ RSpec.describe Scimitar::Resources::Mixin do
816
951
  nature: 'add',
817
952
  path: path,
818
953
  value: 'added_over_original@test.com',
819
- altering_hash: scim_hash
954
+ altering_hash: scim_hash,
955
+ with_attr_map: {
956
+ emails: [
957
+ { match: 'type', with: 'home', using: { value: :home_email, primary: true } },
958
+ { match: 'type', with: 'work', using: { value: :work_email } },
959
+ ]
960
+ }
820
961
  )
821
962
 
822
963
  expect(scim_hash['emails'][0]['value']).to eql('added_over_original@test.com')
@@ -840,7 +981,13 @@ RSpec.describe Scimitar::Resources::Mixin do
840
981
  nature: 'add',
841
982
  path: path,
842
983
  value: [ { 'type' => 'work', 'value' => 'work@test.com' } ], # NOTE - to-add value is an Array (and must be)
843
- altering_hash: scim_hash
984
+ altering_hash: scim_hash,
985
+ with_attr_map: {
986
+ emails: [
987
+ { match: 'type', with: 'home', using: { value: :home_email, primary: true } },
988
+ { match: 'type', with: 'work', using: { value: :work_email } },
989
+ ]
990
+ }
844
991
  )
845
992
 
846
993
  expect(scim_hash['emails'].size).to eql(2)
@@ -888,7 +1035,12 @@ RSpec.describe Scimitar::Resources::Mixin do
888
1035
  nature: 'add',
889
1036
  path: ['root'],
890
1037
  value: {'members' => [{'value' => '3'}]},
891
- altering_hash: scim_hash
1038
+ altering_hash: scim_hash,
1039
+ with_attr_map: {
1040
+ members: [
1041
+ { list: :members, using: { value: :id } }
1042
+ ]
1043
+ }
892
1044
  )
893
1045
 
894
1046
  expect(scim_hash['root']['members']).to match_array([{'value' => '1'}, {'value' => '2'}, {'value' => '3'}])
@@ -906,7 +1058,8 @@ RSpec.describe Scimitar::Resources::Mixin do
906
1058
  nature: 'add',
907
1059
  path: path,
908
1060
  value: 'foo',
909
- altering_hash: scim_hash
1061
+ altering_hash: scim_hash,
1062
+ with_attr_map: { userName: :user_name }
910
1063
  )
911
1064
 
912
1065
  expect(scim_hash['userName']).to eql('foo')
@@ -921,7 +1074,8 @@ RSpec.describe Scimitar::Resources::Mixin do
921
1074
  nature: 'add',
922
1075
  path: path,
923
1076
  value: 'Baz',
924
- altering_hash: scim_hash
1077
+ altering_hash: scim_hash,
1078
+ with_attr_map: { name: { givenName: :first_name, familyName: :last_name } }
925
1079
  )
926
1080
 
927
1081
  expect(scim_hash['name']['givenName']).to eql('Baz')
@@ -936,7 +1090,8 @@ RSpec.describe Scimitar::Resources::Mixin do
936
1090
  nature: 'add',
937
1091
  path: path,
938
1092
  value: 'SOMEORG',
939
- altering_hash: scim_hash
1093
+ altering_hash: scim_hash,
1094
+ with_attr_map: { organization: :org_name }
940
1095
  )
941
1096
 
942
1097
  expect(scim_hash['urn:ietf:params:scim:schemas:extension:enterprise:2.0:User']['organization' ]).to eql('SOMEORG')
@@ -962,7 +1117,13 @@ RSpec.describe Scimitar::Resources::Mixin do
962
1117
  nature: 'add',
963
1118
  path: path,
964
1119
  value: 'added@test.com',
965
- altering_hash: scim_hash
1120
+ altering_hash: scim_hash,
1121
+ with_attr_map: {
1122
+ emails: [
1123
+ { match: 'type', with: 'home', using: { value: :home_email, primary: true } },
1124
+ { match: 'type', with: 'work', using: { value: :work_email } },
1125
+ ]
1126
+ }
966
1127
  )
967
1128
 
968
1129
  expect(scim_hash['emails'][0]['value']).to eql('home@test.com')
@@ -987,7 +1148,13 @@ RSpec.describe Scimitar::Resources::Mixin do
987
1148
  nature: 'add',
988
1149
  path: path,
989
1150
  value: 'added@test.com',
990
- altering_hash: scim_hash
1151
+ altering_hash: scim_hash,
1152
+ with_attr_map: {
1153
+ emails: [
1154
+ { match: 'type', with: 'home', using: { value: :home_email, primary: true } },
1155
+ { match: 'type', with: 'work', using: { value: :work_email } },
1156
+ ]
1157
+ }
991
1158
  )
992
1159
 
993
1160
  expect(scim_hash['emails'][0]['value']).to eql('home@test.com')
@@ -1003,7 +1170,13 @@ RSpec.describe Scimitar::Resources::Mixin do
1003
1170
  nature: 'add',
1004
1171
  path: path,
1005
1172
  value: 'added@test.com',
1006
- altering_hash: scim_hash
1173
+ altering_hash: scim_hash,
1174
+ with_attr_map: {
1175
+ emails: [
1176
+ { match: 'type', with: 'home', using: { value: :home_email, primary: true } },
1177
+ { match: 'type', with: 'work', using: { value: :work_email } },
1178
+ ]
1179
+ }
1007
1180
  )
1008
1181
 
1009
1182
  expect(scim_hash['emails'][0]['value']).to eql('added@test.com')
@@ -1027,7 +1200,13 @@ RSpec.describe Scimitar::Resources::Mixin do
1027
1200
  nature: 'add',
1028
1201
  path: path,
1029
1202
  value: 'added@test.com',
1030
- altering_hash: scim_hash
1203
+ altering_hash: scim_hash,
1204
+ with_attr_map: {
1205
+ emails: [
1206
+ { match: 'type', with: 'home', using: { value: :home_email, primary: true } },
1207
+ { match: 'type', with: 'work', using: { value: :work_email } },
1208
+ ]
1209
+ }
1031
1210
  )
1032
1211
 
1033
1212
  expect(scim_hash['emails'][0]['value']).to eql('added@test.com')
@@ -1044,7 +1223,13 @@ RSpec.describe Scimitar::Resources::Mixin do
1044
1223
  nature: 'add',
1045
1224
  path: path,
1046
1225
  value: [ { 'type' => 'work', 'value' => 'work@test.com' } ], # NOTE - to-add value is an Array (and must be)
1047
- altering_hash: scim_hash
1226
+ altering_hash: scim_hash,
1227
+ with_attr_map: {
1228
+ emails: [
1229
+ { match: 'type', with: 'home', using: { value: :home_email, primary: true } },
1230
+ { match: 'type', with: 'work', using: { value: :work_email } },
1231
+ ]
1232
+ }
1048
1233
  )
1049
1234
 
1050
1235
  expect(scim_hash['emails'].size).to eql(1)
@@ -1060,7 +1245,7 @@ RSpec.describe Scimitar::Resources::Mixin do
1060
1245
  #
1061
1246
  context 'remove' do
1062
1247
  context 'when prior value already exists' do
1063
- it 'simple value: removes' do
1248
+ it 'simple value: clears to "nil" in order to remove' do
1064
1249
  path = [ 'userName' ]
1065
1250
  scim_hash = { 'userName' => 'bar' }.with_indifferent_case_insensitive_access()
1066
1251
 
@@ -1069,13 +1254,14 @@ RSpec.describe Scimitar::Resources::Mixin do
1069
1254
  nature: 'remove',
1070
1255
  path: path,
1071
1256
  value: nil,
1072
- altering_hash: scim_hash
1257
+ altering_hash: scim_hash,
1258
+ with_attr_map: { userName: :user_name }
1073
1259
  )
1074
1260
 
1075
- expect(scim_hash).to be_empty
1261
+ expect(scim_hash).to eql({ 'userName' => nil })
1076
1262
  end
1077
1263
 
1078
- it 'nested simple value: removes' do
1264
+ it 'nested simple value: clears to "nil" in order to remove' do
1079
1265
  path = [ 'name', 'givenName' ]
1080
1266
  scim_hash = { 'name' => { 'givenName' => 'Foo', 'familyName' => 'Bar' } }.with_indifferent_case_insensitive_access()
1081
1267
 
@@ -1084,15 +1270,15 @@ RSpec.describe Scimitar::Resources::Mixin do
1084
1270
  nature: 'remove',
1085
1271
  path: path,
1086
1272
  value: nil,
1087
- altering_hash: scim_hash
1273
+ altering_hash: scim_hash,
1274
+ with_attr_map: { name: { givenName: :first_name, familyName: :last_name } }
1088
1275
  )
1089
1276
 
1090
- expect(scim_hash['name']).to_not have_key('givenName')
1091
- expect(scim_hash['name']['familyName']).to eql('Bar')
1277
+ expect(scim_hash).to eql({ 'name' => { 'givenName' => nil, 'familyName' => 'Bar' } })
1092
1278
  end
1093
1279
 
1094
1280
  context 'with filter mid-path' do
1095
- it 'by string match: removes' do
1281
+ it 'by string match: clears to "nil" in order to remove' do
1096
1282
  path = [ 'emails[type eq "work"]', 'value' ]
1097
1283
  scim_hash = {
1098
1284
  'emails' => [
@@ -1112,14 +1298,30 @@ RSpec.describe Scimitar::Resources::Mixin do
1112
1298
  nature: 'remove',
1113
1299
  path: path,
1114
1300
  value: nil,
1115
- altering_hash: scim_hash
1301
+ altering_hash: scim_hash,
1302
+ with_attr_map: {
1303
+ emails: [
1304
+ { match: 'type', with: 'home', using: { value: :home_email, primary: true } },
1305
+ { match: 'type', with: 'work', using: { value: :work_email } },
1306
+ ]
1307
+ }
1116
1308
  )
1117
1309
 
1118
- expect(scim_hash['emails'][0]['value']).to eql('home@test.com')
1119
- expect(scim_hash['emails'][1]).to_not have_key('value')
1310
+ expect(scim_hash).to eql({
1311
+ 'emails' => [
1312
+ {
1313
+ 'type' => 'home',
1314
+ 'value' => 'home@test.com'
1315
+ },
1316
+ {
1317
+ 'type' => 'work',
1318
+ 'value' => nil
1319
+ }
1320
+ ]
1321
+ })
1120
1322
  end
1121
1323
 
1122
- it 'by boolean match: removes' do
1324
+ it 'by boolean match: clears to "nil" in order to remove' do
1123
1325
  path = [ 'emails[primary eq true]', 'value' ]
1124
1326
  scim_hash = {
1125
1327
  'emails' => [
@@ -1138,14 +1340,29 @@ RSpec.describe Scimitar::Resources::Mixin do
1138
1340
  nature: 'remove',
1139
1341
  path: path,
1140
1342
  value: nil,
1141
- altering_hash: scim_hash
1343
+ altering_hash: scim_hash,
1344
+ with_attr_map: {
1345
+ emails: [
1346
+ { match: 'type', with: 'home', using: { value: :home_email, primary: true } },
1347
+ { match: 'type', with: 'work', using: { value: :work_email } },
1348
+ ]
1349
+ }
1142
1350
  )
1143
1351
 
1144
- expect(scim_hash['emails'][0]['value']).to eql('home@test.com')
1145
- expect(scim_hash['emails'][1]).to_not have_key('value')
1352
+ expect(scim_hash).to eql({
1353
+ 'emails' => [
1354
+ {
1355
+ 'value' => 'home@test.com'
1356
+ },
1357
+ {
1358
+ 'value' => nil,
1359
+ 'primary' => true
1360
+ }
1361
+ ]
1362
+ })
1146
1363
  end
1147
1364
 
1148
- it 'multiple matches: removes all' do
1365
+ it 'multiple matches: clears all to "nil" in order to remove' do
1149
1366
  path = [ 'emails[type eq "work"]', 'value' ]
1150
1367
  scim_hash = {
1151
1368
  'emails' => [
@@ -1156,7 +1373,11 @@ RSpec.describe Scimitar::Resources::Mixin do
1156
1373
  {
1157
1374
  'type' => 'work',
1158
1375
  'value' => 'work_2@test.com'
1159
- }
1376
+ },
1377
+ {
1378
+ 'type' => 'home',
1379
+ 'value' => 'home@test.com'
1380
+ },
1160
1381
  ]
1161
1382
  }.with_indifferent_case_insensitive_access()
1162
1383
 
@@ -1165,16 +1386,36 @@ RSpec.describe Scimitar::Resources::Mixin do
1165
1386
  nature: 'remove',
1166
1387
  path: path,
1167
1388
  value: nil,
1168
- altering_hash: scim_hash
1389
+ altering_hash: scim_hash,
1390
+ with_attr_map: {
1391
+ emails: [
1392
+ { match: 'type', with: 'home', using: { value: :home_email, primary: true } },
1393
+ { match: 'type', with: 'work', using: { value: :work_email } },
1394
+ ]
1395
+ }
1169
1396
  )
1170
1397
 
1171
- expect(scim_hash['emails'][0]).to_not have_key('value')
1172
- expect(scim_hash['emails'][1]).to_not have_key('value')
1398
+ expect(scim_hash).to eql({
1399
+ 'emails' => [
1400
+ {
1401
+ 'type' => 'work',
1402
+ 'value' => nil
1403
+ },
1404
+ {
1405
+ 'type' => 'work',
1406
+ 'value' => nil
1407
+ },
1408
+ {
1409
+ 'type' => 'home',
1410
+ 'value' => 'home@test.com'
1411
+ },
1412
+ ]
1413
+ })
1173
1414
  end
1174
1415
  end # "context 'with filter mid-path' do"
1175
1416
 
1176
1417
  context 'with filter at end of path' do
1177
- it 'by string match: removes entire matching array entry' do
1418
+ it 'by string match: clears to "nil" in order to remove' do
1178
1419
  path = [ 'emails[type eq "work"]' ]
1179
1420
  scim_hash = {
1180
1421
  'emails' => [
@@ -1194,23 +1435,39 @@ RSpec.describe Scimitar::Resources::Mixin do
1194
1435
  nature: 'remove',
1195
1436
  path: path,
1196
1437
  value: nil,
1197
- altering_hash: scim_hash
1438
+ altering_hash: scim_hash,
1439
+ with_attr_map: {
1440
+ emails: [
1441
+ { match: 'type', with: 'home', using: { value: :home_email, primary: true } },
1442
+ { match: 'type', with: 'work', using: { value: :work_email } },
1443
+ ]
1444
+ }
1198
1445
  )
1199
1446
 
1200
- expect(scim_hash['emails'].size).to eql(1)
1201
- expect(scim_hash['emails'][0]['value']).to eql('home@test.com')
1447
+ expect(scim_hash).to eql({
1448
+ 'emails' => [
1449
+ {
1450
+ 'type' => 'home',
1451
+ 'value' => 'home@test.com'
1452
+ },
1453
+ {
1454
+ 'type' => 'work',
1455
+ 'value' => nil
1456
+ }
1457
+ ]
1458
+ })
1202
1459
  end
1203
1460
 
1204
- it 'by boolean match: removes entire matching array entry' do
1461
+ it 'by boolean match: clears to "nil" in order to remove' do
1205
1462
  path = [ 'emails[primary eq true]' ]
1206
1463
  scim_hash = {
1207
1464
  'emails' => [
1208
1465
  {
1209
- 'value' => 'home@test.com'
1466
+ 'value' => 'home@test.com',
1467
+ 'primary' => true
1210
1468
  },
1211
1469
  {
1212
- 'value' => 'work@test.com',
1213
- 'primary' => true
1470
+ 'value' => 'work@test.com'
1214
1471
  }
1215
1472
  ]
1216
1473
  }.with_indifferent_case_insensitive_access()
@@ -1220,14 +1477,29 @@ RSpec.describe Scimitar::Resources::Mixin do
1220
1477
  nature: 'remove',
1221
1478
  path: path,
1222
1479
  value: nil,
1223
- altering_hash: scim_hash
1480
+ altering_hash: scim_hash,
1481
+ with_attr_map: {
1482
+ emails: [
1483
+ { match: 'type', with: 'home', using: { value: :home_email, primary: true } },
1484
+ { match: 'type', with: 'work', using: { value: :work_email } },
1485
+ ]
1486
+ }
1224
1487
  )
1225
1488
 
1226
- expect(scim_hash['emails'].size).to eql(1)
1227
- expect(scim_hash['emails'][0]['value']).to eql('home@test.com')
1489
+ expect(scim_hash).to eql({
1490
+ 'emails' => [
1491
+ {
1492
+ 'value' => nil,
1493
+ 'primary' => true
1494
+ },
1495
+ {
1496
+ 'value' => 'work@test.com'
1497
+ }
1498
+ ]
1499
+ })
1228
1500
  end
1229
1501
 
1230
- it 'multiple matches: removes all matching array entries' do
1502
+ it 'multiple matches: clears all to "nil" in order to remove' do
1231
1503
  path = [ 'emails[type eq "work"]' ]
1232
1504
  scim_hash = {
1233
1505
  'emails' => [
@@ -1251,21 +1523,45 @@ RSpec.describe Scimitar::Resources::Mixin do
1251
1523
  nature: 'remove',
1252
1524
  path: path,
1253
1525
  value: nil,
1254
- altering_hash: scim_hash
1526
+ altering_hash: scim_hash,
1527
+ with_attr_map: {
1528
+ emails: [
1529
+ { match: 'type', with: 'home', using: { value: :home_email, primary: true } },
1530
+ { match: 'type', with: 'work', using: { value: :work_email } },
1531
+ ]
1532
+ }
1255
1533
  )
1256
1534
 
1257
- expect(scim_hash['emails'].size).to eql(1)
1258
- expect(scim_hash['emails'][0]['value']).to eql('home@test.com')
1535
+ expect(scim_hash).to eql({
1536
+ 'emails' => [
1537
+ {
1538
+ 'type' => 'work',
1539
+ 'value' => nil
1540
+ },
1541
+ {
1542
+ 'type' => 'work',
1543
+ 'value' => nil
1544
+ },
1545
+ {
1546
+ 'type' => 'home',
1547
+ 'value' => 'home@test.com'
1548
+ },
1549
+ ]
1550
+ })
1259
1551
  end
1260
1552
  end # "context 'with filter at end of path' do"
1261
1553
 
1262
- it 'whole array: removes' do
1554
+ it 'whole array: clears mapped values to "nil" to remove them' do
1263
1555
  path = [ 'emails' ]
1264
1556
  scim_hash = {
1265
1557
  'emails' => [
1266
1558
  {
1267
1559
  'type' => 'home',
1268
1560
  'value' => 'home@test.com'
1561
+ },
1562
+ {
1563
+ 'type' => 'work',
1564
+ 'value' => 'work@test.com'
1269
1565
  }
1270
1566
  ]
1271
1567
  }.with_indifferent_case_insensitive_access()
@@ -1275,10 +1571,27 @@ RSpec.describe Scimitar::Resources::Mixin do
1275
1571
  nature: 'remove',
1276
1572
  path: path,
1277
1573
  value: nil,
1278
- altering_hash: scim_hash
1574
+ altering_hash: scim_hash,
1575
+ with_attr_map: {
1576
+ emails: [
1577
+ { match: 'type', with: 'home', using: { value: :home_email, primary: true } },
1578
+ { match: 'type', with: 'work', using: { value: :work_email } },
1579
+ ]
1580
+ }
1279
1581
  )
1280
1582
 
1281
- expect(scim_hash).to_not have_key('emails')
1583
+ expect(scim_hash).to eql({
1584
+ 'emails' => [
1585
+ {
1586
+ 'type' => 'home',
1587
+ 'value' => nil
1588
+ },
1589
+ {
1590
+ 'type' => 'work',
1591
+ 'value' => nil
1592
+ }
1593
+ ]
1594
+ })
1282
1595
  end
1283
1596
 
1284
1597
  # What we expect:
@@ -1324,7 +1637,12 @@ RSpec.describe Scimitar::Resources::Mixin do
1324
1637
  nature: 'remove',
1325
1638
  path: path,
1326
1639
  value: value,
1327
- altering_hash: scim_hash
1640
+ altering_hash: scim_hash,
1641
+ with_attr_map: {
1642
+ members: [
1643
+ { list: :members, using: { value: :id, display: :full_name, type: 'User' } }
1644
+ ]
1645
+ }
1328
1646
  )
1329
1647
 
1330
1648
  expect(scim_hash).to eql({
@@ -1376,7 +1694,12 @@ RSpec.describe Scimitar::Resources::Mixin do
1376
1694
  nature: 'remove',
1377
1695
  path: path,
1378
1696
  value: value,
1379
- altering_hash: scim_hash
1697
+ altering_hash: scim_hash,
1698
+ with_attr_map: {
1699
+ members: [
1700
+ { list: :members, using: { value: :id, display: :full_name, type: 'User' } }
1701
+ ]
1702
+ }
1380
1703
  )
1381
1704
 
1382
1705
  expect(scim_hash).to eql({
@@ -1410,7 +1733,12 @@ RSpec.describe Scimitar::Resources::Mixin do
1410
1733
  nature: 'remove',
1411
1734
  path: path,
1412
1735
  value: value,
1413
- altering_hash: scim_hash
1736
+ altering_hash: scim_hash,
1737
+ with_attr_map: {
1738
+ members: [
1739
+ { list: :members, using: { value: :id, display: :full_name, type: 'User' } }
1740
+ ]
1741
+ }
1414
1742
  )
1415
1743
 
1416
1744
  expect(scim_hash).to eql({
@@ -1438,7 +1766,12 @@ RSpec.describe Scimitar::Resources::Mixin do
1438
1766
  nature: 'remove',
1439
1767
  path: path,
1440
1768
  value: value,
1441
- altering_hash: scim_hash
1769
+ altering_hash: scim_hash,
1770
+ with_attr_map: {
1771
+ members: [
1772
+ { list: :members, using: { value: :id, display: :full_name, type: 'User' } }
1773
+ ]
1774
+ }
1442
1775
  )
1443
1776
 
1444
1777
  expect(scim_hash).to eql({
@@ -1466,7 +1799,12 @@ RSpec.describe Scimitar::Resources::Mixin do
1466
1799
  nature: 'remove',
1467
1800
  path: path,
1468
1801
  value: value,
1469
- altering_hash: scim_hash
1802
+ altering_hash: scim_hash,
1803
+ with_attr_map: {
1804
+ members: [
1805
+ { list: :members, using: { value: :id, display: :full_name, type: 'User' } }
1806
+ ]
1807
+ }
1470
1808
  )
1471
1809
 
1472
1810
  # The 'value' mismatched, so the user was not removed.
@@ -1502,7 +1840,12 @@ RSpec.describe Scimitar::Resources::Mixin do
1502
1840
  nature: 'remove',
1503
1841
  path: path,
1504
1842
  value: value,
1505
- altering_hash: scim_hash
1843
+ altering_hash: scim_hash,
1844
+ with_attr_map: {
1845
+ members: [
1846
+ { list: :members, using: { value: :id, display: :full_name, type: 'User' } }
1847
+ ]
1848
+ }
1506
1849
  )
1507
1850
 
1508
1851
  # Type 'Group' mismatches 'User', so the user was not
@@ -1520,7 +1863,7 @@ RSpec.describe Scimitar::Resources::Mixin do
1520
1863
  })
1521
1864
  end
1522
1865
 
1523
- it 'matches keys case-insensitive' do
1866
+ it 'matches keys case-insensitive (but preserves case in response)' do
1524
1867
  path = [ 'members' ]
1525
1868
  value = [ { '$ref' => nil, 'VALUe' => 'f648f8d5ea4e4cd38e9c' } ]
1526
1869
  scim_hash = {
@@ -1539,12 +1882,17 @@ RSpec.describe Scimitar::Resources::Mixin do
1539
1882
  nature: 'remove',
1540
1883
  path: path,
1541
1884
  value: value,
1542
- altering_hash: scim_hash
1885
+ altering_hash: scim_hash,
1886
+ with_attr_map: {
1887
+ members: [
1888
+ { list: :members, using: { value: :id, display: :full_name, type: 'User' } }
1889
+ ]
1890
+ }
1543
1891
  )
1544
1892
 
1545
1893
  expect(scim_hash).to eql({
1546
1894
  'displayname' => 'Mock group',
1547
- 'members' => []
1895
+ 'memBERS' => []
1548
1896
  })
1549
1897
  end
1550
1898
 
@@ -1552,7 +1900,7 @@ RSpec.describe Scimitar::Resources::Mixin do
1552
1900
  path = [ 'members' ]
1553
1901
  value = [ { '$ref' => nil, 'value' => 'f648f8d5ea4e4cd38e9c', 'type' => 'USER' } ]
1554
1902
  scim_hash = {
1555
- 'displayname' => 'Mock group',
1903
+ 'displayName' => 'Mock group',
1556
1904
  'members' => [
1557
1905
  {
1558
1906
  'value' => 'f648f8d5ea4e4cd38e9c',
@@ -1567,13 +1915,18 @@ RSpec.describe Scimitar::Resources::Mixin do
1567
1915
  nature: 'remove',
1568
1916
  path: path,
1569
1917
  value: value,
1570
- altering_hash: scim_hash
1918
+ altering_hash: scim_hash,
1919
+ with_attr_map: {
1920
+ members: [
1921
+ { list: :members, using: { value: :id, display: :full_name, type: 'User' } }
1922
+ ]
1923
+ }
1571
1924
  )
1572
1925
 
1573
- # USER mismatchs User, so the user was not removed.
1926
+ # USER mismatches User, so the user was not removed.
1574
1927
  #
1575
1928
  expect(scim_hash).to eql({
1576
- 'displayname' => 'Mock group',
1929
+ 'displayName' => 'Mock group',
1577
1930
  'members' => [
1578
1931
  {
1579
1932
  'value' => 'f648f8d5ea4e4cd38e9c',
@@ -1586,7 +1939,7 @@ RSpec.describe Scimitar::Resources::Mixin do
1586
1939
  end # "context 'removing a user from a group' do"
1587
1940
 
1588
1941
  context 'generic use' do
1589
- it 'removes matched items' do
1942
+ it 'clears static map matched items to "nil" in order to remove' do
1590
1943
  path = [ 'emails' ]
1591
1944
  value = [ { 'type' => 'work' } ]
1592
1945
  scim_hash = {
@@ -1607,7 +1960,13 @@ RSpec.describe Scimitar::Resources::Mixin do
1607
1960
  nature: 'remove',
1608
1961
  path: path,
1609
1962
  value: value,
1610
- altering_hash: scim_hash
1963
+ altering_hash: scim_hash,
1964
+ with_attr_map: {
1965
+ emails: [
1966
+ { match: 'type', with: 'home', using: { value: :home_email, primary: true } },
1967
+ { match: 'type', with: 'work', using: { value: :work_email } },
1968
+ ]
1969
+ }
1611
1970
  )
1612
1971
 
1613
1972
  expect(scim_hash).to eql({
@@ -1615,6 +1974,10 @@ RSpec.describe Scimitar::Resources::Mixin do
1615
1974
  {
1616
1975
  'type' => 'home',
1617
1976
  'value' => 'home@test.com'
1977
+ },
1978
+ {
1979
+ 'type' => 'work',
1980
+ 'value' => nil
1618
1981
  }
1619
1982
  ]
1620
1983
  })
@@ -1641,7 +2004,13 @@ RSpec.describe Scimitar::Resources::Mixin do
1641
2004
  nature: 'remove',
1642
2005
  path: path,
1643
2006
  value: value,
1644
- altering_hash: scim_hash
2007
+ altering_hash: scim_hash,
2008
+ with_attr_map: {
2009
+ emails: [
2010
+ { match: 'type', with: 'home', using: { value: :home_email, primary: true } },
2011
+ { match: 'type', with: 'work', using: { value: :work_email } },
2012
+ ]
2013
+ }
1645
2014
  )
1646
2015
 
1647
2016
  expect(scim_hash).to eql({
@@ -1673,6 +2042,10 @@ RSpec.describe Scimitar::Resources::Mixin do
1673
2042
  {
1674
2043
  'active' => false,
1675
2044
  'value' => '42'
2045
+ },
2046
+ {
2047
+ 'active' => 'hello',
2048
+ 'value' => 'world'
1676
2049
  }
1677
2050
  ]
1678
2051
  }.with_indifferent_case_insensitive_access()
@@ -1682,10 +2055,28 @@ RSpec.describe Scimitar::Resources::Mixin do
1682
2055
  nature: 'remove',
1683
2056
  path: path,
1684
2057
  value: value,
1685
- altering_hash: scim_hash
2058
+ altering_hash: scim_hash,
2059
+ with_attr_map: {
2060
+ test: [
2061
+ {
2062
+ list: :test,
2063
+ using: {
2064
+ active: :active,
2065
+ value: :value
2066
+ }
2067
+ }
2068
+ ]
2069
+ }
1686
2070
  )
1687
2071
 
1688
- expect(scim_hash).to eql({'test' => []})
2072
+ expect(scim_hash).to eql({
2073
+ 'test' => [
2074
+ {
2075
+ 'active' => 'hello',
2076
+ 'value' => 'world'
2077
+ }
2078
+ ]
2079
+ })
1689
2080
  end
1690
2081
 
1691
2082
  it 'handles a singular to-remove value rather than an array' do
@@ -1709,7 +2100,13 @@ RSpec.describe Scimitar::Resources::Mixin do
1709
2100
  nature: 'remove',
1710
2101
  path: path,
1711
2102
  value: value,
1712
- altering_hash: scim_hash
2103
+ altering_hash: scim_hash,
2104
+ with_attr_map: {
2105
+ emails: [
2106
+ { match: 'type', with: 'home', using: { value: :home_email } },
2107
+ { match: 'type', with: 'work', using: { value: :work_email } },
2108
+ ]
2109
+ }
1713
2110
  )
1714
2111
 
1715
2112
  expect(scim_hash).to eql({
@@ -1717,6 +2114,10 @@ RSpec.describe Scimitar::Resources::Mixin do
1717
2114
  {
1718
2115
  'type' => 'home',
1719
2116
  'value' => 'home@test.com'
2117
+ },
2118
+ {
2119
+ 'type' => 'work',
2120
+ 'value' => nil
1720
2121
  }
1721
2122
  ]
1722
2123
  })
@@ -1738,7 +2139,10 @@ RSpec.describe Scimitar::Resources::Mixin do
1738
2139
  nature: 'remove',
1739
2140
  path: path,
1740
2141
  value: value,
1741
- altering_hash: scim_hash
2142
+ altering_hash: scim_hash,
2143
+ with_attr_map: {
2144
+ test: []
2145
+ }
1742
2146
  )
1743
2147
 
1744
2148
  expect(scim_hash).to eql({
@@ -1778,7 +2182,18 @@ RSpec.describe Scimitar::Resources::Mixin do
1778
2182
  nature: 'remove',
1779
2183
  path: path,
1780
2184
  value: value,
1781
- altering_hash: scim_hash
2185
+ altering_hash: scim_hash,
2186
+ with_attr_map: {
2187
+ displayName: :name,
2188
+ members: [
2189
+ list: :members,
2190
+ using: {
2191
+ value: :id,
2192
+ display: :full_name,
2193
+ type: 'User'
2194
+ }
2195
+ ]
2196
+ }
1782
2197
  )
1783
2198
 
1784
2199
  expect(scim_hash).to eql({
@@ -1817,7 +2232,18 @@ RSpec.describe Scimitar::Resources::Mixin do
1817
2232
  nature: 'remove',
1818
2233
  path: path,
1819
2234
  value: value,
1820
- altering_hash: scim_hash
2235
+ altering_hash: scim_hash,
2236
+ with_attr_map: {
2237
+ displayName: :name,
2238
+ members: [
2239
+ list: :members,
2240
+ using: {
2241
+ value: :id,
2242
+ display: :full_name,
2243
+ type: 'User'
2244
+ }
2245
+ ]
2246
+ }
1821
2247
  )
1822
2248
 
1823
2249
  expect(scim_hash).to eql({
@@ -1851,7 +2277,18 @@ RSpec.describe Scimitar::Resources::Mixin do
1851
2277
  nature: 'remove',
1852
2278
  path: path,
1853
2279
  value: value,
1854
- altering_hash: scim_hash
2280
+ altering_hash: scim_hash,
2281
+ with_attr_map: {
2282
+ displayName: :name,
2283
+ members: [
2284
+ list: :members,
2285
+ using: {
2286
+ value: :id,
2287
+ display: :full_name,
2288
+ type: 'User'
2289
+ }
2290
+ ]
2291
+ }
1855
2292
  )
1856
2293
 
1857
2294
  # The 'value' mismatched, so the user was not removed.
@@ -1881,7 +2318,8 @@ RSpec.describe Scimitar::Resources::Mixin do
1881
2318
  nature: 'remove',
1882
2319
  path: path,
1883
2320
  value: nil,
1884
- altering_hash: scim_hash
2321
+ altering_hash: scim_hash,
2322
+ with_attr_map: { userName: :user_name }
1885
2323
  )
1886
2324
 
1887
2325
  expect(scim_hash).to be_empty
@@ -1896,7 +2334,8 @@ RSpec.describe Scimitar::Resources::Mixin do
1896
2334
  nature: 'remove',
1897
2335
  path: path,
1898
2336
  value: nil,
1899
- altering_hash: scim_hash
2337
+ altering_hash: scim_hash,
2338
+ with_attr_map: { name: { givenName: :first_name, familyName: :last_name } }
1900
2339
  )
1901
2340
 
1902
2341
  expect(scim_hash['name']).to_not have_key('givenName')
@@ -1920,7 +2359,13 @@ RSpec.describe Scimitar::Resources::Mixin do
1920
2359
  nature: 'remove',
1921
2360
  path: path,
1922
2361
  value: nil,
1923
- altering_hash: scim_hash
2362
+ altering_hash: scim_hash,
2363
+ with_attr_map: {
2364
+ emails: [
2365
+ { match: 'type', with: 'home', using: { value: :home_email } },
2366
+ { match: 'type', with: 'work', using: { value: :work_email } },
2367
+ ]
2368
+ }
1924
2369
  )
1925
2370
 
1926
2371
  expect(scim_hash['emails'].size).to eql(1)
@@ -1942,7 +2387,13 @@ RSpec.describe Scimitar::Resources::Mixin do
1942
2387
  nature: 'remove',
1943
2388
  path: path,
1944
2389
  value: nil,
1945
- altering_hash: scim_hash
2390
+ altering_hash: scim_hash,
2391
+ with_attr_map: {
2392
+ emails: [
2393
+ { match: 'type', with: 'home', using: { value: :home_email } },
2394
+ { match: 'type', with: 'work', using: { value: :work_email } },
2395
+ ]
2396
+ }
1946
2397
  )
1947
2398
 
1948
2399
  expect(scim_hash['emails'].size).to eql(1)
@@ -1965,7 +2416,13 @@ RSpec.describe Scimitar::Resources::Mixin do
1965
2416
  nature: 'remove',
1966
2417
  path: path,
1967
2418
  value: nil,
1968
- altering_hash: scim_hash
2419
+ altering_hash: scim_hash,
2420
+ with_attr_map: {
2421
+ emails: [
2422
+ { match: 'type', with: 'home', using: { value: :home_email } },
2423
+ { match: 'type', with: 'work', using: { value: :work_email } },
2424
+ ]
2425
+ }
1969
2426
  )
1970
2427
 
1971
2428
  expect(scim_hash['emails'].size).to eql(1)
@@ -1983,7 +2440,13 @@ RSpec.describe Scimitar::Resources::Mixin do
1983
2440
  nature: 'remove',
1984
2441
  path: path,
1985
2442
  value: nil,
1986
- altering_hash: scim_hash
2443
+ altering_hash: scim_hash,
2444
+ with_attr_map: {
2445
+ emails: [
2446
+ { match: 'type', with: 'home', using: { value: :home_email } },
2447
+ { match: 'type', with: 'work', using: { value: :work_email } },
2448
+ ]
2449
+ }
1987
2450
  )
1988
2451
 
1989
2452
  expect(scim_hash).to be_empty
@@ -2005,7 +2468,13 @@ RSpec.describe Scimitar::Resources::Mixin do
2005
2468
  nature: 'remove',
2006
2469
  path: path,
2007
2470
  value: nil,
2008
- altering_hash: scim_hash
2471
+ altering_hash: scim_hash,
2472
+ with_attr_map: {
2473
+ emails: [
2474
+ { match: 'type', with: 'home', using: { value: :home_email } },
2475
+ { match: 'type', with: 'work', using: { value: :work_email } },
2476
+ ]
2477
+ }
2009
2478
  )
2010
2479
 
2011
2480
  expect(scim_hash['emails'].size).to eql(1)
@@ -2022,7 +2491,13 @@ RSpec.describe Scimitar::Resources::Mixin do
2022
2491
  nature: 'remove',
2023
2492
  path: path,
2024
2493
  value: nil,
2025
- altering_hash: scim_hash
2494
+ altering_hash: scim_hash,
2495
+ with_attr_map: {
2496
+ emails: [
2497
+ { match: 'type', with: 'home', using: { value: :home_email } },
2498
+ { match: 'type', with: 'work', using: { value: :work_email } },
2499
+ ]
2500
+ }
2026
2501
  )
2027
2502
 
2028
2503
  expect(scim_hash).to_not have_key('emails')
@@ -2048,7 +2523,8 @@ RSpec.describe Scimitar::Resources::Mixin do
2048
2523
  nature: 'replace',
2049
2524
  path: path,
2050
2525
  value: 'foo',
2051
- altering_hash: scim_hash
2526
+ altering_hash: scim_hash,
2527
+ with_attr_map: { userName: :user_name }
2052
2528
  )
2053
2529
 
2054
2530
  expect(scim_hash['userName']).to eql('foo')
@@ -2063,7 +2539,8 @@ RSpec.describe Scimitar::Resources::Mixin do
2063
2539
  nature: 'replace',
2064
2540
  path: path,
2065
2541
  value: 'Baz',
2066
- altering_hash: scim_hash
2542
+ altering_hash: scim_hash,
2543
+ with_attr_map: { name: { givenName: :first_name, familyName: :last_name } }
2067
2544
  )
2068
2545
 
2069
2546
  expect(scim_hash['name']['givenName' ]).to eql('Baz')
@@ -2091,7 +2568,13 @@ RSpec.describe Scimitar::Resources::Mixin do
2091
2568
  nature: 'replace',
2092
2569
  path: path,
2093
2570
  value: 'added_over_original@test.com',
2094
- altering_hash: scim_hash
2571
+ altering_hash: scim_hash,
2572
+ with_attr_map: {
2573
+ emails: [
2574
+ { match: 'type', with: 'home', using: { value: :home_email, primary: true } },
2575
+ { match: 'type', with: 'work', using: { value: :work_email } },
2576
+ ]
2577
+ }
2095
2578
  )
2096
2579
 
2097
2580
  expect(scim_hash['emails'][0]['value']).to eql('home@test.com')
@@ -2117,7 +2600,13 @@ RSpec.describe Scimitar::Resources::Mixin do
2117
2600
  nature: 'replace',
2118
2601
  path: path,
2119
2602
  value: 'added_over_original@test.com',
2120
- altering_hash: scim_hash
2603
+ altering_hash: scim_hash,
2604
+ with_attr_map: {
2605
+ emails: [
2606
+ { match: 'type', with: 'home', using: { value: :home_email, primary: true } },
2607
+ { match: 'type', with: 'work', using: { value: :work_email } },
2608
+ ]
2609
+ }
2121
2610
  )
2122
2611
 
2123
2612
  expect(scim_hash['emails'][0]['value']).to eql('home@test.com')
@@ -2144,7 +2633,13 @@ RSpec.describe Scimitar::Resources::Mixin do
2144
2633
  nature: 'replace',
2145
2634
  path: path,
2146
2635
  value: 'added_over_original@test.com',
2147
- altering_hash: scim_hash
2636
+ altering_hash: scim_hash,
2637
+ with_attr_map: {
2638
+ emails: [
2639
+ { match: 'type', with: 'home', using: { value: :home_email, primary: true } },
2640
+ { match: 'type', with: 'work', using: { value: :work_email } },
2641
+ ]
2642
+ }
2148
2643
  )
2149
2644
 
2150
2645
  expect(scim_hash['emails'][0]['value']).to eql('added_over_original@test.com')
@@ -2173,7 +2668,13 @@ RSpec.describe Scimitar::Resources::Mixin do
2173
2668
  nature: 'replace',
2174
2669
  path: path,
2175
2670
  value: {'type' => 'home', 'primary' => true, 'value' => 'home@test.com'},
2176
- altering_hash: scim_hash
2671
+ altering_hash: scim_hash,
2672
+ with_attr_map: {
2673
+ emails: [
2674
+ { match: 'type', with: 'home', using: { value: :home_email, primary: true } },
2675
+ { match: 'type', with: 'work', using: { value: :work_email } },
2676
+ ]
2677
+ }
2177
2678
  )
2178
2679
 
2179
2680
  expect(scim_hash['emails'].size).to eql(2)
@@ -2207,7 +2708,13 @@ RSpec.describe Scimitar::Resources::Mixin do
2207
2708
  nature: 'replace',
2208
2709
  path: path,
2209
2710
  value: {'type' => 'workinate', 'value' => 'replaced@test.com'},
2210
- altering_hash: scim_hash
2711
+ altering_hash: scim_hash,
2712
+ with_attr_map: {
2713
+ emails: [
2714
+ { match: 'type', with: 'home', using: { value: :home_email, primary: true } },
2715
+ { match: 'type', with: 'work', using: { value: :work_email } },
2716
+ ]
2717
+ }
2211
2718
  )
2212
2719
 
2213
2720
  expect(scim_hash['emails'].size).to eql(3)
@@ -2236,7 +2743,13 @@ RSpec.describe Scimitar::Resources::Mixin do
2236
2743
  nature: 'replace',
2237
2744
  path: path,
2238
2745
  value: [ { 'type' => 'work', 'value' => 'work@test.com' } ], # NOTE - to-add value is an Array (and must be)
2239
- altering_hash: scim_hash
2746
+ altering_hash: scim_hash,
2747
+ with_attr_map: {
2748
+ emails: [
2749
+ { match: 'type', with: 'home', using: { value: :home_email, primary: true } },
2750
+ { match: 'type', with: 'work', using: { value: :work_email } },
2751
+ ]
2752
+ }
2240
2753
  )
2241
2754
 
2242
2755
  expect(scim_hash['emails'].size).to eql(1)
@@ -2255,7 +2768,8 @@ RSpec.describe Scimitar::Resources::Mixin do
2255
2768
  nature: 'replace',
2256
2769
  path: path,
2257
2770
  value: 'foo',
2258
- altering_hash: scim_hash
2771
+ altering_hash: scim_hash,
2772
+ with_attr_map: { userName: :user_name }
2259
2773
  )
2260
2774
 
2261
2775
  expect(scim_hash['userName']).to eql('foo')
@@ -2270,7 +2784,8 @@ RSpec.describe Scimitar::Resources::Mixin do
2270
2784
  nature: 'replace',
2271
2785
  path: path,
2272
2786
  value: 'Baz',
2273
- altering_hash: scim_hash
2787
+ altering_hash: scim_hash,
2788
+ with_attr_map: { name: { givenName: :first_name, familyName: :last_name } }
2274
2789
  )
2275
2790
 
2276
2791
  expect(scim_hash['name']['givenName']).to eql('Baz')
@@ -2296,7 +2811,13 @@ RSpec.describe Scimitar::Resources::Mixin do
2296
2811
  nature: 'replace',
2297
2812
  path: path,
2298
2813
  value: 'added@test.com',
2299
- altering_hash: scim_hash
2814
+ altering_hash: scim_hash,
2815
+ with_attr_map: {
2816
+ emails: [
2817
+ { match: 'type', with: 'home', using: { value: :home_email, primary: true } },
2818
+ { match: 'type', with: 'work', using: { value: :work_email } },
2819
+ ]
2820
+ }
2300
2821
  )
2301
2822
 
2302
2823
  expect(scim_hash['emails'][0]['value']).to eql('home@test.com')
@@ -2321,7 +2842,13 @@ RSpec.describe Scimitar::Resources::Mixin do
2321
2842
  nature: 'replace',
2322
2843
  path: path,
2323
2844
  value: 'added@test.com',
2324
- altering_hash: scim_hash
2845
+ altering_hash: scim_hash,
2846
+ with_attr_map: {
2847
+ emails: [
2848
+ { match: 'type', with: 'home', using: { value: :home_email, primary: true } },
2849
+ { match: 'type', with: 'work', using: { value: :work_email } },
2850
+ ]
2851
+ }
2325
2852
  )
2326
2853
 
2327
2854
  expect(scim_hash['emails'][0]['value']).to eql('home@test.com')
@@ -2346,7 +2873,13 @@ RSpec.describe Scimitar::Resources::Mixin do
2346
2873
  nature: 'replace',
2347
2874
  path: path,
2348
2875
  value: 'added@test.com',
2349
- altering_hash: scim_hash
2876
+ altering_hash: scim_hash,
2877
+ with_attr_map: {
2878
+ emails: [
2879
+ { match: 'type', with: 'home', using: { value: :home_email, primary: true } },
2880
+ { match: 'type', with: 'work', using: { value: :work_email } },
2881
+ ]
2882
+ }
2350
2883
  )
2351
2884
 
2352
2885
  expect(scim_hash['emails'][0]['value']).to eql('added@test.com')
@@ -2364,7 +2897,13 @@ RSpec.describe Scimitar::Resources::Mixin do
2364
2897
  nature: 'replace',
2365
2898
  path: path,
2366
2899
  value: {'type' => 'work', 'value' => 'work@test.com'},
2367
- altering_hash: scim_hash
2900
+ altering_hash: scim_hash,
2901
+ with_attr_map: {
2902
+ emails: [
2903
+ { match: 'type', with: 'home', using: { value: :home_email, primary: true } },
2904
+ { match: 'type', with: 'work', using: { value: :work_email } },
2905
+ ]
2906
+ }
2368
2907
  )
2369
2908
 
2370
2909
  expect(scim_hash['emails'].size).to eql(1)
@@ -2388,7 +2927,13 @@ RSpec.describe Scimitar::Resources::Mixin do
2388
2927
  nature: 'replace',
2389
2928
  path: path,
2390
2929
  value: {'type' => 'work', 'value' => 'work@test.com'},
2391
- altering_hash: scim_hash
2930
+ altering_hash: scim_hash,
2931
+ with_attr_map: {
2932
+ emails: [
2933
+ { match: 'type', with: 'home', using: { value: :home_email, primary: true } },
2934
+ { match: 'type', with: 'work', using: { value: :work_email } },
2935
+ ]
2936
+ }
2392
2937
  )
2393
2938
 
2394
2939
  expect(scim_hash['emails'].size).to eql(2)
@@ -2407,7 +2952,13 @@ RSpec.describe Scimitar::Resources::Mixin do
2407
2952
  nature: 'replace',
2408
2953
  path: path,
2409
2954
  value: [ { 'type' => 'work', 'value' => 'work@test.com' } ], # NOTE - to-add value is an Array (and must be)
2410
- altering_hash: scim_hash
2955
+ altering_hash: scim_hash,
2956
+ with_attr_map: {
2957
+ emails: [
2958
+ { match: 'type', with: 'home', using: { value: :home_email, primary: true } },
2959
+ { match: 'type', with: 'work', using: { value: :work_email } },
2960
+ ]
2961
+ }
2411
2962
  )
2412
2963
 
2413
2964
  expect(scim_hash['emails'].size).to eql(1)
@@ -2425,7 +2976,11 @@ RSpec.describe Scimitar::Resources::Mixin do
2425
2976
  nature: 'replace',
2426
2977
  path: path,
2427
2978
  value: { 'active' => false }.with_indifferent_case_insensitive_access(),
2428
- altering_hash: scim_hash
2979
+ altering_hash: scim_hash,
2980
+ with_attr_map: {
2981
+ userName: :user_name,
2982
+ active: :active
2983
+ }
2429
2984
  )
2430
2985
 
2431
2986
  expect(scim_hash['root']['userName']).to eql('bar')
@@ -2546,7 +3101,8 @@ RSpec.describe Scimitar::Resources::Mixin do
2546
3101
  nature: 'add',
2547
3102
  path: ['complex[type eq "type1"]', 'data', 'nested[nature eq "nature2"]', 'info'],
2548
3103
  value: [{ 'deeper' => 'addition' }],
2549
- altering_hash: scim_hash
3104
+ altering_hash: scim_hash,
3105
+ with_attr_map: @contrived_class.scim_attributes_map()
2550
3106
  )
2551
3107
 
2552
3108
  expect(scim_hash.dig('complex', 0, 'data', 'nested', 0, 'info').count).to eql(1) # Unchanged
@@ -2569,7 +3125,8 @@ RSpec.describe Scimitar::Resources::Mixin do
2569
3125
  nature: 'replace',
2570
3126
  path: ['complex[type eq "type1"]', 'data', 'nested[nature eq "nature2"]', 'info'],
2571
3127
  value: [{ 'deeper' => 'addition' }],
2572
- altering_hash: scim_hash
3128
+ altering_hash: scim_hash,
3129
+ with_attr_map: @contrived_class.scim_attributes_map()
2573
3130
  )
2574
3131
 
2575
3132
  expect(scim_hash.dig('complex', 0, 'data', 'nested', 0, 'info').count).to eql(1) # Unchanged?
@@ -2586,7 +3143,7 @@ RSpec.describe Scimitar::Resources::Mixin do
2586
3143
  expect(scim_hash.dig('complex', 2, 'data', 'nested', 0, 'info', 0, 'deep')).to eql('nature2deep3') # Unchanged
2587
3144
  end
2588
3145
 
2589
- it 'removes across multiple deep matching points' do
3146
+ it 'removes via clearing to "nil" or empty Array across multiple deep matching points' do
2590
3147
  scim_hash = @original_hash.deep_dup().with_indifferent_case_insensitive_access()
2591
3148
  contrived_instance = @contrived_class.new
2592
3149
  contrived_instance.send(
@@ -2594,16 +3151,17 @@ RSpec.describe Scimitar::Resources::Mixin do
2594
3151
  nature: 'remove',
2595
3152
  path: ['complex[type eq "type1"]', 'data', 'nested[nature eq "nature2"]', 'info'],
2596
3153
  value: nil,
2597
- altering_hash: scim_hash
3154
+ altering_hash: scim_hash,
3155
+ with_attr_map: @contrived_class.scim_attributes_map()
2598
3156
  )
2599
3157
 
2600
3158
  expect(scim_hash.dig('complex', 0, 'data', 'nested', 0, 'info').count).to eql(1) # Unchanged
2601
- expect(scim_hash.dig('complex', 0, 'data', 'nested', 1, 'info')).to be_nil
3159
+ expect(scim_hash.dig('complex', 0, 'data', 'nested', 1, 'info')).to eql([])
2602
3160
  expect(scim_hash.dig('complex', 0, 'data', 'nested', 2, 'nature')).to be_present
2603
- expect(scim_hash.dig('complex', 0, 'data', 'nested', 1, 'info')).to be_nil
3161
+ expect(scim_hash.dig('complex', 0, 'data', 'nested', 1, 'info')).to eql([])
2604
3162
  expect(scim_hash.dig('complex', 0, 'data', 'nested', 2, 'nature')).to be_present
2605
3163
 
2606
- expect(scim_hash.dig('complex', 1, 'data', 'nested', 0, 'info')).to be_nil
3164
+ expect(scim_hash.dig('complex', 1, 'data', 'nested', 0, 'info')).to eql([])
2607
3165
  expect(scim_hash.dig('complex', 1, 'data', 'nested', 0, 'nature')).to be_present
2608
3166
 
2609
3167
  expect(scim_hash.dig('complex', 2, 'data', 'nested', 0, 'info').count).to eql(1) # Unchanged
@@ -2637,7 +3195,13 @@ RSpec.describe Scimitar::Resources::Mixin do
2637
3195
  nature: 'replace',
2638
3196
  path: path,
2639
3197
  value: 'ignored',
2640
- altering_hash: scim_hash
3198
+ altering_hash: scim_hash,
3199
+ with_attr_map: {
3200
+ emails: [
3201
+ { match: 'type', with: 'home', using: { value: :home_email, primary: true } },
3202
+ { match: 'type', with: 'work', using: { value: :work_email } },
3203
+ ]
3204
+ }
2641
3205
  )
2642
3206
  end.to raise_error(Scimitar::ErrorResponse) { |e| expect(e.as_json['scimType']).to eql('invalidSyntax') }
2643
3207
  end
@@ -2654,7 +3218,8 @@ RSpec.describe Scimitar::Resources::Mixin do
2654
3218
  nature: 'replace',
2655
3219
  path: path,
2656
3220
  value: 'ignored',
2657
- altering_hash: scim_hash
3221
+ altering_hash: scim_hash,
3222
+ with_attr_map: { userName: :user_name }
2658
3223
  )
2659
3224
  end.to raise_error(Scimitar::ErrorResponse) { |e| expect(e.as_json['scimType']).to eql('invalidSyntax') }
2660
3225
  end
@@ -2674,7 +3239,13 @@ RSpec.describe Scimitar::Resources::Mixin do
2674
3239
  nature: 'replace',
2675
3240
  path: path,
2676
3241
  value: 'ignored',
2677
- altering_hash: scim_hash
3242
+ altering_hash: scim_hash,
3243
+ with_attr_map: {
3244
+ emails: [
3245
+ { match: 'type', with: 'home', using: { value: :home_email, primary: true } },
3246
+ { match: 'type', with: 'work', using: { value: :work_email } },
3247
+ ]
3248
+ }
2678
3249
  )
2679
3250
  end.to raise_error(Scimitar::ErrorResponse) { |e| expect(e.as_json['scimType']).to eql('invalidSyntax') }
2680
3251
  end