Completed
Push — master ( a20e35...2a3e96 )
by Greg
03:21
created

tests/cli/CollectionCest.php (1 issue)

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
namespace Robo;
3
4
use \CliGuy;
5
6
use Robo\Collection\Temporary;
7
8
class CollectionCest
9
{
10
    public function _before(CliGuy $I)
11
    {
12
        $I->amInPath(codecept_data_dir().'sandbox');
13
    }
14
15 View Code Duplication
    public function toRunMultipleTasksViaACollectionBuilder(CliGuy $I)
16
    {
17
        // This tests creating multiple tasks in a single builder,
18
        // which implicitly adds them to a collection.  To keep things
19
        // simple, we are only going to use taskFilesystemStack.  It
20
        // would be possible, of course, to do these operations with
21
        // a single FilesystemStack, but our goal is to test creating
22
        // multiple tasks with a builder, and ensure that a propper
23
        // collection is built.
24
        $collection = $I->collectionBuilder();
25
        $result = $collection->taskFilesystemStack()
26
                ->mkdir('a')
27
                ->touch('a/a.txt')
28
            ->rollback(
29
                $I->taskDeleteDir('a')
30
            )
31
            ->taskFilesystemStack()
32
                ->mkdir('a/b')
33
                ->touch('a/b/b.txt')
34
            ->taskFilesystemStack()
35
                ->mkdir('a/c')
36
                ->touch('a/c/c.txt')
37
            ->run();
38
39
        $I->assertEquals(0, $result->getExitCode(), $result->getMessage());
40
41
        // All of the tasks created by the builder should be added
42
        // to a collection, and `run()` should run them all.
43
        $I->seeDirFound('a');
44
        $I->seeFileFound('a/a.txt');
45
        $I->seeDirFound('a/b');
46
        $I->seeFileFound('a/b/b.txt');
47
        $I->seeDirFound('a/c');
48
        $I->seeFileFound('a/c/c.txt');
49
    }
50
51
    public function toUseAWorkingDirWithACollectionBuilder(CliGuy $I)
52
    {
53
        // Run the same test with a working directory.  The working
54
        // directory path will point to a temporary directory which
55
        // will be moved into place once the tasks complete.
56
        $collection = $I->collectionBuilder();
57
        $workDirPath = $collection->workDir("build");
58
        $I->assertNotEquals("build", basename($workDirPath));
59
        $result = $collection->taskFilesystemStack()
60
                ->mkdir("{$workDirPath}/a")
61
                ->touch("{$workDirPath}/a/a.txt")
62
            ->taskFilesystemStack()
63
                ->mkdir("{$workDirPath}/a/b")
64
                ->touch("{$workDirPath}/a/b/b.txt")
65
            ->taskFilesystemStack()
66
                ->mkdir("{$workDirPath}/a/c")
67
                ->touch("{$workDirPath}/a/c/c.txt")
68
            ->run();
69
70
        $I->assertEquals(0, $result->getExitCode(), $result->getMessage());
71
72
        // All of the tasks created by the builder should be added
73
        // to a collection, and `run()` should run them all.
74
        $I->seeDirFound('build/a');
75
        $I->seeFileFound('build/a/a.txt');
76
        $I->seeDirFound('build/a/b');
77
        $I->seeFileFound('build/a/b/b.txt');
78
        $I->seeDirFound('build/a/c');
79
        $I->seeFileFound('build/a/c/c.txt');
80
    }
81
82 View Code Duplication
    public function toRollbackAfterFailureViaACollectionBuilder(CliGuy $I)
83
    {
84
        // This is like the previous test, toRunMultipleTasksViaACollectionBuilder,
85
        // except we force an error at the end, and confirm that the
86
        // rollback function is called.
87
        $collection = $I->collectionBuilder();
88
        $result = $collection->taskFilesystemStack()
89
                ->mkdir('j')
90
                ->touch('j/j.txt')
91
            ->rollback(
92
                $I->taskDeleteDir('j')
93
            )
94
            ->taskFilesystemStack()
95
                ->mkdir('j/k')
96
                ->touch('j/k/k.txt')
97
            ->taskFilesystemStack()
98
                ->mkdir('j/k/m')
99
                ->touch('j/k/m/m.txt')
100
            ->taskCopyDir(['doesNotExist' => 'copied'])
101
            ->run();
102
103
        $I->assertEquals(1, $result->getExitCode(), $result->getMessage());
104
105
        // All of the tasks created by the builder should be added
106
        // to a collection, and `run()` should run them all.
107
        $I->dontSeeFileFound('q/q.txt');
108
        $I->dontSeeFileFound('j/j.txt');
109
        $I->dontSeeFileFound('j/k/k.txt');
110
        $I->dontSeeFileFound('j/k/m/m.txt');
111
    }
112
113
    public function toRollbackAWorkingDir(CliGuy $I)
114
    {
115
        // Run the same test with a working directory.  The working
116
        // directory path will point to a temporary directory which
117
        // will be moved into place once the tasks complete.
118
        $collection = $I->collectionBuilder();
119
        $workDirPath = $collection->workDir("build");
120
        $I->assertNotEquals("build", basename($workDirPath));
121
        $result = $collection->taskFilesystemStack()
122
                ->mkdir("{$workDirPath}/a")
123
                ->touch("{$workDirPath}/a/a.txt")
124
            ->taskFilesystemStack()
125
                ->mkdir("{$workDirPath}/a/b")
126
                ->touch("{$workDirPath}/a/b/b.txt")
127
            ->taskFilesystemStack()
128
                ->mkdir("{$workDirPath}/a/c")
129
                ->touch("{$workDirPath}/a/c/c.txt")
130
            ->taskCopyDir(['doesNotExist' => 'copied'])
131
            ->run();
132
133
        $I->assertEquals(1, $result->getExitCode(), $result->getMessage());
134
135
        // All of the tasks created by the builder should be added
136
        // to a collection, and `run()` should run them all.
137
        $I->dontSeeFileFound('build/a');
138
        $I->dontSeeFileFound($workDirPath);
139
    }
140
141
    public function toBuildFilesViaAddIterable(CliGuy $I)
142
    {
143
        $processList = ['cats', 'dogs', 'sheep', 'fish', 'horses', 'cows'];
144
145
        $collection = $I->collectionBuilder();
146
        $result = $collection
147
            ->taskFilesystemStack()
148
                ->mkdir('stuff')
149
            ->taskForEach($processList)
150
                ->withBuilder(
151
                    function ($builder, $key, $value) {
152
                        return $builder
153
                            ->taskFilesystemStack()
154
                                ->touch("stuff/{$value}.txt");
155
                    }
156
                )
157
            ->run();
158
159
        $I->assertEquals(0, $result->getExitCode(), $result->getMessage());
160
161
        $I->seeFileFound('stuff/cats.txt');
162
        $I->seeFileFound('stuff/dogs.txt');
163
        $I->seeFileFound('stuff/sheep.txt');
164
        $I->seeFileFound('stuff/fish.txt');
165
        $I->seeFileFound('stuff/horses.txt');
166
        $I->seeFileFound('stuff/cows.txt');
167
    }
168
169
    public function toRollbackANestedCollection(CliGuy $I)
170
    {
171
        // This is like the previous test, toRunMultipleTasksViaACollectionBuilder,
172
        // except we force an error at the end, and confirm that the
173
        // rollback function is called.
174
        $collection = $I->collectionBuilder();
175
        $collection->taskFilesystemStack()
176
                ->mkdir('j')
177
                ->touch('j/j.txt')
178
            ->rollback(
179
                $I->taskDeleteDir('j')
180
            )
181
            ->taskFilesystemStack()
182
                ->mkdir('j/k')
183
                ->touch('j/k/k.txt')
184
            ->taskFilesystemStack()
185
                ->mkdir('j/k/m')
186
                ->touch('j/k/m/m.txt');
187
188
        $result = $I->collectionBuilder()
189
            ->taskFilesystemStack()
190
                ->mkdir('q')
191
                ->touch('q/q.txt')
192
            ->addTask($collection)
193
            ->taskCopyDir(['doesNotExist' => 'copied'])
194
            ->run();
195
196
        $I->assertEquals(1, $result->getExitCode(), $result->getMessage());
197
198
        // All of the tasks created by the builder should be added
199
        // to a collection, and `run()` should run them all.
200
        $I->seeFileFound('q/q.txt');
201
        $I->dontSeeFileFound('j/j.txt');
202
        $I->dontSeeFileFound('j/k/k.txt');
203
        $I->dontSeeFileFound('j/k/m/m.txt');
204
    }
205
206
    public function toRollbackInCorrectOrder(CliGuy $I)
207
    {
208
        $expected_order = [4,3,2,1];
209
        $actual_order = [];
210
        $collection = $I->collectionBuilder();
211
        $collection->rollbackCode(function () use (&$actual_order) {
212
            $actual_order[] = 1;
213
        });
214
        $collection->rollbackCode(function () use (&$actual_order) {
215
            $actual_order[] = 2;
216
        });
217
        $collection->rollbackCode(function () use (&$actual_order) {
218
            $actual_order[] = 3;
219
        });
220
        $collection->rollbackCode(function () use (&$actual_order) {
221
            $actual_order[] = 4;
222
        });
223
        $collection->addCode(function () {
224
            return Result::EXITCODE_ERROR;
225
        });
226
        $result = $collection->run();
0 ignored issues
show
$result is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
227
        $I->assertEquals($expected_order, $actual_order);
228
    }
229
230 View Code Duplication
    public function toCreateDirViaCollection(CliGuy $I)
231
    {
232
        // Set up a collection to add tasks to
233
        $collection = $I->collectionBuilder();
234
235
        // Set up a filesystem stack
236
        $collection->taskFilesystemStack()
237
            ->mkdir('log')
238
            ->touch('log/error.txt');
239
240
        // FilesystemStack has not run yet, so file should not be found.
241
        $I->dontSeeFileFound('log/error.txt');
242
243
        // Run the task collection; now the files should be present
244
        $collection->run();
245
        $I->seeFileFound('log/error.txt');
246
        $I->seeDirFound('log');
247
    }
248
249
    public function toUseATmpDirAndConfirmItIsDeleted(CliGuy $I)
250
    {
251
        // Set up a collection to add tasks to
252
        $collection = $I->collectionBuilder();
253
254
        // Get a temporary directory to work in. Note that we get a
255
        // name back, but the directory is not created until the task
256
        // runs.  This technically is not thread-safe, but we create
257
        // a random name, so it is unlikely to conflict.
258
        $tmpPath = $collection->tmpDir();
259
260
        // Set up a filesystem stack, but use a collection to defer execution
261
        $collection->taskFilesystemStack()
262
            ->mkdir("$tmpPath/tmp")
263
            ->touch("$tmpPath/tmp/error.txt")
264
            ->rename("$tmpPath/tmp", "$tmpPath/log");
265
266
        // Copy our tmp directory to a location that is not transient
267
        $collection->taskCopyDir([$tmpPath => 'copied']);
268
269
        // FilesystemStack has not run yet, so no files should be found.
270
        $I->dontSeeFileFound("$tmpPath/tmp/error.txt");
271
        $I->dontSeeFileFound("$tmpPath/log/error.txt");
272
        $I->dontSeeFileFound('copied/log/error.txt');
273
274
        // Run the task collection
275
        $result = $collection->run();
276
        $I->assertEquals(0, $result->getExitCode(), $result->getMessage());
277
        $I->assertEquals($result['path'], $tmpPath, "Tmp dir result matches accessor.");
278
279
        // The file 'error.txt' should have been copied into the "copied" dir.
280
        // This also proves that the tmp directory was created.
281
        $I->seeFileFound('copied/log/error.txt');
282
        // $tmpPath should be deleted after $collection->run() completes.
283
        $I->dontSeeFileFound("$tmpPath/tmp/error.txt");
284
        $I->dontSeeFileFound("$tmpPath/log/error.txt");
285
        $I->dontSeeFileFound("$tmpPath");
286
    }
287
288
    public function toUseATmpDirAndChangeWorkingDirectory(CliGuy $I)
289
    {
290
        // Set up a collection to add tasks to
291
        $collection = $I->collectionBuilder();
292
293
        $cwd = getcwd();
294
295
        $tmpPath = $collection->taskTmpDir()
296
            ->cwd()
297
            ->getPath();
298
299
        // Set up a filesystem stack, but use a collection to defer execution.
300
        // Note that since we used 'cwd()' above, the relative file paths
301
        // used below will be inside the temporary directory.
302
        $collection->taskFilesystemStack()
303
            ->mkdir("log")
304
            ->touch("log/error.txt");
305
306
        // Copy our tmp directory to a location that is not transient
307
        $collection->taskCopyDir(['log' => "$cwd/copied2"]);
308
309
        // FilesystemStack has not run yet, so no files should be found.
310
        $I->dontSeeFileFound("$tmpPath/log/error.txt");
311
        $I->dontSeeFileFound('$cwd/copied2/log/error.txt');
312
313
        // Run the task collection
314
        $result = $collection->run();
315
        $I->assertEquals(0, $result->getExitCode(), $result->getMessage());
316
317
        // The file 'error.txt' should have been copied into the "copied" dir
318
        $I->seeFileFound("$cwd/copied2/error.txt");
319
        // $tmpPath should be deleted after $collection->run() completes.
320
        $I->dontSeeFileFound("$tmpPath/log/error.txt");
321
        // Make sure that 'log' was created in the temporary directory, not
322
        // at the current working directory.
323
        $I->dontSeeFileFound("$cwd/log/error.txt");
324
325
        // Make sure that our working directory was restored.
326
        $finalWorkingDir = getcwd();
327
        $I->assertEquals($cwd, $finalWorkingDir);
328
    }
329
330
    public function toCreateATmpFileAndConfirmItIsDeleted(CliGuy $I)
331
    {
332
        // Set up a collection to add tasks to
333
        $collection = $I->collectionBuilder();
334
335
        // Write to a temporary file. Note that we can get the path
336
        // to the tempoary file that will be created, even though the
337
        // the file is not created until the task collecction runs.
338
        $tmpPath = $collection->taskTmpFile('tmp', '.txt')
339
            ->line("This is a test file")
340
            ->getPath();
341
342
        // Copy our tmp directory to a location that is not transient
343
        $collection->taskFilesystemStack()
344
            ->copy($tmpPath, 'copied.txt');
345
346
        // FilesystemStack has not run yet, so no files should be found.
347
        $I->dontSeeFileFound("$tmpPath");
348
        $I->dontSeeFileFound('copied.txt');
349
350
        // Run the task collection
351
        $result = $collection->run();
352
        $I->assertEquals(0, $result->getExitCode(), $result->getMessage());
353
354
        // The file 'copied.txt' should have been copied from the tmp file
355
        $I->seeFileFound('copied.txt');
356
        // $tmpPath should be deleted after $collection->run() completes.
357
        $I->dontSeeFileFound("$tmpPath");
358
    }
359
360
    public function toUseATmpDirWithAlternateSyntax(CliGuy $I)
361
    {
362
        $collection = $I->collectionBuilder();
363
364
        // This test is equivalent to toUseATmpDirAndConfirmItIsDeleted,
365
        // but uses a different technique to create a collection of tasks.
366
        $tmpPath = $collection->tmpDir();
367
368
        // Now, rather than creating the tasks with a collection builder,
369
        // which automatically adds the tasks to the collection as they are
370
        // created, we will instead create them individually and then add
371
        // them to the collection via the addTaskList() method.
372
        $result = $collection->addTaskList(
373
            [
374
                $I->taskFilesystemStack()->mkdir("$tmpPath/log")->touch("$tmpPath/log/error.txt"),
375
                $I->taskCopyDir([$tmpPath => 'copied3']),
376
            ]
377
        )->run();
378
379
        // The results of this operation should be the same.
380
        $I->assertEquals(0, $result->getExitCode(), $result->getMessage());
381
        $I->seeFileFound('copied3/log/error.txt');
382
        $I->dontSeeFileFound("$tmpPath/log/error.txt");
383
    }
384
385
    public function toCreateATmpDirWithoutACollection(CliGuy $I)
386
    {
387
        // Create a temporary directory, using our function name as
388
        // the prefix for the directory name.
389
        $tmpDirTask = $I->taskTmpDir(__FUNCTION__);
390
        $tmpPath = $tmpDirTask->getPath();
391
        $I->dontSeeFileFound($tmpPath);
392
        $tmpDirTask->run();
393
        $I->seeDirFound($tmpPath);
394
        // Creating a temporary directory without a task collection will
395
        // cause the temporary directory to be deleted when the program
396
        // terminates.  We can force it to clean up sooner by calling
397
        // TransientManager::complete(); note that this deletes ALL global tmp
398
        // directories, so this is not thread-safe!  Useful in tests, though.
399
        Temporary::complete();
400
        $I->dontSeeFileFound($tmpPath);
401
    }
402
403
    public function toCreateATmpDirUsingShortcut(CliGuy $I)
404
    {
405
        // Create a temporary directory, using our function name as
406
        // the prefix for the directory name.
407
        $tmpPath = $I->shortcutTmpDir(__FUNCTION__);
408
        $I->seeDirFound($tmpPath);
409
        // Creating a temporary directory without a task collection will
410
        // cause the temporary directory to be deleted when the program
411
        // terminates.  We can force it to clean up sooner by calling
412
        // TransientManager::complete(); note that this deletes ALL global tmp
413
        // directories, so this is not thread-safe!  Useful in tests, though.
414
        Temporary::complete();
415
        $I->dontSeeFileFound($tmpPath);
416
    }
417
418
    public function toThrowAnExceptionAndConfirmItIsCaught(CliGuy $I)
419
    {
420
        $collection = $I->getContainer()->get('collection');
421
422
        $collection->addCode(
423
            function () {
424
                throw new \RuntimeException('Error');
425
            }
426
        );
427
        $result = $collection->run();
428
        $I->assertEquals('Error', $result->getMessage());
429
        $I->assertEquals(1, $result->getExitCode());
430
    }
431
432
    public function toChainData(CliGuy $I)
433
    {
434
        $collection = $I->collectionBuilder();
435
436
        $result = $collection
437
            ->taskValueProvider()
438
                ->provideMessage('1st') // Sets Result's message to '1st'
439
                ->storeState('one') // Copy Result's message to $state['one']
440
            ->taskValueProvider()
441
                ->provideMessage('2nd')
442
                ->storeState('two')
443
            ->taskValueProvider()
444
                ->deferTaskConfiguration('provideItem', 'one') // Same as ->proivdeItem($state['one']), but runs immediately before this task's run() method.
445
                ->deferTaskConfiguration('provideMessage', 'two')
446
                ->storeState('final')
447
            ->run();
448
449
        $state = $collection->getState();
450
        $I->assertEquals('1st', $state['one']);
451
        $I->assertEquals('1st', $state['item']);
452
        $I->assertEquals('2nd', $state['final']);
453
    }
454
}
455