Passed
Push — master ( cbdf83...8b3ece )
by Kevin
02:05
created

php$3 ➔ can_show_extended_expressions()   A

Complexity

Conditions 1

Size

Total Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 16
rs 9.7333
cc 1
1
<?php
2
3
namespace Zenstruck\ScheduleBundle\Tests\Command;
4
5
use PHPUnit\Framework\TestCase;
0 ignored issues
show
Bug introduced by
The type PHPUnit\Framework\TestCase was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
6
use Symfony\Component\Console\Application;
7
use Symfony\Component\Console\Command\Command;
8
use Symfony\Component\Console\Helper\FormatterHelper;
9
use Symfony\Component\Console\Helper\HelperSet;
10
use Symfony\Component\Console\Output\OutputInterface;
11
use Symfony\Component\Console\Tester\CommandTester;
12
use Zenstruck\ScheduleBundle\Command\ScheduleListCommand;
13
use Zenstruck\ScheduleBundle\Schedule;
14
use Zenstruck\ScheduleBundle\Schedule\Extension\ExtensionHandlerRegistry;
15
use Zenstruck\ScheduleBundle\Schedule\ScheduleBuilder;
16
use Zenstruck\ScheduleBundle\Schedule\Task\CommandTask;
17
use Zenstruck\ScheduleBundle\Tests\Fixture\MockScheduleBuilder;
18
use Zenstruck\ScheduleBundle\Tests\Fixture\MockTask;
19
20
/**
21
 * @author Kevin Bond <[email protected]>
22
 */
23
final class ScheduleListCommandTest extends TestCase
24
{
25
    /**
26
     * @test
27
     */
28
    public function no_tasks_defined()
29
    {
30
        $runner = (new MockScheduleBuilder())->getRunner();
31
        $commandTester = new CommandTester(new ScheduleListCommand($runner, new ExtensionHandlerRegistry([])));
32
33
        $this->expectException(\RuntimeException::class);
34
        $this->expectExceptionMessage('No scheduled tasks configured.');
35
36
        $commandTester->execute([]);
37
    }
38
39
    /**
40
     * @test
41
     */
42
    public function lists_configured_tasks_and_issues()
43
    {
44
        $runner = (new MockScheduleBuilder())
45
            ->addBuilder(new class() implements ScheduleBuilder {
46
                public function buildSchedule(Schedule $schedule): void
47
                {
48
                    $schedule->emailOnFailure('[email protected]');
49
                    $schedule->addCommand('my:command')
50
                        ->mondays()
51
                        ->at('1:30')
52
                        ->emailOnFailure('[email protected]')
53
                        ->pingOnFailure('https://example.com/my-command-failed')
54
                    ;
55
                }
56
            })
57
            ->getRunner()
58
        ;
59
        $command = new ScheduleListCommand($runner, new ExtensionHandlerRegistry([]));
60
        $command->setHelperSet(new HelperSet([new FormatterHelper()]));
61
        $command->setApplication(new Application());
62
        $commandTester = new CommandTester($command);
63
64
        $commandTester->execute([]);
65
        $output = $this->normalizeOutput($commandTester);
66
67
        $this->assertSame(1, $commandTester->getStatusCode());
68
        $this->assertStringContainsString('[!] CommandTask my:command 2 30 1 * * 1 (Every Monday at 1:30am)', $output);
69
        $this->assertStringContainsString('[WARNING] 4 task issues:', $output);
70
        $this->assertStringContainsString('[ERROR] No task runner registered to handle "Zenstruck\ScheduleBundle\Schedule\Task\CommandTask".', $output);
71
        $this->assertStringContainsString('[ERROR] To use the email extension you must configure a mailer (config path: "zenstruck_schedule.email_handler").', $output);
72
        $this->assertStringContainsString('[ERROR] No extension handler registered for "Zenstruck\ScheduleBundle\Schedule\Extension\PingExtension: On Task', $output);
73
        $this->assertStringContainsString('[ERROR] Command "my:command" not registered.', $output);
74
        $this->assertStringContainsString('Failure, ping "https://example.com/my-command-failed"".', $output);
75
        $this->assertStringContainsString('1 Schedule Extension:', $output);
76
        $this->assertStringContainsString('On Schedule Failure, email output to "[email protected]"', $output);
77
        $this->assertStringContainsString('[WARNING] 1 issue with schedule:', $output);
78
    }
79
80
    /**
81
     * @test
82
     */
83
    public function renders_exception_stack_trace_if_verbose()
84
    {
85
        $runner = (new MockScheduleBuilder())
86
            ->addBuilder(new class() implements ScheduleBuilder {
87
                public function buildSchedule(Schedule $schedule): void
88
                {
89
                    $schedule->addCommand('my:command')
90
                        ->mondays()
91
                        ->at('1:30')
92
                    ;
93
                }
94
            })
95
            ->getRunner()
96
        ;
97
        $command = new ScheduleListCommand($runner, new ExtensionHandlerRegistry([]));
98
        $command->setHelperSet(new HelperSet([new FormatterHelper()]));
99
        $command->setApplication(new Application());
100
        $commandTester = new CommandTester($command);
101
102
        $commandTester->execute([], ['verbosity' => OutputInterface::VERBOSITY_VERBOSE]);
103
        $output = $this->normalizeOutput($commandTester);
104
105
        $this->assertSame(1, $commandTester->getStatusCode());
106
        $this->assertStringContainsString('[WARNING] 2 task issues:', $output);
107
        $this->assertStringContainsString('In ScheduleRunner.php line', $output);
108
        $this->assertStringContainsString('[LogicException]', $output);
109
        $this->assertStringContainsString('No task runner registered to handle', $output);
110
        $this->assertStringContainsString('In CommandTask.php line', $output);
111
        $this->assertStringContainsString('[Symfony\Component\Console\Exception\CommandNotFoundException]', $output);
112
        $this->assertStringContainsString('Command "my:command" not registered.', $output);
113
        $this->assertStringContainsString('Exception trace:', $output);
114
    }
115
116
    /**
117
     * @test
118
     */
119
    public function lists_configured_tasks_and_issues_in_detail()
120
    {
121
        $runner = (new MockScheduleBuilder())
122
            ->addBuilder(new class() implements ScheduleBuilder {
123
                public function buildSchedule(Schedule $schedule): void
124
                {
125
                    $schedule->emailOnFailure('[email protected]');
126
                    $schedule->addCommand('my:command')
127
                        ->arguments('arg1', '--option1')
128
                        ->mondays()
129
                        ->at('1:30')
130
                        ->emailOnFailure('[email protected]')
131
                        ->pingOnFailure('https://example.com/my-command-failed')
132
                    ;
133
                }
134
            })
135
            ->getRunner()
136
        ;
137
        $command = new ScheduleListCommand($runner, new ExtensionHandlerRegistry([]));
138
        $command->setHelperSet(new HelperSet([new FormatterHelper()]));
139
        $command->setApplication(new Application());
140
        $commandTester = new CommandTester($command);
141
142
        $commandTester->execute(['--detail' => null]);
143
        $output = $this->normalizeOutput($commandTester);
144
145
        $this->assertSame(1, $commandTester->getStatusCode());
146
        $this->assertStringContainsString('1 Scheduled Task Configured', $output);
147
        $this->assertStringContainsString('(1/1) CommandTask: my:command', $output);
148
        $this->assertStringContainsString('30 1 * * 1 (Every Monday at 1:30am)', $output);
149
        $this->assertStringContainsString('Mon,', $output);
150
        $this->assertStringContainsString('Arguments: arg1 --option1', $output);
151
        $this->assertStringContainsString('2 Task Extensions:', $output);
152
        $this->assertStringContainsString('On Task Failure, email output to "[email protected]"', $output);
153
        $this->assertStringContainsString('On Task Failure, ping "https://example.com/my-command-failed"', $output);
154
        $this->assertStringContainsString('[WARNING] 4 issues with this task:', $output);
155
        $this->assertStringContainsString('[ERROR] No task runner registered to handle "Zenstruck\ScheduleBundle\Schedule\Task\CommandTask".', $output);
156
        $this->assertStringContainsString('[ERROR] To use the email extension you must configure a mailer (config path: "zenstruck_schedule.email_handler").', $output);
157
        $this->assertStringContainsString('[ERROR] No extension handler registered for "Zenstruck\ScheduleBundle\Schedule\Extension\PingExtension: On Task', $output);
158
        $this->assertStringContainsString('[ERROR] Command "my:command" not registered.', $output);
159
        $this->assertStringContainsString('Failure, ping "https://example.com/my-command-failed"".', $output);
160
        $this->assertStringContainsString('1 Schedule Extension:', $output);
161
        $this->assertStringContainsString('On Schedule Failure, email output to "[email protected]"', $output);
162
        $this->assertStringContainsString('[WARNING] 1 issue with schedule:', $output);
163
    }
164
165
    /**
166
     * @test
167
     */
168
    public function command_task_with_invalid_argument_shows_as_error()
169
    {
170
        $runner = (new MockScheduleBuilder())
171
            ->addTask(new CommandTask('my:command -v --option1'))
172
            ->getRunner()
173
        ;
174
175
        $application = new Application();
176
        $application->add(new class() extends Command {
177
            protected static $defaultName = 'my:command';
178
179
            protected function configure()
180
            {
181
                $this->addArgument('arg1');
182
            }
183
        });
184
        $command = new ScheduleListCommand($runner, new ExtensionHandlerRegistry([]));
185
        $command->setHelperSet(new HelperSet([new FormatterHelper()]));
186
        $command->setApplication($application);
187
        $commandTester = new CommandTester($command);
188
189
        $commandTester->execute([]);
190
        $output = $this->normalizeOutput($commandTester);
191
192
        $this->assertSame(1, $commandTester->getStatusCode());
193
        $this->assertStringContainsString('1 Scheduled Task Configured', $output);
194
        $this->assertStringContainsString('CommandTask my:command', $output);
195
        $this->assertStringContainsString('[WARNING] 2 task issues:', $output);
196
        $this->assertStringContainsString('[ERROR] The "--option1" option does not exist.', $output);
197
    }
198
199
    /**
200
     * @test
201
     */
202
    public function no_issues_returns_successful_exit_code()
203
    {
204
        $runner = (new MockScheduleBuilder())
205
            ->addTask(new MockTask('my task'))
206
            ->getRunner()
207
        ;
208
209
        $command = new ScheduleListCommand($runner, new ExtensionHandlerRegistry([]));
210
        $command->setHelperSet(new HelperSet([new FormatterHelper()]));
211
        $command->setApplication(new Application());
212
        $commandTester = new CommandTester($command);
213
214
        $commandTester->execute([]);
215
        $output = $this->normalizeOutput($commandTester);
216
217
        $this->assertSame(0, $commandTester->getStatusCode());
218
        $this->assertStringContainsString('1 Scheduled Task Configured', $output);
219
        $this->assertStringContainsString('MockTask', $output);
220
        $this->assertStringContainsString('my task', $output);
221
    }
222
223
    /**
224
     * @test
225
     */
226
    public function can_show_hashed_expressions()
227
    {
228
        $runner = (new MockScheduleBuilder())
229
            ->addTask((new MockTask('my task'))->cron('#daily'))
230
            ->getRunner()
231
        ;
232
233
        $command = new ScheduleListCommand($runner, new ExtensionHandlerRegistry([]));
234
        $command->setHelperSet(new HelperSet([new FormatterHelper()]));
235
        $command->setApplication(new Application());
236
        $commandTester = new CommandTester($command);
237
238
        $commandTester->execute([]);
239
        $output = $this->normalizeOutput($commandTester);
240
241
        $this->assertStringContainsString('56 20 * * * (Every day at 8:56pm)', $output);
242
        $this->assertStringNotContainsString('#daily', $output);
243
244
        $commandTester->execute(['--detail' => null]);
245
        $output = $this->normalizeOutput($commandTester);
246
247
        $this->assertStringContainsString('Calculated Frequency', $output);
248
        $this->assertStringContainsString('56 20 * * * (Every day at 8:56pm)', $output);
249
        $this->assertStringContainsString('Raw Frequency', $output);
250
        $this->assertStringContainsString('#daily', $output);
251
    }
252
253
    /**
254
     * @test
255
     */
256
    public function can_show_extended_expressions()
257
    {
258
        $runner = (new MockScheduleBuilder())
259
            ->addTask((new MockTask('my task'))->cron('@daily'))
260
            ->getRunner()
261
        ;
262
263
        $command = new ScheduleListCommand($runner, new ExtensionHandlerRegistry([]));
264
        $command->setHelperSet(new HelperSet([new FormatterHelper()]));
265
        $command->setApplication(new Application());
266
        $commandTester = new CommandTester($command);
267
268
        $commandTester->execute([]);
269
        $output = $this->normalizeOutput($commandTester);
270
271
        $this->assertStringContainsString('@daily', $output);
272
    }
273
274
    private function normalizeOutput(CommandTester $tester): string
275
    {
276
        return \preg_replace('/\s+/', ' ', \str_replace("\n", '', $tester->getDisplay(true)));
277
    }
278
}
279