Skip to content

Commit 8083b97

Browse files
committed
Implement ActionInterface for /captcha/refresh
1 parent 5ff31f6 commit 8083b97

File tree

2 files changed

+157
-132
lines changed

2 files changed

+157
-132
lines changed
Lines changed: 49 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,78 @@
11
<?php
22
/**
3-
* Refreshes captcha and returns JSON encoded URL to image (AJAX action)
4-
* Example: {'imgSrc': 'http://example.com/media/captcha/67842gh187612ngf8s.png'}
5-
*
63
* Copyright © Magento, Inc. All rights reserved.
74
* See COPYING.txt for license details.
85
*/
96
namespace Magento\Captcha\Controller\Refresh;
107

11-
use Magento\Framework\App\Action\HttpPostActionInterface as HttpPostActionInterface;
12-
use Magento\Framework\App\Action\Context;
8+
use Magento\Captcha\Helper\Data as CaptchaHelper;
9+
use Magento\Framework\App\Action\HttpPostActionInterface;
10+
use Magento\Framework\App\RequestInterface;
11+
use Magento\Framework\Controller\Result\JsonFactory as JsonResultFactory;
12+
use Magento\Framework\Serialize\Serializer\Json as JsonSerializer;
13+
use Magento\Framework\View\LayoutInterface;
1314

14-
class Index extends \Magento\Framework\App\Action\Action implements HttpPostActionInterface
15+
/**
16+
* Refreshes captcha and returns JSON encoded URL to image (AJAX action)
17+
* Example: {'imgSrc': 'http://example.com/media/captcha/67842gh187612ngf8s.png'}
18+
*/
19+
class Index implements HttpPostActionInterface
1520
{
1621
/**
17-
* @var \Magento\Captcha\Helper\Data
22+
* @var CaptchaHelper
23+
*/
24+
private $captchaHelper;
25+
26+
/**
27+
* @var JsonSerializer
28+
*/
29+
private $serializer;
30+
31+
/**
32+
* @var RequestInterface
1833
*/
19-
protected $captchaHelper;
34+
private $request;
2035

2136
/**
22-
* @var \Magento\Framework\Serialize\Serializer\Json
37+
* @var LayoutInterface
2338
*/
24-
protected $serializer;
39+
private $layout;
2540

2641
/**
27-
* @param Context $context
28-
* @param \Magento\Captcha\Helper\Data $captchaHelper
29-
* @param \Magento\Framework\Serialize\Serializer\Json|null $serializer
30-
* @throws \RuntimeException
42+
* @var JsonResultFactory
43+
*/
44+
private $jsonFactory;
45+
46+
/**
47+
* @param RequestInterface $request
48+
* @param JsonResultFactory $jsonFactory
49+
* @param CaptchaHelper $captchaHelper
50+
* @param LayoutInterface $layout
51+
* @param JsonSerializer $serializer
3152
*/
3253
public function __construct(
33-
Context $context,
34-
\Magento\Captcha\Helper\Data $captchaHelper,
35-
\Magento\Framework\Serialize\Serializer\Json $serializer = null
54+
RequestInterface $request,
55+
JsonResultFactory $jsonFactory,
56+
CaptchaHelper $captchaHelper,
57+
LayoutInterface $layout,
58+
JsonSerializer $serializer
3659
) {
60+
$this->request = $request;
61+
$this->jsonFactory = $jsonFactory;
3762
$this->captchaHelper = $captchaHelper;
38-
$this->serializer = $serializer ?: \Magento\Framework\App\ObjectManager::getInstance()
39-
->get(\Magento\Framework\Serialize\Serializer\Json::class);
40-
parent::__construct($context);
63+
$this->layout = $layout;
64+
$this->serializer = $serializer;
4165
}
4266

4367
/**
4468
* {@inheritdoc}
4569
*/
4670
public function execute()
4771
{
48-
$formId = $this->_request->getPost('formId');
72+
$formId = $this->request->getPost('formId');
4973
if (null === $formId) {
5074
$params = [];
51-
$content = $this->_request->getContent();
75+
$content = $this->request->getContent();
5276
if ($content) {
5377
$params = $this->serializer->unserialize($content);
5478
}
@@ -57,9 +81,9 @@ public function execute()
5781
$captchaModel = $this->captchaHelper->getCaptcha($formId);
5882
$captchaModel->generate();
5983

60-
$block = $this->_view->getLayout()->createBlock($captchaModel->getBlockName());
84+
$block = $this->layout->createBlock($captchaModel->getBlockName());
6185
$block->setFormId($formId)->setIsAjax(true)->toHtml();
62-
$this->_response->representJson($this->serializer->serialize(['imgSrc' => $captchaModel->getImgSrc()]));
63-
$this->_actionFlag->set('', self::FLAG_NO_POST_DISPATCH, true);
86+
87+
return $this->jsonFactory->create(['imgSrc' => $captchaModel->getImgSrc()]);
6488
}
6589
}

app/code/Magento/Captcha/Test/Unit/Controller/Refresh/IndexTest.php

Lines changed: 108 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -5,133 +5,134 @@
55
*/
66
namespace Magento\Captcha\Test\Unit\Controller\Refresh;
77

8-
class IndexTest extends \PHPUnit\Framework\TestCase
8+
use Magento\Captcha\Controller\Refresh\Index;
9+
use Magento\Captcha\Helper\Data as CaptchaHelper;
10+
use Magento\Captcha\Model\CaptchaInterface;
11+
use Magento\Framework\App\RequestInterface;
12+
use Magento\Framework\Controller\Result\JsonFactory as ResultJsonFactory;
13+
use Magento\Framework\Serialize\Serializer\Json as JsonSerializer;
14+
use Magento\Framework\View\Element\BlockInterface;
15+
use Magento\Framework\View\LayoutInterface;
16+
use PHPUnit\Framework\MockObject\MockObject;
17+
use PHPUnit\Framework\TestCase;
18+
19+
class IndexTest extends TestCase
920
{
10-
/**
11-
* @var \PHPUnit_Framework_MockObject_MockObject
12-
*/
13-
protected $captchaHelperMock;
21+
private const STUB_FORM_ID = 'StubFormId';
22+
private const STUB_CAPTCHA_SOURCE = '/stub-captcha-source.jpg';
1423

15-
/**
16-
* @var \PHPUnit_Framework_MockObject_MockObject
17-
*/
18-
protected $captchaMock;
24+
/** @var MockObject|RequestInterface */
25+
private $requestMock;
1926

20-
/**
21-
* @var \PHPUnit_Framework_MockObject_MockObject
22-
*/
23-
protected $requestMock;
27+
/** @var MockObject|ResultJsonFactory */
28+
private $jsonResultFactoryMock;
2429

25-
/**
26-
* @var \PHPUnit_Framework_MockObject_MockObject
27-
*/
28-
protected $responseMock;
30+
/** @var MockObject|CaptchaHelper */
31+
private $captchaHelperMock;
2932

30-
/**
31-
* @var \PHPUnit_Framework_MockObject_MockObject
32-
*/
33-
protected $contextMock;
34-
35-
/**
36-
* @var \PHPUnit_Framework_MockObject_MockObject
37-
*/
38-
protected $viewMock;
39-
40-
/**
41-
* @var \PHPUnit_Framework_MockObject_MockObject
42-
*/
43-
protected $layoutMock;
33+
/** @var MockObject|LayoutInterface */
34+
private $layoutMock;
4435

45-
/**
46-
* @var \PHPUnit_Framework_MockObject_MockObject
47-
*/
48-
protected $flagMock;
36+
/** @var MockObject|BlockInterface */
37+
private $blockMock;
4938

50-
/**
51-
* @var \PHPUnit_Framework_MockObject_MockObject
52-
*/
53-
protected $serializerMock;
39+
/** @var MockObject|JsonSerializer */
40+
private $jsonSerializerMock;
5441

55-
/**
56-
* @var \Magento\Captcha\Controller\Refresh\Index
57-
*/
58-
protected $model;
42+
/** @var Index */
43+
private $refreshAction;
5944

6045
protected function setUp()
6146
{
62-
$this->captchaHelperMock = $this->createMock(\Magento\Captcha\Helper\Data::class);
63-
$this->captchaMock = $this->createMock(\Magento\Captcha\Model\DefaultModel::class);
64-
$this->requestMock = $this->createMock(\Magento\Framework\App\Request\Http::class);
65-
$this->responseMock = $this->createMock(\Magento\Framework\App\Response\Http::class);
66-
$this->contextMock = $this->createMock(\Magento\Framework\App\Action\Context::class);
67-
$this->viewMock = $this->createMock(\Magento\Framework\App\ViewInterface::class);
68-
$this->layoutMock = $this->createMock(\Magento\Framework\View\LayoutInterface::class);
69-
$this->flagMock = $this->createMock(\Magento\Framework\App\ActionFlag::class);
70-
$this->serializerMock = $this->createMock(\Magento\Framework\Serialize\Serializer\Json::class);
71-
72-
$this->contextMock->expects($this->any())->method('getRequest')->will($this->returnValue($this->requestMock));
73-
$this->contextMock->expects($this->any())->method('getView')->will($this->returnValue($this->viewMock));
74-
$this->contextMock->expects($this->any())->method('getResponse')->will($this->returnValue($this->responseMock));
75-
$this->contextMock->expects($this->any())->method('getActionFlag')->will($this->returnValue($this->flagMock));
76-
$this->viewMock->expects($this->any())->method('getLayout')->will($this->returnValue($this->layoutMock));
77-
78-
$this->model = new \Magento\Captcha\Controller\Refresh\Index(
79-
$this->contextMock,
47+
$this->requestMock = $this->getMockBuilder(RequestInterface::class)
48+
->setMethods(['getPost', 'getContent'])
49+
->getMockForAbstractClass();
50+
$this->layoutMock = $this->getMockBuilder(LayoutInterface::class)
51+
->setMethods(['createBlock'])
52+
->getMockForAbstractClass();
53+
$this->blockMock = $this->getMockBuilder(BlockInterface::class)
54+
->setMethods(['setFormId', 'setIsAjax', 'toHtml'])
55+
->getMockForAbstractClass();
56+
$this->jsonResultFactoryMock = $this->createMock(ResultJsonFactory::class);
57+
$this->jsonSerializerMock = $this->createMock(JsonSerializer::class);
58+
$this->captchaHelperMock = $this->createMock(CaptchaHelper::class);
59+
60+
$this->blockMock->method('setIsAjax')
61+
->willReturnSelf();
62+
63+
$this->layoutMock->method('createBlock')
64+
->willReturn($this->blockMock);
65+
66+
$this->refreshAction = new Index(
67+
$this->requestMock,
68+
$this->jsonResultFactoryMock,
8069
$this->captchaHelperMock,
81-
$this->serializerMock
70+
$this->layoutMock,
71+
$this->jsonSerializerMock
8272
);
8373
}
8474

85-
/**
86-
* @dataProvider executeDataProvider
87-
* @param int $formId
88-
* @param int $callsNumber
89-
*/
90-
public function testExecute($formId, $callsNumber)
75+
public function testCaptchaGeneratedWhenPostDataContainsFormId()
9176
{
92-
$content = ['formId' => $formId];
93-
$imgSource = ['imgSrc' => 'source'];
94-
95-
$blockMethods = ['setFormId', 'setIsAjax', 'toHtml'];
96-
$blockMock = $this->createPartialMock(\Magento\Captcha\Block\Captcha::class, $blockMethods);
97-
98-
$this->requestMock->expects($this->any())->method('getPost')->with('formId')->will($this->returnValue($formId));
99-
$this->requestMock->expects($this->exactly($callsNumber))->method('getContent')
100-
->will($this->returnValue(json_encode($content)));
101-
$this->captchaHelperMock->expects($this->any())->method('getCaptcha')->with($formId)
102-
->will($this->returnValue($this->captchaMock));
103-
$this->captchaMock->expects($this->once())->method('generate');
104-
$this->captchaMock->expects($this->once())->method('getBlockName')->will($this->returnValue('block'));
105-
$this->captchaMock->expects($this->once())->method('getImgSrc')->will($this->returnValue('source'));
106-
$this->layoutMock->expects($this->once())->method('createBlock')->with('block')
107-
->will($this->returnValue($blockMock));
108-
$blockMock->expects($this->any())->method('setFormId')->with($formId)->will($this->returnValue($blockMock));
109-
$blockMock->expects($this->any())->method('setIsAjax')->with(true)->will($this->returnValue($blockMock));
110-
$blockMock->expects($this->once())->method('toHtml');
111-
$this->responseMock->expects($this->once())->method('representJson')->with(json_encode($imgSource));
112-
$this->flagMock->expects($this->once())->method('set')->with('', 'no-postDispatch', true);
113-
$this->serializerMock->expects($this->exactly($callsNumber))
114-
->method('unserialize')->will($this->returnValue($content));
115-
$this->serializerMock->expects($this->once())
116-
->method('serialize')->will($this->returnValue(json_encode($imgSource)));
117-
118-
$this->model->execute();
77+
// Given
78+
$this->requestMock->method('getPost')
79+
->with('formId')
80+
->willReturn(self::STUB_FORM_ID);
81+
$this->blockMock->method('setFormId')
82+
->willReturnSelf();
83+
84+
// Expect
85+
$this->requestMock->expects($this->never())
86+
->method('getContent');
87+
$this->captchaHelperMock->expects($this->once())
88+
->method('getCaptcha')
89+
->with(self::STUB_FORM_ID)
90+
->willReturn(
91+
$this->getCaptchaModelMock(self::STUB_CAPTCHA_SOURCE)
92+
);
93+
94+
// When
95+
$this->refreshAction->execute();
96+
}
97+
98+
public function testCaptchaFallsBackToRequestContentIfPostMissing()
99+
{
100+
// Given
101+
$this->requestMock->method('getPost')
102+
->with('formId')
103+
->willReturn(null);
104+
$this->blockMock->method('setFormId')
105+
->willReturnSelf();
106+
107+
// Expect
108+
$this->requestMock->expects(self::once())
109+
->method('getContent')
110+
->willReturn(null);
111+
$this->captchaHelperMock->expects($this->once())
112+
->method('getCaptcha')
113+
->with(null)
114+
->willReturn(
115+
$this->getCaptchaModelMock(self::STUB_CAPTCHA_SOURCE)
116+
);
117+
118+
// When
119+
$this->refreshAction->execute();
120+
119121
}
120122

121123
/**
122-
* @return array
124+
* @param string $imageSource
125+
* @return MockObject|CaptchaInterface
123126
*/
124-
public function executeDataProvider()
127+
private function getCaptchaModelMock(string $imageSource): CaptchaInterface
125128
{
126-
return [
127-
[
128-
'formId' => null,
129-
'callsNumber' => 1,
130-
],
131-
[
132-
'formId' => 1,
133-
'callsNumber' => 0,
134-
]
135-
];
129+
$modelMock = $this->getMockBuilder(CaptchaInterface::class)
130+
->setMethods(['generate', 'getBlockName', 'getImgSrc'])
131+
->getMockForAbstractClass();
132+
133+
$modelMock->method('getImgSrc')
134+
->willReturn($imageSource);
135+
136+
return $modelMock;
136137
}
137138
}

0 commit comments

Comments
 (0)