MigrateHandlerTest::setUp()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 8
rs 9.4286
cc 1
eloc 6
nc 1
nop 0
1
<?php
2
/*
3
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
4
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
5
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
6
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
7
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
8
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
9
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
10
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
11
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
12
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
13
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14
 *
15
 * This software consists of voluntary contributions made by many individuals
16
 * and is licensed under the MIT license. For more information, see
17
 * <http://www.doctrine-project.org>.
18
 */
19
20
namespace BaleenTest\Cli\CommandBus\Timeline;
21
22
use Baleen\Cli\CommandBus\Timeline\MigrateMessage;
23
use Baleen\Cli\CommandBus\Timeline\MigrateHandler;
24
use Baleen\Cli\Exception\CliException;
25
use Baleen\Migrations\Event\EventInterface;
26
use Baleen\Migrations\Event\Timeline\CollectionEvent;
27
use Baleen\Migrations\Event\Timeline\MigrationEvent;
28
use Baleen\Migrations\Migration\Options;
29
use Baleen\Migrations\Version;
30
use BaleenTest\Cli\CommandBus\HandlerTestCase;
31
use Mockery as m;
32
use Symfony\Component\Console\Command\Command;
33
use Symfony\Component\Console\Output\OutputInterface;
34
use Symfony\Component\EventDispatcher\EventDispatcher;
35
36
/**
37
 * Class MigrateHandlerTest
38
 * @author Gabriel Somoza <[email protected]>
39
 */
40
class MigrateHandlerTest extends HandlerTestCase
41
{
42
    /**
43
     * setUp
44
     */
45
    public function setUp()
46
    {
47
        $this->instance = m::mock(MigrateHandler::class)
48
            ->shouldAllowMockingProtectedMethods()
49
            ->makePartial();
50
        $this->command = m::mock(MigrateMessage::class)->makePartial();
51
        parent::setUp();
52
    }
53
54
    /**
55
     * testHandle
56
     * @param $verbosity
57
     * @param $noProgress
58
     * @param $noStorage
59
     * @dataProvider executeProvider
60
     */
61
    public function testHandle($verbosity, $noProgress, $noStorage)
62
    {
63
        // values don't matter here
64
        $strategy = 'both';
65
        $target = 'someTarget';
66
        $dryRun = 'no!'; // again: this really doesn't matter for the test
67
        $shouldTrackProgress = $verbosity !== OutputInterface::VERBOSITY_QUIET;
68
69
        $dispatcher = m::mock(EventDispatcher::class);
70
        $this->command->shouldReceive('getTimeline->getEventDispatcher')->once()->andReturn($dispatcher);
71
72
        $this->output->shouldReceive('getVerbosity')->once()->andReturn($verbosity);
73
        if ($shouldTrackProgress) {
74
            $this->input->shouldReceive('getOption')
75
                ->once()
76
                ->with(MigrateMessage::OPT_NOPROGRESS)
77
                ->andReturn($noProgress);
78
            $shouldTrackProgress = !$noProgress;
79
        }
80
81
        $this->input->shouldReceive('getArgument')->with(MigrateMessage::ARG_TARGET)->once()->andReturn($target);
82
        $this->input->shouldReceive('getOption')->with(MigrateMessage::OPT_DRY_RUN)->once()->andReturn($dryRun);
83
        $this->input->shouldReceive('getOption')->with(MigrateMessage::OPT_NO_STORAGE)->once()->andReturn($noStorage);
84
        $this->instance->shouldReceive('getStrategyOption')->with($this->input)->andReturn($strategy);
85
        $this->instance->shouldReceive('attachEvents')->once()->with($this->output, $dispatcher);
86
        $this->command->shouldReceive('getTimeline->' . $strategy)->once()->with($target, m::type(Options::class));
87
88
        $this->handle();
89
90
        $this->assertEquals(
91
            $shouldTrackProgress,
92
            $this->getPropVal('trackProgress', $this->instance),
93
            'Should track progress.'
94
        );
95
        $this->assertEquals(
96
            !$noStorage && !$dryRun,
97
            $this->getPropVal('saveChanges', $this->instance),
98
            'Should NOT save changes if --no-storage or --dry-run specified.'
99
        );
100
    }
101
102
    /**
103
     * handleProvider
104
     * @return array
105
     */
106
    public function executeProvider()
107
    {
108
        $verbosities = [
109
            OutputInterface::VERBOSITY_NORMAL,
110
            OutputInterface::VERBOSITY_QUIET,
111
            OutputInterface::VERBOSITY_VERBOSE,
112
            OutputInterface::VERBOSITY_VERY_VERBOSE,
113
            OutputInterface::VERBOSITY_DEBUG,
114
        ];
115
        $trueFalse = [true, false];
116
        return $this->combinations([$verbosities, $trueFalse, $trueFalse]);
117
    }
118
119
    /**
120
     * testGetStrategyOption
121
     * @dataProvider getStrategyOptionProvider
122
     */
123
    public function testGetStrategyOption($strategy, $throwException = false)
124
    {
125
        $this->input->shouldReceive('getOption')->once()->with(MigrateMessage::OPT_STRATEGY)->andReturn($strategy);
126
127
        if ($throwException) {
128
            $this->setExpectedException(CliException::class, 'Unknown');
129
        }
130
131
        $this->invokeMethod('getStrategyOption', $this->instance, [$this->input]);
132
    }
133
134
    /**
135
     * getStrategyOptionProvider
136
     * @return array
137
     */
138
    public function getStrategyOptionProvider()
139
    {
140
        return [
141
            ['both'],
142
            ['up'],
143
            ['down'],
144
            ['oops!', true],
145
        ];
146
    }
147
148
    /**
149
     * testOnCollectionAfter
150
     * @param $withProgress
151
     * @dataProvider trueFalseProvider
152
     */
153
    public function testOnCollectionAfter($withProgress)
154
    {
155
        $this->output->shouldReceive('writeln')->with('/END/')->once();
156
        if ($withProgress) {
157
            $progress = m::mock();
158
            $progress->shouldReceive('finish')->once();
159
            $this->setPropVal('progress', $progress, $this->instance);
160
            $this->output->shouldReceive('writeln')->once();
161
        }
162
        $this->setPropVal('output', $this->output, $this->instance);
163
        $this->invokeMethod('onCollectionAfter', $this->instance);
164
    }
165
166
    /**
167
     * testOnMigrationAfter
168
     * @param $withProgress
169
     * @dataProvider trueFalseProvider
170
     */
171
    public function testOnMigrationAfter($withProgress)
172
    {
173
        $currentProgress = 50;
174
        $event = m::mock(MigrationEvent::class);
175
        if ($withProgress) {
176
            $progress = m::mock();
177
            $progress->shouldReceive('setProgress')->once()->with($currentProgress);
178
            $this->setPropVal('progress', $progress, $this->instance);
179
180
            $event->shouldReceive('getProgress->getCurrent')->andReturn($currentProgress);
181
        } else {
182
            $event->shouldNotReceive('getProgress');
183
        }
184
        $this->invokeMethod('onMigrationAfter', $this->instance, [$event]);
185
    }
186
187
    /**
188
     * testSaveVersionListener
189
     */
190
    public function testSaveVersionListener()
191
    {
192
        $version = new Version(1); // value doesn't really matter
193
        $event = m::mock(MigrationEvent::class);
194
        $event->shouldReceive('getVersion')->once()->andReturn($version);
195
196
        $command = m::mock(Command::class);
197
        $command->shouldReceive('getStorage->update')->once()->with($version);
198
        $this->setPropVal('command', $command, $this->instance);
199
200
        $this->invokeMethod('saveVersionListener', $this->instance, [$event]);
201
    }
202
203
    /**
204
     * testOnCollectionBefore
205
     * @param bool $trackProgress
206
     * @param bool $isDirectionUp
207
     * @dataProvider onCollectionBeforeProvider
208
     */
209
    public function testOnCollectionBefore($trackProgress = true, $isDirectionUp = true)
210
    {
211
        $target = new Version('v10');
212
        /** @var m\Mock|CollectionEvent $event */
213
        $event = m::mock(CollectionEvent::class);
214
        $event->shouldReceive([
215
            'getTarget' => $target,
216
            'getOptions->isDirectionUp' => $isDirectionUp,
217
        ])->once();
218
        $this->output->shouldReceive('writeln')->with('/' . $target->getId() . '/')->once();
219
        $this->setPropVal('output', $this->output, $this->instance);
220
221
        $this->setPropVal('trackProgress', $trackProgress, $this->instance);
222
        if ($trackProgress) {
223
            $event->shouldReceive('getProgress->getTotal')->atLeast(1)->andReturn(10);
224
            $this->output->shouldReceive('isDecorated')->zeroOrMoreTimes()->andReturn(true);
225
            $this->output
226
                ->shouldReceive('getVerbosity')
227
                ->zeroOrMoreTimes()
228
                ->andReturn(OutputInterface::VERBOSITY_NORMAL);
229
        } else {
230
            $event->shouldNotReceive('getProgress');
231
        }
232
233
        $this->invokeMethod('onCollectionBefore', $this->instance, [$event]);
234
    }
235
236
    /**
237
     * onCollectionBeforeProvider
238
     * @return array
239
     */
240
    public function onCollectionBeforeProvider()
241
    {
242
        $trueFalse = [true, false];
243
        return $this->combinations([$trueFalse, $trueFalse]);
244
    }
245
246
    /**
247
     * testOnMigrationBefore
248
     */
249
    public function testOnMigrationBefore()
250
    {
251
        $version = new Version('v10');
252
        $event = m::mock(MigrationEvent::class);
253
        $event->shouldReceive([
254
            'getVersion' => $version,
255
            'getOptions' => new Options(Options::DIRECTION_UP),
256
        ])->once();
257
        $this->output->shouldReceive('writeln')->with('/' . $version->getId() . '/')->once();
258
        $this->setPropVal('output', $this->output, $this->instance);
259
        $this->invokeMethod('onMigrationBefore', $this->instance, [$event]);
260
    }
261
262
    /**
263
     * testAttachEvents
264
     * @param int $verbosity
265
     * @param $saveChanges
266
     * @dataProvider attachEventsProvider
267
     */
268
    public function testAttachEvents($verbosity, $saveChanges)
269
    {
270
        $dispatcher = m::mock(EventDispatcher::class);
271
        $this->setPropVal('saveChanges', $saveChanges, $this->instance);
272
        $this->output->shouldReceive('getVerbosity')->andReturn($verbosity);
273
        $counts = [
274
            EventInterface::MIGRATION_BEFORE => 0,
275
            EventInterface::MIGRATION_AFTER => 0,
276
            EventInterface::COLLECTION_BEFORE => 0,
277
            EventInterface::COLLECTION_AFTER => 0,
278
        ];
279
        if ($verbosity >= OutputInterface::VERBOSITY_NORMAL) {
280
            $counts = [
281
                EventInterface::MIGRATION_BEFORE => 1,
282
                EventInterface::MIGRATION_AFTER => 1,
283
                EventInterface::COLLECTION_BEFORE => 1,
284
                EventInterface::COLLECTION_AFTER => 1,
285
            ];
286
        }
287
        if ($saveChanges) {
288
            $counts[EventInterface::MIGRATION_AFTER] += 1;
289
        }
290
        foreach ($counts as $event => $count) {
291
            $dispatcher->shouldReceive('addListener')->times($count)->with($event, m::any());
292
        }
293
        $this->invokeMethod('attachEvents', $this->instance, [$this->output, $dispatcher]);
294
    }
295
296
    /**
297
     * attachEventsProvider
298
     * @return array
299
     */
300
    public function attachEventsProvider()
301
    {
302
        $trueFalse = [true, false];
303
        $verbosities = [
304
            OutputInterface::VERBOSITY_QUIET,
305
            OutputInterface::OUTPUT_NORMAL,
306
            OutputInterface::VERBOSITY_VERY_VERBOSE,
307
        ];
308
        return $this->combinations([$verbosities, $trueFalse]);
309
    }
310
}
311