TranslatableTypeTest::testSubmit()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 55
Code Lines 40

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 55
rs 9.7692
c 0
b 0
f 0
cc 1
eloc 40
nc 1
nop 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/*
4
 * This file is part of the Lug package.
5
 *
6
 * (c) Eric GELOEN <[email protected]>
7
 *
8
 * For the full copyright and license information, please read the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Lug\Bundle\TranslationBundle\Tests\Form\Type;
13
14
use A2lix\TranslationFormBundle\Form\EventListener\TranslationsFormsListener;
15
use A2lix\TranslationFormBundle\Form\Type\TranslationsFormsType;
16
use A2lix\TranslationFormBundle\Locale\DefaultProvider;
17
use A2lix\TranslationFormBundle\TranslationForm\TranslationForm;
18
use Doctrine\Common\Persistence\ManagerRegistry;
19
use Lug\Bundle\TranslationBundle\Form\Type\AbstractTranslatableType;
20
use Lug\Bundle\TranslationBundle\Form\Type\TranslatableType;
21
use Lug\Component\Resource\Factory\FactoryInterface;
22
use Lug\Component\Resource\Form\Type\ResourceType;
23
use Lug\Component\Resource\Model\ResourceInterface;
24
use Lug\Component\Translation\Model\TranslatableInterface;
25
use Lug\Component\Translation\Model\TranslatableTrait;
26
use Lug\Component\Translation\Model\TranslationInterface;
27
use Lug\Component\Translation\Model\TranslationTrait;
28
use Symfony\Component\Form\AbstractType;
29
use Symfony\Component\Form\Extension\Core\Type\TextType;
30
use Symfony\Component\Form\FormBuilderInterface;
31
use Symfony\Component\Form\FormFactoryInterface;
32
use Symfony\Component\Form\FormRegistry;
33
use Symfony\Component\Form\Forms;
34
use Symfony\Component\OptionsResolver\OptionsResolver;
35
36
/**
37
 * @author GeLo <[email protected]>
38
 */
39
class TranslatableTypeTest extends \PHPUnit_Framework_TestCase
40
{
41
    /**
42
     * @var FormFactoryInterface
43
     */
44
    private $formFactory;
45
46
    /**
47
     * @var TranslatableType
48
     */
49
    private $translatableType;
50
51
    /**
52
     * @var \PHPUnit_Framework_MockObject_MockObject|ResourceInterface
53
     */
54
    private $translatableResource;
55
56
    /**
57
     * @var \PHPUnit_Framework_MockObject_MockObject|FactoryInterface
58
     */
59
    private $translatableFactory;
60
61
    /**
62
     * {@inheritdoc}
63
     */
64
    protected function setUp()
65
    {
66
        $this->translatableType = new TranslatableType();
67
        $this->translatableResource = $this->createResourceMock();
68
        $this->translatableFactory = $this->createFactoryMock();
69
70
        $this->formFactory = Forms::createFormFactoryBuilder()
71
            ->addType(new ResourceType())
72
            ->addType($this->translatableType)
73
            ->addType(new TranslationsFormsType(
74
                new TranslationForm($this->createFormRegistryMock(), $this->createManagerRegistryMock()),
0 ignored issues
show
Bug introduced by
It seems like $this->createFormRegistryMock() targeting Lug\Bundle\TranslationBu...reateFormRegistryMock() can also be of type object<PHPUnit_Framework_MockObject_MockObject>; however, A2lix\TranslationFormBun...tionForm::__construct() does only seem to accept object<Symfony\Component\Form\FormRegistry>, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
Bug introduced by
It seems like $this->createManagerRegistryMock() targeting Lug\Bundle\TranslationBu...teManagerRegistryMock() can also be of type object<PHPUnit_Framework_MockObject_MockObject>; however, A2lix\TranslationFormBun...tionForm::__construct() does only seem to accept object<Doctrine\Common\P...stence\ManagerRegistry>, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
75
                new TranslationsFormsListener(),
76
                new DefaultProvider(['en', 'fr'], 'en', ['en'])
77
            ))
78
            ->addType(new TranslationTestType())
79
            ->addType(new TranslatableTestType($this->translatableResource, $this->translatableFactory))
80
            ->getFormFactory();
81
    }
82
83
    public function testInheritance()
84
    {
85
        $this->assertInstanceOf(AbstractType::class, $this->translatableType);
86
        $this->assertSame(ResourceType::class, $this->translatableType->getParent());
87
    }
88
89
    public function testSubmit()
90
    {
91
        $this->translatableResource
0 ignored issues
show
Bug introduced by
The method expects does only exist in PHPUnit_Framework_MockObject_MockObject, but not in Lug\Component\Resource\Model\ResourceInterface.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
92
            ->expects($this->once())
93
            ->method('getModel')
94
            ->will($this->returnValue(TranslatableTest::class));
95
96
        $this->translatableResource
97
            ->expects($this->once())
98
            ->method('getRelation')
99
            ->with($this->identicalTo('translation'))
100
            ->will($this->returnValue($translationResource = $this->createResourceMock()));
101
102
        $translationResource
103
            ->expects($this->once())
104
            ->method('getForm')
105
            ->will($this->returnValue(TranslationTestType::class));
106
107
        $this->translatableFactory
0 ignored issues
show
Bug introduced by
The method expects does only exist in PHPUnit_Framework_MockObject_MockObject, but not in Lug\Component\Resource\Factory\FactoryInterface.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
108
            ->expects($this->once())
109
            ->method('create')
110
            ->will($this->returnValue(new TranslatableTest()));
111
112
        $form = $this->formFactory
113
            ->create(TranslatableTestType::class)
114
            ->submit(['translations' => ['en' => ['value' => 'value-en'], 'fr' => ['value' => 'value-fr']]]);
115
116
        $translatable = $form->getData();
117
        $view = $form->createView();
118
119
        $this->assertInstanceOf(TranslatableTest::class, $translatable);
120
121
        $this->assertCount(1, $view->children);
122
        $this->assertArrayHasKey('translations', $view->children);
123
124
        $this->assertCount(2, $translatable->getTranslations());
125
        $this->assertTrue($translatable->getTranslations()->containsKey('en'));
126
        $this->assertTrue($translatable->getTranslations()->containsKey('fr'));
127
128
        $this->assertCount(2, $view->children['translations']);
129
        $this->assertArrayHasKey('en', $view->children['translations']);
130
        $this->assertArrayHasKey('fr', $view->children['translations']);
131
132
        $this->assertInstanceOf(TranslationTest::class, $translatable->getTranslations()['en']);
133
        $this->assertSame('value-en', $translatable->getTranslations()['en']->getValue());
134
135
        $this->assertCount(1, $view->children['translations']['en']);
136
        $this->assertArrayHasKey('value', $view->children['translations']['en']);
137
138
        $this->assertInstanceOf(TranslationTest::class, $translatable->getTranslations()['fr']);
139
        $this->assertSame('value-fr', $translatable->getTranslations()['fr']->getValue());
140
141
        $this->assertCount(1, $view->children['translations']['fr']);
142
        $this->assertArrayHasKey('value', $view->children['translations']['fr']);
143
    }
144
145
    /**
146
     * @return \PHPUnit_Framework_MockObject_MockObject|FormRegistry
147
     */
148
    private function createFormRegistryMock()
149
    {
150
        return $this->createMock(FormRegistry::class);
151
    }
152
153
    /**
154
     * @return \PHPUnit_Framework_MockObject_MockObject|ManagerRegistry
155
     */
156
    private function createManagerRegistryMock()
157
    {
158
        return $this->createMock(ManagerRegistry::class);
159
    }
160
161
    /**
162
     * @return \PHPUnit_Framework_MockObject_MockObject|ResourceInterface
163
     */
164
    private function createResourceMock()
165
    {
166
        return $this->createMock(ResourceInterface::class);
167
    }
168
169
    /**
170
     * @return \PHPUnit_Framework_MockObject_MockObject|FactoryInterface
171
     */
172
    private function createFactoryMock()
173
    {
174
        return $this->createMock(FactoryInterface::class);
175
    }
176
}
177
178
/**
179
 * @author GeLo <[email protected]>
180
 */
181
class TranslatableTest implements TranslatableInterface
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
182
{
183
    use TranslatableTrait;
184
185
    public function __construct()
186
    {
187
        $this->initTranslatable();
188
    }
189
}
190
191
/**
192
 * @author GeLo <[email protected]>
193
 */
194
class TranslationTest implements TranslationInterface
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
195
{
196
    use TranslationTrait;
197
198
    /**
199
     * @var string
200
     */
201
    private $value;
202
203
    /**
204
     * @return string
205
     */
206
    public function getValue()
207
    {
208
        return $this->value;
209
    }
210
211
    /**
212
     * @param string $value
213
     */
214
    public function setValue($value)
215
    {
216
        $this->value = $value;
217
    }
218
}
219
220
/**
221
 * @author GeLo <[email protected]>
222
 */
223
class TranslatableTestType extends AbstractTranslatableType
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
224
{
225
}
226
227
/**
228
 * @author GeLo <[email protected]>
229
 */
230
class TranslationTestType extends AbstractType
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
231
{
232
    /**
233
     * {@inheritdoc}
234
     */
235
    public function buildForm(FormBuilderInterface $builder, array $options)
236
    {
237
        $builder->add('value', TextType::class);
238
    }
239
240
    /**
241
     * {@inheritdoc}
242
     */
243
    public function configureOptions(OptionsResolver $resolver)
244
    {
245
        $resolver->setDefault('data_class', TranslationTest::class);
246
    }
247
}
248