CompareCommandTest::testExecute()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 16
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 9
nc 2
nop 8
dl 0
loc 16
rs 9.9666
c 0
b 0
f 0

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
namespace Incenteev\TranslationCheckerBundle\Tests\Command;
4
5
use Incenteev\TranslationCheckerBundle\Command\CompareCommand;
6
use PHPUnit\Framework\TestCase;
7
use Prophecy\PhpUnit\ProphecyTrait;
8
use Symfony\Component\Console\Output\OutputInterface;
9
use Symfony\Component\Console\Tester\CommandTester;
10
use Symfony\Component\Translation\MessageCatalogue;
11
use Symfony\Component\Translation\TranslatorBagInterface;
12
13
class CompareCommandTest extends TestCase
14
{
15
    use ProphecyTrait;
16
17
    /**
18
     * @param array<string, array<string, string>> $sourceMessages
19
     * @param array<string, array<string, string>> $comparedMessages
20
     * @param array<string, mixed> $input
21
     * @param string|string[] $expectedMessages
22
     *
23
     * @dataProvider provideCommandData
24
     */
25
    public function testExecute(string $sourceLocale, array $sourceMessages, string $comparedLocale, array $comparedMessages, array $input, int $expectedExitCode, $expectedMessages, int $verbosity = OutputInterface::VERBOSITY_NORMAL)
26
    {
27
        $loader = $this->prophesize(TranslatorBagInterface::class);
28
29
        $loader->getCatalogue($sourceLocale)->willReturn(new MessageCatalogue($sourceLocale, $sourceMessages));
30
        $loader->getCatalogue($comparedLocale)->willReturn(new MessageCatalogue($comparedLocale, $comparedMessages));
31
32
        $command = new CompareCommand($loader->reveal());
33
34
        $tester = new CommandTester($command);
35
        $exitCode = $tester->execute($input, array('decorated' => false, 'verbosity' => $verbosity));
36
37
        $this->assertEquals($expectedExitCode, $exitCode);
38
39
        foreach ((array) $expectedMessages as $message) {
40
            $this->assertStringContainsString($message, $tester->getDisplay());
41
        }
42
    }
43
44
    public function provideCommandData(): iterable
45
    {
46
        return array(
47
            'sync with en' => array(
48
                'en',
49
                array('messages' => array('foo' => 'bar')),
50
                'fr',
51
                array('messages' => array('foo' => 'baz')),
52
                array('locale' => 'fr'),
53
                0,
54
                'The fr catalogue is in sync with the en one.',
55
            ),
56
            'sync with en explicit' => array(
57
                'en',
58
                array('messages' => array('foo' => 'bar'), 'test' => array('me' => 'Me')),
59
                'fr',
60
                array('messages' => array('foo' => 'baz'), 'test' => array('me' => 'Moi')),
61
                array('locale' => 'fr', 'source' => 'en'),
62
                0,
63
                'The fr catalogue is in sync with the en one.',
64
                OutputInterface::VERBOSITY_VERBOSE,
65
            ),
66
            'missing message' => array(
67
                'en',
68
                array('messages' => array('foo' => 'bar')),
69
                'fr',
70
                array('messages' => array()),
71
                array('locale' => 'fr'),
72
                1,
73
                '1 messages are missing in the messages domain',
74
            ),
75
            'missing message verbose' => array(
76
                'en',
77
                array('messages' => array('foo' => 'bar')),
78
                'fr',
79
                array('messages' => array()),
80
                array('locale' => 'fr'),
81
                1,
82
                array('1 messages are missing in the messages domain', '    foo'),
83
                OutputInterface::VERBOSITY_VERBOSE,
84
            ),
85
            'obsolete message' => array(
86
                'en',
87
                array('messages' => array('foo' => 'bar')),
88
                'fr',
89
                array('messages' => array('foo' => 'bar', 'bar' => 'baz', 'old' => 'one')),
90
                array('locale' => 'fr'),
91
                1,
92
                '2 messages are obsolete in the messages domain',
93
            ),
94
            'obsolete message verbose' => array(
95
                'en',
96
                array('messages' => array('foo' => 'bar')),
97
                'fr',
98
                array('messages' => array('foo' => 'bar', 'bar' => 'baz', 'old.key' => 'one')),
99
                array('locale' => 'fr'),
100
                1,
101
                array('2 messages are obsolete in the messages domain', '    bar', '    old.key'),
102
                OutputInterface::VERBOSITY_VERBOSE,
103
            ),
104
            'missing and obsolete message' => array(
105
                'en',
106
                array('messages' => array('foo' => 'bar'), 'test' => array('hello' => 'world')),
107
                'fr',
108
                array('messages' => array('foo' => 'bar', 'bar' => 'baz', 'old' => 'one')),
109
                array('locale' => 'fr'),
110
                1,
111
                array('2 messages are obsolete in the messages domain', '1 messages are missing in the test domain'),
112
            ),
113
            'domain restriction sync' => array(
114
                'en',
115
                array('messages' => array('foo' => 'bar'), 'test' => array('foo' => 'bar')),
116
                'fr',
117
                array('messages' => array('foo' => 'baz')),
118
                array('locale' => 'fr', '--domain' => array('messages', 'other')),
119
                0,
120
                array('The fr catalogue is in sync with the en one.', 'Checking the domains messages'),
121
            ),
122
            'domain restriction missing' => array(
123
                'en',
124
                array('messages' => array('foo' => 'bar'), 'test' => array('foo' => 'bar')),
125
                'fr',
126
                array('messages' => array('foo' => 'baz'), 'other' => array('hello' => 'world')),
127
                array('locale' => 'fr', '--domain' => array('test', 'other')),
128
                1,
129
                array('1 messages are missing in the test domain', 'Checking the domains other, test'),
130
            ),
131
            'missing and obsolete message with obsolete only' => array(
132
                'en',
133
                array('messages' => array('foo' => 'bar'), 'test' => array('hello' => 'world')),
134
                'fr',
135
                array('messages' => array('foo' => 'bar', 'bar' => 'baz', 'old' => 'one')),
136
                array('locale' => 'fr', '--obsolete-only' => true),
137
                1,
138
                array('2 messages are obsolete in the messages domain'),
139
            ),
140
            'missing message with obsolete only' => array(
141
                'en',
142
                array('messages' => array('foo' => 'bar')),
143
                'fr',
144
                array('messages' => array()),
145
                array('locale' => 'fr', '--obsolete-only' => true),
146
                0,
147
                'The fr catalogue is in sync with the en one.',
148
            ),
149
        );
150
    }
151
152
    public function testFailsForNonExistentWhitelist()
153
    {
154
        $loader = $this->prophesize(TranslatorBagInterface::class);
155
156
        $loader->getCatalogue('en')->willReturn(new MessageCatalogue('en', array('messages' => array('foo' => 'bar'))));
157
        $loader->getCatalogue('fr')->willReturn(new MessageCatalogue('fr', array('messages' => array('foo' => 'baz'))));
158
159
        $command = new CompareCommand($loader->reveal());
160
161
        $tester = new CommandTester($command);
162
        $exitCode = $tester->execute(array('locale' => 'fr', '--whitelist-file' => __DIR__.'/../fixtures/non_existent.yml'), array('decorated' => false));
163
164
        $this->assertEquals(1, $exitCode);
165
166
        $this->assertStringMatchesFormat('%AThe whitelist file "%s" does not exist.%A', $tester->getDisplay());
167
    }
168
169
    public function testFailsForInvalidWhitelist()
170
    {
171
        $loader = $this->prophesize(TranslatorBagInterface::class);
172
173
        $loader->getCatalogue('en')->willReturn(new MessageCatalogue('en', array('messages' => array('foo' => 'bar'))));
174
        $loader->getCatalogue('fr')->willReturn(new MessageCatalogue('fr', array('messages' => array('foo' => 'baz'))));
175
176
        $command = new CompareCommand($loader->reveal());
177
178
        $tester = new CommandTester($command);
179
        $exitCode = $tester->execute(array('locale' => 'fr', '--whitelist-file' => __DIR__.'/../fixtures/invalid_whitelist.yml'), array('decorated' => false));
180
181
        $this->assertEquals(1, $exitCode);
182
183
        $this->assertStringMatchesFormat('%AThe whitelist file "%s" is invalid. It must be a Yaml file containing a map.%A', $tester->getDisplay());
184
    }
185
186
    public function testSucceedWithWhitelistedMessages()
187
    {
188
        $loader = $this->prophesize(TranslatorBagInterface::class);
189
190
        $loader->getCatalogue('en')->willReturn(new MessageCatalogue('en', array('incenteev_tests' => array('foo' => 'bar', 'this key can go missing' => 'not defined in fr'))));
191
        $loader->getCatalogue('fr')->willReturn(new MessageCatalogue('fr', array('incenteev_tests' => array('foo' => 'baz', 'this.one.also' => 'obsolete... or no'))));
192
193
        $command = new CompareCommand($loader->reveal());
194
195
        $tester = new CommandTester($command);
196
        $exitCode = $tester->execute(array('locale' => 'fr', '--whitelist-file' => __DIR__.'/../fixtures/whitelist.yml'), array('decorated' => false));
197
198
        $this->assertEquals(0, $exitCode);
199
    }
200
201
    public function testFailsWithWhitelistedMessagesAndMissingMessage()
202
    {
203
        $loader = $this->prophesize(TranslatorBagInterface::class);
204
205
        $loader->getCatalogue('en')->willReturn(new MessageCatalogue('en', array('incenteev_tests' => array(
206
            'foo' => 'bar',
207
            'this key can go missing' => 'not defined in fr',
208
            'this key is required' => 'but missing in fr',
209
        ))));
210
        $loader->getCatalogue('fr')->willReturn(new MessageCatalogue('fr', array('incenteev_tests' => array('foo' => 'baz', 'this.one.also' => 'obsolete... or no'))));
211
212
        $command = new CompareCommand($loader->reveal());
213
214
        $tester = new CommandTester($command);
215
        $exitCode = $tester->execute(array('locale' => 'fr', '--whitelist-file' => __DIR__.'/../fixtures/whitelist.yml'), array('decorated' => false));
216
217
        $this->assertEquals(1, $exitCode);
218
219
        $this->assertStringContainsString('1 messages are missing in the incenteev_tests domain', $tester->getDisplay());
220
    }
221
222
    public function testWhitelistIsDomainBased()
223
    {
224
        $loader = $this->prophesize(TranslatorBagInterface::class);
225
226
        $loader->getCatalogue('en')->willReturn(new MessageCatalogue('en', array('messages' => array('foo' => 'bar', 'this key can go missing' => 'not defined in fr'))));
227
        $loader->getCatalogue('fr')->willReturn(new MessageCatalogue('fr', array('messages' => array('foo' => 'baz', 'this.one.also' => 'obsolete... or no'))));
228
229
        $command = new CompareCommand($loader->reveal());
230
231
        $tester = new CommandTester($command);
232
        $exitCode = $tester->execute(array('locale' => 'fr', '--whitelist-file' => __DIR__.'/../fixtures/whitelist.yml'), array('decorated' => false));
233
234
        $this->assertEquals(1, $exitCode);
235
236
        $this->assertStringContainsString('1 messages are obsolete in the messages domain', $tester->getDisplay());
237
        $this->assertStringContainsString('1 messages are missing in the messages domain', $tester->getDisplay());
238
    }
239
}
240