Passed
Push — master ( 6b73cf...cbdf83 )
by Kevin
02:15
created

TaskTest.php$0 ➔ task()   A

Complexity

Conditions 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

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

163
        $task->getExtensions()[0]->/** @scrutinizer ignore-call */ 
164
                                   filterTask(new BeforeTaskEvent(new BeforeScheduleEvent(new Schedule()), $task));
Loading history...
164
    }
165
166
    /**
167
     * @test
168
     */
169
    public function callback_returning_false_when_filter_skips_task()
170
    {
171
        $task = self::task();
172
173
        $task->when('callback value', function () { return false; });
174
175
        $this->expectException(SkipTask::class);
176
        $this->expectExceptionMessage('callback value');
177
178
        $task->getExtensions()[0]->filterTask(new BeforeTaskEvent(new BeforeScheduleEvent(new Schedule()), $task));
179
    }
180
181
    /**
182
     * @test
183
     */
184
    public function true_when_filter_allows_task_to_run()
185
    {
186
        $task = self::task();
187
188
        $task->when('boolean value', true);
189
190
        $task->getExtensions()[0]->filterTask(new BeforeTaskEvent(new BeforeScheduleEvent(new Schedule()), $task));
191
192
        $this->assertTrue(true);
193
    }
194
195
    /**
196
     * @test
197
     */
198
    public function callback_returning_true_when_filter_allows_task_to_run()
199
    {
200
        $task = self::task();
201
202
        $task->when('callback value', function () { return true; });
203
204
        $task->getExtensions()[0]->filterTask(new BeforeTaskEvent(new BeforeScheduleEvent(new Schedule()), $task));
205
206
        $this->assertTrue(true);
207
    }
208
209
    /**
210
     * @test
211
     */
212
    public function true_skip_filter_skips_task()
213
    {
214
        $task = self::task();
215
216
        $task->skip('boolean value', true);
217
218
        $this->expectException(SkipTask::class);
219
        $this->expectExceptionMessage('boolean value');
220
221
        $task->getExtensions()[0]->filterTask(new BeforeTaskEvent(new BeforeScheduleEvent(new Schedule()), $task));
222
    }
223
224
    /**
225
     * @test
226
     */
227
    public function callback_returning_true_skip_filter_skips_task()
228
    {
229
        $task = self::task();
230
231
        $task->skip('callback value', function () { return true; });
232
233
        $this->expectException(SkipTask::class);
234
        $this->expectExceptionMessage('callback value');
235
236
        $task->getExtensions()[0]->filterTask(new BeforeTaskEvent(new BeforeScheduleEvent(new Schedule()), $task));
237
    }
238
239
    /**
240
     * @test
241
     */
242
    public function false_skip_filter_allows_task_to_run()
243
    {
244
        $task = self::task();
245
246
        $task->skip('boolean value', false);
247
248
        $task->getExtensions()[0]->filterTask(new BeforeTaskEvent(new BeforeScheduleEvent(new Schedule()), $task));
249
250
        $this->assertTrue(true);
251
    }
252
253
    /**
254
     * @test
255
     */
256
    public function callback_returning_false_skip_filter_allows_task_to_run()
257
    {
258
        $task = self::task();
259
260
        $task->skip('callback value', function () { return false; });
261
262
        $task->getExtensions()[0]->filterTask(new BeforeTaskEvent(new BeforeScheduleEvent(new Schedule()), $task));
263
264
        $this->assertTrue(true);
265
    }
266
267
    /**
268
     * @test
269
     */
270
    public function can_add_callback_extensions()
271
    {
272
        $task = self::task();
273
        $calls = [];
274
275
        $task->filter(function () use (&$calls) { $calls[] = 'filter'; });
276
        $task->before(function () use (&$calls) { $calls[] = 'before'; });
277
        $task->after(function () use (&$calls) { $calls[] = 'after'; });
278
        $task->then(function () use (&$calls) { $calls[] = 'then'; });
279
        $task->onSuccess(function () use (&$calls) { $calls[] = 'onSuccess'; });
280
        $task->onFailure(function () use (&$calls) { $calls[] = 'onFailure'; });
281
282
        $task->getExtensions()[0]->filterTask($event = new BeforeTaskEvent(new BeforeScheduleEvent(new Schedule()), $task));
283
        $task->getExtensions()[1]->beforeTask($event);
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

283
        $task->getExtensions()[1]->/** @scrutinizer ignore-call */ 
284
                                   beforeTask($event);
Loading history...
284
        $task->getExtensions()[2]->afterTask($event = new AfterTaskEvent($event, Result::successful($task)));
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

284
        $task->getExtensions()[2]->/** @scrutinizer ignore-call */ 
285
                                   afterTask($event = new AfterTaskEvent($event, Result::successful($task)));
Loading history...
285
        $task->getExtensions()[3]->afterTask($event);
286
        $task->getExtensions()[4]->onTaskSuccess($event);
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

286
        $task->getExtensions()[4]->/** @scrutinizer ignore-call */ 
287
                                   onTaskSuccess($event);
Loading history...
287
        $task->getExtensions()[5]->onTaskFailure($event);
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

287
        $task->getExtensions()[5]->/** @scrutinizer ignore-call */ 
288
                                   onTaskFailure($event);
Loading history...
288
289
        $this->assertSame([
290
            'filter',
291
            'before',
292
            'after',
293
            'then',
294
            'onSuccess',
295
            'onFailure',
296
        ], $calls);
297
    }
298
299
    /**
300
     * @test
301
     */
302
    public function can_add_ping_extensions()
303
    {
304
        $task = self::task();
305
306
        $task->pingBefore('http://before.com');
307
        $task->pingAfter('http://after.com', 'POST');
308
        $task->thenPing('http://then.com');
309
        $task->pingOnSuccess('http://success.com');
310
        $task->pingOnFailure('http://failure.com');
311
312
        $client = $this->createMock(HttpClientInterface::class);
313
        $client->expects($this->exactly(5))->method('request')->withConsecutive(
314
            [$this->equalTo('GET'), $this->equalTo('http://before.com'), $this->isType('array')],
315
            [$this->equalTo('POST'), $this->equalTo('http://after.com'), $this->isType('array')],
316
            [$this->equalTo('GET'), $this->equalTo('http://then.com'), $this->isType('array')],
317
            [$this->equalTo('GET'), $this->equalTo('http://success.com'), $this->isType('array')],
318
            [$this->equalTo('GET'), $this->equalTo('http://failure.com'), $this->isType('array')]
319
        );
320
321
        $task->getExtensions()[0]->setHttpClient($client)->beforeTask($event = new BeforeTaskEvent(new BeforeScheduleEvent(new Schedule()), $task));
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

321
        $task->getExtensions()[0]->/** @scrutinizer ignore-call */ 
322
                                   setHttpClient($client)->beforeTask($event = new BeforeTaskEvent(new BeforeScheduleEvent(new Schedule()), $task));
Loading history...
322
        $task->getExtensions()[1]->setHttpClient($client)->afterTask($event = new AfterTaskEvent($event, Result::successful($task)));
323
        $task->getExtensions()[2]->setHttpClient($client)->afterTask($event);
324
        $task->getExtensions()[3]->setHttpClient($client)->onTaskSuccess($event);
325
        $task->getExtensions()[4]->setHttpClient($client)->onTaskFailure($event);
326
    }
327
328
    /**
329
     * @test
330
     * @dataProvider emailAfterMethodProvider
331
     */
332
    public function can_add_email_after_extension($method)
333
    {
334
        $task = self::task();
335
        $task->{$method}('[email protected]', 'my subject', function (Email $email) {
336
            $email->cc('[email protected]');
337
        });
338
339
        $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

339
        $this->assertTrue($task->getExtensions()[0]->/** @scrutinizer ignore-call */ isHook(Extension::TASK_AFTER));
Loading history...
340
        $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

340
        $this->assertSame('[email protected]', $task->getExtensions()[0]->/** @scrutinizer ignore-call */ getEmail()->getTo()[0]->toString());
Loading history...
341
        $this->assertSame('[email protected]', $task->getExtensions()[0]->getEmail()->getCc()[0]->toString());
342
        $this->assertSame('my subject', $task->getExtensions()[0]->getEmail()->getSubject());
343
    }
344
345
    public static function emailAfterMethodProvider()
346
    {
347
        return [
348
            ['emailAfter'],
349
            ['thenEmail'],
350
        ];
351
    }
352
353
    /**
354
     * @test
355
     */
356
    public function can_add_email_on_failure_extension()
357
    {
358
        $task = self::task();
359
        $task->emailOnFailure('[email protected]', 'my subject', function (Email $email) {
360
            $email->cc('[email protected]');
361
        });
362
363
        $this->assertTrue($task->getExtensions()[0]->isHook(Extension::TASK_FAILURE));
364
        $this->assertSame('[email protected]', $task->getExtensions()[0]->getEmail()->getTo()[0]->toString());
365
        $this->assertSame('[email protected]', $task->getExtensions()[0]->getEmail()->getCc()[0]->toString());
366
        $this->assertSame('my subject', $task->getExtensions()[0]->getEmail()->getSubject());
367
    }
368
369
    /**
370
     * @test
371
     */
372
    public function can_add_single_server_extension()
373
    {
374
        $task1 = self::task('task')->onSingleServer();
375
        $task2 = self::task('task')->onSingleServer();
376
377
        $lockFactory = new LockFactory(new FlockStore());
378
379
        $task1->getExtensions()[0]->aquireTaskLock($lockFactory, $task1, \time());
0 ignored issues
show
Bug introduced by
The method aquireTaskLock() 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\SingleServerExtension. ( Ignorable by Annotation )

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

379
        $task1->getExtensions()[0]->/** @scrutinizer ignore-call */ 
380
                                    aquireTaskLock($lockFactory, $task1, \time());
Loading history...
380
381
        $this->expectException(SkipTask::class);
382
        $this->expectExceptionMessage('Task running on another server.');
383
384
        $task2->getExtensions()[0]->aquireTaskLock($lockFactory, $task2, \time());
385
    }
386
387
    /**
388
     * @test
389
     */
390
    public function can_add_without_overlapping_extension()
391
    {
392
        $task1 = self::task('task')->withoutOverlapping();
393
        $task2 = self::task('task')->withoutOverlapping();
394
395
        $task1->getExtensions()[0]->filterTask(new BeforeTaskEvent(new BeforeScheduleEvent(new Schedule()), $task1));
396
397
        $this->expectException(SkipTask::class);
398
        $this->expectExceptionMessage('Task running in another process.');
399
400
        $task2->getExtensions()[0]->filterTask(new BeforeTaskEvent(new BeforeScheduleEvent(new Schedule()), $task2));
401
    }
402
403
    /**
404
     * @test
405
     * @dataProvider betweenExtensionSkipProvider
406
     */
407
    public function between_extension_skip($start, $end, $inclusive)
408
    {
409
        $start = (new \DateTime($start))->format('H:i');
410
        $end = (new \DateTime($end))->format('H:i');
411
412
        $task = self::task()->between($start, $end, $inclusive);
413
414
        $this->expectException(SkipTask::class);
415
        $this->expectExceptionMessage("Only runs between {$start} and {$end}");
416
417
        $task->getExtensions()[0]->filterTask(new BeforeTaskEvent(new BeforeScheduleEvent(new Schedule()), $task));
418
    }
419
420
    public static function betweenExtensionSkipProvider()
421
    {
422
        return [
423
            ['+2 minutes', '+3 minutes', true],
424
            ['now', '+3 minutes', false],
425
            ['+5 minutes', '+23 hours', true],
426
        ];
427
    }
428
429
    /**
430
     * @test
431
     * @dataProvider betweenExtensionRunProvider
432
     */
433
    public function between_extension_run($start, $end, $inclusive)
434
    {
435
        $start = (new \DateTime($start))->format('H:i');
436
        $end = (new \DateTime($end))->format('H:i');
437
438
        $task = self::task()->between($start, $end, $inclusive);
439
440
        $task->getExtensions()[0]->filterTask(new BeforeTaskEvent(new BeforeScheduleEvent(new Schedule()), $task));
441
442
        $this->assertTrue(true);
443
    }
444
445
    public static function betweenExtensionRunProvider()
446
    {
447
        return [
448
            ['now', '+3 minutes', true],
449
            ['-1 minute', '+3 minutes', false],
450
            ['-1 minutes', '+23 hours', true],
451
        ];
452
    }
453
454
    /**
455
     * @test
456
     * @dataProvider unlessBetweenExtensionSkipProvider
457
     */
458
    public function unless_between_extension_skip($start, $end, $inclusive)
459
    {
460
        $start = (new \DateTime($start))->format('H:i');
461
        $end = (new \DateTime($end))->format('H:i');
462
463
        $task = self::task()->unlessBetween($start, $end, $inclusive);
464
465
        $this->expectException(SkipTask::class);
466
        $this->expectExceptionMessage("Only runs if not between {$start} and {$end}");
467
468
        $task->getExtensions()[0]->filterTask(new BeforeTaskEvent(new BeforeScheduleEvent(new Schedule()), $task));
469
    }
470
471
    public static function unlessBetweenExtensionSkipProvider()
472
    {
473
        return [
474
            ['-1 minute', '+3 minutes', false],
475
            ['now', '+3 minutes', true],
476
            ['-1 minutes', '+23 hours', true],
477
        ];
478
    }
479
480
    /**
481
     * @test
482
     * @dataProvider unlessBetweenExtensionRunProvider
483
     */
484
    public function unless_between_extension_run($start, $end, $inclusive)
485
    {
486
        $start = (new \DateTime($start))->format('H:i');
487
        $end = (new \DateTime($end))->format('H:i');
488
489
        $task = self::task()->unlessBetween($start, $end, $inclusive);
490
491
        $task->getExtensions()[0]->filterTask(new BeforeTaskEvent(new BeforeScheduleEvent(new Schedule()), $task));
492
493
        $this->assertTrue(true);
494
    }
495
496
    public static function unlessBetweenExtensionRunProvider()
497
    {
498
        return [
499
            ['now', '+3 minutes', false],
500
            ['+1 minute', '+3 minutes', true],
501
            ['+5 minutes', '+23 hours', true],
502
        ];
503
    }
504
505
    private static function task(string $description = 'task description'): Task
506
    {
507
        return new MockTask($description);
508
    }
509
}
510