1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/** |
4
|
|
|
* @package silverstripe-jsontext |
5
|
|
|
* @subpackage fields |
6
|
|
|
* @author Russell Michell <[email protected]> |
7
|
|
|
*/ |
8
|
|
|
|
9
|
|
|
use PhpTek\JSONText\ORM\FieldType\JSONText; |
10
|
|
|
use PhpTek\JSONText\Exception\JSONTextException; |
11
|
|
|
use SilverStripe\Dev\SapphireTest; |
12
|
|
|
|
13
|
|
|
class JSONTextSetValueTest extends SapphireTest |
14
|
|
|
{ |
15
|
|
|
/** |
16
|
|
|
* @var array |
17
|
|
|
*/ |
18
|
|
|
protected $fixtures = [ |
19
|
|
|
'array' => 'fixtures/json/array.json', |
20
|
|
|
'object' => 'fixtures/json/object.json' |
21
|
|
|
]; |
22
|
|
|
|
23
|
|
|
/** |
24
|
|
|
* JSONTextTest constructor. |
25
|
|
|
* |
26
|
|
|
* Modify fixtures property to be able to run on PHP <5.6 without use of constant in class property which 5.6+ allows |
27
|
|
|
*/ |
28
|
|
View Code Duplication |
public function __construct() |
|
|
|
|
29
|
|
|
{ |
30
|
|
|
foreach($this->fixtures as $name => $path) { |
31
|
|
|
$this->fixtures[$name] = realpath(__DIR__) . '/' . $path; |
32
|
|
|
} |
33
|
|
|
|
34
|
|
|
parent::__construct(); |
35
|
|
|
} |
36
|
|
|
|
37
|
|
|
/** |
38
|
|
|
* Tests JSONText::setValue() by means of a simple JSONPath expression operating on a JSON array |
39
|
|
|
*/ |
40
|
|
|
public function testSetValueOnSourceArray() |
41
|
|
|
{ |
42
|
|
|
// Data Source: Array |
43
|
|
|
// Return Type: ARRAY |
44
|
|
|
// Expression: '$.[2]' The third item |
45
|
|
|
$field = JSONText::create('MyJSON'); |
46
|
|
|
$field->setReturnType('array'); |
47
|
|
|
$field->setValue($this->getFixture('array')); |
48
|
|
|
// Assert current value |
49
|
|
|
$this->assertEquals(['trabant'], $field->query('$.[2]')); |
50
|
|
|
// Now update it... |
51
|
|
|
$field->setValue('lada', null, '$.[2]'); |
52
|
|
|
// Assert new value |
53
|
|
|
$this->assertEquals(['lada'], $field->query('$.[2]')); |
54
|
|
|
|
55
|
|
|
// Data Source: Array |
56
|
|
|
// Return Type: ARRAY |
57
|
|
|
// Expression: '$.[6]' The seventh item |
58
|
|
|
$field = JSONText::create('MyJSON'); |
59
|
|
|
$field->setReturnType('array'); |
60
|
|
|
$field->setValue($this->getFixture('array')); |
61
|
|
|
// Assert current value |
62
|
|
|
$this->assertEquals([33.3333], $field->query('$.[6]')); |
63
|
|
|
// Now update it... |
64
|
|
|
$field->setValue(99.99, null, '$.[6]'); |
65
|
|
|
// Assert new value |
66
|
|
|
$this->assertEquals([99.99], $field->query('$.[6]')); |
67
|
|
|
|
68
|
|
|
// Invalid #1 |
69
|
|
|
$this->setExpectedException(JSONTextException::class); |
|
|
|
|
70
|
|
|
$field->setValue(99.99, null, '$[6]'); // Invalid JSON path expression |
71
|
|
|
|
72
|
|
|
// Reset expected exception |
73
|
|
|
$this->setExpectedException(null); |
|
|
|
|
74
|
|
|
|
75
|
|
|
// Invalid #2 |
76
|
|
|
$this->setExpectedException(JSONTextException::class); |
|
|
|
|
77
|
|
|
$field->setValue('true'); // Invalid JSON passed to setValue() |
78
|
|
|
|
79
|
|
|
// Reset expected exception |
80
|
|
|
$this->setExpectedException(null); |
|
|
|
|
81
|
|
|
|
82
|
|
|
// Invalid #3 |
83
|
|
|
$this->setExpectedException(JSONTextException::class); |
|
|
|
|
84
|
|
|
$field->setValue('{'); // Invalid JSON. Period. |
85
|
|
|
|
86
|
|
|
// Ensure default SS behaviour is respected with empty strings, evenm though it's invalid JSON |
87
|
|
|
$field->setValue(''); |
88
|
|
|
$this->assertEquals('', $field->getValue()); |
89
|
|
|
} |
90
|
|
|
|
91
|
|
|
/** |
92
|
|
|
* Tests JSONText::setValue() by means of a simple JSONPath expression operating on a JSON object |
93
|
|
|
* |
94
|
|
|
* Tests performing single and multiple updates |
95
|
|
|
*/ |
96
|
|
|
public function testSetValueOnSourceObject() |
97
|
|
|
{ |
98
|
|
|
// Data Source: Object |
99
|
|
|
// Return Type: ARRAY |
100
|
|
|
// Expression: '$.[2]' The third item |
101
|
|
|
$field = JSONText::create('MyJSON'); |
102
|
|
|
$field->setReturnType('array'); |
103
|
|
|
$field->setValue($this->getFixture('object')); |
104
|
|
|
// Assert we cannot use array accessors at the root level of the source JSON _object_ |
105
|
|
|
$this->assertEmpty($field->query('$.[2]')); |
106
|
|
|
// Assert current types and value |
107
|
|
|
$this->assertInternalType('array', $field->query('$.cars')); |
108
|
|
|
$this->assertCount(1, $field->query('$.cars')); // The "cars" key's value is an object returned as a single value array |
109
|
|
|
$this->assertCount(3, $field->query('$.cars')[0]); //...with three classifications of car manufacturer by country |
110
|
|
|
$this->assertCount(2, $field->query('$.cars')[0]['british']); |
111
|
|
|
$this->assertEquals('morris', $field->query('$.cars')[0]['british'][1]); |
112
|
|
|
|
113
|
|
|
// Now do a multiple update |
114
|
|
|
$newCars = [ |
115
|
|
|
'american' => ['ford', 'tesla'], |
116
|
|
|
'british' => ['aston martin', 'austin', 'rover'] |
117
|
|
|
]; |
118
|
|
|
|
119
|
|
|
$field->setValue($newCars, null, '$.cars'); |
120
|
|
|
|
121
|
|
|
// Assert news types and value |
122
|
|
|
$this->assertInternalType('array', $field->query('$.cars')); |
123
|
|
|
$this->assertCount(1, $field->query('$.cars')); // The "cars" key's value is an object returned as a single value array |
124
|
|
|
$this->assertCount(2, $field->query('$.cars')[0]); //...with three classifications of car manufacturer by country |
125
|
|
|
$this->assertCount(3, $field->query('$.cars')[0]['british']); |
126
|
|
|
$this->assertEquals('austin', $field->query('$.cars')[0]['british'][1]); |
127
|
|
|
|
128
|
|
|
// So far we've used JSONPath to identify and update, let's try Postgres operators too |
129
|
|
|
// Now do attempt multiple update |
130
|
|
|
$newerCars = [ |
131
|
|
|
'american' => ['chrysler', 'general motors', 'edsel'] |
132
|
|
|
]; |
133
|
|
|
|
134
|
|
|
$this->setExpectedException(JSONTextException::class); |
|
|
|
|
135
|
|
|
$field->setValue($newerCars, null, '{"cars":"american"}'); // setValue() only takes JSONPath expressions |
136
|
|
|
} |
137
|
|
|
|
138
|
|
|
/** |
139
|
|
|
* Get the contents of a fixture |
140
|
|
|
* |
141
|
|
|
* @param string $fixture |
142
|
|
|
* @return string |
143
|
|
|
*/ |
144
|
|
|
private function getFixture($fixture) |
145
|
|
|
{ |
146
|
|
|
$files = $this->fixtures; |
147
|
|
|
return file_get_contents($files[$fixture]); |
148
|
|
|
} |
149
|
|
|
|
150
|
|
|
} |
151
|
|
|
|
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.