Passed
Pull Request — master (#5)
by Kevin
02:07
created

minimum_task_configuration()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 26
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

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