FragmentTestCase::appendAttribute()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 2
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
namespace Agavi\Testing;
3
4
// +---------------------------------------------------------------------------+
5
// | This file is part of the Agavi package.                                   |
6
// | Copyright (c) 2005-2011 the Agavi Project.                                |
7
// |                                                                           |
8
// | For the full copyright and license information, please view the LICENSE   |
9
// | file that was distributed with this source code. You can also view the    |
10
// | LICENSE file online at http://www.agavi.org/LICENSE.txt                   |
11
// |   vi: set noexpandtab:                                                    |
12
// |   Local Variables:                                                        |
13
// |   indent-tabs-mode: t                                                     |
14
// |   End:                                                                    |
15
// +---------------------------------------------------------------------------+
16
use Agavi\Controller\Controller;
17
use Agavi\Core\Context;
18
use Agavi\Dispatcher\ExecutionContainer;
19
use Agavi\Dispatcher\OutputType;
20
use Agavi\Filter\ExecutionFilter;
21
use Agavi\Request\RequestDataHolder;
22
use Agavi\Util\Toolkit;
23
use Agavi\View\View;
24
25
/**
26
 * FragmentTestCase is the base class for all fragment tests and provides
27
 * the necessary assertions
28
 *
29
 *
30
 * @package    agavi
31
 * @subpackage testing
32
 *
33
 * @author     Felix Gilcher <[email protected]>
34
 * @copyright  The Agavi Project
35
 *
36
 * @since      1.0.0
37
 *
38
 * @version    $Id$
39
 */
40
abstract class FragmentTestCase extends PhpUnitTestCase implements FragmentTestCaseInterface
41
{
42
    /**
43
     * @var        string the name of the context to use, null for default context
44
     */
45
    protected $contextName = null;
46
    
47
    /**
48
     * @var        string the name of the controller to test
49
     */
50
    protected $controllerName;
51
    
52
    /**
53
     * @var        string the name of the module
54
     */
55
    protected $moduleName;
56
    
57
    /**
58
     * @var        bool   the result of the validation process
59
     */
60
    protected $validationSuccess;
61
    
62
    /**
63
     * @var        ExecutionContainer the container to run the controller in
64
     */
65
    protected $container;
66
67
68
    /**
69
     * Constructs a test case with the given name.
70
     *
71
     * @param  string $name
72
     * @param  array  $data
73
     * @param  string $dataName
74
     */
75
    public function __construct($name = null, array $data = array(), $dataName = '')
76
    {
77
        parent::__construct($name, $data, $dataName);
78
        $this->setRunTestInSeparateProcess(true);
79
    }
80
    
81
    
82
    /**
83
     * creates a new ExecutionContainer for each test
84
     *
85
     * @return void
86
     *
87
     * @author     Felix Gilcher <[email protected]>
88
     * @since      1.0.0
89
     */
90
    public function setUp()
91
    {
92
        $this->container = $this->createExecutionContainer();
93
    }
94
    
95
    
96
    /**
97
     * unsets the ExecutionContainer after each test
98
     *
99
     * @return void
100
     *
101
     * @author     Felix Gilcher <[email protected]>
102
     * @since      1.0.0
103
     */
104
    public function tearDown()
105
    {
106
        $this->container = null;
107
    }
108
    
109
    /**
110
     * Return the context defined for this test (or the default one).
111
     *
112
     * @return     Context The context instance defined for this test.
113
     *
114
     * @author     Felix Gilcher <[email protected]>
115
     * @since      1.0.0
116
     */
117
    public function getContext()
118
    {
119
        return Context::getInstance($this->contextName);
120
    }
121
    
122
    /**
123
     * normalizes a viewname according to the configured rules
124
     *
125
     * Please do not use this method, it exists only for internal
126
     * purposes and will be removed ASAP. You have been warned
127
     *
128
     * @param      string $shortName the short view name
129
     *
130
     * @return     string the full view name
131
     *
132
     * @author     Felix Gilcher <[email protected]>
133
     * @since      1.0.0
134
     */
135
    protected function normalizeViewName($shortName)
136
    {
137
        if ($shortName !== View::NONE) {
138
            $shortName = Toolkit::evaluateModuleDirective(
139
                $this->moduleName,
140
                'agavi.view.name',
141
                array(
142
                    'controllerName' => $this->controllerName,
143
                    'viewName' => $shortName,
144
                )
145
            );
146
            $shortName = Toolkit::canonicalName($shortName);
147
        }
148
        
149
        return $shortName;
150
    }
151
152
    /**
153
     * create an executionfilter for the test
154
     *
155
     * the configured executionfilter class will be wrapped in a testing
156
     * extension to provide advanced capabilities required for testing
157
     * only
158
     *
159
     * @return     ExecutionFilter
160
     *
161
     * @author     Felix Gilcher <[email protected]>
162
     * @since      1.0.0
163
     */
164
    protected function createExecutionFilter()
165
    {
166
        $effi = $this->getContext()->getFactoryInfo('execution_filter');
167
168
        $wrapper_class = $effi['class'].'UnitTesting';
169
170
        // Grab the actual class name
171 View Code Duplication
        if (($pos = strrpos($wrapper_class, '\\')) !== false) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
172
            $wrapper_class = substr($wrapper_class, $pos+1);
173
        }
174
175
        //extend the original class to overwrite runController, so that the containers request data is cloned
176 View Code Duplication
        if (!class_exists($wrapper_class)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
177
            $code = sprintf('class %1$s extends %2$s
178
{
179
	protected $validationResult = null;
180
	
181
	public function executeView(Agavi\Dispatcher\ExecutionContainer $container)
182
	{
183
		$container->initRequestData();
184
		return parent::executeView($container);
185
	}
186
}',
187
            $wrapper_class,
188
            $effi['class']);
189
190
            eval($code);
0 ignored issues
show
Coding Style introduced by
It is generally not recommended to use eval unless absolutely required.

On one hand, eval might be exploited by malicious users if they somehow manage to inject dynamic content. On the other hand, with the emergence of faster PHP runtimes like the HHVM, eval prevents some optimization that they perform.

Loading history...
191
        }
192
193
        // create a new execution container with the wrapped class
194
        $filter = new $wrapper_class();
195
        $filter->initialize($this->getContext(), $effi['parameters']);
196
        return $filter;
197
    }
198
199
    /**
200
     * create an ExecutionContainer for the test
201
     *
202
     * the configured ExecutionContainer class will be wrapped in a testing
203
     * extension to provide advanced capabilities required for testing
204
     * only
205
     *
206
     * @return     ExecutionContainer
207
     *
208
     * @author     Felix Gilcher <[email protected]>
209
     * @since      1.0.0
210
     */
211
    protected function createExecutionContainer($arguments = null, $outputType = null, $requestMethod = null)
212
    {
213
        $context = $this->getContext();
214
215
        $ecfi = $context->getFactoryInfo('execution_container');
216
        $wrapper_class = $ecfi['class'].'UnitTesting';
217
218
        // Grab the actual class name
219 View Code Duplication
        if (($pos = strrpos($wrapper_class, '\\')) !== false) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
220
            $wrapper_class = substr($wrapper_class, $pos+1);
221
        }
222
223
        //extend the original class to add a setter for the controller instance
224 View Code Duplication
        if (!class_exists($wrapper_class)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
225
            $code = sprintf('class %1$s extends %2$s
226
{
227
228
	public function setControllerInstance(Agavi\Controller\Controller $controller)
229
	{
230
		$this->controllerInstance = $controller;
231
	}
232
	
233
	public function initRequestData()
234
	{
235
		parent::initRequestData();
236
	}
237
}',
238
            $wrapper_class,
239
            $ecfi['class']);
240
241
            eval($code);
0 ignored issues
show
Coding Style introduced by
It is generally not recommended to use eval unless absolutely required.

On one hand, eval might be exploited by malicious users if they somehow manage to inject dynamic content. On the other hand, with the emergence of faster PHP runtimes like the HHVM, eval prevents some optimization that they perform.

Loading history...
242
        }
243
        
244
        $ecfi['class'] = $wrapper_class;
245
        $context->setFactoryInfo('execution_container', $ecfi);
246
        
247
        if (!($arguments instanceof RequestDataHolder)) {
248
            $arguments = $this->createRequestDataHolder(array(RequestDataHolder::SOURCE_PARAMETERS => $arguments));
249
        }
250
        // create a new execution container with the wrapped class
251
        $container = $context->getDispatcher()->createExecutionContainer($this->moduleName, $this->controllerName, $arguments, $outputType, $requestMethod);
252
        
253
        return $container;
254
    }
255
256
    /**
257
     * creates an Controller instance and initializes it with this testcases
258
     * container
259
     *
260
     * @return     Controller
261
     *
262
     * @author     Felix Gilcher <[email protected]>
263
     * @since      1.0.0
264
     */
265
    protected function createControllerInstance()
266
    {
267
        $controllerInstance = $this->getContext()->getDispatcher()->createControllerInstance($this->moduleName, $this->controllerName);
268
        $controllerInstance->initialize($this->container);
269
        return $controllerInstance;
270
    }
271
    
272
    /**
273
     * create a requestDataHolder with the given arguments and type
274
     *
275
     * arguments need to be passed in the way {@see AgaviRequestDataHolder} accepts them
276
     *
277
     * array(AgaviRequestDataHolder::SOURCE_PARAMETERS => array('foo' => 'bar'))
278
     *
279
     * if no type is passed, the default for the configured request class will be used
280
     *
281
     * @param      array   a two-dimensional array with the arguments
282
     * @param      string  the subclass of AgaviRequestDataHolder to create
283
     *
284
     * @return     RequestDataHolder
285
     *
286
     * @author     Felix Gilcher <[email protected]>
287
     * @since      1.0.0
288
     */
289
    protected function createRequestDataHolder(array $arguments = array(), $type = null)
290
    {
291
        if (null === $type) {
292
            $type = $this->getContext()->getRequest()->getParameter('request_data_holder_class', 'AgaviRequestDataHolder');
293
        }
294
        
295
        $class = new $type($arguments);
296
        return $class;
297
    }
298
    
299
    
300
    /**
301
     * assert that the exectionContainer has a given attribute with the expected value
302
     *
303
     * @param      mixed   $expected the expected attribute value
304
     * @param      string  $attributeName the attribute name
305
     * @param      string  $namespace the attribute namespace
306
     * @param      string  $message an optional message to display if the test fails
307
     * @param      float   $delta
308
     * @param      integer $maxDepth
309
     * @param      boolean $canonicalizeEol
310
     *
311
     * @see        PHPUnit_Framework_Assert::assertEquals()
312
     *
313
     * @author     Felix Gilcher <[email protected]>
314
     * @since      1.0.0
315
     */
316
    protected function assertContainerAttributeEquals($expected, $attributeName, $namespace = null, $message = 'Failed asserting that the attribute <%1$s/%2$s> has the value <%3$s>', $delta = 0.0, $maxDepth = 10, $canonicalizeEol = false)
317
    {
318
        $this->assertEquals($expected, $this->container->getAttribute($attributeName, $namespace), sprintf($message, $namespace, $attributeName, $expected), $delta, $maxDepth, $canonicalizeEol);
319
    }
320
    
321
    /**
322
     * assert that the executionContainer has a given attribute
323
     *
324
     * @param      string  $attributeName the attribute name
325
     * @param      string  $namespace the attribute namespace
326
     * @param      string  $message an optional message to display if the test fails
327
     *
328
     * @author     Felix Gilcher <[email protected]>
329
     * @since      1.0.0
330
     */
331
    protected function assertContainerAttributeExists($attributeName, $namespace = null, $message = 'Failed asserting that the container has an attribute named <%1$s/%2$s>.')
332
    {
333
        $this->assertTrue($this->container->hasAttribute($attributeName, $namespace), sprintf($message, $namespace, $attributeName));
334
    }
335
    
336
    /* --- container delegates --- */
337
338
    /**
339
     * @see        AgaviExcutionContainer::setOutputType()
340
     *
341
     * @author     Felix Gilcher <[email protected]>
342
     * @since      1.0.0
343
     */
344
    protected function setOutputType(OutputType $outputType)
345
    {
346
        $this->container->setOutputType($outputType);
347
    }
348
349
    /**
350
     * @see        AgaviRequest::setRequestData()
351
     *
352
     * @author     Felix Gilcher <[email protected]>
353
     * @since      1.0.0
354
     */
355
    protected function setRequestData(RequestDataHolder $rd)
356
    {
357
        $this->container->setRequestData($rd);
358
    }
359
    
360
    /**
361
     * @see        AgaviExcutionContainer::setArguments()
362
     *
363
     * @author     Felix Gilcher <[email protected]>
364
     * @since      1.0.0
365
     */
366
    protected function setArguments(RequestDataHolder $rd)
367
    {
368
        $this->container->setArguments($rd);
369
    }
370
371
    /**
372
     * @see        AgaviExcutionContainer::setRequestMethod()
373
     *
374
     * @author     Felix Gilcher <[email protected]>
375
     * @since      1.0.0
376
     */
377
    protected function setRequestMethod($method)
378
    {
379
        $this->container->setRequestMethod($method);
380
    }
381
382
    /**
383
     * @see        AgaviAttributeHolder::clearAttributes()
384
     *
385
     * @author     Felix Gilcher <[email protected]>
386
     * @since      1.0.0
387
     */
388
    protected function clearAttributes()
389
    {
390
        $this->container->clearAttributes();
391
    }
392
393
    /**
394
     * @see        AgaviAttributeHolder::getAttribute()
395
     *
396
     * @author     Felix Gilcher <[email protected]>
397
     * @since      1.0.0
398
     */
399
    protected function &getAttribute($name, $default = null)
400
    {
401
        return $this->container->getAttribute($name, null, $default);
402
    }
403
404
    /**
405
     * @see        AgaviAttributeHolder::getAttributeNames()
406
     *
407
     * @author     Felix Gilcher <[email protected]>
408
     * @since      1.0.0
409
     */
410
    protected function getAttributeNames()
411
    {
412
        return $this->container->getAttributeNames();
413
    }
414
415
    /**
416
     * @see        AgaviAttributeHolder::getAttributes()
417
     *
418
     * @author     Felix Gilcher <[email protected]>
419
     * @since      1.0.0
420
     */
421
    protected function &getAttributes()
422
    {
423
        return $this->container->getAttributes();
424
    }
425
426
    /**
427
     * @see        AgaviAttributeHolder::hasAttribute()
428
     *
429
     * @author     Felix Gilcher <[email protected]>
430
     * @since      1.0.0
431
     */
432
    protected function hasAttribute($name)
433
    {
434
        return $this->container->hasAttribute($name);
435
    }
436
437
    /**
438
     * @see        AgaviAttributeHolder::removeAttribute()
439
     *
440
     * @author     Felix Gilcher <[email protected]>
441
     * @since      1.0.0
442
     */
443
    protected function &removeAttribute($name)
444
    {
445
        return $this->container->removeAttribute($name);
446
    }
447
448
    /**
449
     * @see        AgaviAttributeHolder::setAttribute()
450
     *
451
     * @author     Felix Gilcher <[email protected]>
452
     * @since      1.0.0
453
     */
454
    protected function setAttribute($name, $value)
455
    {
456
        $this->container->setAttribute($name, $value);
457
    }
458
459
    /**
460
     * @see        AgaviAttributeHolder::appendAttribute()
461
     *
462
     * @author     Felix Gilcher <[email protected]>
463
     * @since      1.0.0
464
     */
465
    protected function appendAttribute($name, $value)
466
    {
467
        $this->container->appendAttribute($name, $value);
468
    }
469
470
    /**
471
     * @see        AgaviAttributeHolder::setAttributesByRef()
472
     *
473
     * @author     Felix Gilcher <[email protected]>
474
     * @since      1.0.0
475
     */
476
    protected function setAttributeByRef($name, &$value)
477
    {
478
        $this->container->setAttributeByRef($name, $value);
479
    }
480
481
    /**
482
     * @see        AgaviAttributeHolder::appendAttributeByRef()
483
     *
484
     * @author     Felix Gilcher <[email protected]>
485
     * @since      1.0.0
486
     */
487
    protected function appendAttributeByRef($name, &$value)
488
    {
489
        $this->container->appendAttributeByRef($name, $value);
490
    }
491
492
    /**
493
     * @see        AgaviAttributeHolder::setAttributes()
494
     *
495
     * @author     Felix Gilcher <[email protected]>
496
     * @since      1.0.0
497
     */
498
    protected function setAttributes(array $attributes)
499
    {
500
        $this->container->setAttributes($attributes);
501
    }
502
503
    /**
504
     * @see        AgaviAttributeHolder::setAttributesByRef()
505
     *
506
     * @author     Felix Gilcher <[email protected]>
507
     * @since      1.0.0
508
     */
509
    protected function setAttributesByRef(array &$attributes)
510
    {
511
        $this->container->setAttributesByRef($attributes);
512
    }
513
}
514