Completed
Push — 3.x ( e95e95...638cd1 )
by Oskar
05:54
created

tests/Action/SetObjectFieldValueActionTest.php (16 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the Sonata Project package.
7
 *
8
 * (c) Thomas Rabaix <[email protected]>
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
14
namespace Sonata\AdminBundle\Tests\Action;
15
16
use PHPUnit\Framework\TestCase;
17
use Prophecy\Argument;
18
use Sonata\AdminBundle\Action\GetShortObjectDescriptionAction;
19
use Sonata\AdminBundle\Action\SetObjectFieldValueAction;
20
use Sonata\AdminBundle\Admin\AbstractAdmin;
21
use Sonata\AdminBundle\Admin\FieldDescriptionInterface;
22
use Sonata\AdminBundle\Admin\Pool;
23
use Sonata\AdminBundle\Model\ModelManagerInterface;
24
use Sonata\AdminBundle\Templating\TemplateRegistryInterface;
25
use Sonata\AdminBundle\Twig\Extension\SonataAdminExtension;
26
use Symfony\Bridge\Twig\AppVariable;
27
use Symfony\Bridge\Twig\Command\DebugCommand;
28
use Symfony\Bridge\Twig\Extension\FormExtension;
29
use Symfony\Bridge\Twig\Form\TwigRenderer;
30
use Symfony\Component\DependencyInjection\ContainerInterface;
31
use Symfony\Component\Form\FormRenderer;
32
use Symfony\Component\Form\FormRendererEngineInterface;
33
use Symfony\Component\HttpFoundation\Request;
34
use Symfony\Component\PropertyAccess\PropertyAccessor;
35
use Symfony\Component\Translation\TranslatorInterface;
36
use Symfony\Component\Validator\ConstraintViolation;
37
use Symfony\Component\Validator\ConstraintViolationList;
38
use Symfony\Component\Validator\Validator\ValidatorInterface;
39
use Twig\Environment;
40
use Twig\Loader\ArrayLoader;
41
use Twig\RuntimeLoader\FactoryRuntimeLoader;
42
use Twig\Template;
43
44
final class SetObjectFieldValueActionTest extends TestCase
45
{
46
    /**
47
     * @var Pool
48
     */
49
    private $pool;
50
51
    /**
52
     * @var Environment
53
     */
54
    private $twig;
55
56
    /**
57
     * @var GetShortObjectDescriptionAction
58
     */
59
    private $action;
60
61
    /**
62
     * @var AbstractAdmin
63
     */
64
    private $admin;
65
66
    /**
67
     * @var ValidatorInterface
68
     */
69
    private $validator;
70
71
    protected function setUp(): void
72
    {
73
        $this->twig = new Environment(new ArrayLoader([
74
            'admin_template' => 'renderedTemplate',
75
            'field_template' => 'renderedTemplate',
76
        ]));
77
        $this->pool = $this->prophesize(Pool::class);
78
        $this->admin = $this->prophesize(AbstractAdmin::class);
79
        $this->pool->getInstance(Argument::any())->willReturn($this->admin->reveal());
80
        $this->admin->setRequest(Argument::type(Request::class))->shouldBeCalled();
81
        $this->validator = $this->prophesize(ValidatorInterface::class);
82
        $this->action = new SetObjectFieldValueAction(
83
            $this->twig,
84
            $this->pool->reveal(),
85
            $this->validator->reveal()
86
        );
87
    }
88
89
    public function testSetObjectFieldValueAction(): void
90
    {
91
        $object = new Foo();
92
        $request = new Request([
93
            'code' => 'sonata.post.admin',
94
            'objectId' => 42,
95
            'field' => 'enabled',
96
            'value' => 1,
97
            'context' => 'list',
98
        ], [], [], [], [], ['REQUEST_METHOD' => 'POST', 'HTTP_X_REQUESTED_WITH' => 'XMLHttpRequest']);
99
100
        $fieldDescription = $this->prophesize(FieldDescriptionInterface::class);
101
        $pool = $this->prophesize(Pool::class);
102
        $template = $this->prophesize(Template::class);
103
        $translator = $this->prophesize(TranslatorInterface::class);
104
        $propertyAccessor = new PropertyAccessor();
105
        $templateRegistry = $this->prophesize(TemplateRegistryInterface::class);
106
        $container = $this->prophesize(ContainerInterface::class);
107
108
        $this->admin->getObject(42)->willReturn($object);
109
        $this->admin->getCode()->willReturn('sonata.post.admin');
110
        $this->admin->hasAccess('edit', $object)->willReturn(true);
0 ignored issues
show
The method willReturn cannot be called on $this->admin->hasAccess('edit', $object) (of type boolean).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
111
        $this->admin->getListFieldDescription('enabled')->willReturn($fieldDescription->reveal());
0 ignored issues
show
The method willReturn() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
112
        $this->admin->update($object)->shouldBeCalled();
113
        // NEXT_MAJOR: Remove this line
114
        $this->admin->getTemplate('base_list_field')->willReturn('admin_template');
115
        $templateRegistry->getTemplate('base_list_field')->willReturn('admin_template');
116
        $container->get('sonata.post.admin.template_registry')->willReturn($templateRegistry->reveal());
117
        $this->pool->getPropertyAccessor()->willReturn($propertyAccessor);
0 ignored issues
show
The method willReturn() does not seem to exist on object<Symfony\Component...pertyAccessorInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
118
        $this->twig->addExtension(new SonataAdminExtension(
119
            $pool->reveal(),
120
            null,
121
            $translator->reveal(),
122
            $container->reveal()
123
        ));
124
        $fieldDescription->getOption('editable')->willReturn(true);
125
        $fieldDescription->getAdmin()->willReturn($this->admin->reveal());
0 ignored issues
show
The method reveal() does not seem to exist on object<Sonata\AdminBundle\Admin\AbstractAdmin>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
126
        $fieldDescription->getType()->willReturn('boolean');
127
        $fieldDescription->getTemplate()->willReturn(false);
128
        $fieldDescription->getValue(Argument::cetera())->willReturn('some value');
129
130
        $this->validator->validate($object)->willReturn(new ConstraintViolationList([]));
0 ignored issues
show
The method willReturn() does not seem to exist on object<Symfony\Component...ViolationListInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
131
        $action = $this->action;
132
        $response = $action($request);
133
134
        $this->assertSame(200, $response->getStatusCode());
135
    }
136
137
    public function testSetObjectFieldValueActionOnARelationField(): void
138
    {
139
        $object = new Baz();
140
        $associationObject = new Bar();
141
        $request = new Request([
142
            'code' => 'sonata.post.admin',
143
            'objectId' => 42,
144
            'field' => 'bar',
145
            'value' => 1,
146
            'context' => 'list',
147
        ], [], [], [], [], ['REQUEST_METHOD' => 'POST', 'HTTP_X_REQUESTED_WITH' => 'XMLHttpRequest']);
148
149
        $fieldDescription = $this->prophesize(FieldDescriptionInterface::class);
150
        $modelManager = $this->prophesize(ModelManagerInterface::class);
151
        $template = $this->prophesize(Template::class);
152
        $translator = $this->prophesize(TranslatorInterface::class);
153
        $propertyAccessor = new PropertyAccessor();
154
        $templateRegistry = $this->prophesize(TemplateRegistryInterface::class);
155
        $container = $this->prophesize(ContainerInterface::class);
156
157
        $this->admin->getObject(42)->willReturn($object);
158
        $this->admin->getCode()->willReturn('sonata.post.admin');
159
        $this->admin->hasAccess('edit', $object)->willReturn(true);
0 ignored issues
show
The method willReturn cannot be called on $this->admin->hasAccess('edit', $object) (of type boolean).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
160
        $this->admin->getListFieldDescription('bar')->willReturn($fieldDescription->reveal());
0 ignored issues
show
The method willReturn() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
161
        $this->admin->getClass()->willReturn(\get_class($object));
0 ignored issues
show
The method willReturn cannot be called on $this->admin->getClass() (of type string).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
162
        $this->admin->update($object)->shouldBeCalled();
163
        $container->get('sonata.post.admin.template_registry')->willReturn($templateRegistry->reveal());
164
        // NEXT_MAJOR: Remove this line
165
        $this->admin->getTemplate('base_list_field')->willReturn('admin_template');
166
        $templateRegistry->getTemplate('base_list_field')->willReturn('admin_template');
167
        $this->admin->getModelManager()->willReturn($modelManager->reveal());
0 ignored issues
show
The method willReturn() does not seem to exist on object<Sonata\AdminBundl...\ModelManagerInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
168
        $this->twig->addExtension(new SonataAdminExtension(
169
            $this->pool->reveal(),
170
            null,
171
            $translator->reveal(),
172
            $container->reveal()
173
        ));
174
        $this->pool->getPropertyAccessor()->willReturn($propertyAccessor);
0 ignored issues
show
The method willReturn() does not seem to exist on object<Symfony\Component...pertyAccessorInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
175
        $fieldDescription->getType()->willReturn('choice');
176
        $fieldDescription->getOption('editable')->willReturn(true);
177
        $fieldDescription->getOption('class')->willReturn(Bar::class);
178
        $fieldDescription->getTargetEntity()->willReturn(Bar::class);
179
        $fieldDescription->getAdmin()->willReturn($this->admin->reveal());
0 ignored issues
show
The method reveal() does not seem to exist on object<Sonata\AdminBundle\Admin\AbstractAdmin>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
180
        $fieldDescription->getTemplate()->willReturn('field_template');
181
        $fieldDescription->getValue(Argument::cetera())->willReturn('some value');
182
        $modelManager->find(\get_class($associationObject), 1)->willReturn($associationObject);
183
184
        $this->validator->validate($object)->willReturn(new ConstraintViolationList([]));
0 ignored issues
show
The method willReturn() does not seem to exist on object<Symfony\Component...ViolationListInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
185
        $action = $this->action;
186
        $response = $action($request);
187
188
        $this->assertSame(200, $response->getStatusCode());
189
    }
190
191
    public function testSetObjectFieldValueActionWithViolations(): void
192
    {
193
        $bar = new Bar();
194
        $object = new Baz();
195
        $object->setBar($bar);
196
        $request = new Request([
197
            'code' => 'sonata.post.admin',
198
            'objectId' => 42,
199
            'field' => 'bar.enabled',
200
            'value' => 1,
201
            'context' => 'list',
202
        ], [], [], [], [], ['REQUEST_METHOD' => 'POST', 'HTTP_X_REQUESTED_WITH' => 'XMLHttpRequest']);
203
204
        $fieldDescription = $this->prophesize(FieldDescriptionInterface::class);
205
        $propertyAccessor = new PropertyAccessor();
206
207
        $this->pool->getPropertyAccessor()->willReturn($propertyAccessor);
0 ignored issues
show
The method willReturn() does not seem to exist on object<Symfony\Component...pertyAccessorInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
208
        $this->admin->getObject(42)->willReturn($object);
209
        $this->admin->hasAccess('edit', $object)->willReturn(true);
0 ignored issues
show
The method willReturn cannot be called on $this->admin->hasAccess('edit', $object) (of type boolean).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
210
        $this->admin->getListFieldDescription('bar.enabled')->willReturn($fieldDescription->reveal());
0 ignored issues
show
The method willReturn() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
211
        $this->validator->validate($bar)->willReturn(new ConstraintViolationList([
0 ignored issues
show
The method willReturn() does not seem to exist on object<Symfony\Component...ViolationListInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
212
            new ConstraintViolation('error1', null, [], null, 'enabled', null),
213
            new ConstraintViolation('error2', null, [], null, 'enabled', null),
214
        ]));
215
        $fieldDescription->getOption('editable')->willReturn(true);
216
        $fieldDescription->getType()->willReturn('boolean');
217
218
        $action = $this->action;
219
        $response = $action($request);
220
221
        $this->assertSame(400, $response->getStatusCode());
222
        $this->assertSame(json_encode("error1\nerror2"), $response->getContent());
223
    }
224
225
    private function configureFormRenderer()
226
    {
227
        $runtime = new FormRenderer($this->createMock(
228
            FormRendererEngineInterface::class,
229
            CsrfTokenManagerInterface::class
230
        ));
231
232
        // Remove the condition when dropping sf < 3.2
233
        if (!method_exists(AppVariable::class, 'getToken')) {
234
            $extension = new FormExtension();
235
236
            $this->twig->addExtension($extension);
237
            $extension->renderer = $runtime;
238
239
            return $runtime;
240
        }
241
242
        // Remove the condition when dropping sf < 3.4
243
        if (!method_exists(DebugCommand::class, 'getLoaderPaths')) {
244
            $twigRuntime = $this->prophesize(TwigRenderer::class);
245
246
            $this->twig->addRuntimeLoader(new FactoryRuntimeLoader(
247
                FormRenderer::class,
248
                static function () use ($runtime) {
249
                    return $runtime;
250
                }
251
            ));
252
            $this->twig->getRuntime(TwigRenderer::class)->willReturn($twigRuntime->reveal());
253
            $twigRuntime->setEnvironment($this->twig)->shouldBeCalled();
254
255
            return $twigRuntime;
256
        }
257
258
        $this->twig->addRuntimeLoader(new FactoryRuntimeLoader(
259
            FormRenderer::class,
260
            static function () use ($runtime) {
261
                return $runtime;
262
            }
263
        ));
264
265
        return $runtime;
266
    }
267
}
268