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

task_frequency_must_be_valid()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 6
c 0
b 0
f 0
dl 0
loc 10
rs 10
cc 1
nc 1
nop 0
1
<?php
2
3
namespace Zenstruck\ScheduleBundle\Tests\DependencyInjection;
4
5
use Matthias\SymfonyDependencyInjectionTest\PhpUnit\AbstractExtensionTestCase;
6
use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
7
use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument;
8
use Zenstruck\ScheduleBundle\Command\ScheduleListCommand;
9
use Zenstruck\ScheduleBundle\Command\ScheduleRunCommand;
10
use Zenstruck\ScheduleBundle\DependencyInjection\ZenstruckScheduleExtension;
11
use Zenstruck\ScheduleBundle\EventListener\ScheduleBuilderSubscriber;
12
use Zenstruck\ScheduleBundle\EventListener\ScheduleExtensionSubscriber;
13
use Zenstruck\ScheduleBundle\EventListener\ScheduleLoggerSubscriber;
14
use Zenstruck\ScheduleBundle\EventListener\ScheduleTimezoneSubscriber;
15
use Zenstruck\ScheduleBundle\EventListener\SelfSchedulingCommandSubscriber;
16
use Zenstruck\ScheduleBundle\EventListener\TaskConfigurationSubscriber;
17
use Zenstruck\ScheduleBundle\Schedule\Extension\EmailExtension;
18
use Zenstruck\ScheduleBundle\Schedule\Extension\EnvironmentExtension;
19
use Zenstruck\ScheduleBundle\Schedule\Extension\ExtensionHandlerRegistry;
20
use Zenstruck\ScheduleBundle\Schedule\Extension\Handler\EmailHandler;
21
use Zenstruck\ScheduleBundle\Schedule\Extension\Handler\EnvironmentHandler;
22
use Zenstruck\ScheduleBundle\Schedule\Extension\Handler\PingHandler;
23
use Zenstruck\ScheduleBundle\Schedule\Extension\Handler\SelfHandlingHandler;
24
use Zenstruck\ScheduleBundle\Schedule\Extension\Handler\SingleServerHandler;
25
use Zenstruck\ScheduleBundle\Schedule\Extension\Handler\WithoutOverlappingHandler;
26
use Zenstruck\ScheduleBundle\Schedule\Extension\PingExtension;
27
use Zenstruck\ScheduleBundle\Schedule\Extension\SingleServerExtension;
28
use Zenstruck\ScheduleBundle\Schedule\Extension\WithoutOverlappingExtension;
29
use Zenstruck\ScheduleBundle\Schedule\ScheduleRunner;
30
use Zenstruck\ScheduleBundle\Schedule\Task\Runner\CommandTaskRunner;
31
use Zenstruck\ScheduleBundle\Schedule\Task\Runner\SelfRunningTaskRunner;
32
33
/**
34
 * @author Kevin Bond <[email protected]>
35
 */
36
final class ZenstruckScheduleExtensionTest extends AbstractExtensionTestCase
37
{
38
    /**
39
     * @test
40
     */
41
    public function empty_config_loads_default_services()
42
    {
43
        $this->load([]);
44
45
        $this->assertContainerBuilderHasService(ScheduleListCommand::class);
46
        $this->assertContainerBuilderHasServiceDefinitionWithTag(ScheduleListCommand::class, 'console.command');
47
48
        $this->assertContainerBuilderHasService(ScheduleRunCommand::class);
49
        $this->assertContainerBuilderHasServiceDefinitionWithTag(ScheduleRunCommand::class, 'console.command');
50
51
        $this->assertContainerBuilderHasService(ScheduleRunner::class);
52
53
        $this->assertContainerBuilderHasService(ScheduleBuilderSubscriber::class);
54
        $this->assertContainerBuilderHasServiceDefinitionWithTag(ScheduleBuilderSubscriber::class, 'kernel.event_subscriber');
55
56
        $this->assertContainerBuilderHasService(ScheduleExtensionSubscriber::class);
57
        $this->assertContainerBuilderHasServiceDefinitionWithTag(ScheduleExtensionSubscriber::class, 'kernel.event_subscriber');
58
59
        $this->assertContainerBuilderHasService(SelfSchedulingCommandSubscriber::class);
60
        $this->assertContainerBuilderHasServiceDefinitionWithTag(SelfSchedulingCommandSubscriber::class, 'kernel.event_subscriber');
61
62
        $this->assertContainerBuilderHasService(CommandTaskRunner::class);
63
        $this->assertContainerBuilderHasServiceDefinitionWithTag(CommandTaskRunner::class, 'schedule.task_runner');
64
65
        $this->assertContainerBuilderHasService(SelfRunningTaskRunner::class);
66
        $this->assertContainerBuilderHasServiceDefinitionWithTag(SelfRunningTaskRunner::class, 'schedule.task_runner');
67
68
        $this->assertContainerBuilderHasService(ScheduleLoggerSubscriber::class);
69
        $this->assertContainerBuilderHasServiceDefinitionWithTag(ScheduleLoggerSubscriber::class, 'kernel.event_subscriber');
70
        $this->assertContainerBuilderHasServiceDefinitionWithTag(ScheduleLoggerSubscriber::class, 'monolog.logger', ['channel' => 'schedule']);
71
72
        $this->assertContainerBuilderHasService(ExtensionHandlerRegistry::class);
73
74
        $this->assertContainerBuilderHasService(SelfHandlingHandler::class);
75
        $this->assertContainerBuilderHasServiceDefinitionWithTag(SelfHandlingHandler::class, 'schedule.extension_handler', ['priority' => -100]);
76
77
        $this->assertContainerBuilderHasService(EnvironmentHandler::class);
78
        $this->assertContainerBuilderHasServiceDefinitionWithTag(EnvironmentHandler::class, 'schedule.extension_handler');
79
80
        $this->assertContainerBuilderHasService(TaskConfigurationSubscriber::class);
81
        $this->assertContainerBuilderHasServiceDefinitionWithTag(ScheduleBuilderSubscriber::class, 'kernel.event_subscriber');
82
        $this->assertContainerBuilderHasServiceDefinitionWithArgument(TaskConfigurationSubscriber::class, 0, []);
83
    }
84
85
    /**
86
     * @test
87
     */
88
    public function can_configure_default_timezone()
89
    {
90
        $this->load(['timezone' => 'UTC']);
91
92
        $this->assertContainerBuilderHasService(ScheduleTimezoneSubscriber::class);
93
        $this->assertContainerBuilderHasServiceDefinitionWithArgument(ScheduleTimezoneSubscriber::class, 0, 'UTC');
94
        $this->assertContainerBuilderHasServiceDefinitionWithTag(ScheduleTimezoneSubscriber::class, 'kernel.event_subscriber');
95
    }
96
97
    /**
98
     * @test
99
     */
100
    public function schedule_timezone_must_be_valid()
101
    {
102
        $this->expectException(InvalidConfigurationException::class);
103
        $this->expectExceptionMessage('Invalid configuration for path "zenstruck_schedule.timezone": Timezone "invalid" is not available');
104
105
        $this->load(['timezone' => 'invalid']);
106
    }
107
108
    /**
109
     * @test
110
     */
111
    public function can_configure_single_server_lock_factory()
112
    {
113
        $this->load(['single_server_handler' => 'my_factory']);
114
115
        $this->assertContainerBuilderHasServiceDefinitionWithArgument(SingleServerHandler::class, 0, 'my_factory');
116
        $this->assertContainerBuilderHasServiceDefinitionWithTag(SingleServerHandler::class, 'schedule.extension_handler');
117
    }
118
119
    /**
120
     * @test
121
     */
122
    public function can_configure_without_overlapping_handler_lock_factory()
123
    {
124
        $this->load(['without_overlapping_handler' => 'my_factory']);
125
126
        $this->assertContainerBuilderHasServiceDefinitionWithArgument(WithoutOverlappingHandler::class, 0, 'my_factory');
127
        $this->assertContainerBuilderHasServiceDefinitionWithTag(WithoutOverlappingHandler::class, 'schedule.extension_handler');
128
    }
129
130
    /**
131
     * @test
132
     */
133
    public function can_configure_ping_handler_http_client()
134
    {
135
        $this->load(['ping_handler' => 'my_client']);
136
137
        $this->assertContainerBuilderHasServiceDefinitionWithArgument(PingHandler::class, 0, 'my_client');
138
        $this->assertContainerBuilderHasServiceDefinitionWithTag(PingHandler::class, 'schedule.extension_handler');
139
    }
140
141
    /**
142
     * @test
143
     */
144
    public function can_configure_email_handler()
145
    {
146
        $this->load(['email_handler' => [
147
            'service' => 'my_mailer',
148
            'default_from' => '[email protected]',
149
            'default_to' => '[email protected]',
150
            'subject_prefix' => '[Acme Inc]',
151
        ]]);
152
153
        $this->assertContainerBuilderHasServiceDefinitionWithArgument(EmailHandler::class, 0, 'my_mailer');
154
        $this->assertContainerBuilderHasServiceDefinitionWithTag(EmailHandler::class, 'schedule.extension_handler');
155
        $this->assertContainerBuilderHasServiceDefinitionWithArgument(EmailHandler::class, 1, '[email protected]');
156
        $this->assertContainerBuilderHasServiceDefinitionWithArgument(EmailHandler::class, 2, '[email protected]');
157
        $this->assertContainerBuilderHasServiceDefinitionWithArgument(EmailHandler::class, 3, '[Acme Inc]');
158
    }
159
160
    /**
161
     * @test
162
     */
163
    public function minimum_email_handler_configuration()
164
    {
165
        $this->load(['email_handler' => [
166
            'service' => 'my_mailer',
167
        ]]);
168
169
        $this->assertContainerBuilderHasServiceDefinitionWithArgument(EmailHandler::class, 0, 'my_mailer');
170
        $this->assertContainerBuilderHasServiceDefinitionWithTag(EmailHandler::class, 'schedule.extension_handler');
171
        $this->assertContainerBuilderHasServiceDefinitionWithArgument(EmailHandler::class, 1, null);
172
        $this->assertContainerBuilderHasServiceDefinitionWithArgument(EmailHandler::class, 2, null);
173
        $this->assertContainerBuilderHasServiceDefinitionWithArgument(EmailHandler::class, 3, null);
174
    }
175
176
    /**
177
     * @test
178
     */
179
    public function can_add_schedule_environment_as_string()
180
    {
181
        $this->load(['schedule_extensions' => [
182
            'environments' => 'prod',
183
        ]]);
184
185
        $this->assertContainerBuilderHasService('zenstruck_schedule.extension.environments', EnvironmentExtension::class);
186
        $this->assertContainerBuilderHasServiceDefinitionWithArgument('zenstruck_schedule.extension.environments', 0, ['prod']);
187
        $this->assertContainerBuilderHasServiceDefinitionWithTag('zenstruck_schedule.extension.environments', 'schedule.extension');
188
189
        $extensionIterator = $this->container->getDefinition(ScheduleExtensionSubscriber::class)->getArgument(0);
190
191
        $this->assertInstanceOf(TaggedIteratorArgument::class, $extensionIterator);
192
        $this->assertSame('schedule.extension', $extensionIterator->getTag());
193
    }
194
195
    /**
196
     * @test
197
     */
198
    public function can_add_schedule_environment_as_array()
199
    {
200
        $this->load(['schedule_extensions' => [
201
            'environments' => ['prod', 'stage'],
202
        ]]);
203
204
        $this->assertContainerBuilderHasServiceDefinitionWithArgument('zenstruck_schedule.extension.environments', 0, ['prod', 'stage']);
205
    }
206
207
    /**
208
     * @test
209
     */
210
    public function can_enable_single_server_schedule_extension()
211
    {
212
        $this->load(['schedule_extensions' => [
213
            'on_single_server' => null,
214
        ]]);
215
216
        $this->assertContainerBuilderHasService('zenstruck_schedule.extension.on_single_server', SingleServerExtension::class);
217
        $this->assertContainerBuilderHasServiceDefinitionWithTag('zenstruck_schedule.extension.on_single_server', 'schedule.extension');
218
219
        $extensionIterator = $this->container->getDefinition(ScheduleExtensionSubscriber::class)->getArgument(0);
220
221
        $this->assertInstanceOf(TaggedIteratorArgument::class, $extensionIterator);
222
        $this->assertSame('schedule.extension', $extensionIterator->getTag());
223
    }
224
225
    /**
226
     * @test
227
     */
228
    public function can_enable_email_on_failure_schedule_extension()
229
    {
230
        $this->load(['schedule_extensions' => [
231
            'email_on_failure' => [
232
                'to' => '[email protected]',
233
                'subject' => 'my subject',
234
            ],
235
        ]]);
236
237
        $this->assertContainerBuilderHasService('zenstruck_schedule.extension.email_on_failure', EmailExtension::class);
238
        $this->assertContainerBuilderHasServiceDefinitionWithTag('zenstruck_schedule.extension.email_on_failure', 'schedule.extension');
239
240
        $definition = $this->container->getDefinition('zenstruck_schedule.extension.email_on_failure');
241
242
        $this->assertSame([EmailExtension::class, 'scheduleFailure'], $definition->getFactory());
243
        $this->assertSame(['[email protected]', 'my subject'], $definition->getArguments());
244
245
        $extensionIterator = $this->container->getDefinition(ScheduleExtensionSubscriber::class)->getArgument(0);
246
247
        $this->assertInstanceOf(TaggedIteratorArgument::class, $extensionIterator);
248
        $this->assertSame('schedule.extension', $extensionIterator->getTag());
249
    }
250
251
    /**
252
     * @test
253
     * @dataProvider pingScheduleExtensionProvider
254
     */
255
    public function can_enable_ping_schedule_extensions($key, $method)
256
    {
257
        $this->load(['schedule_extensions' => [
258
            $key => [
259
                'url' => 'example.com',
260
            ],
261
        ]]);
262
263
        $this->assertContainerBuilderHasService('zenstruck_schedule.extension.'.$key, PingExtension::class);
264
        $this->assertContainerBuilderHasServiceDefinitionWithTag('zenstruck_schedule.extension.'.$key, 'schedule.extension');
265
266
        $definition = $this->container->getDefinition('zenstruck_schedule.extension.'.$key);
267
268
        $this->assertSame([PingExtension::class, $method], $definition->getFactory());
269
        $this->assertSame(['example.com', 'GET', []], $definition->getArguments());
270
271
        $extensionIterator = $this->container->getDefinition(ScheduleExtensionSubscriber::class)->getArgument(0);
272
273
        $this->assertInstanceOf(TaggedIteratorArgument::class, $extensionIterator);
274
        $this->assertSame('schedule.extension', $extensionIterator->getTag());
275
    }
276
277
    public static function pingScheduleExtensionProvider()
278
    {
279
        return [
280
            ['ping_before', 'scheduleBefore'],
281
            ['ping_after', 'scheduleAfter'],
282
            ['ping_on_success', 'scheduleSuccess'],
283
            ['ping_on_failure', 'scheduleFailure'],
284
        ];
285
    }
286
287
    /**
288
     * @test
289
     */
290
    public function minimum_task_configuration()
291
    {
292
        $this->load([
293
            'tasks' => [
294
                [
295
                    'command' => 'my:command',
296
                    'frequency' => '0 * * * *',
297
                ],
298
            ],
299
        ]);
300
301
        $config = $this->container->getDefinition(TaskConfigurationSubscriber::class)->getArgument(0)[0];
302
303
        $this->assertSame(['my:command'], $config['command']);
304
        $this->assertSame('0 * * * *', $config['frequency']);
305
        $this->assertNull($config['description']);
306
        $this->assertNull($config['timezone']);
307
        $this->assertFalse($config['without_overlapping']['enabled']);
308
        $this->assertFalse($config['between']['enabled']);
309
        $this->assertFalse($config['unless_between']['enabled']);
310
        $this->assertFalse($config['ping_before']['enabled']);
311
        $this->assertFalse($config['ping_after']['enabled']);
312
        $this->assertFalse($config['ping_on_success']['enabled']);
313
        $this->assertFalse($config['ping_on_failure']['enabled']);
314
        $this->assertFalse($config['email_after']['enabled']);
315
        $this->assertFalse($config['email_on_failure']['enabled']);
316
    }
317
318
    /**
319
     * @test
320
     */
321
    public function can_configure_a_compound_task()
322
    {
323
        $this->load([
324
            'tasks' => [
325
                [
326
                    'command' => ['my:command', 'bash:/my-script'],
327
                    'frequency' => '0 * * * *',
328
                ],
329
            ],
330
        ]);
331
332
        $config = $this->container->getDefinition(TaskConfigurationSubscriber::class)->getArgument(0)[0];
333
334
        $this->assertSame(['my:command', 'bash:/my-script'], $config['command']);
335
    }
336
337
    /**
338
     * @test
339
     */
340
    public function can_configure_a_compound_task_with_descriptions()
341
    {
342
        $this->load([
343
            'tasks' => [
344
                [
345
                    'command' => [
346
                        'task1' => 'my:command',
347
                        'task2' => 'bash:/my-script',
348
                    ],
349
                    'frequency' => '0 * * * *',
350
                ],
351
            ],
352
        ]);
353
354
        $config = $this->container->getDefinition(TaskConfigurationSubscriber::class)->getArgument(0)[0];
355
356
        $this->assertSame(['task1' => 'my:command', 'task2' => 'bash:/my-script'], $config['command']);
357
    }
358
359
    /**
360
     * @test
361
     */
362
    public function compound_tasks_cannot_be_an_empty_array()
363
    {
364
        $this->expectException(InvalidConfigurationException::class);
365
        $this->expectExceptionMessage('The path "zenstruck_schedule.tasks.0.command" should have at least 1 element(s) defined.');
366
367
        $this->load([
368
            'tasks' => [
369
                [
370
                    'command' => [],
371
                    'frequency' => 'invalid',
372
                ],
373
            ],
374
        ]);
375
    }
376
377
    /**
378
     * @test
379
     */
380
    public function can_configure_a_null_task()
381
    {
382
        $this->load([
383
            'tasks' => [
384
                [
385
                    'command' => null,
386
                    'frequency' => '0 * * * *',
387
                    'description' => 'my task',
388
                ],
389
            ],
390
        ]);
391
392
        $config = $this->container->getDefinition(TaskConfigurationSubscriber::class)->getArgument(0)[0];
393
394
        $this->assertSame([null], $config['command']);
395
    }
396
397
    /**
398
     * @test
399
     */
400
    public function null_task_must_have_a_description()
401
    {
402
        $this->expectException(InvalidConfigurationException::class);
403
        $this->expectExceptionMessage('Invalid configuration for path "zenstruck_schedule.tasks.0": "null" tasks must have a description.');
404
405
        $this->load([
406
            'tasks' => [
407
                [
408
                    'command' => null,
409
                    'frequency' => '0 * * * *',
410
                ],
411
            ],
412
        ]);
413
    }
414
415
    /**
416
     * @test
417
     */
418
    public function compound_tasks_must_not_contain_null_tasks()
419
    {
420
        $this->expectException(InvalidConfigurationException::class);
421
        $this->expectExceptionMessage('Invalid configuration for path "zenstruck_schedule.tasks.0.command": "null" tasks cannot be added to compound tasks.');
422
423
        $this->load([
424
            'tasks' => [
425
                [
426
                    'command' => ['my:command', null],
427
                    'frequency' => 'invalid',
428
                ],
429
            ],
430
        ]);
431
    }
432
433
    /**
434
     * @test
435
     */
436
    public function task_frequency_must_be_valid()
437
    {
438
        $this->expectException(InvalidConfigurationException::class);
439
        $this->expectExceptionMessage('Invalid configuration for path "zenstruck_schedule.tasks.0.frequency": "invalid" is an invalid cron expression.');
440
441
        $this->load([
442
            'tasks' => [
443
                [
444
                    'command' => 'my:command',
445
                    'frequency' => 'invalid',
446
                ],
447
            ],
448
        ]);
449
    }
450
451
    /**
452
     * @test
453
     */
454
    public function can_use_extended_frequency_expression()
455
    {
456
        $this->load([
457
            'tasks' => [
458
                [
459
                    'command' => 'my:command',
460
                    'frequency' => '@daily',
461
                ],
462
            ],
463
        ]);
464
465
        $config = $this->container->getDefinition(TaskConfigurationSubscriber::class)->getArgument(0)[0];
466
467
        $this->assertSame('@daily', $config['frequency']);
468
    }
469
470
    /**
471
     * @test
472
     */
473
    public function can_use_hashed_frequency_expression()
474
    {
475
        $this->load([
476
            'tasks' => [
477
                [
478
                    'command' => 'my:command',
479
                    'frequency' => 'H H * * *',
480
                ],
481
            ],
482
        ]);
483
484
        $config = $this->container->getDefinition(TaskConfigurationSubscriber::class)->getArgument(0)[0];
485
486
        $this->assertSame('H H * * *', $config['frequency']);
487
    }
488
489
    /**
490
     * @test
491
     */
492
    public function can_use_frequency_alias()
493
    {
494
        $this->load([
495
            'tasks' => [
496
                [
497
                    'command' => 'my:command',
498
                    'frequency' => '#midnight',
499
                ],
500
            ],
501
        ]);
502
503
        $config = $this->container->getDefinition(TaskConfigurationSubscriber::class)->getArgument(0)[0];
504
505
        $this->assertSame('#midnight', $config['frequency']);
506
    }
507
508
    /**
509
     * @test
510
     */
511
    public function full_task_configuration()
512
    {
513
        $this->load([
514
            'tasks' => [
515
                [
516
                    'command' => [
517
                        'my:command --option',
518
                        'another:command',
519
                    ],
520
                    'frequency' => '0 0 * * *',
521
                    'description' => 'my description',
522
                    'timezone' => 'UTC',
523
                    'without_overlapping' => null,
524
                    'between' => [
525
                        'start' => 9,
526
                        'end' => 17,
527
                    ],
528
                    'unless_between' => [
529
                        'start' => 12,
530
                        'end' => '13:30',
531
                    ],
532
                    'ping_before' => [
533
                        'url' => 'https://example.com/before',
534
                    ],
535
                    'ping_after' => [
536
                        'url' => 'https://example.com/after',
537
                    ],
538
                    'ping_on_success' => [
539
                        'url' => 'https://example.com/success',
540
                    ],
541
                    'ping_on_failure' => [
542
                        'url' => 'https://example.com/failure',
543
                        'method' => 'POST',
544
                    ],
545
                    'email_after' => null,
546
                    'email_on_failure' => [
547
                        'to' => '[email protected]',
548
                        'subject' => 'my subject',
549
                    ],
550
                ],
551
            ],
552
        ]);
553
554
        $config = $this->container->getDefinition(TaskConfigurationSubscriber::class)->getArgument(0)[0];
555
556
        $this->assertSame(['my:command --option', 'another:command'], $config['command']);
557
        $this->assertSame('0 0 * * *', $config['frequency']);
558
        $this->assertSame('my description', $config['description']);
559
        $this->assertSame('UTC', $config['timezone']);
560
        $this->assertTrue($config['without_overlapping']['enabled']);
561
        $this->assertSame(WithoutOverlappingExtension::DEFAULT_TTL, $config['without_overlapping']['ttl']);
562
        $this->assertTrue($config['between']['enabled']);
563
        $this->assertSame(9, $config['between']['start']);
564
        $this->assertSame(17, $config['between']['end']);
565
        $this->assertTrue($config['unless_between']['enabled']);
566
        $this->assertSame(12, $config['unless_between']['start']);
567
        $this->assertSame('13:30', $config['unless_between']['end']);
568
        $this->assertTrue($config['ping_before']['enabled']);
569
        $this->assertSame('https://example.com/before', $config['ping_before']['url']);
570
        $this->assertSame('GET', $config['ping_before']['method']);
571
        $this->assertTrue($config['ping_after']['enabled']);
572
        $this->assertSame('https://example.com/after', $config['ping_after']['url']);
573
        $this->assertSame('GET', $config['ping_after']['method']);
574
        $this->assertTrue($config['ping_on_success']['enabled']);
575
        $this->assertSame('https://example.com/success', $config['ping_on_success']['url']);
576
        $this->assertSame('GET', $config['ping_on_success']['method']);
577
        $this->assertTrue($config['ping_on_failure']['enabled']);
578
        $this->assertSame('https://example.com/failure', $config['ping_on_failure']['url']);
579
        $this->assertSame('POST', $config['ping_on_failure']['method']);
580
        $this->assertTrue($config['email_after']['enabled']);
581
        $this->assertNull($config['email_after']['to']);
582
        $this->assertNull($config['email_after']['subject']);
583
        $this->assertTrue($config['email_on_failure']['enabled']);
584
        $this->assertSame('[email protected]', $config['email_on_failure']['to']);
585
        $this->assertSame('my subject', $config['email_on_failure']['subject']);
586
    }
587
588
    /**
589
     * @test
590
     */
591
    public function email_and_ping_configuration_can_be_shortened()
592
    {
593
        $this->load([
594
            'tasks' => [
595
                [
596
                    'command' => 'my:command --option',
597
                    'frequency' => '0 0 * * *',
598
                    'ping_after' => 'https://example.com/after',
599
                    'email_after' => '[email protected]',
600
                ],
601
            ],
602
        ]);
603
604
        $config = $this->container->getDefinition(TaskConfigurationSubscriber::class)->getArgument(0)[0];
605
606
        $this->assertTrue($config['ping_after']['enabled']);
607
        $this->assertSame('https://example.com/after', $config['ping_after']['url']);
608
        $this->assertSame('GET', $config['ping_after']['method']);
609
        $this->assertSame([], $config['ping_after']['options']);
610
611
        $this->assertTrue($config['email_after']['enabled']);
612
        $this->assertSame('[email protected]', $config['email_after']['to']);
613
        $this->assertNull($config['email_after']['subject']);
614
    }
615
616
    /**
617
     * @test
618
     */
619
    public function between_and_unless_between_config_can_be_shortened()
620
    {
621
        $this->load([
622
            'tasks' => [
623
                [
624
                    'command' => 'my:command --option',
625
                    'frequency' => '0 0 * * *',
626
                    'between' => '9-17',
627
                    'unless_between' => '11:30-13:15',
628
                ],
629
            ],
630
        ]);
631
632
        $config = $this->container->getDefinition(TaskConfigurationSubscriber::class)->getArgument(0)[0];
633
634
        $this->assertTrue($config['between']['enabled']);
635
        $this->assertSame('9', $config['between']['start']);
636
        $this->assertSame('17', $config['between']['end']);
637
638
        $this->assertTrue($config['unless_between']['enabled']);
639
        $this->assertSame('11:30', $config['unless_between']['start']);
640
        $this->assertSame('13:15', $config['unless_between']['end']);
641
    }
642
643
    protected function getContainerExtensions(): array
644
    {
645
        return [new ZenstruckScheduleExtension()];
646
    }
647
}
648