Skip to content

Commit 08c6140

Browse files
committed
tests(bridge): APIP WIP
1 parent 50273c2 commit 08c6140

File tree

6 files changed

+218
-7
lines changed

6 files changed

+218
-7
lines changed

.github/workflows/daily.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ jobs:
8181

8282
# —— Infection —————————————————————————————————————————————————————
8383
- name: Infection
84-
run: php vendor/bin/infection --no-progress --min-covered-msi=85 --min-msi=80 --show-mutations --threads=4
84+
run: php vendor/bin/infection --no-progress --min-covered-msi=86 --min-msi=80 --show-mutations --threads=4
8585
env:
8686
SCHEDULER_REDIS_DSN: redis://127.0.0.1:6379/_symfony_scheduler_tasks
8787
INFECTION_BADGE_API_KEY: ${{ secrets.INFECTION_BADGE_API_KEY }}

.github/workflows/infection.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ jobs:
4141
composer-options: "--prefer-stable"
4242

4343
- name: Run Infection
44-
run: php vendor/bin/infection --no-progress --min-covered-msi=85 --min-msi=80 --show-mutations --threads=4
44+
run: php vendor/bin/infection --no-progress --min-covered-msi=86 --min-msi=80 --show-mutations --threads=4
4545
env:
4646
SCHEDULER_REDIS_DSN: redis://127.0.0.1:6379/_symfony_scheduler_tasks
4747
INFECTION_BADGE_API_KEY: ${{ secrets.INFECTION_BADGE_API_KEY }}

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
- Retry / Remove / Sort policies
1919
- Background worker
2020
- [Symfony/Messenger](https://symfony.com/doc/current/messenger.html) integration
21-
- API-Platform support
21+
- [API-Platform](https://api-platform.com/) support
2222

2323
## Installation
2424

src/Bridge/ApiPlatform/Filter/SearchFilter.php

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ public function getDescription(string $resourceClass): array
4545
],
4646
],
4747
'state' => [
48-
'type' => 'bool',
48+
'type' => 'string',
4949
'required' => false,
5050
'property' => 'state',
5151
'swagger' => [
@@ -55,7 +55,7 @@ public function getDescription(string $resourceClass): array
5555
],
5656
],
5757
'timezone' => [
58-
'type' => 'bool',
58+
'type' => 'string',
5959
'required' => false,
6060
'property' => 'timezone',
6161
'swagger' => [
@@ -65,7 +65,7 @@ public function getDescription(string $resourceClass): array
6565
],
6666
],
6767
'type' => [
68-
'type' => 'bool',
68+
'type' => 'string',
6969
'required' => false,
7070
'property' => 'type',
7171
'swagger' => [
@@ -83,6 +83,10 @@ public function filter(TaskListInterface $list, array $filters = []): TaskListIn
8383
return $list;
8484
}
8585

86+
if (0 === $list->count()) {
87+
return $list;
88+
}
89+
8690
foreach ($filters as $filter => $value) {
8791
switch ($filter) {
8892
case 'expression':

tests/Bridge/ApiPlatform/CollectionDataProviderTest.php

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,10 @@ public function testProviderCannotReturnListWithError(): void
5656
$provider->getCollection(TaskInterface::class);
5757
}
5858

59-
public function testProviderCanReturnTask(): void
59+
public function testProviderCanReturnTaskList(): void
6060
{
6161
$list = $this->createMock(TaskListInterface::class);
62+
$list->expects(self::never())->method('filter');
6263

6364
$transport = $this->createMock(TransportInterface::class);
6465
$transport->expects(self::once())->method('list')->willReturn($list);
@@ -70,4 +71,40 @@ public function testProviderCanReturnTask(): void
7071

7172
self::assertSame($list, $provider->getCollection(TaskInterface::class));
7273
}
74+
75+
public function testProviderCannotReturnFilteredTaskListWithoutFilters(): void
76+
{
77+
$list = $this->createMock(TaskListInterface::class);
78+
$list->expects(self::never())->method('filter')->willReturnSelf();
79+
80+
$transport = $this->createMock(TransportInterface::class);
81+
$transport->expects(self::once())->method('list')->willReturn($list);
82+
83+
$logger = $this->createMock(LoggerInterface::class);
84+
$logger->expects(self::never())->method('critical');
85+
86+
$provider = new CollectionDataProvider(new SearchFilter(), $transport, $logger);
87+
$provider->getCollection(TaskInterface::class, 'GET', [
88+
'filters' => [],
89+
]);
90+
}
91+
92+
public function testProviderCanReturnFilteredTaskList(): void
93+
{
94+
$list = $this->createMock(TaskListInterface::class);
95+
$list->expects(self::once())->method('filter')->willReturnSelf();
96+
97+
$transport = $this->createMock(TransportInterface::class);
98+
$transport->expects(self::once())->method('list')->willReturn($list);
99+
100+
$logger = $this->createMock(LoggerInterface::class);
101+
$logger->expects(self::never())->method('critical');
102+
103+
$provider = new CollectionDataProvider(new SearchFilter(), $transport, $logger);
104+
$provider->getCollection(TaskInterface::class, 'GET', [
105+
'filters' => [
106+
'expression' => '* * * * *',
107+
],
108+
]);
109+
}
73110
}

tests/Bridge/ApiPlatform/Filter/SearchFilterTest.php

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,13 @@
44

55
namespace Tests\SchedulerBundle\Bridge\ApiPlatform\Filter;
66

7+
use DateTimeZone;
78
use PHPUnit\Framework\TestCase;
89
use SchedulerBundle\Bridge\ApiPlatform\Filter\SearchFilter;
10+
use SchedulerBundle\Task\NullTask;
911
use SchedulerBundle\Task\TaskInterface;
12+
use SchedulerBundle\Task\TaskList;
13+
use SchedulerBundle\Task\TaskListInterface;
1014
use stdClass;
1115

1216
/**
@@ -21,4 +25,170 @@ public function testFilterCanDefineDescription(): void
2125
self::assertEmpty($filter->getDescription(stdClass::class));
2226
self::assertNotEmpty($filter->getDescription(TaskInterface::class));
2327
}
28+
29+
public function testFilterDescriptionIsDefined(): void
30+
{
31+
$filter = new SearchFilter();
32+
33+
$description = $filter->getDescription(TaskInterface::class);
34+
35+
self::assertCount(5, $description);
36+
self::assertArrayHasKey('expression', $description);
37+
self::assertArrayHasKey('queued', $description);
38+
self::assertArrayHasKey('state', $description);
39+
self::assertArrayHasKey('timezone', $description);
40+
self::assertArrayHasKey('type', $description);
41+
self::assertCount(4, $description['expression']);
42+
self::assertCount(4, $description['queued']);
43+
self::assertCount(4, $description['state']);
44+
self::assertCount(4, $description['timezone']);
45+
self::assertCount(4, $description['type']);
46+
self::assertSame('string', $description['expression']['type']);
47+
self::assertFalse($description['expression']['required']);
48+
self::assertSame('expression', $description['expression']['property']);
49+
self::assertSame([
50+
'description' => 'Filter tasks using the expression',
51+
'name' => 'expression',
52+
'type' => 'string',
53+
], $description['expression']['swagger']);
54+
self::assertSame('bool', $description['queued']['type']);
55+
self::assertFalse($description['queued']['required']);
56+
self::assertSame('queued', $description['queued']['property']);
57+
self::assertSame([
58+
'description' => 'Filter tasks that are queued',
59+
'name' => 'queued',
60+
'type' => 'bool',
61+
], $description['queued']['swagger']);
62+
self::assertSame('string', $description['state']['type']);
63+
self::assertFalse($description['state']['required']);
64+
self::assertSame('state', $description['state']['property']);
65+
self::assertSame([
66+
'description' => 'Filter tasks with a specific state',
67+
'name' => 'state',
68+
'type' => 'string',
69+
], $description['state']['swagger']);
70+
self::assertSame('string', $description['timezone']['type']);
71+
self::assertFalse($description['timezone']['required']);
72+
self::assertSame('timezone', $description['timezone']['property']);
73+
self::assertSame([
74+
'description' => 'Filter tasks scheduled using a specific timezone',
75+
'name' => 'timezone',
76+
'type' => 'string',
77+
], $description['timezone']['swagger']);
78+
self::assertSame('string', $description['type']['type']);
79+
self::assertFalse($description['type']['required']);
80+
self::assertSame('type', $description['type']['property']);
81+
self::assertSame([
82+
'description' => 'Filter tasks depending on internal type',
83+
'name' => 'timezone',
84+
'type' => 'string',
85+
], $description['type']['swagger']);
86+
}
87+
88+
public function testFilterCannotFilterWithoutFilters(): void
89+
{
90+
$list = $this->createMock(TaskListInterface::class);
91+
$list->expects(self::never())->method('count');
92+
$list->expects(self::never())->method('filter');
93+
94+
$filter = new SearchFilter();
95+
$filter->filter($list);
96+
}
97+
98+
public function testFilterCannotFilterEmptyList(): void
99+
{
100+
$list = $this->createMock(TaskListInterface::class);
101+
$list->expects(self::once())->method('count')->willReturn(0);
102+
$list->expects(self::never())->method('filter');
103+
104+
$filter = new SearchFilter();
105+
$filter->filter($list, [
106+
'expression' => '* * * * *',
107+
]);
108+
}
109+
110+
public function testFilterCanFilterOnExpression(): void
111+
{
112+
$task = $this->createMock(TaskInterface::class);
113+
$task->expects(self::once())->method('getExpression')->willReturn('* * * * *');
114+
$task->expects(self::never())->method('isQueued');
115+
$task->expects(self::never())->method('getState');
116+
$task->expects(self::never())->method('getTimezone');
117+
118+
$filter = new SearchFilter();
119+
$list = $filter->filter(new TaskList([$task]), [
120+
'expression' => '* * * * *',
121+
]);
122+
123+
self::assertNotEmpty($list);
124+
self::assertCount(1, $list);
125+
}
126+
127+
public function testFilterCanFilterOnQueuedTask(): void
128+
{
129+
$task = $this->createMock(TaskInterface::class);
130+
$task->expects(self::never())->method('getExpression');
131+
$task->expects(self::once())->method('isQueued')->willReturn(true);
132+
$task->expects(self::never())->method('getState');
133+
$task->expects(self::never())->method('getTimezone');
134+
135+
$filter = new SearchFilter();
136+
$list = $filter->filter(new TaskList([$task]), [
137+
'queued' => true,
138+
]);
139+
140+
self::assertNotEmpty($list);
141+
self::assertCount(1, $list);
142+
}
143+
144+
public function testFilterCanFilterOnTaskState(): void
145+
{
146+
$task = $this->createMock(TaskInterface::class);
147+
$task->expects(self::never())->method('getExpression');
148+
$task->expects(self::never())->method('isQueued');
149+
$task->expects(self::once())->method('getState')->willReturn(TaskInterface::SUCCEED);
150+
$task->expects(self::never())->method('getTimezone');
151+
152+
$filter = new SearchFilter();
153+
$list = $filter->filter(new TaskList([$task]), [
154+
'state' => TaskInterface::SUCCEED,
155+
]);
156+
157+
self::assertNotEmpty($list);
158+
self::assertCount(1, $list);
159+
}
160+
161+
public function testFilterCanFilterOnTaskTimezone(): void
162+
{
163+
$task = $this->createMock(TaskInterface::class);
164+
$task->expects(self::never())->method('getExpression');
165+
$task->expects(self::never())->method('isQueued');
166+
$task->expects(self::never())->method('getState');
167+
$task->expects(self::exactly(2))->method('getTimezone')->willReturn(new DateTimeZone('UTC'));
168+
169+
$filter = new SearchFilter();
170+
$list = $filter->filter(new TaskList([$task]), [
171+
'timezone' => 'UTC',
172+
]);
173+
174+
self::assertNotEmpty($list);
175+
self::assertCount(1, $list);
176+
}
177+
178+
public function testFilterCanFilterOnTaskType(): void
179+
{
180+
$task = $this->createMock(TaskInterface::class);
181+
$task->expects(self::never())->method('getExpression');
182+
$task->expects(self::never())->method('isQueued');
183+
$task->expects(self::never())->method('getState');
184+
$task->expects(self::never())->method('getTimezone');
185+
186+
$filter = new SearchFilter();
187+
$list = $filter->filter(new TaskList([new NullTask('foo')]), [
188+
'type' => NullTask::class,
189+
]);
190+
191+
self::assertNotEmpty($list);
192+
self::assertCount(1, $list);
193+
}
24194
}

0 commit comments

Comments
 (0)