Completed
Push — master ( e32202...083db4 )
by Alex
08:17
created

AbstractActionTest::test update current step unsets steps that have to be changed()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 25
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 25
rs 8.8571
c 0
b 0
f 0
cc 1
eloc 16
nc 1
nop 0
1
<?php
2
3
/**
4
 * This file is part of the PierstovalCharacterManagerBundle package.
5
 *
6
 * (c) Alexandre Rock Ancelet <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Pierstoval\Bundle\CharacterManagerBundle\Tests\Action;
13
14
use InvalidArgumentException;
15
use PHPUnit_Framework_MockObject_MockObject as MockObject;
16
use Pierstoval\Bundle\CharacterManagerBundle\Model\Step;
17
use Pierstoval\Bundle\CharacterManagerBundle\Resolver\StepResolver;
18
use Pierstoval\Bundle\CharacterManagerBundle\Resolver\StepResolverInterface;
19
use Pierstoval\Bundle\CharacterManagerBundle\Tests\Controller\AbstractGeneratorControllerTest;
20
use Pierstoval\Bundle\CharacterManagerBundle\Tests\Fixtures\Stubs\Action\ConcreteAbstractActionStub;
21
use Pierstoval\Bundle\CharacterManagerBundle\Tests\Fixtures\Stubs\Entity\CharacterStub;
22
use Pierstoval\Bundle\CharacterManagerBundle\Tests\Fixtures\Stubs\Model\StepStub;
23
use RuntimeException;
24
use Symfony\Component\HttpFoundation\RedirectResponse;
25
use Symfony\Component\HttpFoundation\Request;
26
use Symfony\Component\Routing\RouterInterface;
27
use Symfony\Component\Translation\TranslatorInterface;
28
29
class AbstractActionTest extends AbstractGeneratorControllerTest
30
{
31
    /**
32
     * @dataProvider provideMethodsThatDependOnStepObject
33
     * @expectedException \RuntimeException
34
     * @expectedExceptionMessage Step is not defined in current step action. Did you run the "configure()" method?
35
     */
36
    public function test any method depending on step object throws exception(string $method, array $arguments = [])
37
    {
38
        $stub = new ConcreteAbstractActionStub();
39
        $stub->setRequest($this->createRequest());
40
41
        $stub->{$method}(...$arguments);
42
    }
43
44
    /**
45
     * @expectedException \InvalidArgumentException
46
     * @expectedExceptionMessage Step action must be a valid class implementing Pierstoval\Bundle\CharacterManagerBundle\Model\CharacterInterface. "stdClass" given.
47
     */
48
    public function test configure with wrong character class throws exception()
49
    {
50
        $stub = new ConcreteAbstractActionStub();
51
        $stub->configure('', '', \stdClass::class, $this->createMock(StepResolverInterface::class));
52
    }
53
54
    /**
55
     * @expectedException \InvalidArgumentException
56
     * @expectedExceptionMessage Step action must be a valid class implementing Pierstoval\Bundle\CharacterManagerBundle\Model\CharacterInterface. "string" given.
57
     */
58
    public function test configure with wrong character class type throws exception()
59
    {
60
        $stub = new ConcreteAbstractActionStub();
61
        $stub->configure('', '', 'wrong_class_name', $this->createMock(StepResolverInterface::class));
62
    }
63
64
    /**
65
     * @expectedException \InvalidArgumentException
66
     * @expectedExceptionMessage Expected Pierstoval\Bundle\CharacterManagerBundle\Action\StepActionInterface instance, "stdClass" given.
67
     */
68
    public function test configure with wrong steps class throws exception()
69
    {
70
        $stub = new ConcreteAbstractActionStub();
71
        $resolver = $this->createMock(StepResolverInterface::class);
72
        $resolver->expects($this->once())->method('resolve');
73
        $resolver->expects($this->once())->method('getManagerSteps')->willReturn([new \stdClass]);
74
        $stub->configure('', '', CharacterStub::class, $resolver);
75
    }
76
77
    /**
78
     * @expectedException \InvalidArgumentException
79
     * @expectedExceptionMessage Expected Pierstoval\Bundle\CharacterManagerBundle\Action\StepActionInterface instance, "string" given.
80
     */
81
    public function test configure with wrong steps type throws exception()
82
    {
83
        $stub = new ConcreteAbstractActionStub();
84
        $resolver = $this->createMock(StepResolverInterface::class);
85
        $resolver->expects($this->once())->method('resolve');
86
        $resolver->expects($this->once())->method('getManagerSteps')->willReturn(['error']);
87
        $stub->configure('', '', CharacterStub::class, $resolver);
88
    }
89
90
    public function provideMethodsThatDependOnStepObject()
91
    {
92
        yield ['updateCharacterStep', ['']];
93
        yield ['getCharacterProperty', []];
94
        yield ['nextStep', []];
95
    }
96
97
    public function test next step should increment in session()
98
    {
99
        /** @var RouterInterface|MockObject $router */
100
        $router = $this->createMock(RouterInterface::class);
101
102
        $router
103
            ->expects($this->once())
104
            ->method('generate')
105
            ->with('pierstoval_character_generator_step', ['requestStep' => 'step_2'])
106
            ->willReturn('/steps/step_2')
107
        ;
108
109
        $resolver = new StepResolver([
110
            'test_manager' => $this->createManagerConfiguration('test_manager', [
111
                'step_1' => [
112
                    'number' => 1,
113
                ],
114
                'step_2' => [
115
                    'number' => 2,
116
                ]
117
            ]),
118
        ]);
119
120
        $request = $this->createRequest();
121
122
        $stub1 = new ConcreteAbstractActionStub();
123
        $stub1->configure('test_manager', 'step_1', CharacterStub::class, $resolver);
124
125
        $stub1->setRequest($request);
126
        $stub1->setRouter($router);
127
128
        $response = $stub1->nextStep();
129
130
        static::assertInstanceOf(RedirectResponse::class, $response);
131
        static::assertEquals(2, $request->getSession()->get('step.test_manager'));
132
        static::assertTrue($response->isRedirect('/steps/step_2'));
133
    }
134
135
    public function test getCurrentCharacter with a correct session value()
136
    {
137
        $stub = new ConcreteAbstractActionStub();
138
        $stepStub = StepStub::createStub();
139
        $resolver = $this->createMock(StepResolverInterface::class);
140
        $resolver->expects($this->once())->method('resolve')->willReturn($stepStub);
141
        $resolver->expects($this->once())->method('getManagerSteps')->willReturn([$stepStub]);
142
143
        $stub->configure($stepStub->getManagerName(), $stepStub->getName(), CharacterStub::class, $resolver);
144
145
        // Prepare request & session
146
        $request = $this->createRequest();
147
        $value = ['key' => 'value'];
148
        $request->getSession()->set('character.test_manager', $value);
149
150
        $stub->setRequest($request);
151
152
        static::assertSame($stub->getCurrentCharacter(), $value);
153
    }
154
155
    public function test getCharacterProperty with no key()
156
    {
157
        $stub = new ConcreteAbstractActionStub();
158
        $stepStub = StepStub::createStub();
159
        $resolver = $this->createMock(StepResolverInterface::class);
160
        $resolver->expects($this->once())->method('resolve')->willReturn($stepStub);
161
        $resolver->expects($this->once())->method('getManagerSteps')->willReturn([$stepStub]);
162
163
        $stub->configure($stepStub->getManagerName(), $stepStub->getName(), CharacterStub::class, $resolver);
164
165
        // Prepare request & session
166
        $request = $this->createRequest();
167
        $value = ['test_step' => 'value'];
168
        $request->getSession()->set('character.test_manager', $value);
169
170
        $stub->setRequest($request);
171
172
        static::assertSame($value['test_step'], $stub->getCharacterProperty());
173
    }
174
175
    public function test getCharacterProperty with valid key()
176
    {
177
        $stub = new ConcreteAbstractActionStub();
178
        $stepStub = StepStub::createStub();
179
        $resolver = $this->createMock(StepResolverInterface::class);
180
        $resolver->expects($this->once())->method('resolve')->willReturn($stepStub);
181
        $resolver->expects($this->once())->method('getManagerSteps')->willReturn([$stepStub]);
182
183
        $stub->configure($stepStub->getManagerName(), $stepStub->getName(), CharacterStub::class, $resolver);
184
185
        // Prepare request & session
186
        $request = $this->createRequest();
187
        $value = ['test_step' => 'value'];
188
        $request->getSession()->set('character.test_manager', $value);
189
190
        $stub->setRequest($request);
191
192
        static::assertSame($value['test_step'], $stub->getCharacterProperty('test_step'));
193
    }
194
195
    public function test getCharacterProperty with non existent key()
196
    {
197
        $stub = new ConcreteAbstractActionStub();
198
        $stepStub = StepStub::createStub();
199
        $resolver = $this->createMock(StepResolverInterface::class);
200
        $resolver->expects($this->once())->method('resolve')->willReturn($stepStub);
201
        $resolver->expects($this->once())->method('getManagerSteps')->willReturn([$stepStub]);
202
203
        $stub->configure($stepStub->getManagerName(), $stepStub->getName(), CharacterStub::class, $resolver);
204
205
        $stub->setRequest($this->createRequest());
206
207
        static::assertNull($stub->getCharacterProperty('non_existent_key'));
208
    }
209
210
    public function test update current step value()
211
    {
212
        $stub = new ConcreteAbstractActionStub();
213
        $stepStub = StepStub::createStub(['number' => 2, 'name' => 'step_1']);
214
        $resolver = $this->createMock(StepResolverInterface::class);
215
        $resolver->expects($this->once())->method('resolve')->willReturn($stepStub);
216
        $resolver->expects($this->once())->method('getManagerSteps')->willReturn([$stepStub]);
217
218
        $stub->configure($stepStub->getManagerName(), $stepStub->getName(), CharacterStub::class, $resolver);
219
220
        // Prepare request & session
221
        $request = $this->createRequest();
222
223
        $stub->setRequest($request);
224
225
        $stub->updateCharacterStep('new_value');
226
227
        static::assertSame(['step_1' => 'new_value'], $request->getSession()->get('character.test_manager'));
228
        static::assertSame(2, $request->getSession()->get('step.test_manager'));
229
    }
230
231
    public function test update current step unsets steps that have to be changed()
232
    {
233
        $stub = new ConcreteAbstractActionStub();
234
        $stepStub = StepStub::createStub(['number' => 2, 'name' => 'step_1', 'onchange_clear' => ['step_2', 'step_3']]);
235
        $resolver = $this->createMock(StepResolverInterface::class);
236
        $resolver->expects($this->once())->method('resolve')->willReturn($stepStub);
237
        $resolver->expects($this->once())->method('getManagerSteps')->willReturn([$stepStub]);
238
        $step = new Step(2, 'step_1', \get_class($stub), 'step_1', 'main_manager', ['step_2', 'step_3'], []);
239
240
        // Prepare request & session
241
        $request = $this->createRequest();
242
243
        // Add "onchange" steps in session
244
        $request->getSession()->set('character.test_manager', ['step_2' => true, 'step_3' => true]);
245
246
        $stub->configure($stepStub->getManagerName(), $stepStub->getName(), CharacterStub::class, $resolver);
247
        $stub->setRequest($request);
248
249
        $stub->updateCharacterStep('new_value');
250
251
        static::assertSame(['step_1' => 'new_value'], $request->getSession()->get('character.test_manager'));
252
        static::assertSame($step->getNumber(), $request->getSession()->get('step.test_manager'));
253
        static::assertArrayNotHasKey('step_2', $request->getSession()->get('character.test_manager'));
254
        static::assertArrayNotHasKey('step_3', $request->getSession()->get('character.test_manager'));
255
    }
256
257
    public function test goToStep returns RedirectResponse object()
258
    {
259
        /** @var RouterInterface|MockObject $router */
260
        $router = $this->createMock(RouterInterface::class);
261
262
        $router
263
            ->expects($this->once())
264
            ->method('generate')
265
            ->with('pierstoval_character_generator_step', ['requestStep' => 'step_3'])
266
            ->willReturn('/steps/step_3')
267
        ;
268
269
        // Prepare all stubs for testing
270
        $stub = new ConcreteAbstractActionStub();
271
        $step1 = new Step(1, 'step_1', \get_class($stub), 'step_1', 'test_manager', [], []);
272
        $step2 = new Step(2, 'step_2', \get_class($stub), 'step_2', 'test_manager', [], []);
273
        $step3 = new Step(3, 'step_3', \get_class($stub), 'step_3', 'test_manager', [], []);
274
        $resolver = $this->createMock(StepResolverInterface::class);
275
        $resolver->expects($this->once())->method('resolve')->willReturn($step1);
276
        $resolver->expects($this->once())->method('getManagerSteps')->willReturn([$step1, $step2, $step3]);
277
        $stub->setRouter($router);
278
        $request = $this->createRequest();
279
        $stub->configure('test_manager', 'step_1', CharacterStub::class, $resolver);
280
        $stub->setRequest($request);
281
282
        $response = $stub->goToStep(3);
283
284
        static::assertInstanceOf(RedirectResponse::class, $response);
285
        static::assertTrue($response->isRedirect('/steps/step_3'));
286
        static::assertSame(3, $request->getSession()->get('step.test_manager'));
287
    }
288
289
    /**
290
     * @expectedException \InvalidArgumentException
291
     * @expectedExceptionMessage Cannot use Pierstoval\Bundle\CharacterManagerBundle\Action\AbstractStepAction::goToStep if no router is injected in AbstractStepAction.
292
     */
293
    public function test goToStep throws exception if no router()
294
    {
295
        $stub = new ConcreteAbstractActionStub();
296
        $stub->goToStep(1);
297
    }
298
299
    /**
300
     * @expectedException \InvalidArgumentException
301
     * @expectedExceptionMessage Invalid step: 25
302
     */
303
    public function test goToStep throws exception if step does not exist()
304
    {
305
        /** @var RouterInterface|MockObject $router */
306
        $router = $this->createMock(RouterInterface::class);
307
308
        $stub = new ConcreteAbstractActionStub();
309
        $stub->setRouter($router);
310
        $stub->goToStep(25);
311
    }
312
313
    /**
314
     * @expectedException \RuntimeException
315
     * @expectedExceptionMessage Request is not set in step action.
316
     */
317
    public function test flashMessage should throw exception if no request()
318
    {
319
        $stub = new ConcreteAbstractActionStub();
320
        $stub->flashMessage('message');
321
    }
322
323
    /**
324
     * @expectedException \RuntimeException
325
     * @expectedExceptionMessage The session must be available to manage characters. Did you forget to enable the session in the framework?
326
     */
327
    public function test flashMessage should throw exception if no session()
328
    {
329
        $stub = new ConcreteAbstractActionStub();
330
        $stub->setRequest(new Request());
331
        $stub->flashMessage('message');
332
    }
333
334
    public function test flashMessage with no parameters()
335
    {
336
        $stub = new ConcreteAbstractActionStub();
337
        $request = $this->createRequest();
338
        $stub->setRequest($request);
339
340
        $stub->flashMessage('message');
341
342
        static::assertSame(['message'], $stub->getSession()->getFlashBag()->get('error'));
343
    }
344
345
    public function test flashMessage removes duplicates()
346
    {
347
        $stub = new ConcreteAbstractActionStub();
348
        $request = $this->createRequest();
349
        $stub->setRequest($request);
350
351
        // Execute twice to make sure the method keeps only unique messages
352
        $stub->flashMessage('message');
353
        $stub->flashMessage('message');
354
355
        static::assertSame(['message'], $stub->getSession()->getFlashBag()->get('error'));
356
    }
357
358
    public function test flashMessage with parameters()
359
    {
360
        $stub = new ConcreteAbstractActionStub();
361
        $request = $this->createRequest();
362
        $stub->setRequest($request);
363
364
        // Execute twice to make sure the method keeps only unique messages
365
        $stub->flashMessage('Message with %replacement%', null, ['%replacement%' => 'REPLACEMENT']);
366
367
        static::assertSame(['Message with REPLACEMENT'], $stub->getSession()->getFlashBag()->get('error'));
368
    }
369
370
    public function test flashMessage with translator()
371
    {
372
        $stub = new ConcreteAbstractActionStub();
373
        $request = $this->createRequest();
374
        $stub->setRequest($request);
375
376
        $translatorMock = $this->createMock(TranslatorInterface::class);
377
        $translatorMock->expects($this->once())
378
            ->method('trans')
379
            ->with('message')
380
            ->willReturn('translated')
381
        ;
382
        $stub->setTranslator($translatorMock);
383
384
        $stub->flashMessage('message');
385
386
        static::assertSame(['translated'], $stub->getSession()->getFlashBag()->get('error'));
387
    }
388
389
    /**
390
     * @expectedException \RuntimeException
391
     * @expectedExceptionMessage Request is not set in step action.
392
     */
393
    public function test update current step should throw exception if no request()
394
    {
395
        $stub = new ConcreteAbstractActionStub();
396
        $stub->updateCharacterStep(null);
397
    }
398
399
    /**
400
     * @expectedException \RuntimeException
401
     * @expectedExceptionMessage Request is not set in step action.
402
     */
403
    public function test getCurrentCharacter should throw exception if no request()
404
    {
405
        $stub = new ConcreteAbstractActionStub();
406
        $stub->getCurrentCharacter();
407
    }
408
409
    /**
410
     * @expectedException \RuntimeException
411
     * @expectedExceptionMessage The session must be available to manage characters. Did you forget to enable the session in the framework?
412
     */
413
    public function test getCurrentCharacter should throw exception if no session()
414
    {
415
        $stub = new ConcreteAbstractActionStub();
416
        $stub->setRequest(new Request());
417
        $stub->getCurrentCharacter();
418
    }
419
420
    public function test invalid character class in step action()
421
    {
422
        $this->expectException(InvalidArgumentException::class);
423
        $this->expectExceptionMessage('Step action must be a valid class implementing Pierstoval\Bundle\CharacterManagerBundle\Model\CharacterInterface. "stdClass" given.');
424
425
        $stub = new ConcreteAbstractActionStub();
426
        $stub->configure('', '', \stdClass::class, $this->createMock(StepResolverInterface::class));
427
    }
428
429
    /**
430
     * @expectedException RuntimeException
431
     * @expectedExceptionMessage The session must be available to manage characters. Did you forget to enable the session in the framework?
432
     */
433
    public function test flash message when session is not available()
434
    {
435
        $action = new ConcreteAbstractActionStub();
436
        $action->setRequest(new Request());
437
438
        $action->flashMessage('Whatever, it should throw an exception anyway.');
439
    }
440
}
441