1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* test for RecordOriginConstraint |
4
|
|
|
*/ |
5
|
|
|
|
6
|
|
|
namespace Graviton\SchemaBundle\Tests\ConstraintBuilder; |
7
|
|
|
|
8
|
|
|
use Graviton\SchemaBundle\Constraint\RecordOriginConstraint; |
9
|
|
|
use Graviton\TestBundle\Test\RestTestCase; |
10
|
|
|
use Symfony\Component\HttpFoundation\Response; |
11
|
|
|
use JsonSchema\Rfc3339; |
12
|
|
|
|
13
|
|
|
/** |
14
|
|
|
* @author List of contributors <https://github.com/libgraviton/graviton/graphs/contributors> |
15
|
|
|
* @license http://opensource.org/licenses/gpl-license.php GNU Public License |
16
|
|
|
* @link http://swisscom.ch |
17
|
|
|
*/ |
18
|
|
|
class RecordOriginConstraintTest extends RestTestCase |
19
|
|
|
{ |
20
|
|
|
|
21
|
|
|
/** |
22
|
|
|
* load fixtures |
23
|
|
|
* |
24
|
|
|
* @return void |
25
|
|
|
*/ |
26
|
|
|
public function setUp() |
27
|
|
|
{ |
28
|
|
|
$this->loadFixtures( |
29
|
|
|
array( |
30
|
|
|
'GravitonDyn\CustomerBundle\DataFixtures\MongoDB\LoadCustomerData', |
31
|
|
|
), |
32
|
|
|
null, |
33
|
|
|
'doctrine_mongodb' |
34
|
|
|
); |
35
|
|
|
} |
36
|
|
|
|
37
|
|
|
/** |
38
|
|
|
* test the validation of the RecordOriginConstraint |
39
|
|
|
* |
40
|
|
|
* @dataProvider createDataProvider |
41
|
|
|
* |
42
|
|
|
* @param object $entity The object to create |
43
|
|
|
* @param integer $expectedStatus Header status code |
44
|
|
|
* @param string $expectedResponse Post data result of post |
45
|
|
|
* |
46
|
|
|
* @return void |
47
|
|
|
*/ |
48
|
|
View Code Duplication |
public function testRecordOriginHandlingOnCreate($entity, $expectedStatus, $expectedResponse) |
|
|
|
|
49
|
|
|
{ |
50
|
|
|
$client = static::createRestClient(); |
51
|
|
|
$client->post('/person/customer/', $entity); |
52
|
|
|
|
53
|
|
|
$response = $client->getResponse(); |
54
|
|
|
$this->assertEquals($expectedStatus, $response->getStatusCode()); |
55
|
|
|
$this->assertEquals($expectedResponse, $client->getResults()); |
56
|
|
|
} |
57
|
|
|
|
58
|
|
|
/** |
59
|
|
|
* tests for the case if user doesn't provide an id in payload.. constraint |
60
|
|
|
* must take the id from the request in that case. |
61
|
|
|
* |
62
|
|
|
* @return void |
63
|
|
|
*/ |
64
|
|
|
public function testRecordOriginHandlingWithNoIdInPayload() |
65
|
|
|
{ |
66
|
|
|
$record = (object) [ |
67
|
|
|
//'id' => '' - no, no id.. that's the point ;-) |
68
|
|
|
'customerNumber' => 555, |
69
|
|
|
'name' => 'Muster Hans' |
70
|
|
|
]; |
71
|
|
|
|
72
|
|
|
$client = static::createRestClient(); |
73
|
|
|
$client->put('/person/customer/100', $record); |
74
|
|
|
|
75
|
|
|
$this->assertEquals( |
76
|
|
|
$this->getExpectedErrorMessage('customerNumber, name')[0], |
77
|
|
|
$client->getResults()[0] |
78
|
|
|
); |
79
|
|
|
|
80
|
|
|
$this->assertEquals(1, count($client->getResults())); |
81
|
|
|
$this->assertEquals(Response::HTTP_BAD_REQUEST, $client->getResponse()->getStatusCode()); |
82
|
|
|
} |
83
|
|
|
|
84
|
|
|
/** |
85
|
|
|
* Test the validation of the RecordOriginConstraint |
86
|
|
|
* |
87
|
|
|
* @param array $fieldsToSet Fields to be modified |
88
|
|
|
* @param integer $expectedStatus Header status code |
89
|
|
|
* @param string $expectedResponse Result to be returned |
90
|
|
|
* @param boolean $checkSavedEntry To check db for correct result |
91
|
|
|
* |
92
|
|
|
* @dataProvider updateDataProvider |
93
|
|
|
* |
94
|
|
|
* @return void |
95
|
|
|
*/ |
96
|
|
|
public function testRecordOriginHandlingOnUpdate( |
97
|
|
|
$fieldsToSet, |
98
|
|
|
$expectedStatus, |
99
|
|
|
$expectedResponse, |
100
|
|
|
$checkSavedEntry = true |
101
|
|
|
) { |
102
|
|
|
$client = static::createRestClient(); |
103
|
|
|
$client->request('GET', '/person/customer/100'); |
104
|
|
|
$result = $client->getResults(); |
105
|
|
|
|
106
|
|
|
// apply changes |
107
|
|
|
foreach ($fieldsToSet as $key => $val) { |
108
|
|
|
$result->{$key} = $val; |
109
|
|
|
} |
110
|
|
|
|
111
|
|
|
$expectedObject = $result; |
112
|
|
|
|
113
|
|
|
$client = static::createRestClient(); |
114
|
|
|
$client->put('/person/customer/100', $result); |
115
|
|
|
|
116
|
|
|
$response = $client->getResponse(); |
117
|
|
|
$this->assertEquals($expectedStatus, $response->getStatusCode()); |
118
|
|
|
$this->assertEquals($expectedResponse, $client->getResults()); |
119
|
|
|
|
120
|
|
|
if ($checkSavedEntry) { |
121
|
|
|
// fetch it again and compare |
122
|
|
|
$client = static::createRestClient(); |
123
|
|
|
$client->request('GET', '/person/customer/100'); |
124
|
|
|
$this->assertEquals($expectedObject, $client->getResults()); |
125
|
|
|
} |
126
|
|
|
} |
127
|
|
|
|
128
|
|
|
/** |
129
|
|
|
* Test the validation of the RecordOriginConstraint |
130
|
|
|
* |
131
|
|
|
* @param array $ops PATCH operations |
132
|
|
|
* @param integer $expectedStatus Header status code |
133
|
|
|
* @param string $expectedResponse Result to be returned |
134
|
|
|
* |
135
|
|
|
* @dataProvider patchDataProvider |
136
|
|
|
* |
137
|
|
|
* @return void |
138
|
|
|
*/ |
139
|
|
View Code Duplication |
public function testRecordOriginHandlingOnPatch( |
|
|
|
|
140
|
|
|
$ops, |
141
|
|
|
$expectedStatus, |
142
|
|
|
$expectedResponse |
143
|
|
|
) { |
144
|
|
|
$client = static::createRestClient(); |
145
|
|
|
|
146
|
|
|
$client->request('PATCH', '/person/customer/100', [], [], [], json_encode($ops)); |
147
|
|
|
|
148
|
|
|
$response = $client->getResponse(); |
149
|
|
|
$this->assertEquals($expectedStatus, $response->getStatusCode()); |
150
|
|
|
$this->assertEquals($expectedResponse, $client->getResults()); |
151
|
|
|
} |
152
|
|
|
|
153
|
|
|
/** |
154
|
|
|
* test to see if DELETE on a recordorigin: core is denied |
155
|
|
|
* |
156
|
|
|
* @return void |
157
|
|
|
*/ |
158
|
|
|
public function testDeleteHandling() |
159
|
|
|
{ |
160
|
|
|
$client = static::createRestClient(); |
161
|
|
|
$client->request('DELETE', '/person/customer/100'); |
162
|
|
|
$response = $client->getResponse(); |
163
|
|
|
|
164
|
|
|
$this->assertEquals(Response::HTTP_BAD_REQUEST, $response->getStatusCode()); |
165
|
|
|
$this->assertEquals( |
166
|
|
|
(object) [ |
167
|
|
|
'propertyPath' => 'recordOrigin', |
168
|
|
|
'message' => 'Must not be one of the following keywords: core' |
169
|
|
|
], |
170
|
|
|
$client->getResults() |
171
|
|
|
); |
172
|
|
|
} |
173
|
|
|
|
174
|
|
|
/** |
175
|
|
|
* Data provider for POST related stuff |
176
|
|
|
* |
177
|
|
|
* @return array |
|
|
|
|
178
|
|
|
*/ |
179
|
|
|
public function createDataProvider() |
180
|
|
|
{ |
181
|
|
|
$baseObj = [ |
182
|
|
|
'customerNumber' => 888, |
183
|
|
|
'name' => 'Muster Hans' |
184
|
|
|
]; |
185
|
|
|
|
186
|
|
|
return [ |
187
|
|
|
|
188
|
|
|
/*** STUFF THAT SHOULD BE ALLOWED ***/ |
189
|
|
|
|
190
|
|
|
'create-allowed-object' => [ |
191
|
|
|
'entity' => (object) array_merge( |
192
|
|
|
$baseObj, |
193
|
|
|
[ |
194
|
|
|
'recordOrigin' => 'hans' |
195
|
|
|
] |
196
|
|
|
), |
197
|
|
|
'httpStatusExpected' => Response::HTTP_CREATED, |
198
|
|
|
'expectedResponse' => null |
199
|
|
|
], |
200
|
|
|
|
201
|
|
|
/*** STUFF THAT SHOULD BE DENIED ***/ |
202
|
|
|
|
203
|
|
|
'create-recordorigin-core' => [ |
204
|
|
|
'entity' => (object) array_merge( |
205
|
|
|
$baseObj, |
206
|
|
|
[ |
207
|
|
|
'recordOrigin' => 'core' |
208
|
|
|
] |
209
|
|
|
), |
210
|
|
|
'httpStatusExpected' => Response::HTTP_BAD_REQUEST, |
211
|
|
|
'expectedResponse' => [ |
212
|
|
|
(object) [ |
213
|
|
|
'propertyPath' => 'recordOrigin', |
214
|
|
|
'message' => 'Creating documents with the recordOrigin field having a '. |
215
|
|
|
'value of core is not permitted.' |
216
|
|
|
] |
217
|
|
|
] |
218
|
|
|
] |
219
|
|
|
]; |
220
|
|
|
} |
221
|
|
|
|
222
|
|
|
/** |
223
|
|
|
* Data provider for PUT related stuff |
224
|
|
|
* |
225
|
|
|
* @return array |
|
|
|
|
226
|
|
|
*/ |
227
|
|
|
public function updateDataProvider() |
228
|
|
|
{ |
229
|
|
|
return [ |
230
|
|
|
|
231
|
|
|
/*** STUFF THAT SHOULD BE ALLOWED ***/ |
232
|
|
|
'create-allowed-object' => [ |
233
|
|
|
'fieldsToSet' => [ |
234
|
|
|
'addedField' => (object) [ |
235
|
|
|
'some' => 'property', |
236
|
|
|
'another' => 'one' |
237
|
|
|
] |
238
|
|
|
], |
239
|
|
|
'httpStatusExpected' => Response::HTTP_NO_CONTENT, |
240
|
|
|
'expectedResponse' => null |
241
|
|
|
], |
242
|
|
|
'subproperty-modification' => [ |
243
|
|
|
'fieldsToSet' => [ |
244
|
|
|
'someObject' => (object) [ |
245
|
|
|
'oneField' => 'value', |
246
|
|
|
'twoField' => 'twofield' |
247
|
|
|
] |
248
|
|
|
], |
249
|
|
|
'httpStatusExpected' => Response::HTTP_NO_CONTENT, |
250
|
|
|
'expectedResponse' => null |
251
|
|
|
], |
252
|
|
|
|
253
|
|
|
/*** STUFF THAT NEEDS TO BE DENIED ***/ |
254
|
|
|
'denied-subproperty-modification' => [ |
255
|
|
|
'fieldsToSet' => [ |
256
|
|
|
'someObject' => (object) [ |
257
|
|
|
'oneField' => 'changed-value' |
258
|
|
|
] |
259
|
|
|
], |
260
|
|
|
'httpStatusExpected' => Response::HTTP_BAD_REQUEST, |
261
|
|
|
'expectedResponse' => $this->getExpectedErrorMessage('someObject.oneField'), |
262
|
|
|
'checkSavedEntry' => false |
263
|
|
|
], |
264
|
|
|
'denied-try-change-recordorigin' => [ |
265
|
|
|
'fieldsToSet' => [ |
266
|
|
|
'recordOrigin' => 'hans' |
267
|
|
|
], |
268
|
|
|
'httpStatusExpected' => Response::HTTP_BAD_REQUEST, |
269
|
|
|
'expectedResponse' => $this->getExpectedErrorMessage('recordOrigin'), |
270
|
|
|
'checkSavedEntry' => false |
271
|
|
|
], |
272
|
|
|
]; |
273
|
|
|
} |
274
|
|
|
|
275
|
|
|
|
276
|
|
|
/** |
277
|
|
|
* providing the conditional errorMessage Object |
278
|
|
|
* |
279
|
|
|
* @param string $changedFields the Field the user wants to change |
280
|
|
|
* |
281
|
|
|
* @return array |
282
|
|
|
*/ |
283
|
|
|
private function getExpectedErrorMessage($changedFields) |
284
|
|
|
{ |
285
|
|
|
$expectedErrorOutput = [ |
286
|
|
|
(object) [ |
287
|
|
|
'propertyPath' => 'recordOrigin', |
288
|
|
|
'message' => 'Prohibited modification attempt on record with recordOrigin of core.' |
289
|
|
|
.' You tried to change ('.$changedFields.'), but you can only change' |
290
|
|
|
.' (addedField, someObject.twoField) by recordOriginException.' |
291
|
|
|
] |
292
|
|
|
]; |
293
|
|
|
return $expectedErrorOutput; |
294
|
|
|
} |
295
|
|
|
|
296
|
|
|
/** |
297
|
|
|
* Data provider for PATCH related stuff |
298
|
|
|
* |
299
|
|
|
* @return array |
|
|
|
|
300
|
|
|
*/ |
301
|
|
|
public function patchDataProvider() |
302
|
|
|
{ |
303
|
|
|
return [ |
304
|
|
|
|
305
|
|
|
/*** STUFF THAT SHOULD BE ALLOWED ***/ |
306
|
|
|
|
307
|
|
|
'patch-allowed-attribute' => [ |
308
|
|
|
'ops' => [ |
309
|
|
|
[ |
310
|
|
|
'op' => 'add', |
311
|
|
|
'path' => '/someObject/twoField', |
312
|
|
|
'value' => 'myValue' |
313
|
|
|
] |
314
|
|
|
], |
315
|
|
|
'httpStatusExpected' => Response::HTTP_OK, |
316
|
|
|
'expectedResponse' => null |
317
|
|
|
], |
318
|
|
|
'patch-add-object-data' => [ |
319
|
|
|
'ops' => [ |
320
|
|
|
[ |
321
|
|
|
'op' => 'add', |
322
|
|
|
'path' => '/addedField', |
323
|
|
|
'value' => [ |
324
|
|
|
'someProperty' => 'someValue', |
325
|
|
|
'anotherOne' => 'oneMore' |
326
|
|
|
] |
327
|
|
|
] |
328
|
|
|
], |
329
|
|
|
'httpStatusExpected' => Response::HTTP_OK, |
330
|
|
|
'expectedResponse' => null |
331
|
|
|
], |
332
|
|
|
|
333
|
|
|
/*** STUFF THAT NEEDS TO BE DENIED ***/ |
334
|
|
|
'patch-denied-subproperty' => [ |
335
|
|
|
'ops' => [ |
336
|
|
|
[ |
337
|
|
|
'op' => 'add', |
338
|
|
|
'path' => '/someObject/oneField', |
339
|
|
|
'value' => 'myValue' |
340
|
|
|
] |
341
|
|
|
], |
342
|
|
|
'httpStatusExpected' => Response::HTTP_BAD_REQUEST, |
343
|
|
|
'expectedResponse' => $this->getExpectedErrorMessage('someObject.oneField') |
344
|
|
|
], |
345
|
|
|
'patch-denied-recordorigin-change' => [ |
346
|
|
|
'ops' => [ |
347
|
|
|
[ |
348
|
|
|
'op' => 'replace', |
349
|
|
|
'path' => '/recordOrigin', |
350
|
|
|
'value' => 'hans' |
351
|
|
|
] |
352
|
|
|
], |
353
|
|
|
'httpStatusExpected' => Response::HTTP_BAD_REQUEST, |
354
|
|
|
'expectedResponse' => $this->getExpectedErrorMessage('recordOrigin') |
355
|
|
|
], |
356
|
|
|
|
357
|
|
|
]; |
358
|
|
|
} |
359
|
|
|
|
360
|
|
|
/** |
361
|
|
|
* test the validation of the RecordOriginConstraint |
362
|
|
|
* |
363
|
|
|
* @return void |
364
|
|
|
*/ |
365
|
|
|
public function testRecordOriginUTCDateHandling() |
366
|
|
|
{ |
367
|
|
|
$client = static::createRestClient(); |
368
|
|
|
$client->request('get', '/person/customer/100'); |
369
|
|
|
$customer = $client->getResults(); |
370
|
|
|
|
371
|
|
|
$this->assertObjectHasAttribute('createDate', $customer, json_encode($customer)); |
372
|
|
|
|
373
|
|
|
// Check date and convert it, make a UTC+1 change |
374
|
|
|
$createDate = Rfc3339::createFromString($customer->createDate); |
375
|
|
|
$zone = new \DateTimeZone('America/Los_Angeles'); |
376
|
|
|
$createDate->setTimezone($zone); |
377
|
|
|
$customer->createDate = $createDate->format(\DateTime::ATOM); |
378
|
|
|
|
379
|
|
|
$client = static::createRestClient(); |
380
|
|
|
$client->put('/person/customer/100', $customer); |
381
|
|
|
$response = $client->getResponse(); |
382
|
|
|
$this->assertEquals(Response::HTTP_NO_CONTENT, $response->getStatusCode()); |
383
|
|
|
} |
384
|
|
|
|
385
|
|
|
/** |
386
|
|
|
* test the validation of the convertDatetimeToUTC |
387
|
|
|
* |
388
|
|
|
* @return void |
389
|
|
|
*/ |
390
|
|
|
public function testPrivateConvertUTC() |
391
|
|
|
{ |
392
|
|
|
$data = [ |
393
|
|
|
"fielddata" => "2016-05-09T22:00:00+0100", |
394
|
|
|
"fieldobj" => [ |
395
|
|
|
"subfield" => "2016-10-09T10:00:00+0100" |
396
|
|
|
] |
397
|
|
|
]; |
398
|
|
|
$schema = [ |
399
|
|
|
"properties" => [ |
400
|
|
|
"fielddata" => ["format" => "date-time"], |
401
|
|
|
"fieldobj" => [ |
402
|
|
|
"properties" => [ |
403
|
|
|
"subfield" => [ |
404
|
|
|
"format" => "date-time" |
405
|
|
|
] |
406
|
|
|
] |
407
|
|
|
] |
408
|
|
|
] |
409
|
|
|
]; |
410
|
|
|
$schema = json_decode(json_encode($schema)); |
411
|
|
|
$data = json_decode(json_encode($data)); |
412
|
|
|
|
413
|
|
|
$zone = new \DateTimeZone('UTC'); |
414
|
|
|
|
415
|
|
|
/** @var RecordOriginConstraint $class */ |
416
|
|
|
$class = $this->getContainer()->get('graviton.schema.constraint.recordorigin'); |
417
|
|
|
$method = $this->getPrivateClassMethod(get_class($class), 'convertDatetimeToUTC'); |
418
|
|
|
|
419
|
|
|
$result = $method->invokeArgs($class, [$data, $schema, $zone]); |
420
|
|
|
|
421
|
|
|
$this->assertEquals('2016-05-09T21:00:00+0000', $result->fielddata); |
422
|
|
|
$this->assertEquals('2016-10-09T09:00:00+0000', $result->fieldobj->subfield); |
423
|
|
|
} |
424
|
|
|
} |
425
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.