Completed
Push — master ( f4a0a7...1f0805 )
by
unknown
16:09
created

testRecordOriginUTCDateHandling()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 19
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
dl 0
loc 19
rs 9.4285
c 1
b 0
f 1
cc 1
eloc 13
nc 1
nop 0
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)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
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(
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
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
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use array<string,array<string,null|array>>.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
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
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use array<string,array>.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
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
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use array<string,array>.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
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