-
Notifications
You must be signed in to change notification settings - Fork 152
[TASK] Add trait providing standard implementation of Commentable
#1206
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
fa0e11c
de45497
94a17b4
65bb1e7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| <?php | ||
|
|
||
| declare(strict_types=1); | ||
|
|
||
| namespace Sabberworm\CSS\Comment; | ||
|
|
||
| /** | ||
| * Provides a standard reusable implementation of `Commentable`. | ||
| * | ||
| * @internal | ||
| * | ||
| * @phpstan-require-implements Commentable | ||
| */ | ||
| trait CommentContainer | ||
|
oliverklee marked this conversation as resolved.
|
||
| { | ||
| /** | ||
| * @var list<Comment> | ||
| */ | ||
| protected $comments = []; | ||
|
|
||
| /** | ||
| * @param list<Comment> $comments | ||
| */ | ||
| public function addComments(array $comments): void | ||
| { | ||
| $this->comments = \array_merge($this->comments, $comments); | ||
| } | ||
|
|
||
| /** | ||
| * @return list<Comment> | ||
| */ | ||
| public function getComments(): array | ||
| { | ||
| return $this->comments; | ||
| } | ||
|
|
||
| /** | ||
| * @param list<Comment> $comments | ||
| */ | ||
| public function setComments(array $comments): void | ||
| { | ||
| $this->comments = $comments; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,239 @@ | ||||||
| <?php | ||||||
|
|
||||||
| declare(strict_types=1); | ||||||
|
|
||||||
| namespace Sabberworm\CSS\Tests\Unit\Comment; | ||||||
|
|
||||||
| use PHPUnit\Framework\Constraint\LogicalAnd; | ||||||
| use PHPUnit\Framework\Constraint\TraversableContains; | ||||||
| use PHPUnit\Framework\TestCase; | ||||||
| use Sabberworm\CSS\Comment\Comment; | ||||||
| use Sabberworm\CSS\Comment\Commentable; | ||||||
| use Sabberworm\CSS\Tests\Unit\Comment\Fixtures\ConcreteCommentContainer; | ||||||
| use TRegx\DataProvider\DataProviders; | ||||||
|
|
||||||
| /** | ||||||
| * @covers \Sabberworm\CSS\Comment\CommentContainer | ||||||
| */ | ||||||
| final class CommentContainerTest extends TestCase | ||||||
| { | ||||||
| /** | ||||||
| * @var Commentable | ||||||
|
JakeQZ marked this conversation as resolved.
Outdated
|
||||||
| */ | ||||||
| private $subject; | ||||||
|
|
||||||
| protected function setUp(): void | ||||||
| { | ||||||
| $this->subject = new ConcreteCommentContainer(); | ||||||
| } | ||||||
|
|
||||||
| /** | ||||||
| * @test | ||||||
| */ | ||||||
| public function getCommentsInitiallyReturnsEmptyArray(): void | ||||||
| { | ||||||
| self::assertSame([], $this->subject->getComments()); | ||||||
| } | ||||||
|
|
||||||
| /** | ||||||
| * @return array<non-empty-string, array{0: list<Comment>}> | ||||||
| */ | ||||||
| public function provideCommentArray(): array | ||||||
| { | ||||||
| return [ | ||||||
| 'no comment' => [[]], | ||||||
| 'one comment' => [[new Comment('Is this really a spoon?')]], | ||||||
| 'two comments' => [[ | ||||||
| new Comment('I’m a teapot.'), | ||||||
| new Comment('I’m a cafetière.'), | ||||||
|
JakeQZ marked this conversation as resolved.
|
||||||
| ]], | ||||||
| ]; | ||||||
| } | ||||||
|
|
||||||
| /** | ||||||
| * @test | ||||||
| * | ||||||
| * @param list<Comment> $comments | ||||||
| * | ||||||
| * @dataProvider provideCommentArray | ||||||
| */ | ||||||
| public function getCommentsAfterCommentsAddedToVirginContainerReturnsThoseComments(array $comments): void | ||||||
| { | ||||||
| $this->subject->addComments($comments); | ||||||
|
|
||||||
| self::assertSame($comments, $this->subject->getComments()); | ||||||
| } | ||||||
|
|
||||||
| /** | ||||||
| * @test | ||||||
| * | ||||||
| * @param list<Comment> $comments | ||||||
| * | ||||||
| * @dataProvider provideCommentArray | ||||||
| */ | ||||||
| public function getCommentsAfterEmptyArrayOfCommentsAddedReturnsOriginalComments(array $comments): void | ||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe we can describe the effects instead of focusing on the methods:
Suggested change
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Apart from
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, I'd like that!
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done. |
||||||
| { | ||||||
| $this->subject->setComments($comments); | ||||||
|
|
||||||
| $this->subject->addComments([]); | ||||||
|
|
||||||
| self::assertSame($comments, $this->subject->getComments()); | ||||||
| } | ||||||
|
|
||||||
| /** | ||||||
| * @return array<non-empty-string, array{0: list<Comment>}> | ||||||
| */ | ||||||
| public function provideAlternativeCommentArray(): array | ||||||
| { | ||||||
| return [ | ||||||
| 'no comment' => [[]], | ||||||
| 'one comment' => [[new Comment('Can I eat it with my hands?')]], | ||||||
| 'two comments' => [[ | ||||||
| new Comment('I’m a beer barrel.'), | ||||||
| new Comment('I’m a vineyard.'), | ||||||
| ]], | ||||||
| ]; | ||||||
| } | ||||||
|
|
||||||
| /** | ||||||
| * @return array<non-empty-string, array{0: non-empty-list<Comment>}> | ||||||
| */ | ||||||
| public function provideAlternativeNonemptyCommentArray(): array | ||||||
| { | ||||||
| $data = $this->provideAlternativeCommentArray(); | ||||||
|
|
||||||
| unset($data['no comment']); | ||||||
|
|
||||||
| return $data; | ||||||
| } | ||||||
|
|
||||||
| /** | ||||||
| * This provider crosses two comment arrays (0, 1 or 2 comments) with different comments, | ||||||
| * so that all combinations can be tested. | ||||||
| * | ||||||
| * @return array<non-empty-string, array{0: list<Comment>, 1: list<Comment>}> | ||||||
| */ | ||||||
| public function provideTwoDistinctCommentArrays(): array | ||||||
| { | ||||||
| return DataProviders::cross($this->provideCommentArray(), $this->provideAlternativeCommentArray()); | ||||||
| } | ||||||
|
|
||||||
| /** | ||||||
| * @return array<non-empty-string, array{0: list<Comment>, 1: non-empty-list<Comment>}> | ||||||
| */ | ||||||
| public function provideTwoDistinctCommentArraysWithSecondNonempty(): array | ||||||
| { | ||||||
| return DataProviders::cross($this->provideCommentArray(), $this->provideAlternativeNonemptyCommentArray()); | ||||||
| } | ||||||
|
|
||||||
| private static function createContainsContstraint(Comment $comment): TraversableContains | ||||||
| { | ||||||
| return new TraversableContains($comment); | ||||||
| } | ||||||
|
|
||||||
| /** | ||||||
| * @param non-empty-list<Comment> $comments | ||||||
| * | ||||||
| * @return non-empty-list<TraversableContains> | ||||||
| */ | ||||||
| private static function createContainsContstraints(array $comments): array | ||||||
| { | ||||||
| return \array_map([self::class, 'createContainsContstraint'], $comments); | ||||||
| } | ||||||
|
|
||||||
| /** | ||||||
| * @test | ||||||
| * | ||||||
| * @param list<Comment> $commentsToAdd | ||||||
| * @param non-empty-list<Comment> $originalComments | ||||||
| * | ||||||
| * @dataProvider provideTwoDistinctCommentArraysWithSecondNonempty | ||||||
| */ | ||||||
| public function getCommentsAfterCommentsAddedIncludesOriginalComments( | ||||||
| array $commentsToAdd, | ||||||
| array $originalComments | ||||||
| ): void { | ||||||
| $this->subject->setComments($originalComments); | ||||||
|
|
||||||
| $this->subject->addComments($commentsToAdd); | ||||||
|
|
||||||
| self::assertThat( | ||||||
| $this->subject->getComments(), | ||||||
| LogicalAnd::fromConstraints(...self::createContainsContstraints($originalComments)) | ||||||
| ); | ||||||
| } | ||||||
|
|
||||||
| /** | ||||||
| * @test | ||||||
| * | ||||||
| * @param list<Comment> $originalComments | ||||||
| * @param non-empty-list<Comment> $commentsToAdd | ||||||
| * | ||||||
| * @dataProvider provideTwoDistinctCommentArraysWithSecondNonempty | ||||||
| */ | ||||||
| public function getCommentsAfterCommentsAddedIncludesCommentsAdded( | ||||||
|
oliverklee marked this conversation as resolved.
Outdated
|
||||||
| array $originalComments, | ||||||
| array $commentsToAdd | ||||||
| ): void { | ||||||
| $this->subject->setComments($originalComments); | ||||||
|
|
||||||
| $this->subject->addComments($commentsToAdd); | ||||||
|
|
||||||
| self::assertThat( | ||||||
| $this->subject->getComments(), | ||||||
| LogicalAnd::fromConstraints(...self::createContainsContstraints($commentsToAdd)) | ||||||
| ); | ||||||
| } | ||||||
|
|
||||||
| /** | ||||||
| * @test | ||||||
| * | ||||||
| * @param non-empty-list<Comment> $comments | ||||||
| * | ||||||
| * @dataProvider provideAlternativeNonemptyCommentArray | ||||||
| */ | ||||||
| public function addCommentsAppends(array $comments): void | ||||||
| { | ||||||
| $firstComment = new Comment('I must be first!'); | ||||||
| $this->subject->setComments([$firstComment]); | ||||||
|
|
||||||
| $this->subject->addComments($comments); | ||||||
|
|
||||||
| $result = $this->subject->getComments(); | ||||||
| self::assertNotEmpty($result); | ||||||
| self::assertSame($firstComment, $result[0]); | ||||||
| } | ||||||
|
|
||||||
| /** | ||||||
| * @test | ||||||
| * | ||||||
| * @param list<Comment> $comments | ||||||
| * | ||||||
| * @dataProvider provideCommentArray | ||||||
| */ | ||||||
| public function getCommentsAfterCommentsSetOnVirginContainerReturnsThoseComments(array $comments): void | ||||||
| { | ||||||
| $this->subject->setComments($comments); | ||||||
|
|
||||||
| self::assertSame($comments, $this->subject->getComments()); | ||||||
| } | ||||||
|
|
||||||
| /** | ||||||
| * @test | ||||||
| * | ||||||
| * @param list<Comment> $originalComments | ||||||
| * @param list<Comment> $commentsToSet | ||||||
| * | ||||||
| * @dataProvider provideTwoDistinctCommentArrays | ||||||
| */ | ||||||
| public function getCommentsAfterCommentsSetOnContainerWithCommentsReturnsOnlyCommentsSet( | ||||||
| array $originalComments, | ||||||
| array $commentsToSet | ||||||
| ): void { | ||||||
| $this->subject->setComments($originalComments); | ||||||
|
|
||||||
| $this->subject->setComments($commentsToSet); | ||||||
|
|
||||||
| self::assertSame($commentsToSet, $this->subject->getComments()); | ||||||
| } | ||||||
| } | ||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| <?php | ||
|
|
||
| declare(strict_types=1); | ||
|
|
||
| namespace Sabberworm\CSS\Tests\Unit\Comment\Fixtures; | ||
|
|
||
| use Sabberworm\CSS\Comment\Commentable; | ||
| use Sabberworm\CSS\Comment\CommentContainer; | ||
|
|
||
| final class ConcreteCommentContainer implements Commentable | ||
| { | ||
| use CommentContainer; | ||
| } |
Uh oh!
There was an error while loading. Please reload this page.