mockClient = $this->createMock(HttpClientInterface::class); $this->mockResponse = $this->createMock(ResponseInterface::class); $this->mockGateway = $this->createMock(WebmentionGatewayInterface::class); } private function objectContains(string $key, mixed $expected) { return $this->callback(function (object $obj) use ($expected, $key) { $val = $obj->$key; $type = gettype($val); return match ($type) { "object" => $val == $expected, "array" => count(array_diff($val, $expected)) === 0, default => $val === $expected }; }); } private function callEndpoint(string $source, string $target) { $this->mockClient->method('request') ->with($this->identicalTo('GET'), $this->identicalTo($source)) ->will($this->returnValue($this->mockResponse)); $endpoint = new Endpoint($this->mockClient, $this->mockGateway); $endpoint->receiveWebmention($source, $target); } #[TestWith(["https://my-valid-source.url", "htt://my-invalid-target.com"])] #[TestWith(["my-invalid-source", "https://my-valid-target.com"])] #[TestWith(["http:///an-invalid-source", "an-invalid-target"])] public function testThrowsInvalidUrlExceptionIfTheUrlIsInvalid(string $source, string $target) { $this->expectException(InvalidUrlException::class); $this->callEndpoint($source, $target); } public function testThrowsInvalidTargetExceptionIfTheTargetUrlIsNotOnCurrentSite() { $this->expectException(InvalidTargetException::class); $this->callEndpoint("https://a-valid-source.url", "https://not-my-site.com"); } #[TestWith([404])] #[TestWith([401])] #[TestWith([500])] #[TestWith([501])] #[TestWith([502])] #[TestWith([503])] #[TestWith([500])] public function testItShouldThrowASourceNotFoundExceptionIfTheSourceUrlIsUnreachable(int $statusCode) { $source = "https://my-valid-source-url.com"; $target = "https://lewisdale.dev/post/a-post-page"; $this->mockClient->expects($this->once()) ->method('request') ->with($this->identicalTo('GET'), $this->identicalTo($source)) ->will($this->returnValue($this->mockResponse)); $this->mockResponse->method('getStatusCode') ->will($this->returnValue($statusCode)); $this->expectException(SourceNotFoundException::class); $this->callEndpoint($source, $target); } public function testItShouldThrowATargetNotMentionedErrorIfTheSourceDoesNotMentionTheTarget() { $source = "https://my-valid-source-url.com"; $target = "https://lewisdale.dev/post/a-post-page"; $content = <<

Some content

Here's some body content. It contains a url.

But it does not mention the target.

XML; $this->mockResponse->method('getStatusCode') ->will($this->returnValue(200)); $this->mockResponse->method('getContent') ->willReturn($content); $this->expectException(TargetNotMentionedException::class); $this->callEndpoint($source, $target); } private function verifyContent(string $source, string $target, string $content, \PHPUnit\Framework\Constraint\Callback $verify) { $this->mockResponse->method('getStatusCode') ->will($this->returnValue(200)); $this->mockResponse->method('getContent') ->willReturn($content); $this->mockGateway->expects($this->once()) ->method('save') ->with($verify); $this->callEndpoint($source, $target); } public function testItShouldParseAWebmentionAsALikeIfItHasTheCorrectMicroFormat() { $source = "https://my-valid-source-url.com"; $target = "https://lewisdale.dev/post/a-post-page"; $content = << XML; $this->verifyContent($source, $target, $content, $this->objectContains('type', MentionType::Like)); } public function testItShouldParseAWebmentionAsAMentionIfItHasNoMicroformat() { $source = "https://my-valid-source-url.com"; $target = "https://lewisdale.dev/post/a-post-page"; $content = << XML; $this->verifyContent($source, $target, $content, $this->objectContains('type', MentionType::Mention)); } public function testItShouldParseAWebmentionAsAReplyIfItHasTheCorrectMicroFormat() { $source = "https://my-valid-source-url.com"; $target = "https://lewisdale.dev/post/a-post-page"; $content = << XML; $this->verifyContent($source, $target, $content, $this->objectContains('type', MentionType::Reply)); } public function testItShouldParseAWebmentionAsARepost() { $source = "https://my-valid-source-url.com"; $target = "https://lewisdale.dev/post/a-post-page"; $content = <<

Some content

Here's some body content. It contains a url.

I'm writing about this post.

XML; $this->verifyContent($source, $target, $content, $this->objectContains('type', MentionType::Repost)); } public function testItShouldParseARepostsContent() { $source = "https://my-valid-source-url.com"; $target = "https://lewisdale.dev/post/a-post-page"; $content = <<

Some content

Here's some body content. It contains a url.

I'm writing about this post.

XML; $this->verifyContent($source, $target, $content, $this->objectContains('content', "Reposted this post")); } public function testItShouldParseALikeContent() { $source = "https://my-valid-source-url.com"; $target = "https://lewisdale.dev/post/a-post-page"; $content = << A Cool Post HTML; $this->verifyContent($source, $target, $content, $this->objectContains('content', "Liked this post")); } public function testItShouldParseAReplyContent() { $source = "https://my-valid-source-url.com"; $target = "https://lewisdale.dev/post/a-post-page"; $content = <<
@post: That's a great idea!
HTML; $this->verifyContent($source, $target, $content, $this->objectContains('content', "@post: That's a great idea!")); } public function testItShouldParseAnAuthorCardWithANameUrlAndPhoto() { $source = "https://my-valid-source-url.com"; $target = "https://lewisdale.dev/post/a-post-page"; $content = << HTML; $expected = new \Lewisdale\Webmentions\Models\Author(null, "Anne Author", "https://my-blog.com", "https://dummyimage.com/100x100/fff/aaa"); $this->verifyContent($source, $target, $content, $this->objectContains('author', $expected)); } public function testItShouldParseAnAuthorCardWithAMinimalHCard() { $source = "https://my-valid-source-url.com"; $target = "https://lewisdale.dev/post/a-post-page"; $content = << HTML; $expected = new \Lewisdale\Webmentions\Models\Author( null, "microformats.org", "https://microformats.org/", "" ); $this->verifyContent($source, $target, $content, $this->objectContains('author', $expected)); } public function testItShouldParseAnAuthorCardWithAVeryMinimalHCard() { $source = "https://my-valid-source-url.com"; $target = "https://lewisdale.dev/post/a-post-page"; $content = << HTML; $expected = new \Lewisdale\Webmentions\Models\Author( null, "microformats.org", "https://microformats.org/", "" ); $this->verifyContent($source, $target, $content, $this->objectContains('author', $expected)); } public function testItShouldParseAnAuthorCardOutsideTheEntrry() { $source = "https://my-valid-source-url.com"; $target = "https://lewisdale.dev/post/a-post-page"; $content = <<
@post: That's a great idea!

Anne Author

who can be found at my-blog.com. My profile picture
HTML; $expected = new \Lewisdale\Webmentions\Models\Author( null, "Anne Author", "https://my-blog.com", "https://dummyimage.com/100x100/fff/aaa" ); $this->verifyContent($source, $target, $content, $this->objectContains('author', $expected)); } }