Passed
Push — master ( 8b3ece...7c044f )
by Kevin
01:49
created

TaskTest.php$0 ➔ onlyBetweenExtensionRunProvider()   A

Complexity

Conditions 1

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 6
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()->cron('@hourly'); }, '@hourly'],
133
            [function () { return self::task()->cron('@daily'); }, '@daily'],
134
            [function () { return self::task()->cron('@weekly'); }, '@weekly'],
135
            [function () { return self::task()->cron('@monthly'); }, '@monthly'],
136
            [function () { return self::task()->cron('@yearly'); }, '@yearly'],
137
            [function () { return self::task()->cron('@annually'); }, '@annually'],
138
139
            [function () { return self::task('my task')->cron('# 0 * * *'); }, '56 0 * * *'],
140
            [function () { return self::task('my task')->cron('#daily'); }, '56 20 * * *'],
141
            [function () { return self::task('my task')->cron('#midnight'); }, '56 2 * * *'],
142
            [function () { return self::task('my task')->cron('#midnight')->daily(); }, '0 0 * * *'],
143
        ];
144
    }
145
146
    /**
147
     * @test
148
     */
149
    public function has_unique_id_based_on_description_and_frequency()
150
    {
151
        $this->assertSame(self::task()->getId(), self::task()->getId());
152
        $this->assertNotSame(self::task()->daily()->getId(), self::task()->getId());
153
        $this->assertNotSame(self::task('task1')->getId(), self::task('task2')->getId());
154
        $this->assertNotSame((new class('task') extends Task {
155
        })->getId(), self::task('task')->getId());
156
    }
157
158
    /**
159
     * @test
160
     */
161
    public function false_when_filter_skips_task()
162
    {
163
        $task = self::task();
164
165
        $task->when('boolean value', false);
166
167
        $this->expectException(SkipTask::class);
168
        $this->expectExceptionMessage('boolean value');
169
170
        $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

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

290
        $task->getExtensions()[1]->/** @scrutinizer ignore-call */ 
291
                                   beforeTask($event);
Loading history...
291
        $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

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

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

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

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

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

347
        $this->assertSame('[email protected]', $task->getExtensions()[0]->/** @scrutinizer ignore-call */ getEmail()->getTo()[0]->toString());
Loading history...
348
        $this->assertSame('[email protected]', $task->getExtensions()[0]->getEmail()->getCc()[0]->toString());
349
        $this->assertSame('my subject', $task->getExtensions()[0]->getEmail()->getSubject());
350
    }
351
352
    public static function emailAfterMethodProvider()
353
    {
354
        return [
355
            ['emailAfter'],
356
            ['thenEmail'],
357
        ];
358
    }
359
360
    /**
361
     * @test
362
     */
363
    public function can_add_email_on_failure_extension()
364
    {
365
        $task = self::task();
366
        $task->emailOnFailure('[email protected]', 'my subject', function (Email $email) {
367
            $email->cc('[email protected]');
368
        });
369
370
        $this->assertTrue($task->getExtensions()[0]->isHook(Extension::TASK_FAILURE));
371
        $this->assertSame('[email protected]', $task->getExtensions()[0]->getEmail()->getTo()[0]->toString());
372
        $this->assertSame('[email protected]', $task->getExtensions()[0]->getEmail()->getCc()[0]->toString());
373
        $this->assertSame('my subject', $task->getExtensions()[0]->getEmail()->getSubject());
374
    }
375
376
    /**
377
     * @test
378
     */
379
    public function can_add_single_server_extension()
380
    {
381
        $task1 = self::task('task')->onSingleServer();
382
        $task2 = self::task('task')->onSingleServer();
383
384
        $lockFactory = new LockFactory(new FlockStore());
385
386
        $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

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