1
|
|
|
<?php |
2
|
|
|
/* |
3
|
|
|
* This file is a part of GraphQL project. |
4
|
|
|
* |
5
|
|
|
* @author Alexandr Viniychuk <[email protected]> |
6
|
|
|
* created: 11:02 PM 5/13/16 |
7
|
|
|
*/ |
8
|
|
|
|
9
|
|
|
namespace Youshido\Tests\Schema; |
10
|
|
|
|
11
|
|
|
|
12
|
|
|
use Youshido\GraphQL\Execution\Processor; |
13
|
|
|
use Youshido\GraphQL\Execution\ResolveStringResolverInterface; |
14
|
|
|
use Youshido\GraphQL\Execution\ResolveInfo; |
15
|
|
|
use Youshido\GraphQL\Field\Field; |
16
|
|
|
use Youshido\GraphQL\Schema\Schema; |
17
|
|
|
use Youshido\GraphQL\Type\ListType\ListType; |
18
|
|
|
use Youshido\GraphQL\Type\NonNullType; |
19
|
|
|
use Youshido\GraphQL\Type\Object\ObjectType; |
20
|
|
|
use Youshido\GraphQL\Type\Scalar\BooleanType; |
21
|
|
|
use Youshido\GraphQL\Type\Scalar\IntType; |
22
|
|
|
use Youshido\GraphQL\Type\Scalar\StringType; |
23
|
|
|
use Youshido\GraphQL\Type\Union\UnionType; |
24
|
|
|
use Youshido\Tests\DataProvider\TestEmptySchema; |
25
|
|
|
use Youshido\Tests\DataProvider\TestEnumType; |
26
|
|
|
use Youshido\Tests\DataProvider\TestInterfaceType; |
27
|
|
|
use Youshido\Tests\DataProvider\TestObjectType; |
28
|
|
|
use Youshido\Tests\DataProvider\TestSchema; |
29
|
|
|
|
30
|
|
|
class ProcessorTest extends \PHPUnit_Framework_TestCase |
31
|
|
|
{ |
32
|
|
|
|
33
|
|
|
private $_counter = 0; |
34
|
|
|
|
35
|
|
|
/** |
36
|
|
|
* @expectedException \Youshido\GraphQL\Validator\Exception\ConfigurationException |
37
|
|
|
* @expectedExceptionMessage Schema has to have fields |
38
|
|
|
*/ |
39
|
|
|
public function testInit() |
40
|
|
|
{ |
41
|
|
|
new Processor(new TestEmptySchema()); |
42
|
|
|
} |
43
|
|
|
|
44
|
|
|
public function testEmptyQueries() |
45
|
|
|
{ |
46
|
|
|
$processor = new Processor(new TestSchema()); |
47
|
|
|
$processor->processPayload(''); |
48
|
|
|
$this->assertEquals(['errors' => [ |
49
|
|
|
['message' => 'Must provide an operation.'] |
50
|
|
|
]], $processor->getResponseData()); |
51
|
|
|
|
52
|
|
|
$processor->processPayload('{ me { name } }'); |
53
|
|
|
$this->assertEquals(['data' => [ |
54
|
|
|
'me' => ['name' => 'John'] |
55
|
|
|
]], $processor->getResponseData()); |
56
|
|
|
|
57
|
|
|
} |
58
|
|
|
|
59
|
|
|
public function testNestedVariables() { |
60
|
|
|
$processor = new Processor(new TestSchema()); |
61
|
|
|
$noArgsQuery = '{ me { echo(value:"foo") } }'; |
62
|
|
|
$expectedData = ['data' => ['me' => ['echo' => 'foo']]]; |
63
|
|
|
$processor->processPayload($noArgsQuery, ['value' => 'foo']); |
64
|
|
|
$this->assertEquals($expectedData, $processor->getResponseData()); |
65
|
|
|
|
66
|
|
|
$parameterizedFieldQuery = |
67
|
|
|
'query nestedFieldQuery($value:String!){ |
68
|
|
|
me { |
69
|
|
|
echo(value:$value) |
70
|
|
|
} |
71
|
|
|
}'; |
72
|
|
|
$processor->processPayload($parameterizedFieldQuery, ['value' => 'foo']); |
73
|
|
|
$this->assertEquals($expectedData, $processor->getResponseData()); |
74
|
|
|
|
75
|
|
|
$parameterizedQueryQuery = |
76
|
|
|
'query nestedQueryQuery($value:Int){ |
77
|
|
|
me { |
78
|
|
|
location(noop:$value) { |
79
|
|
|
address |
80
|
|
|
} |
81
|
|
|
} |
82
|
|
|
}'; |
83
|
|
|
$processor->processPayload($parameterizedQueryQuery, ['value' => 1]); |
84
|
|
|
$this->assertArrayNotHasKey('errors', $processor->getResponseData()); |
85
|
|
|
} |
86
|
|
|
|
87
|
|
View Code Duplication |
public function testListNullResponse() |
|
|
|
|
88
|
|
|
{ |
89
|
|
|
$processor = new Processor(new Schema([ |
90
|
|
|
'query' => new ObjectType([ |
91
|
|
|
'name' => 'RootQuery', |
92
|
|
|
'fields' => [ |
93
|
|
|
'list' => [ |
94
|
|
|
'type' => new ListType(new StringType()), |
95
|
|
|
'resolve' => function() { |
96
|
|
|
return null; |
97
|
|
|
} |
98
|
|
|
] |
99
|
|
|
] |
100
|
|
|
]) |
101
|
|
|
])); |
102
|
|
|
$data = $processor->processPayload(' { list }')->getResponseData(); |
103
|
|
|
$this->assertEquals(['data' => ['list' => null]], $data); |
104
|
|
|
} |
105
|
|
|
|
106
|
|
|
|
107
|
|
View Code Duplication |
public function testSubscriptionNullResponse() |
|
|
|
|
108
|
|
|
{ |
109
|
|
|
$processor = new Processor(new Schema([ |
110
|
|
|
'query' => new ObjectType([ |
111
|
|
|
'name' => 'RootQuery', |
112
|
|
|
'fields' => [ |
113
|
|
|
'list' => [ |
114
|
|
|
'type' => new ListType(new StringType()), |
115
|
|
|
'resolve' => function() { |
116
|
|
|
return null; |
117
|
|
|
} |
118
|
|
|
] |
119
|
|
|
] |
120
|
|
|
]) |
121
|
|
|
])); |
122
|
|
|
$data = $processor->processPayload(' { __schema { subscriptionType { name } } }')->getResponseData(); |
123
|
|
|
$this->assertEquals(['data' => ['__schema' => ['subscriptionType' => null]]], $data); |
124
|
|
|
} |
125
|
|
|
|
126
|
|
|
public function testSchemaOperations() |
127
|
|
|
{ |
128
|
|
|
$schema = new Schema([ |
129
|
|
|
'query' => new ObjectType([ |
130
|
|
|
'name' => 'RootQuery', |
131
|
|
|
'fields' => [ |
132
|
|
|
'me' => [ |
133
|
|
|
'type' => new ObjectType([ |
134
|
|
|
'name' => 'User', |
135
|
|
|
'fields' => [ |
136
|
|
|
'firstName' => [ |
137
|
|
|
'type' => new StringType(), |
138
|
|
|
'args' => [ |
139
|
|
|
'shorten' => new BooleanType() |
140
|
|
|
], |
141
|
|
|
'resolve' => function ($value, $args) { |
142
|
|
|
return empty($args['shorten']) ? $value : $value; |
143
|
|
|
} |
144
|
|
|
], |
145
|
|
|
'lastName' => new StringType(), |
146
|
|
|
'code' => new StringType(), |
147
|
|
|
] |
148
|
|
|
]), |
149
|
|
|
'resolve' => function ($value, $args) { |
150
|
|
|
$data = ['firstName' => 'John', 'code' => '007']; |
151
|
|
|
if (!empty($args['upper'])) { |
152
|
|
|
foreach ($data as $key => $value) { |
153
|
|
|
$data[$key] = strtoupper($value); |
154
|
|
|
} |
155
|
|
|
} |
156
|
|
|
|
157
|
|
|
return $data; |
158
|
|
|
}, |
159
|
|
|
'args' => [ |
160
|
|
|
'upper' => [ |
161
|
|
|
'type' => new BooleanType(), |
162
|
|
|
'default' => false |
163
|
|
|
] |
164
|
|
|
] |
165
|
|
|
], |
166
|
|
|
'randomUser' => [ |
167
|
|
|
'type' => new TestObjectType(), |
168
|
|
|
'resolve' => function () { |
169
|
|
|
return ['invalidField' => 'John']; |
170
|
|
|
} |
171
|
|
|
], |
172
|
|
|
'invalidValueQuery' => [ |
173
|
|
|
'type' => new TestObjectType(), |
174
|
|
|
'resolve' => function () { |
175
|
|
|
return 'stringValue'; |
176
|
|
|
} |
177
|
|
|
], |
178
|
|
|
], |
179
|
|
|
]) |
180
|
|
|
]); |
181
|
|
|
$processor = new Processor($schema); |
182
|
|
|
|
183
|
|
|
$processor->processPayload('{ me { firstName } }'); |
184
|
|
|
$this->assertEquals(['data' => ['me' => ['firstName' => 'John']]], $processor->getResponseData()); |
185
|
|
|
|
186
|
|
|
$processor->processPayload('{ me { firstName, lastName } }'); |
187
|
|
|
$this->assertEquals(['data' => ['me' => ['firstName' => 'John', 'lastName' => null]]], $processor->getResponseData()); |
188
|
|
|
|
189
|
|
|
$processor->processPayload('{ me { code } }'); |
190
|
|
|
$this->assertEquals(['data' => ['me' => ['code' => 7]]], $processor->getResponseData()); |
191
|
|
|
|
192
|
|
|
$processor->processPayload('{ me(upper:true) { firstName } }'); |
193
|
|
|
$this->assertEquals(['data' => ['me' => ['firstName' => 'JOHN']]], $processor->getResponseData()); |
194
|
|
|
|
195
|
|
|
$schema->getMutationType() |
196
|
|
|
->addField(new Field([ |
197
|
|
|
'name' => 'increaseCounter', |
198
|
|
|
'type' => new IntType(), |
199
|
|
|
'resolve' => function ($value, $args, ResolveInfo $info) { |
|
|
|
|
200
|
|
|
return $this->_counter += $args['amount']; |
201
|
|
|
}, |
202
|
|
|
'args' => [ |
203
|
|
|
'amount' => [ |
204
|
|
|
'type' => new IntType(), |
205
|
|
|
'default' => 1 |
206
|
|
|
] |
207
|
|
|
] |
208
|
|
|
]))->addField(new Field([ |
209
|
|
|
'name' => 'invalidResolveTypeMutation', |
210
|
|
|
'type' => new NonNullType(new IntType()), |
211
|
|
|
'resolve' => function () { |
212
|
|
|
return null; |
213
|
|
|
} |
214
|
|
|
]))->addField(new Field([ |
215
|
|
|
'name' => 'interfacedMutation', |
216
|
|
|
'type' => new TestInterfaceType(), |
217
|
|
|
'resolve' => function () { |
218
|
|
|
return ['name' => 'John']; |
219
|
|
|
} |
220
|
|
|
])); |
221
|
|
|
$processor->processPayload('mutation { increaseCounter }'); |
222
|
|
|
$this->assertEquals(['data' => ['increaseCounter' => 1]], $processor->getResponseData()); |
223
|
|
|
|
224
|
|
|
$processor->processPayload('mutation { invalidMutation }'); |
225
|
|
|
$this->assertEquals(['errors' => [['message' => 'Field "invalidMutation" not found in type "RootSchemaMutation"']]], $processor->getResponseData()); |
226
|
|
|
|
227
|
|
|
$processor->processPayload('mutation { increaseCounter(noArg: 2) }'); |
228
|
|
|
$this->assertEquals(['errors' => [['message' => 'Unknown argument "noArg" on field "increaseCounter"']]], $processor->getResponseData()); |
229
|
|
|
|
230
|
|
|
$processor->processPayload('mutation { increaseCounter(amount: 2) { invalidProp } }'); |
231
|
|
|
$this->assertEquals(['errors' => [['message' => 'Field "invalidProp" not found in type "Int"']], 'data' => ['increaseCounter' => null]], $processor->getResponseData()); |
232
|
|
|
|
233
|
|
|
$processor->processPayload('mutation { increaseCounter(amount: 2) }'); |
234
|
|
|
$this->assertEquals(['data' => ['increaseCounter' => 5]], $processor->getResponseData()); |
235
|
|
|
|
236
|
|
|
$processor->processPayload('{ invalidQuery }'); |
237
|
|
|
$this->assertEquals(['errors' => [['message' => 'Field "invalidQuery" not found in type "RootQuery"']]], $processor->getResponseData()); |
238
|
|
|
|
239
|
|
|
$processor->processPayload('{ invalidValueQuery { id } }'); |
240
|
|
|
$this->assertEquals(['errors' => [['message' => 'Not valid value for OBJECT field invalidValueQuery']], 'data' => ['invalidValueQuery' => null]], $processor->getResponseData()); |
241
|
|
|
|
242
|
|
|
$processor->processPayload('{ me { firstName(shorten: true), middle }}'); |
243
|
|
|
$this->assertEquals(['errors' => [['message' => 'Field "middle" not found in type "User"']], 'data' => ['me' => null]], $processor->getResponseData()); |
244
|
|
|
|
245
|
|
|
$processor->processPayload('{ randomUser { region }}'); |
246
|
|
|
$this->assertEquals(['errors' => [['message' => 'Property "region" not found in resolve result']]], $processor->getResponseData()); |
247
|
|
|
|
248
|
|
|
$processor->processPayload('mutation { invalidResolveTypeMutation }'); |
249
|
|
|
$this->assertEquals(['errors' => [['message' => 'Cannot return null for non-nullable field invalidResolveTypeMutation']], 'data' => ['invalidResolveTypeMutation' => null]], $processor->getResponseData()); |
250
|
|
|
|
251
|
|
|
$processor->processPayload('mutation { user:interfacedMutation { name } }'); |
252
|
|
|
$this->assertEquals(['data' => ['user' => ['name' => 'John']]], $processor->getResponseData()); |
253
|
|
|
} |
254
|
|
|
|
255
|
|
|
public function testListEnumsSchemaOperations() |
256
|
|
|
{ |
257
|
|
|
$processor = new Processor(new Schema([ |
258
|
|
|
'query' => new ObjectType([ |
259
|
|
|
'name' => 'RootQuery', |
260
|
|
|
'fields' => [ |
261
|
|
|
'listQuery' => [ |
262
|
|
|
'type' => new ListType(new TestEnumType()), |
263
|
|
|
'resolve' => function () { |
264
|
|
|
return 'invalid list'; |
265
|
|
|
} |
266
|
|
|
], |
267
|
|
|
'listEnumQuery' => [ |
268
|
|
|
'type' => new ListType(new TestEnumType()), |
269
|
|
|
'resolve' => function () { |
270
|
|
|
return ['invalid enum']; |
271
|
|
|
} |
272
|
|
|
], |
273
|
|
|
'invalidEnumQuery' => [ |
274
|
|
|
'type' => new TestEnumType(), |
275
|
|
|
'resolve' => function () { |
276
|
|
|
return 'invalid enum'; |
277
|
|
|
} |
278
|
|
|
], |
279
|
|
|
'enumQuery' => [ |
280
|
|
|
'type' => new TestEnumType(), |
281
|
|
|
'resolve' => function () { |
282
|
|
|
return 1; |
283
|
|
|
} |
284
|
|
|
], |
285
|
|
|
'invalidNonNullQuery' => [ |
286
|
|
|
'type' => new NonNullType(new IntType()), |
287
|
|
|
'resolve' => function () { |
288
|
|
|
return null; |
289
|
|
|
} |
290
|
|
|
], |
291
|
|
|
'invalidNonNullInsideQuery' => [ |
292
|
|
|
'type' => new NonNullType(new IntType()), |
293
|
|
|
'resolve' => function () { |
294
|
|
|
return 'hello'; |
295
|
|
|
} |
296
|
|
|
], |
297
|
|
|
'objectQuery' => [ |
298
|
|
|
'type' => new TestObjectType(), |
299
|
|
|
'resolve' => function () { |
300
|
|
|
return ['name' => 'John']; |
301
|
|
|
} |
302
|
|
|
], |
303
|
|
|
'deepObjectQuery' => [ |
304
|
|
|
'type' => new ObjectType([ |
305
|
|
|
'name' => 'deepObject', |
306
|
|
|
'fields' => [ |
307
|
|
|
'object' => new TestObjectType(), |
308
|
|
|
'enum' => new TestEnumType(), |
309
|
|
|
], |
310
|
|
|
]), |
311
|
|
|
'resolve' => function () { |
312
|
|
|
return [ |
313
|
|
|
'object' => [ |
314
|
|
|
'name' => 'John' |
315
|
|
|
], |
316
|
|
|
'enum' => 1 |
317
|
|
|
]; |
318
|
|
|
}, |
319
|
|
|
], |
320
|
|
|
] |
321
|
|
|
]) |
322
|
|
|
])); |
323
|
|
|
|
324
|
|
|
$processor->processPayload('{ listQuery }'); |
325
|
|
|
$this->assertEquals(['errors' => [ |
326
|
|
|
['message' => 'Not valid value for LIST field listQuery'] |
327
|
|
|
], 'data' => ['listQuery' => null]], $processor->getResponseData()); |
328
|
|
|
|
329
|
|
|
$processor->processPayload('{ listEnumQuery }'); |
330
|
|
|
$this->assertEquals(['errors' => [ |
331
|
|
|
['message' => 'Not valid resolve value in listEnumQuery field'] |
332
|
|
|
], 'data' => ['listEnumQuery' => [null]]], $processor->getResponseData()); |
333
|
|
|
|
334
|
|
|
$processor->processPayload('{ invalidEnumQuery }'); |
335
|
|
|
$this->assertEquals(['errors' => [ |
336
|
|
|
['message' => 'Not valid value for ENUM field invalidEnumQuery'] |
337
|
|
|
], 'data' => ['invalidEnumQuery' => null]], $processor->getResponseData()); |
338
|
|
|
|
339
|
|
|
$processor->processPayload('{ enumQuery }'); |
340
|
|
|
$this->assertEquals(['data' => ['enumQuery' => 'FINISHED']], $processor->getResponseData()); |
341
|
|
|
|
342
|
|
|
$processor->processPayload('{ invalidNonNullQuery }'); |
343
|
|
|
$this->assertEquals(['errors' => [ |
344
|
|
|
['message' => 'Cannot return null for non-nullable field invalidNonNullQuery'] |
345
|
|
|
], 'data' => ['invalidNonNullQuery' => null]], $processor->getResponseData()); |
346
|
|
|
|
347
|
|
|
$processor->processPayload('{ invalidNonNullInsideQuery }'); |
348
|
|
|
$this->assertEquals(['errors' => [ |
349
|
|
|
['message' => 'Not valid value for SCALAR field invalidNonNullInsideQuery'] |
350
|
|
|
], 'data' => ['invalidNonNullInsideQuery' => null]], $processor->getResponseData()); |
351
|
|
|
|
352
|
|
|
$processor->processPayload('{ test:deepObjectQuery { object { name } } }'); |
353
|
|
|
$this->assertEquals(['data' => ['test' => ['object' => ['name' => 'John']]]], $processor->getResponseData()); |
354
|
|
|
} |
355
|
|
|
|
356
|
|
|
public function testTypedFragment() |
357
|
|
|
{ |
358
|
|
|
|
359
|
|
|
$object1 = new ObjectType([ |
360
|
|
|
'name' => 'Object1', |
361
|
|
|
'fields' => [ |
362
|
|
|
'id' => ['type' => 'int'] |
363
|
|
|
] |
364
|
|
|
]); |
365
|
|
|
|
366
|
|
|
$object2 = new ObjectType([ |
367
|
|
|
'name' => 'Object2', |
368
|
|
|
'fields' => [ |
369
|
|
|
'name' => ['type' => 'string'] |
370
|
|
|
] |
371
|
|
|
]); |
372
|
|
|
|
373
|
|
|
$object3 = new ObjectType([ |
374
|
|
|
'name' => 'Object3', |
375
|
|
|
'fields' => [ |
376
|
|
|
'name' => ['type' => 'string'] |
377
|
|
|
] |
378
|
|
|
]); |
379
|
|
|
|
380
|
|
|
$union = new UnionType([ |
381
|
|
|
'name' => 'TestUnion', |
382
|
|
|
'types' => [$object1, $object2], |
383
|
|
|
'resolveType' => function ($object) use ($object1, $object2) { |
384
|
|
|
if (isset($object['id'])) { |
385
|
|
|
return $object1; |
386
|
|
|
} |
387
|
|
|
|
388
|
|
|
return $object2; |
389
|
|
|
} |
390
|
|
|
]); |
391
|
|
|
$invalidUnion = new UnionType([ |
392
|
|
|
'name' => 'TestUnion', |
393
|
|
|
'types' => [$object1, $object2], |
394
|
|
|
'resolveType' => function ($object) use ($object3) { |
|
|
|
|
395
|
|
|
return $object3; |
396
|
|
|
} |
397
|
|
|
]); |
398
|
|
|
$processor = new Processor(new Schema([ |
399
|
|
|
'query' => new ObjectType([ |
400
|
|
|
'name' => 'RootQuery', |
401
|
|
|
'fields' => [ |
402
|
|
|
'union' => [ |
403
|
|
|
'type' => $union, |
404
|
|
|
'args' => [ |
405
|
|
|
'type' => ['type' => 'string'] |
406
|
|
|
], |
407
|
|
|
'resolve' => function ($value, $args) { |
408
|
|
|
if ($args['type'] == 'object1') { |
409
|
|
|
return [ |
410
|
|
|
'id' => 43 |
411
|
|
|
]; |
412
|
|
|
} else { |
413
|
|
|
return [ |
414
|
|
|
'name' => 'name resolved' |
415
|
|
|
]; |
416
|
|
|
} |
417
|
|
|
} |
418
|
|
|
], |
419
|
|
|
'invalidUnion' => [ |
420
|
|
|
'type' => $invalidUnion, |
421
|
|
|
'resolve' => function () { |
422
|
|
|
return ['name' => 'name resolved']; |
423
|
|
|
} |
424
|
|
|
], |
425
|
|
|
] |
426
|
|
|
]) |
427
|
|
|
])); |
428
|
|
|
$processor->processPayload('{ union(type: "object1") { ... on Object2 { id } } }'); |
429
|
|
|
$this->assertEquals(['data' => ['union' => []]], $processor->getResponseData()); |
430
|
|
|
|
431
|
|
|
$processor->processPayload('{ union(type: "object1") { ... on Object1 { name } } }'); |
432
|
|
|
$this->assertEquals([ |
433
|
|
|
'data' => [ |
434
|
|
|
'union' => [] |
435
|
|
|
], |
436
|
|
|
'errors' => [ |
437
|
|
|
['message' => 'Field "name" not found in type "Object1"'] |
438
|
|
|
] |
439
|
|
|
], $processor->getResponseData()); |
440
|
|
|
|
441
|
|
|
$processor->processPayload('{ union(type: "object1") { ... on Object1 { id } } }'); |
442
|
|
|
$this->assertEquals(['data' => ['union' => ['id' => 43]]], $processor->getResponseData()); |
443
|
|
|
|
444
|
|
|
$processor->processPayload('{ union(type: "asd") { ... on Object2 { name } } }'); |
445
|
|
|
$this->assertEquals(['data' => ['union' => ['name' => 'name resolved']]], $processor->getResponseData()); |
446
|
|
|
|
447
|
|
|
$processor->processPayload('{ invalidUnion { ... on Object2 { name } } }'); |
448
|
|
|
$this->assertEquals(['errors' => [['message' => 'Type Object3 not exist in types of Object2']]], $processor->getResponseData()); |
449
|
|
|
|
450
|
|
|
} |
451
|
|
|
|
452
|
|
|
public function testSchemaWithResolveString() |
453
|
|
|
{ |
454
|
|
|
$resolveFactory = $this->prophesize(ResolveStringResolverInterface::class); |
455
|
|
|
$resolveFactory->resolve('service_name:get') |
456
|
|
|
->shouldBeCalled() |
457
|
|
|
->willReturn(function () { |
458
|
|
|
return 'hello'; |
459
|
|
|
}); |
460
|
|
|
|
461
|
|
|
$processor = new Processor(new Schema([ |
462
|
|
|
'query' => new ObjectType([ |
463
|
|
|
'name' => 'RootQuery', |
464
|
|
|
'fields' => [ |
465
|
|
|
'string' => [ |
466
|
|
|
'type' => new StringType(), |
467
|
|
|
'resolveString' => 'service_name:get', |
468
|
|
|
] |
469
|
|
|
] |
470
|
|
|
]) |
471
|
|
|
]), $resolveFactory->reveal()); |
472
|
|
|
$data = $processor->processPayload(' { string }')->getResponseData(); |
473
|
|
|
$this->assertEquals(['data' => ['string' => 'hello']], $data); |
474
|
|
|
} |
475
|
|
|
|
476
|
|
|
|
477
|
|
|
} |
478
|
|
|
|
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.