1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Oro\Bundle\WorkflowBundle\Tests\Unit\Model; |
4
|
|
|
|
5
|
|
|
use Oro\Bundle\WorkflowBundle\Configuration\WorkflowConfiguration; |
6
|
|
|
use Oro\Bundle\WorkflowBundle\Form\Type\WorkflowTransitionType; |
7
|
|
|
use Oro\Bundle\WorkflowBundle\Model\Transition; |
8
|
|
|
use Oro\Bundle\WorkflowBundle\Model\TransitionAssembler; |
9
|
|
|
|
10
|
|
|
use Oro\Component\Action\Action\Configurable as ConfigurableAction; |
11
|
|
|
use Oro\Component\Action\Condition\Configurable as ConfigurableCondition; |
12
|
|
|
|
13
|
|
|
class TransitionAssemblerTest extends \PHPUnit_Framework_TestCase |
14
|
|
|
{ |
15
|
|
|
/** |
16
|
|
|
* @var \PHPUnit_Framework_MockObject_MockObject |
17
|
|
|
*/ |
18
|
|
|
protected $formOptionsAssembler; |
19
|
|
|
|
20
|
|
|
/** |
21
|
|
|
* @var \PHPUnit_Framework_MockObject_MockObject |
22
|
|
|
*/ |
23
|
|
|
protected $conditionFactory; |
24
|
|
|
|
25
|
|
|
/** |
26
|
|
|
* @var \PHPUnit_Framework_MockObject_MockObject |
27
|
|
|
*/ |
28
|
|
|
protected $actionFactory; |
29
|
|
|
|
30
|
|
|
/** |
31
|
|
|
* @var TransitionAssembler |
32
|
|
|
*/ |
33
|
|
|
protected $assembler; |
34
|
|
|
|
35
|
|
|
/** |
36
|
|
|
* @var array |
37
|
|
|
*/ |
38
|
|
|
protected $transitionDefinitions = array( |
39
|
|
|
'empty_definition' => array(), |
40
|
|
|
'with_pre_condition' => array( |
41
|
|
|
'pre_conditions' => array('@true' => null) |
42
|
|
|
), |
43
|
|
|
'with_condition' => array( |
44
|
|
|
'conditions' => array('@true' => null) |
45
|
|
|
), |
46
|
|
|
'with_post_actions' => array( |
47
|
|
|
'post_actions' => array('@assign_value' => array('parameters' => array('$attribute', 'first_value'))) |
48
|
|
|
), |
49
|
|
|
'full_definition' => array( |
50
|
|
|
'page_template' => 'Test:Page:template', |
51
|
|
|
'dialog_template' => 'Test:Dialog:template', |
52
|
|
|
'pre_conditions' => array('@true' => null), |
53
|
|
|
'conditions' => array('@true' => null), |
54
|
|
|
'post_actions' => array('@assign_value' => array('parameters' => array('$attribute', 'first_value'))), |
55
|
|
|
) |
56
|
|
|
); |
57
|
|
|
|
58
|
|
|
protected function setUp() |
59
|
|
|
{ |
60
|
|
|
$this->formOptionsAssembler = $this->getMockBuilder('Oro\Bundle\WorkflowBundle\Model\FormOptionsAssembler') |
61
|
|
|
->disableOriginalConstructor() |
62
|
|
|
->setMethods(array('assemble')) |
63
|
|
|
->getMock(); |
64
|
|
|
|
65
|
|
|
$this->conditionFactory = $this->getMockBuilder('Oro\Component\ConfigExpression\ExpressionFactory') |
66
|
|
|
->disableOriginalConstructor() |
67
|
|
|
->getMock(); |
68
|
|
|
$this->actionFactory = $this->getMockBuilder('Oro\Component\Action\Action\ActionFactory') |
69
|
|
|
->disableOriginalConstructor() |
70
|
|
|
->getMock(); |
71
|
|
|
$this->assembler = new TransitionAssembler( |
72
|
|
|
$this->formOptionsAssembler, |
73
|
|
|
$this->conditionFactory, |
74
|
|
|
$this->actionFactory |
75
|
|
|
); |
76
|
|
|
} |
77
|
|
|
|
78
|
|
|
/** |
79
|
|
|
* @expectedException \Oro\Component\Action\Exception\AssemblerException |
80
|
|
|
* @dataProvider missedTransitionDefinitionDataProvider |
81
|
|
|
* @param array $configuration |
82
|
|
|
*/ |
83
|
|
|
public function testAssembleNoRequiredTransitionDefinitionException($configuration) |
84
|
|
|
{ |
85
|
|
|
$this->assembler->assemble($configuration, array(), array(), array()); |
86
|
|
|
} |
87
|
|
|
|
88
|
|
|
public function missedTransitionDefinitionDataProvider() |
89
|
|
|
{ |
90
|
|
|
return array( |
91
|
|
|
'no options' => array( |
92
|
|
|
array( |
93
|
|
|
'name' => array() |
94
|
|
|
) |
95
|
|
|
), |
96
|
|
|
'no transition_definition' => array( |
97
|
|
|
array( |
98
|
|
|
'name' => array( |
99
|
|
|
'' => 'test' |
100
|
|
|
) |
101
|
|
|
) |
102
|
|
|
) |
103
|
|
|
); |
104
|
|
|
} |
105
|
|
|
|
106
|
|
|
/** |
107
|
|
|
* @expectedException \Oro\Component\Action\Exception\AssemblerException |
108
|
|
|
* @dataProvider incorrectTransitionDefinitionDataProvider |
109
|
|
|
* @param array $definitions |
110
|
|
|
*/ |
111
|
|
|
public function testUnknownTransitionDefinitionAssembler($definitions) |
112
|
|
|
{ |
113
|
|
|
$configuration = array( |
114
|
|
|
'test' => array( |
115
|
|
|
'transition_definition' => 'unknown' |
116
|
|
|
) |
117
|
|
|
); |
118
|
|
|
$this->assembler->assemble($configuration, $definitions, array(), array()); |
119
|
|
|
} |
120
|
|
|
|
121
|
|
|
public function incorrectTransitionDefinitionDataProvider() |
122
|
|
|
{ |
123
|
|
|
return array( |
124
|
|
|
'no definitions' => array( |
125
|
|
|
array() |
126
|
|
|
), |
127
|
|
|
'definitions as null' => array( |
128
|
|
|
array('some' => null) |
129
|
|
|
), |
130
|
|
|
'unknown definition' => array( |
131
|
|
|
array('known' => array()) |
132
|
|
|
) |
133
|
|
|
); |
134
|
|
|
} |
135
|
|
|
|
136
|
|
|
/** |
137
|
|
|
* @expectedException \Oro\Component\Action\Exception\AssemblerException |
138
|
|
|
* @dataProvider incorrectStepsDataProvider |
139
|
|
|
* @param array $steps |
140
|
|
|
*/ |
141
|
|
|
public function testUnknownStepException($steps) |
142
|
|
|
{ |
143
|
|
|
$configuration = array( |
144
|
|
|
'test' => array( |
145
|
|
|
'transition_definition' => 'transition_definition', |
146
|
|
|
'label' => 'label', |
147
|
|
|
'step_to' => 'unknown' |
148
|
|
|
) |
149
|
|
|
); |
150
|
|
|
$definitions = array('transition_definition' => array()); |
151
|
|
|
$this->assembler->assemble($configuration, $definitions, $steps, array()); |
152
|
|
|
} |
153
|
|
|
|
154
|
|
|
public function incorrectStepsDataProvider() |
155
|
|
|
{ |
156
|
|
|
return array( |
157
|
|
|
'no steps' => array( |
158
|
|
|
array() |
159
|
|
|
), |
160
|
|
|
'unknown step' => array( |
161
|
|
|
array('known' => $this->createStep()) |
162
|
|
|
) |
163
|
|
|
); |
164
|
|
|
} |
165
|
|
|
|
166
|
|
|
/** |
167
|
|
|
* @dataProvider configurationDataProvider |
168
|
|
|
* @param array $configuration |
169
|
|
|
* @param array $transitionDefinition |
170
|
|
|
* @SuppressWarnings(PHPMD.NPathComplexity) |
171
|
|
|
* @SuppressWarnings(PHPMD.ExcessiveMethodLength) |
172
|
|
|
*/ |
173
|
|
|
public function testAssemble(array $configuration, array $transitionDefinition) |
174
|
|
|
{ |
175
|
|
|
$steps = array( |
176
|
|
|
'step' => $this->createStep() |
177
|
|
|
); |
178
|
|
|
|
179
|
|
|
$attributes = array( |
180
|
|
|
'attribute' => $this->createAttribute() |
181
|
|
|
); |
182
|
|
|
|
183
|
|
|
$expectedCondition = null; |
184
|
|
|
$expectedPreCondition = $this->createCondition(); |
185
|
|
|
$expectedAction = null; |
186
|
|
|
$defaultAclPrecondition = array(); |
187
|
|
|
$preConditions = array(); |
188
|
|
|
|
189
|
|
|
if (isset($configuration['acl_resource'])) { |
190
|
|
|
$defaultAclPrecondition = array( |
191
|
|
|
'@acl_granted' => array( |
192
|
|
|
'parameters' => array($configuration['acl_resource']) |
193
|
|
|
) |
194
|
|
|
); |
195
|
|
|
|
196
|
|
|
if (isset($configuration['acl_message'])) { |
197
|
|
|
$defaultAclPrecondition['@acl_granted']['message'] = $configuration['acl_message']; |
198
|
|
|
} |
199
|
|
|
} |
200
|
|
|
|
201
|
|
|
if (isset($transitionDefinition['pre_conditions']) && $defaultAclPrecondition) { |
|
|
|
|
202
|
|
|
$preConditions = array( |
203
|
|
|
'@and' => array( |
204
|
|
|
$defaultAclPrecondition, |
205
|
|
|
$transitionDefinition['pre_conditions'] |
206
|
|
|
) |
207
|
|
|
); |
208
|
|
|
} elseif (isset($transitionDefinition['pre_conditions'])) { |
209
|
|
|
$preConditions = $transitionDefinition['pre_conditions']; |
210
|
|
|
} |
211
|
|
|
|
212
|
|
|
$count = 0; |
213
|
|
|
|
214
|
|
|
if ($preConditions) { |
215
|
|
|
$this->conditionFactory->expects($this->at($count)) |
216
|
|
|
->method('create') |
217
|
|
|
->with(ConfigurableCondition::ALIAS, $preConditions) |
218
|
|
|
->will($this->returnValue($expectedPreCondition)); |
219
|
|
|
$count++; |
220
|
|
|
} |
221
|
|
|
|
222
|
|
|
if (array_key_exists('conditions', $transitionDefinition)) { |
223
|
|
|
$expectedCondition = $this->createCondition(); |
224
|
|
|
$this->conditionFactory->expects($this->at($count)) |
225
|
|
|
->method('create') |
226
|
|
|
->with(ConfigurableCondition::ALIAS, $transitionDefinition['conditions']) |
227
|
|
|
->will($this->returnValue($expectedCondition)); |
228
|
|
|
} |
229
|
|
|
|
230
|
|
|
$actionFactoryCallCount = 0; |
231
|
|
|
|
232
|
|
|
if (array_key_exists('post_actions', $transitionDefinition)) { |
233
|
|
|
$actionFactoryCallCount++; |
234
|
|
|
} |
235
|
|
|
|
236
|
|
|
if (array_key_exists('init_actions', $transitionDefinition)) { |
237
|
|
|
$actionFactoryCallCount++; |
238
|
|
|
} |
239
|
|
|
|
240
|
|
|
if ($actionFactoryCallCount) { |
241
|
|
|
$expectedAction = $this->createAction(); |
242
|
|
|
$this->actionFactory->expects($this->exactly($actionFactoryCallCount)) |
243
|
|
|
->method('create') |
244
|
|
|
->with(ConfigurableAction::ALIAS, $transitionDefinition['post_actions']) |
245
|
|
|
->will($this->returnValue($this->createAction())); |
246
|
|
|
} |
247
|
|
|
|
248
|
|
|
$this->formOptionsAssembler->expects($this->once()) |
249
|
|
|
->method('assemble') |
250
|
|
|
->with( |
251
|
|
|
isset($configuration['form_options']) ? $configuration['form_options'] : array(), |
252
|
|
|
$attributes, |
253
|
|
|
'transition', |
254
|
|
|
'test' |
255
|
|
|
) |
256
|
|
|
->will($this->returnArgument(0)); |
257
|
|
|
|
258
|
|
|
$transitions = $this->assembler->assemble( |
259
|
|
|
array('test' => $configuration), |
260
|
|
|
$this->transitionDefinitions, |
261
|
|
|
$steps, |
262
|
|
|
$attributes |
263
|
|
|
); |
264
|
|
|
|
265
|
|
|
$configuration = array_merge( |
266
|
|
|
array( |
267
|
|
|
'is_start' => false, |
268
|
|
|
'form_type' => WorkflowTransitionType::NAME, |
269
|
|
|
'form_options' => array(), |
270
|
|
|
'frontend_options' => array(), |
271
|
|
|
), |
272
|
|
|
$configuration |
273
|
|
|
); |
274
|
|
|
|
275
|
|
|
$this->assertInstanceOf('Doctrine\Common\Collections\ArrayCollection', $transitions); |
276
|
|
|
$this->assertCount(1, $transitions); |
277
|
|
|
$this->assertTrue($transitions->containsKey('test')); |
278
|
|
|
|
279
|
|
|
/** @var Transition $actualTransition */ |
280
|
|
|
$actualTransition = $transitions->get('test'); |
281
|
|
|
$this->assertEquals('test', $actualTransition->getName(), 'Incorrect name'); |
282
|
|
|
$this->assertEquals($steps['step'], $actualTransition->getStepTo(), 'Incorrect step_to'); |
283
|
|
|
$this->assertEquals($configuration['label'], $actualTransition->getLabel(), 'Incorrect label'); |
284
|
|
|
|
285
|
|
|
$expectedDisplayType = WorkflowConfiguration::DEFAULT_TRANSITION_DISPLAY_TYPE; |
286
|
|
|
|
287
|
|
|
if (isset($configuration['display_type'])) { |
288
|
|
|
$expectedDisplayType = $configuration['display_type']; |
289
|
|
|
} |
290
|
|
|
|
291
|
|
|
$this->assertEquals($expectedDisplayType, $actualTransition->getDisplayType(), 'Incorrect display type'); |
292
|
|
|
$this->assertEquals( |
293
|
|
|
$configuration['frontend_options'], |
294
|
|
|
$actualTransition->getFrontendOptions(), |
295
|
|
|
'Incorrect frontend_options' |
296
|
|
|
); |
297
|
|
|
$this->assertEquals($configuration['is_start'], $actualTransition->isStart(), 'Incorrect is_start'); |
298
|
|
|
$this->assertEquals($configuration['form_type'], $actualTransition->getFormType(), 'Incorrect form_type'); |
299
|
|
|
$this->assertEquals( |
300
|
|
|
$configuration['form_options'], |
301
|
|
|
$actualTransition->getFormOptions(), |
302
|
|
|
'Incorrect form_options' |
303
|
|
|
); |
304
|
|
|
|
305
|
|
|
$this->assertTemplate('page', $configuration, $actualTransition); |
306
|
|
|
$this->assertTemplate('dialog', $configuration, $actualTransition); |
307
|
|
|
|
308
|
|
|
if ($preConditions) { |
309
|
|
|
$this->assertEquals($expectedPreCondition, $actualTransition->getPreCondition(), 'Incorrect Precondition'); |
310
|
|
|
} else { |
311
|
|
|
$this->assertNull($actualTransition->getPreCondition(), 'Incorrect Precondition'); |
312
|
|
|
} |
313
|
|
|
|
314
|
|
|
$this->assertEquals($expectedCondition, $actualTransition->getCondition(), 'Incorrect condition'); |
315
|
|
|
$this->assertEquals($expectedAction, $actualTransition->getPostAction(), 'Incorrect post_action'); |
316
|
|
|
} |
317
|
|
|
|
318
|
|
|
/** |
319
|
|
|
* @param string $templateType |
320
|
|
|
* @param array $configuration |
321
|
|
|
* @param $actualTransition |
322
|
|
|
*/ |
323
|
|
|
protected function assertTemplate($templateType, $configuration, $actualTransition) |
324
|
|
|
{ |
325
|
|
|
$configKey = $templateType . '_template'; |
326
|
|
|
$getter = 'get' . ucfirst($templateType) . 'Template'; |
327
|
|
|
|
328
|
|
|
if (array_key_exists($configKey, $configuration)) { |
329
|
|
|
$this->assertEquals($configuration[$configKey], $actualTransition->$getter()); |
330
|
|
|
} else { |
331
|
|
|
$this->assertNull($actualTransition->$getter()); |
332
|
|
|
} |
333
|
|
|
} |
334
|
|
|
|
335
|
|
|
public function configurationDataProvider() |
336
|
|
|
{ |
337
|
|
|
return array( |
338
|
|
|
'empty_definition' => array( |
339
|
|
|
'configuration' => array( |
340
|
|
|
'transition_definition' => 'empty_definition', |
341
|
|
|
'label' => 'label', |
342
|
|
|
'step_to' => 'step', |
343
|
|
|
'form_type' => 'custom_workflow_transition', |
344
|
|
|
'display_type' => 'page', |
345
|
|
|
'form_options' => array( |
346
|
|
|
'attribute_fields' => array( |
347
|
|
|
'attribute_on_be' => array('type' => 'text') |
348
|
|
|
) |
349
|
|
|
), |
350
|
|
|
'frontend_options' => array('class' => 'foo', 'icon' => 'bar'), |
351
|
|
|
), |
352
|
|
|
'transitionDefinition' => $this->transitionDefinitions['empty_definition'], |
353
|
|
|
), |
354
|
|
|
'with_condition' => array( |
355
|
|
|
'configuration' => array( |
356
|
|
|
'transition_definition' => 'with_condition', |
357
|
|
|
'label' => 'label', |
358
|
|
|
'step_to' => 'step', |
359
|
|
|
), |
360
|
|
|
'transitionDefinition' => $this->transitionDefinitions['with_condition'], |
361
|
|
|
), |
362
|
|
|
'with_post_actions' => array( |
363
|
|
|
'configuration' => array( |
364
|
|
|
'transition_definition' => 'with_post_actions', |
365
|
|
|
'label' => 'label', |
366
|
|
|
'step_to' => 'step', |
367
|
|
|
), |
368
|
|
|
'transitionDefinition' => $this->transitionDefinitions['with_post_actions'], |
369
|
|
|
), |
370
|
|
|
'full_definition' => array( |
371
|
|
|
'configuration' => array( |
372
|
|
|
'transition_definition' => 'full_definition', |
373
|
|
|
'acl_resource' => 'test_acl', |
374
|
|
|
'acl_message' => 'test acl message', |
375
|
|
|
'label' => 'label', |
376
|
|
|
'step_to' => 'step', |
377
|
|
|
), |
378
|
|
|
'transitionDefinition' => $this->transitionDefinitions['full_definition'], |
379
|
|
|
), |
380
|
|
|
'start_transition' => array( |
381
|
|
|
'configuration' => array( |
382
|
|
|
'transition_definition' => 'empty_definition', |
383
|
|
|
'acl_resource' => 'test_acl', |
384
|
|
|
'acl_message' => 'test acl message', |
385
|
|
|
'label' => 'label', |
386
|
|
|
'step_to' => 'step', |
387
|
|
|
'is_start' => true, |
388
|
|
|
), |
389
|
|
|
'transitionDefinition' => $this->transitionDefinitions['empty_definition'], |
390
|
|
|
), |
391
|
|
|
); |
392
|
|
|
} |
393
|
|
|
|
394
|
|
|
protected function createStep() |
395
|
|
|
{ |
396
|
|
|
return $this->getMockBuilder('Oro\Bundle\WorkflowBundle\Model\Step') |
397
|
|
|
->disableOriginalConstructor() |
398
|
|
|
->getMock(); |
399
|
|
|
} |
400
|
|
|
|
401
|
|
|
protected function createAttribute() |
402
|
|
|
{ |
403
|
|
|
return $this->getMockBuilder('Oro\Bundle\ActionBundle\Model\Attribute') |
404
|
|
|
->disableOriginalConstructor() |
405
|
|
|
->getMock(); |
406
|
|
|
} |
407
|
|
|
|
408
|
|
|
protected function createCondition() |
409
|
|
|
{ |
410
|
|
|
return $this->getMockBuilder('Oro\Component\ConfigExpression\ExpressionInterface') |
411
|
|
|
->getMockForAbstractClass(); |
412
|
|
|
} |
413
|
|
|
|
414
|
|
|
protected function createAction() |
415
|
|
|
{ |
416
|
|
|
return $this->getMockBuilder('Oro\Component\Action\Action\ActionInterface') |
417
|
|
|
->getMockForAbstractClass(); |
418
|
|
|
} |
419
|
|
|
} |
420
|
|
|
|
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.