PostIT   A
last analyzed

Complexity

Total Complexity 9

Size/Duplication

Total Lines 289
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 133
c 1
b 0
f 0
dl 0
loc 289
rs 10
wmc 9

9 Methods

Rating   Name   Duplication   Size   Complexity  
A shouldUpdateCommentsOnExistingPost() 0 65 1
A shouldUpdateExistingBlogPost() 0 40 1
A shouldCreateNewBlogPost() 0 31 1
A shouldBaselineAllPosts() 0 18 1
A setupKernel() 0 9 1
A shouldFetchAllCreatedPosts() 0 29 1
A getPostsApi() 0 3 1
A shouldDeleteExistingBlogPost() 0 21 1
A shouldFetchSingleCreatedPost() 0 19 1
1
<?php
2
3
namespace App\Tests\Modules\Posts\Integration;
4
5
use App\Modules\Posts\Api\Command\BaselinePostsCommand;
6
use App\Modules\Posts\Api\Command\CreatePostCommand;
7
use App\Modules\Posts\Api\Command\DeletePostCommand;
8
use App\Modules\Posts\Api\Command\Response\CreatePostCommandResponse;
9
use App\Modules\Posts\Api\Command\UpdatePostCommand;
10
use App\Modules\Posts\Api\Event\Inbound\CommentCreatedPostsIEvent;
11
use App\Modules\Posts\Api\Event\Inbound\CommentsBaselinedPostsIEvent;
12
use App\Modules\Posts\Api\Event\Inbound\UserRenamedPostsIEvent;
13
use App\Modules\Posts\Api\PostsApiInterface;
14
use App\Modules\Posts\Api\Query\FindAllPostsQuery;
15
use App\Modules\Posts\Api\Query\FindPostByIdQuery;
16
use App\Modules\Posts\Api\Query\Response\FindPostHeaderQueryResponse;
17
use App\Modules\Posts\Domain\Event\Outbound\PostBaselinedOEvent;
18
use App\Modules\Posts\Domain\Event\Outbound\PostCreatedOEvent;
19
use App\Modules\Posts\Domain\Event\Outbound\PostDeletedOEvent;
20
use App\Modules\Posts\Domain\Event\Outbound\PostUpdatedOEvent;
21
use App\Modules\Posts\Domain\Repository\PostsFindingRepositoryInterface;
22
use App\Tests\Modules\Posts\Integration\Http\PostsHttpTrait;
23
use App\Tests\TestUtils\Contracts\ApplicationEventContractLoader;
24
use App\Tests\TestUtils\Events\InMemoryEventPublisher;
25
use App\Tests\TestUtils\IntegrationTest;
26
use Symfony\Bundle\FrameworkBundle\Console\Application;
27
use Symfony\Component\Console\Tester\CommandTester;
28
use Symfony\Component\Uid\Ulid;
29
30
class PostIT extends IntegrationTest
31
{
32
    use PostsHttpTrait;
33
    use ApplicationEventContractLoader;
34
35
    /**
36
     * @test
37
     */
38
    public function shouldCreateNewBlogPost(): void
39
    {
40
        //given: User has written a new Blog Post
41
        $command = new CreatePostCommand('Post Title', 'Post Body', ['t1']);
42
43
        //when: User posts the Post
44
        $response = $this->createPost($command);
45
46
        //then: the response is OK
47
        self::assertResponseIsSuccessful();
48
49
        //and: the Response contains the proper Object
50
        self::assertInstanceOf(CreatePostCommandResponse::class, $response);
51
52
        //and: The Response Object contains ID of newly created Blog Post
53
        self::assertNotNull($response->getId());
54
55
        //and: a Post Created Output Event was Published
56
        $events = InMemoryEventPublisher::get(PostCreatedOEvent::class);
57
        self::assertCount(1, $events);
58
59
        //and: The Event has the correct data
60
        InMemoryEventPublisher::assertEventData([
61
            'title' => 'Post Title',
62
            'body' => 'Post Body',
63
            'tags' => ['t1'],
64
            'summary' => 'Post Body',
65
            'createdByName' => IntegrationTest::DEFAULT_USER_ID,
66
            'createdAt' => 'createdAt',
67
            'createdById' => 'createdById'
68
        ], $events[0]);
69
    }
70
71
    /**
72
     * @param Ulid $postId
73
     * @return Ulid
74
     * @test
75
     */
76
    public function shouldUpdateExistingBlogPost(): void
77
    {
78
        //given: There is a Post created
79
        $createCommand = new CreatePostCommand('Post Title', 'Post Body', ['t1']);
80
        $createResponse = $this->createPost($createCommand);
81
82
        //when: the Post is updated
83
        $updateCommand = new UpdatePostCommand('Post Title updated', 'Post Body updated', ['t2']);
84
        $updateCommand->setId($createResponse->getId());
85
        $this->updatePost($updateCommand);
86
87
        //then: the response is OK
88
        self::assertResponseIsSuccessful();
89
90
        //and: a Post Updated Output Event was Published
91
        $events = InMemoryEventPublisher::get(PostUpdatedOEvent::class);
92
        self::assertCount(1, $events);
93
94
        //and: The Event has the correct data
95
        InMemoryEventPublisher::assertEventData([
96
            'id' => $createResponse->getId(),
97
            'title' => 'Post Title updated',
98
            'body' => 'Post Body updated',
99
            'tags' => ['t2'],
100
            'summary' => 'Post Body updated',
101
            'updatedAt' => 'updatedAt',
102
        ], $events[0]);
103
104
        //when: the User Renamed Event is handled
105
        $data = $this->getInboundEvent("Posts/UserRenamedPostsIEvent");
106
        $event = new UserRenamedPostsIEvent($data);
107
        $this->getPostsApi()->onUserRenamed($event);
108
109
        //and: User fetches the Post
110
        $findResponse = $this->findPostById(new FindPostByIdQuery($createResponse->getId()));
111
112
        //then: Previously created Post is fetched with the Comment
113
        self::assertNotNull($findResponse);
114
        self::assertEquals($createResponse->getId(), $findResponse->getId());
115
        self::assertEquals($event->getNewLogin(), $findResponse->getCreatedByName());
116
    }
117
118
    /**
119
     * @param Ulid $postId
120
     * @test
121
     */
122
    public function shouldDeleteExistingBlogPost(): void
123
    {
124
        //given: There is a Post created
125
        $createCommand = new CreatePostCommand('Post Title', 'Post Body', ['t1']);
126
        $createResponse = $this->createPost($createCommand);
127
128
        //when:
129
        $updateCommand = new DeletePostCommand($createResponse->getId());
130
        $this->deletePost($updateCommand);
131
132
        //then: the response is OK
133
        self::assertResponseIsSuccessful();
134
135
        //and: a Post Updated Output Event was Published
136
        $events = InMemoryEventPublisher::get(PostDeletedOEvent::class);
137
        self::assertCount(1, $events);
138
139
        //and: The Event has the correct data
140
        InMemoryEventPublisher::assertEventData([
141
            'id' => $createResponse->getId(),
142
        ], $events[0]);
143
    }
144
145
    /**
146
     * @test
147
     */
148
    public function shouldFetchAllCreatedPosts(): void
149
    {
150
        //given: There is a Post created
151
        $command = new CreatePostCommand('Post Title', 'Post Body', ['t1']);
152
        $createResponse = $this->createPost($command);
153
154
        //when: User fetches all the Posts
155
        $page = $this->findAllPosts(new FindAllPostsQuery(1));
156
157
        //then: the response is OK
158
        self::assertResponseIsSuccessful();
159
160
        //and: Previously created Post is fetched
161
        self::assertNotNull($page);
162
        self::assertEquals(1, $page->getPageNo());
163
        self::assertEquals(1, $page->getCount());
164
        self::assertCount(1, $page->getData());
165
        self::assertEquals(PostsFindingRepositoryInterface::PAGE_SIZE, $page->getPageSize());
166
167
        self::assertTrue(isset($page->getData()[0]));
168
169
        //and: The fetched Post is valid
170
        $postHeader = $this->convert($page->getData()[0], FindPostHeaderQueryResponse::class);
171
        self::assertNotNull($postHeader);
172
        self::assertEquals('Post Title', $postHeader->getTitle());
173
        self::assertEquals('Post Body', $postHeader->getSummary());
174
        self::assertEquals(['t1'], $postHeader->getTags());
175
        self::assertEquals(0, $postHeader->getCommentsCount());
176
        self::assertEquals($createResponse->getId(), $postHeader->getId());
177
    }
178
179
    /**
180
     * @param Ulid $postId
181
     * @return Ulid
182
     * @test
183
     */
184
    public function shouldFetchSingleCreatedPost(): void
185
    {
186
        //given: There is a Post created
187
        $command = new CreatePostCommand('Post Title', 'Post Body', ['t1']);
188
        $createResponse = $this->createPost($command);
189
190
        //when: User fetches the Post
191
        $post = $this->findPostById(new FindPostByIdQuery($createResponse->getId()));
192
193
        //then: the response is OK
194
        self::assertResponseIsSuccessful();
195
196
        //and: Previously created Post is fetched
197
        self::assertNotNull($post);
198
        self::assertEquals('Post Title', $post->getTitle());
199
        self::assertEquals('Post Body', $post->getBody());
200
        self::assertEquals(['t1'], $post->getTags());
201
        self::assertEquals([], $post->getComments());
202
        self::assertEquals($createResponse->getId(), $post->getId());
203
    }
204
205
    /**
206
     * @param Ulid $postId
207
     * @return Ulid
208
     * @test
209
     */
210
    public function shouldUpdateCommentsOnExistingPost(): void
211
    {
212
        //given: There is a Post created
213
        $command = new CreatePostCommand('Post Title', 'Post Body', ['t1']);
214
        $createResponse = $this->createPost($command);
215
216
        //and: There was a Comment Created
217
        $data = $this->getInboundEvent("Posts/CommentCreatedPostsIEvent");
218
        $data['postId'] = $createResponse->getId();
219
        $event = new CommentCreatedPostsIEvent($data);
220
221
        //when: the Comment Created Event is handled
222
        $this->getPostsApi()->onCommentCreated($event);
223
224
        //and: User fetches the Post
225
        $post = $this->findPostById(new FindPostByIdQuery($createResponse->getId()));
226
227
        //then: the response is OK
228
        self::assertResponseIsSuccessful();
229
230
        //and: Previously created Post is fetched with the Comment
231
        self::assertNotNull($post);
232
        self::assertEquals('Post Title', $post->getTitle());
233
        self::assertEquals('Post Body', $post->getBody());
234
        self::assertEquals(['t1'], $post->getTags());
235
        self::assertCount(1, $post->getComments());
236
        self::assertEquals('Comment Author', $post->getComments()[0]['author']);
237
        self::assertEquals('Comment Body', $post->getComments()[0]['body']);
238
        self::assertEquals($createResponse->getId(), $post->getId());
239
240
        //when: User fetches all the Posts
241
        $page = $this->findAllPosts(new FindAllPostsQuery(1));
242
243
        //then: the response is OK
244
        self::assertResponseIsSuccessful();
245
246
        //and: Previously created Post is fetched with the correct Comments count
247
        self::assertNotNull($page);
248
        self::assertEquals(1, $page->getPageNo());
249
        self::assertEquals(1, $page->getCount());
250
        self::assertCount(1, $page->getData());
251
        self::assertEquals(PostsFindingRepositoryInterface::PAGE_SIZE, $page->getPageSize());
252
        self::assertTrue(isset($page->getData()[0]));
253
        $postHeader = $this->convert($page->getData()[0], FindPostHeaderQueryResponse::class);
254
        self::assertNotNull($postHeader);
255
        self::assertEquals(1, $postHeader->getCommentsCount());
256
        self::assertEquals($createResponse->getId(), $postHeader->getId());
257
258
        //and: There was a Comment Created
259
        $data = $this->getInboundEvent("Posts/CommentsBaselinedPostsIEvent");
260
        $data['postId'] = $createResponse->getId();
261
        $event = new CommentsBaselinedPostsIEvent($data);
262
263
        //when: the Comment Created Event is handled
264
        $this->getPostsApi()->onCommentsBaselined($event);
265
266
        //and: User fetches the Post
267
        $post = $this->findPostById(new FindPostByIdQuery($createResponse->getId()));
268
269
        //then: the response is OK
270
        self::assertResponseIsSuccessful();
271
272
        //and: Previously created Post is fetched with the Comment
273
        self::assertNotNull($post);
274
        self::assertCount(2, $post->getComments());
275
    }
276
277
    /**
278
     * @param Ulid $postId
279
     * @return Ulid
280
     * @test
281
     */
282
    public function shouldBaselineAllPosts(): void
283
    {
284
        //given: There is a Post created
285
        $command = new CreatePostCommand('Post Title', 'Post Body', ['t1']);
286
        $createResponse = $this->createPost($command);
287
288
        //when: Comments are baselined
289
        $application = $this->setupKernel();
290
        $command = $application->find('app:posts:baseline');
291
        $commandTester = new CommandTester($command);
292
        $commandTester->execute([]);
293
        $output = $commandTester->getDisplay();
294
295
        //then: Comments were baselined correctly
296
        self::assertStringStartsWith('Successfully base-lined all Posts', $output);
297
        $events = InMemoryEventPublisher::get(PostBaselinedOEvent::class);
298
        self::assertCount(1, $events);
299
        self::assertEquals($createResponse->getId(), $events[0]->getData()['id']);
300
    }
301
302
    private function getPostsApi(): PostsApiInterface
303
    {
304
        return self::getContainer()->get(PostsApiInterface::class);
305
    }
306
307
    /**
308
     * @return Application
309
     */
310
    protected function setupKernel(): Application
311
    {
312
        $kernel = static::createKernel();
313
        $kernel->boot();
314
        $application = new Application($kernel);
315
        $application->add(new BaselinePostsCommand(
316
            $this->getContainer()->get(PostsApiInterface::class)
317
        ));
318
        return $application;
319
    }
320
}