Passed
Branch master (eb91a4)
by Kevin
01:55
created

TaskTest::can_cast_to_string()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 2
c 1
b 0
f 0
dl 0
loc 5
rs 10
cc 1
nc 1
nop 0
1
<?php
2
3
namespace Zenstruck\ScheduleBundle\Tests\Schedule;
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\Mime\Email;
7
use Symfony\Contracts\HttpClient\HttpClientInterface;
8
use Zenstruck\ScheduleBundle\Schedule;
9
use Zenstruck\ScheduleBundle\Schedule\Exception\SkipTask;
10
use Zenstruck\ScheduleBundle\Schedule\Extension;
11
use Zenstruck\ScheduleBundle\Schedule\Extension\SingleServerExtension;
12
use Zenstruck\ScheduleBundle\Schedule\ScheduleRunContext;
13
use Zenstruck\ScheduleBundle\Schedule\Task;
14
use Zenstruck\ScheduleBundle\Schedule\Task\TaskRunContext;
15
use Zenstruck\ScheduleBundle\Tests\Fixture\MockTask;
16
17
/**
18
 * @author Kevin Bond <[email protected]>
19
 */
20
final class TaskTest extends TestCase
21
{
22
    /**
23
     * @test
24
     */
25
    public function can_set_description()
26
    {
27
        $task = self::task()->description('my description');
28
29
        $this->assertSame('my description', $task->getDescription());
30
    }
31
32
    /**
33
     * @test
34
     */
35
    public function can_cast_to_string()
36
    {
37
        $task = new MockTask('my description');
38
39
        $this->assertSame('MockTask: my description', (string) $task);
40
    }
41
42
    /**
43
     * @test
44
     */
45
    public function can_set_timezone()
46
    {
47
        $task = self::task();
48
49
        $this->assertNull($task->getTimezone());
50
51
        $task->timezone('UTC');
52
53
        $this->assertSame('UTC', $task->getTimezone()->getName());
54
55
        $task->timezone(new \DateTimeZone('America/Los_Angeles'));
56
57
        $this->assertSame('America/Los_Angeles', $task->getTimezone()->getName());
58
    }
59
60
    /**
61
     * @test
62
     */
63
    public function can_get_next_run()
64
    {
65
        $this->assertSame(
66
            (new \DateTime('1st Jan next year'))->getTimestamp(),
67
            self::task()->yearly()->getNextRun()->getTimestamp()
68
        );
69
    }
70
71
    /**
72
     * @test
73
     */
74
    public function can_determine_if_due()
75
    {
76
        $this->assertTrue(self::task()->everyMinute()->isDue());
77
    }
78
79
    /**
80
     * @test
81
     * @dataProvider frequencyProvider
82
     */
83
    public function can_fluently_create_frequency(callable $createTask, string $expectedExpression)
84
    {
85
        $task = $createTask();
86
87
        $this->assertSame($expectedExpression, (string) $task->getExpression());
88
        $this->assertInstanceOf(\DateTimeInterface::class, $task->getNextRun());
89
    }
90
91
    public static function frequencyProvider(): array
92
    {
93
        return [
94
            [function () { return self::task(); }, '* * * * *'],
95
            [function () { return self::task()->minutes(37)->cron('0 0,12 1 */2 *'); }, '0 0,12 1 */2 *'],
96
            [function () { return self::task()->weekly()->everyMinute(); }, '* * * * *'],
97
            [function () { return self::task()->weekly()->everyFiveMinutes(); }, '*/5 * * * *'],
98
            [function () { return self::task()->weekly()->everyTenMinutes(); }, '*/10 * * * *'],
99
            [function () { return self::task()->weekly()->everyFifteenMinutes(); }, '*/15 * * * *'],
100
            [function () { return self::task()->weekly()->everyTwentyMinutes(); }, '*/20 * * * *'],
101
            [function () { return self::task()->weekly()->everyThirtyMinutes(); }, '0,30 * * * *'],
102
            [function () { return self::task()->minutes(37)->hourly(); }, '0 * * * *'],
103
            [function () { return self::task()->minutes(37)->hourlyAt(2); }, '2 * * * *'],
104
            [function () { return self::task()->minutes(37)->hourlyAt(2, 3, '4-5'); }, '2,3,4-5 * * * *'],
105
            [function () { return self::task()->minutes(37)->daily(); }, '0 0 * * *'],
106
            [function () { return self::task()->minutes(37)->dailyOn(2, 3, '4-5'); }, '0 2,3,4-5 * * *'],
107
            [function () { return self::task()->minutes(37)->dailyBetween(9, 17); }, '0 9-17 * * *'],
108
            [function () { return self::task()->minutes(37)->twiceDaily(); }, '0 1,13 * * *'],
109
            [function () { return self::task()->minutes(37)->twiceDaily(2, 14); }, '0 2,14 * * *'],
110
            [function () { return self::task()->minutes(37)->dailyAt(2); }, '0 2 * * *'],
111
            [function () { return self::task()->minutes(37)->dailyAt('1:34'); }, '34 1 * * *'],
112
            [function () { return self::task()->minutes(37)->weekly(); }, '0 0 * * 0'],
113
            [function () { return self::task()->minutes(37)->weeklyOn(2, 3, '4-5'); }, '0 0 * * 2,3,4-5'],
114
            [function () { return self::task()->minutes(37)->monthly(); }, '0 0 1 * *'],
115
            [function () { return self::task()->minutes(37)->monthlyOn(2, 3, '4-5'); }, '0 0 2,3,4-5 * *'],
116
            [function () { return self::task()->minutes(37)->twiceMonthly(); }, '0 0 1,16 * *'],
117
            [function () { return self::task()->minutes(37)->twiceMonthly(3, 17); }, '0 0 3,17 * *'],
118
            [function () { return self::task()->minutes(37)->quarterly(); }, '0 0 1 */3 *'],
119
            [function () { return self::task()->minutes(37)->yearly(); }, '0 0 1 1 *'],
120
            [function () { return self::task()->weekly()->minutes(2, 3, '4-5'); }, '2,3,4-5 0 * * 0'],
121
            [function () { return self::task()->weekly()->hours(2, 3, '4-5'); }, '0 2,3,4-5 * * 0'],
122
            [function () { return self::task()->weekly()->daysOfMonth(2, 3, '4-5'); }, '0 0 2,3,4-5 * 0'],
123
            [function () { return self::task()->weekly()->months(2, 3, '4-5'); }, '0 0 * 2,3,4-5 0'],
124
            [function () { return self::task()->monthly()->daysOfWeek(2, 3, '4-5'); }, '0 0 1 * 2,3,4-5'],
125
            [function () { return self::task()->minutes(37)->weekdays(); }, '37 * * * 1-5'],
126
            [function () { return self::task()->minutes(37)->weekends(); }, '37 * * * 0,6'],
127
            [function () { return self::task()->minutes(37)->mondays(); }, '37 * * * 1'],
128
            [function () { return self::task()->minutes(37)->tuesdays(); }, '37 * * * 2'],
129
            [function () { return self::task()->minutes(37)->wednesdays(); }, '37 * * * 3'],
130
            [function () { return self::task()->minutes(37)->thursdays(); }, '37 * * * 4'],
131
            [function () { return self::task()->minutes(37)->fridays(); }, '37 * * * 5'],
132
            [function () { return self::task()->minutes(37)->saturdays(); }, '37 * * * 6'],
133
            [function () { return self::task()->minutes(37)->sundays(); }, '37 * * * 0'],
134
            [function () { return self::task()->weekly()->at(1); }, '0 1 * * 0'],
135
            [function () { return self::task()->weekly()->at('2:45'); }, '45 2 * * 0'],
136
137
            [function () { return self::task()->cron('invalid...')->mondays(); }, '* * * * 1'],
138
139
            [function () { return self::task()->cron('@hourly'); }, '@hourly'],
140
            [function () { return self::task()->cron('@daily'); }, '@daily'],
141
            [function () { return self::task()->cron('@weekly'); }, '@weekly'],
142
            [function () { return self::task()->cron('@monthly'); }, '@monthly'],
143
            [function () { return self::task()->cron('@yearly'); }, '@yearly'],
144
            [function () { return self::task()->cron('@annually'); }, '@annually'],
145
146
            [function () { return self::task('my task')->cron('# 0 * * *'); }, '56 0 * * *'],
147
            [function () { return self::task('my task')->cron('#daily'); }, '56 20 * * *'],
148
            [function () { return self::task('my task')->cron('#midnight'); }, '56 2 * * *'],
149
            [function () { return self::task('my task')->cron('#midnight')->daily(); }, '0 0 * * *'],
150
        ];
151
    }
152
153
    /**
154
     * @test
155
     */
156
    public function has_unique_id_based_on_description_and_frequency()
157
    {
158
        $this->assertSame(self::task()->getId(), self::task()->getId());
159
        $this->assertNotSame(self::task()->daily()->getId(), self::task()->getId());
160
        $this->assertNotSame(self::task('task1')->getId(), self::task('task2')->getId());
161
        $this->assertNotSame((new class('task') extends Task {
162
        })->getId(), self::task('task')->getId());
163
    }
164
165
    /**
166
     * @test
167
     */
168
    public function false_when_filter_skips_task()
169
    {
170
        $task = self::task();
171
172
        $task->when('boolean value', false);
173
174
        $this->expectException(SkipTask::class);
175
        $this->expectExceptionMessage('boolean value');
176
177
        $task->getExtensions()[0]->filterTask(self::taskRunContext());
0 ignored issues
show
Bug introduced by
The method filterTask() does not exist on Zenstruck\ScheduleBundle\Schedule\Extension. It seems like you code against a sub-type of Zenstruck\ScheduleBundle\Schedule\Extension such as Zenstruck\ScheduleBundle...n\SelfHandlingExtension. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

177
        $task->getExtensions()[0]->/** @scrutinizer ignore-call */ 
178
                                   filterTask(self::taskRunContext());
Loading history...
178
    }
179
180
    /**
181
     * @test
182
     */
183
    public function callback_returning_false_when_filter_skips_task()
184
    {
185
        $task = self::task();
186
187
        $task->when('callback value', function () { return false; });
188
189
        $this->expectException(SkipTask::class);
190
        $this->expectExceptionMessage('callback value');
191
192
        $task->getExtensions()[0]->filterTask(self::taskRunContext());
193
    }
194
195
    /**
196
     * @test
197
     */
198
    public function true_when_filter_allows_task_to_run()
199
    {
200
        $task = self::task();
201
202
        $task->when('boolean value', true);
203
204
        $task->getExtensions()[0]->filterTask(self::taskRunContext());
205
206
        $this->assertTrue(true);
207
    }
208
209
    /**
210
     * @test
211
     */
212
    public function callback_returning_true_when_filter_allows_task_to_run()
213
    {
214
        $task = self::task();
215
216
        $task->when('callback value', function () { return true; });
217
218
        $task->getExtensions()[0]->filterTask(self::taskRunContext());
219
220
        $this->assertTrue(true);
221
    }
222
223
    /**
224
     * @test
225
     */
226
    public function true_skip_filter_skips_task()
227
    {
228
        $task = self::task();
229
230
        $task->skip('boolean value', true);
231
232
        $this->expectException(SkipTask::class);
233
        $this->expectExceptionMessage('boolean value');
234
235
        $task->getExtensions()[0]->filterTask(self::taskRunContext());
236
    }
237
238
    /**
239
     * @test
240
     */
241
    public function callback_returning_true_skip_filter_skips_task()
242
    {
243
        $task = self::task();
244
245
        $task->skip('callback value', function () { return true; });
246
247
        $this->expectException(SkipTask::class);
248
        $this->expectExceptionMessage('callback value');
249
250
        $task->getExtensions()[0]->filterTask(self::taskRunContext());
251
    }
252
253
    /**
254
     * @test
255
     */
256
    public function false_skip_filter_allows_task_to_run()
257
    {
258
        $task = self::task();
259
260
        $task->skip('boolean value', false);
261
262
        $task->getExtensions()[0]->filterTask(self::taskRunContext());
263
264
        $this->assertTrue(true);
265
    }
266
267
    /**
268
     * @test
269
     */
270
    public function callback_returning_false_skip_filter_allows_task_to_run()
271
    {
272
        $task = self::task();
273
274
        $task->skip('callback value', function () { return false; });
275
276
        $task->getExtensions()[0]->filterTask(self::taskRunContext());
277
278
        $this->assertTrue(true);
279
    }
280
281
    /**
282
     * @test
283
     */
284
    public function can_add_callback_extensions()
285
    {
286
        $task = self::task();
287
        $calls = [];
288
289
        $task->filter(function () use (&$calls) { $calls[] = 'filter'; });
290
        $task->before(function () use (&$calls) { $calls[] = 'before'; });
291
        $task->after(function () use (&$calls) { $calls[] = 'after'; });
292
        $task->then(function () use (&$calls) { $calls[] = 'then'; });
293
        $task->onSuccess(function () use (&$calls) { $calls[] = 'onSuccess'; });
294
        $task->onFailure(function () use (&$calls) { $calls[] = 'onFailure'; });
295
296
        $task->getExtensions()[0]->filterTask(self::taskRunContext());
297
        $task->getExtensions()[1]->beforeTask(self::taskRunContext());
0 ignored issues
show
Bug introduced by
The method beforeTask() does not exist on Zenstruck\ScheduleBundle\Schedule\Extension. It seems like you code against a sub-type of Zenstruck\ScheduleBundle\Schedule\Extension such as Zenstruck\ScheduleBundle...n\SelfHandlingExtension. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

297
        $task->getExtensions()[1]->/** @scrutinizer ignore-call */ 
298
                                   beforeTask(self::taskRunContext());
Loading history...
298
        $task->getExtensions()[2]->afterTask(self::taskRunContext());
0 ignored issues
show
Bug introduced by
The method afterTask() does not exist on Zenstruck\ScheduleBundle\Schedule\Extension. It seems like you code against a sub-type of Zenstruck\ScheduleBundle\Schedule\Extension such as Zenstruck\ScheduleBundle...n\SelfHandlingExtension. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

298
        $task->getExtensions()[2]->/** @scrutinizer ignore-call */ 
299
                                   afterTask(self::taskRunContext());
Loading history...
299
        $task->getExtensions()[3]->afterTask(self::taskRunContext());
300
        $task->getExtensions()[4]->onTaskSuccess(self::taskRunContext());
0 ignored issues
show
Bug introduced by
The method onTaskSuccess() does not exist on Zenstruck\ScheduleBundle\Schedule\Extension. It seems like you code against a sub-type of Zenstruck\ScheduleBundle\Schedule\Extension such as Zenstruck\ScheduleBundle...n\SelfHandlingExtension. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

300
        $task->getExtensions()[4]->/** @scrutinizer ignore-call */ 
301
                                   onTaskSuccess(self::taskRunContext());
Loading history...
301
        $task->getExtensions()[5]->onTaskFailure(self::taskRunContext());
0 ignored issues
show
Bug introduced by
The method onTaskFailure() does not exist on Zenstruck\ScheduleBundle\Schedule\Extension. It seems like you code against a sub-type of Zenstruck\ScheduleBundle\Schedule\Extension such as Zenstruck\ScheduleBundle...n\SelfHandlingExtension. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

301
        $task->getExtensions()[5]->/** @scrutinizer ignore-call */ 
302
                                   onTaskFailure(self::taskRunContext());
Loading history...
302
303
        $this->assertSame([
304
            'filter',
305
            'before',
306
            'after',
307
            'then',
308
            'onSuccess',
309
            'onFailure',
310
        ], $calls);
311
    }
312
313
    /**
314
     * @test
315
     */
316
    public function can_add_ping_extensions()
317
    {
318
        $task = self::task();
319
320
        $task->pingBefore('http://before.com');
321
        $task->pingAfter('http://after.com', 'POST');
322
        $task->thenPing('http://then.com');
323
        $task->pingOnSuccess('http://success.com');
324
        $task->pingOnFailure('http://failure.com');
325
326
        $client = $this->createMock(HttpClientInterface::class);
327
        $client->expects($this->exactly(5))->method('request')->withConsecutive(
328
            [$this->equalTo('GET'), $this->equalTo('http://before.com'), $this->isType('array')],
329
            [$this->equalTo('POST'), $this->equalTo('http://after.com'), $this->isType('array')],
330
            [$this->equalTo('GET'), $this->equalTo('http://then.com'), $this->isType('array')],
331
            [$this->equalTo('GET'), $this->equalTo('http://success.com'), $this->isType('array')],
332
            [$this->equalTo('GET'), $this->equalTo('http://failure.com'), $this->isType('array')]
333
        );
334
335
        $task->getExtensions()[0]->setHttpClient($client)->beforeTask(self::taskRunContext());
0 ignored issues
show
Bug introduced by
The method setHttpClient() does not exist on Zenstruck\ScheduleBundle\Schedule\Extension. It seems like you code against a sub-type of Zenstruck\ScheduleBundle\Schedule\Extension such as Zenstruck\ScheduleBundle...Extension\PingExtension. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

335
        $task->getExtensions()[0]->/** @scrutinizer ignore-call */ 
336
                                   setHttpClient($client)->beforeTask(self::taskRunContext());
Loading history...
336
        $task->getExtensions()[1]->setHttpClient($client)->afterTask(self::taskRunContext());
337
        $task->getExtensions()[2]->setHttpClient($client)->afterTask(self::taskRunContext());
338
        $task->getExtensions()[3]->setHttpClient($client)->onTaskSuccess(self::taskRunContext());
339
        $task->getExtensions()[4]->setHttpClient($client)->onTaskFailure(self::taskRunContext());
340
    }
341
342
    /**
343
     * @test
344
     * @dataProvider emailAfterMethodProvider
345
     */
346
    public function can_add_email_after_extension($method)
347
    {
348
        $task = self::task();
349
        $task->{$method}('[email protected]', 'my subject', function (Email $email) {
350
            $email->cc('[email protected]');
351
        });
352
353
        $this->assertTrue($task->getExtensions()[0]->isHook(Extension::TASK_AFTER));
0 ignored issues
show
Bug introduced by
The method isHook() does not exist on Zenstruck\ScheduleBundle\Schedule\Extension. It seems like you code against a sub-type of Zenstruck\ScheduleBundle\Schedule\Extension such as Zenstruck\ScheduleBundle...xtension\EmailExtension. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

353
        $this->assertTrue($task->getExtensions()[0]->/** @scrutinizer ignore-call */ isHook(Extension::TASK_AFTER));
Loading history...
354
        $this->assertSame('[email protected]', $task->getExtensions()[0]->getEmail()->getTo()[0]->toString());
0 ignored issues
show
Bug introduced by
The method getEmail() does not exist on Zenstruck\ScheduleBundle\Schedule\Extension. It seems like you code against a sub-type of Zenstruck\ScheduleBundle\Schedule\Extension such as Zenstruck\ScheduleBundle...xtension\EmailExtension. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

354
        $this->assertSame('[email protected]', $task->getExtensions()[0]->/** @scrutinizer ignore-call */ getEmail()->getTo()[0]->toString());
Loading history...
355
        $this->assertSame('[email protected]', $task->getExtensions()[0]->getEmail()->getCc()[0]->toString());
356
        $this->assertSame('my subject', $task->getExtensions()[0]->getEmail()->getSubject());
357
    }
358
359
    public static function emailAfterMethodProvider()
360
    {
361
        return [
362
            ['emailAfter'],
363
            ['thenEmail'],
364
        ];
365
    }
366
367
    /**
368
     * @test
369
     */
370
    public function can_add_email_on_failure_extension()
371
    {
372
        $task = self::task();
373
        $task->emailOnFailure('[email protected]', 'my subject', function (Email $email) {
374
            $email->cc('[email protected]');
375
        });
376
377
        $this->assertTrue($task->getExtensions()[0]->isHook(Extension::TASK_FAILURE));
378
        $this->assertSame('[email protected]', $task->getExtensions()[0]->getEmail()->getTo()[0]->toString());
379
        $this->assertSame('[email protected]', $task->getExtensions()[0]->getEmail()->getCc()[0]->toString());
380
        $this->assertSame('my subject', $task->getExtensions()[0]->getEmail()->getSubject());
381
    }
382
383
    /**
384
     * @test
385
     */
386
    public function can_add_single_server_extension()
387
    {
388
        $task = self::task()->onSingleServer();
389
390
        $this->assertInstanceOf(SingleServerExtension::class, $task->getExtensions()[0]);
391
    }
392
393
    /**
394
     * @test
395
     */
396
    public function can_add_without_overlapping_extension()
397
    {
398
        $task1 = self::task('task')->withoutOverlapping();
399
        $task2 = self::task('task')->withoutOverlapping();
400
401
        $task1->getExtensions()[0]->filterTask(self::taskRunContext());
402
403
        $this->expectException(SkipTask::class);
404
        $this->expectExceptionMessage('Task running in another process.');
405
406
        $task2->getExtensions()[0]->filterTask(self::taskRunContext());
407
    }
408
409
    /**
410
     * @test
411
     * @dataProvider onlyBetweenExtensionSkipProvider
412
     */
413
    public function only_between_extension_skip($start, $end, $inclusive)
414
    {
415
        $start = (new \DateTime($start))->format('H:i');
416
        $end = (new \DateTime($end))->format('H:i');
417
418
        $task = self::task()->onlyBetween($start, $end, $inclusive);
419
420
        $this->expectException(SkipTask::class);
421
        $this->expectExceptionMessage("Only runs between {$start} and {$end}");
422
423
        $task->getExtensions()[0]->filterTask(self::taskRunContext());
424
    }
425
426
    public static function onlyBetweenExtensionSkipProvider()
427
    {
428
        return [
429
            ['+2 minutes', '+3 minutes', true],
430
            ['now', '+3 minutes', false],
431
            ['+5 minutes', '+23 hours', true],
432
        ];
433
    }
434
435
    /**
436
     * @test
437
     * @dataProvider onlyBetweenExtensionRunProvider
438
     */
439
    public function only_between_extension_run($start, $end, $inclusive)
440
    {
441
        $start = (new \DateTime($start))->format('H:i');
442
        $end = (new \DateTime($end))->format('H:i');
443
444
        $task = self::task()->onlyBetween($start, $end, $inclusive);
445
446
        $task->getExtensions()[0]->filterTask(self::taskRunContext());
447
448
        $this->assertTrue(true);
449
    }
450
451
    public static function onlyBetweenExtensionRunProvider()
452
    {
453
        return [
454
            ['now', '+3 minutes', true],
455
            ['-1 minute', '+3 minutes', false],
456
            ['-1 minutes', '+23 hours', true],
457
        ];
458
    }
459
460
    /**
461
     * @test
462
     * @dataProvider unlessBetweenExtensionSkipProvider
463
     */
464
    public function unless_between_extension_skip($start, $end, $inclusive)
465
    {
466
        $start = (new \DateTime($start))->format('H:i');
467
        $end = (new \DateTime($end))->format('H:i');
468
469
        $task = self::task()->unlessBetween($start, $end, $inclusive);
470
471
        $this->expectException(SkipTask::class);
472
        $this->expectExceptionMessage("Only runs if not between {$start} and {$end}");
473
474
        $task->getExtensions()[0]->filterTask(self::taskRunContext());
475
    }
476
477
    public static function unlessBetweenExtensionSkipProvider()
478
    {
479
        return [
480
            ['-1 minute', '+3 minutes', false],
481
            ['now', '+3 minutes', true],
482
            ['-1 minutes', '+23 hours', true],
483
        ];
484
    }
485
486
    /**
487
     * @test
488
     * @dataProvider unlessBetweenExtensionRunProvider
489
     */
490
    public function unless_between_extension_run($start, $end, $inclusive)
491
    {
492
        $start = (new \DateTime($start))->format('H:i');
493
        $end = (new \DateTime($end))->format('H:i');
494
495
        $task = self::task()->unlessBetween($start, $end, $inclusive);
496
497
        $task->getExtensions()[0]->filterTask(self::taskRunContext());
498
499
        $this->assertTrue(true);
500
    }
501
502
    public static function unlessBetweenExtensionRunProvider()
503
    {
504
        return [
505
            ['now', '+3 minutes', false],
506
            ['+1 minute', '+3 minutes', true],
507
            ['+5 minutes', '+23 hours', true],
508
        ];
509
    }
510
511
    private static function taskRunContext(): TaskRunContext
512
    {
513
        return new TaskRunContext(new ScheduleRunContext(new Schedule()), self::task());
514
    }
515
516
    private static function task(string $description = 'task description'): Task
517
    {
518
        return new MockTask($description);
519
    }
520
}
521