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 }; }); } #[TestWith(["https://my.url.com", true])] #[TestWith(["my.url.com", false])] public function testValidatesUrls(string $url, bool $expected) { $endpoint = new Endpoint($this->createMock(HttpClientInterface::class), $this->createMock(WebmentionGatewayInterface::class)); $this->assertEquals($expected, $endpoint->validateUrl($url), "Expected $url"); } #[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); $endpoint = new Endpoint($this->createMock(HttpClientInterface::class), $this->createMock(WebmentionGatewayInterface::class)); $endpoint->receiveWebmention($source, $target); } public function testThrowsInvalidTargetExceptionIfTheTargetUrlIsNotOnCurrentSite() { $this->expectException(InvalidTargetException::class); $endpoint = new Endpoint($this->createMock(HttpClientInterface::class), $this->createMock(WebmentionGatewayInterface::class)); $endpoint->receiveWebmention("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"; $mockClient = $this->createMock(HttpClientInterface::class); $mockResponse = $this->createMock(ResponseInterface::class); $mockClient->expects($this->once()) ->method('request') ->with($this->identicalTo('GET'), $this->identicalTo($source)) ->will($this->returnValue($mockResponse)); $mockResponse->method('getStatusCode') ->will($this->returnValue($statusCode)); $this->expectException(SourceNotFoundException::class); $endpoint = new Endpoint($mockClient, $this->createMock(WebmentionGatewayInterface::class)); $endpoint->receiveWebmention($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; $mockClient = $this->createMock(HttpClientInterface::class); $mockResponse = $this->createMock(ResponseInterface::class); $mockClient->expects($this->once()) ->method('request') ->with($this->identicalTo('GET'), $this->identicalTo($source)) ->will($this->returnValue($mockResponse)); $mockResponse->method('getStatusCode') ->will($this->returnValue(200)); $mockResponse->method('getContent') ->willReturn($content); $this->expectException(TargetNotMentionedException::class); $endpoint = new Endpoint($mockClient, $this->createMock(WebmentionGatewayInterface::class)); $endpoint->receiveWebmention($source, $target); } public function testItShouldParseAWebmentionAsALikeIfItHasTheCorrectMicroFormat() { $source = "https://my-valid-source-url.com"; $target = "https://lewisdale.dev/post/a-post-page"; $content = << XML; $mockClient = $this->createMock(HttpClientInterface::class); $mockResponse = $this->createMock(ResponseInterface::class); $mockGateway = $this->createMock(WebmentionGatewayInterface::class); $mockClient->expects($this->once()) ->method('request') ->with($this->identicalTo('GET'), $this->identicalTo($source)) ->will($this->returnValue($mockResponse)); $mockResponse->method('getStatusCode') ->will($this->returnValue(200)); $mockResponse->method('getContent') ->willReturn($content); $mockGateway->expects($this->once()) ->method('save') ->with($this->objectContains('type', MentionType::Like)); $endpoint = new Endpoint($mockClient, $mockGateway); $endpoint->receiveWebmention($source, $target); } public function testItShouldParseAWebmentionAsAMentionIfItHasNoMicroformat() { $source = "https://my-valid-source-url.com"; $target = "https://lewisdale.dev/post/a-post-page"; $content = << XML; $mockClient = $this->createMock(HttpClientInterface::class); $mockResponse = $this->createMock(ResponseInterface::class); $mockGateway = $this->createMock(WebmentionGatewayInterface::class); $mockClient->expects($this->once()) ->method('request') ->with($this->identicalTo('GET'), $this->identicalTo($source)) ->will($this->returnValue($mockResponse)); $mockResponse->method('getStatusCode') ->will($this->returnValue(200)); $mockResponse->method('getContent') ->willReturn($content); $mockGateway->expects($this->once()) ->method('save') ->with($this->objectContains('type', MentionType::Mention)); $endpoint = new Endpoint($mockClient, $mockGateway); $endpoint->receiveWebmention($source, $target); } public function testItShouldParseAWebmentionAsAReplyIfItHasTheCorrectMicroFormat() { $source = "https://my-valid-source-url.com"; $target = "https://lewisdale.dev/post/a-post-page"; $content = << XML; $mockClient = $this->createMock(HttpClientInterface::class); $mockResponse = $this->createMock(ResponseInterface::class); $mockGateway = $this->createMock(WebmentionGatewayInterface::class); $mockClient->expects($this->once()) ->method('request') ->with($this->identicalTo('GET'), $this->identicalTo($source)) ->will($this->returnValue($mockResponse)); $mockResponse->method('getStatusCode') ->will($this->returnValue(200)); $mockResponse->method('getContent') ->willReturn($content); $mockGateway->expects($this->once()) ->method('save') ->with($this->objectContains('type', MentionType::Reply)); $endpoint = new Endpoint($mockClient, $mockGateway); $endpoint->receiveWebmention($source, $target); } 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; $mockClient = $this->createMock(HttpClientInterface::class); $mockResponse = $this->createMock(ResponseInterface::class); $mockGateway = $this->createMock(WebmentionGatewayInterface::class); $mockClient->expects($this->once()) ->method('request') ->with($this->identicalTo('GET'), $this->identicalTo($source)) ->will($this->returnValue($mockResponse)); $mockResponse->method('getStatusCode') ->will($this->returnValue(200)); $mockResponse->method('getContent') ->willReturn($content); $mockGateway->expects($this->once()) ->method('save') ->with($this->objectContains('type', MentionType::Repost)); $endpoint = new Endpoint($mockClient, $mockGateway); $endpoint->receiveWebmention($source, $target); } 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; $mockClient = $this->createMock(HttpClientInterface::class); $mockResponse = $this->createMock(ResponseInterface::class); $mockGateway = $this->createMock(WebmentionGatewayInterface::class); $mockClient->expects($this->once()) ->method('request') ->with($this->identicalTo('GET'), $this->identicalTo($source)) ->will($this->returnValue($mockResponse)); $mockResponse->method('getStatusCode') ->will($this->returnValue(200)); $mockResponse->method('getContent') ->willReturn($content); $mockGateway->expects($this->once()) ->method('save') ->with($this->objectContains('content', "Reposted this post")); $endpoint = new Endpoint($mockClient, $mockGateway); $endpoint->receiveWebmention($source, $target); } public function testItShouldParseALikeContent() { $source = "https://my-valid-source-url.com"; $target = "https://lewisdale.dev/post/a-post-page"; $content = << A Cool Post HTML; $mockClient = $this->createMock(HttpClientInterface::class); $mockResponse = $this->createMock(ResponseInterface::class); $mockGateway = $this->createMock(WebmentionGatewayInterface::class); $mockClient->expects($this->once()) ->method('request') ->with($this->identicalTo('GET'), $this->identicalTo($source)) ->will($this->returnValue($mockResponse)); $mockResponse->method('getStatusCode') ->will($this->returnValue(200)); $mockResponse->method('getContent') ->willReturn($content); $mockGateway->expects($this->once()) ->method('save') ->with($this->objectContains('content', "Liked this post")); $endpoint = new Endpoint($mockClient, $mockGateway); $endpoint->receiveWebmention($source, $target); } 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; $mockClient = $this->createMock(HttpClientInterface::class); $mockResponse = $this->createMock(ResponseInterface::class); $mockGateway = $this->createMock(WebmentionGatewayInterface::class); $mockClient->expects($this->once()) ->method('request') ->with($this->identicalTo('GET'), $this->identicalTo($source)) ->will($this->returnValue($mockResponse)); $mockResponse->method('getStatusCode') ->will($this->returnValue(200)); $mockResponse->method('getContent') ->willReturn($content); $mockGateway->expects($this->once()) ->method('save') ->with($this->objectContains('content', "@post: That's a great idea!")); $endpoint = new Endpoint($mockClient, $mockGateway); $endpoint->receiveWebmention($source, $target); } public function testItShouldParseAnAuthorCardWithANameUrlAndPhoto() { $source = "https://my-valid-source-url.com"; $target = "https://lewisdale.dev/post/a-post-page"; $content = << HTML; $mockClient = $this->createMock(HttpClientInterface::class); $mockResponse = $this->createMock(ResponseInterface::class); $mockGateway = $this->createMock(WebmentionGatewayInterface::class); $mockClient->expects($this->once()) ->method('request') ->with($this->identicalTo('GET'), $this->identicalTo($source)) ->will($this->returnValue($mockResponse)); $mockResponse->method('getStatusCode') ->will($this->returnValue(200)); $mockResponse->method('getContent') ->willReturn($content); $expected = new \Lewisdale\Webmentions\Models\Author( null, "Anne Author", "https://my-blog.com", "https://dummyimage.com/100x100/fff/aaa" ); $mockGateway->expects($this->once()) ->method('save') ->with($this->objectContains('author', $expected)); $endpoint = new Endpoint($mockClient, $mockGateway); $endpoint->receiveWebmention($source, $target); } public function testItShouldParseAnAuthorCardWithAMinimalHCard() { $source = "https://my-valid-source-url.com"; $target = "https://lewisdale.dev/post/a-post-page"; $content = << HTML; $mockClient = $this->createMock(HttpClientInterface::class); $mockResponse = $this->createMock(ResponseInterface::class); $mockGateway = $this->createMock(WebmentionGatewayInterface::class); $mockClient->expects($this->once()) ->method('request') ->with($this->identicalTo('GET'), $this->identicalTo($source)) ->will($this->returnValue($mockResponse)); $mockResponse->method('getStatusCode') ->will($this->returnValue(200)); $mockResponse->method('getContent') ->willReturn($content); $expected = new \Lewisdale\Webmentions\Models\Author( null, "microformats.org", "https://microformats.org/", "" ); $mockGateway->expects($this->once()) ->method('save') ->with($this->objectContains('author', $expected)); $endpoint = new Endpoint($mockClient, $mockGateway); $endpoint->receiveWebmention($source, $target); } public function testItShouldParseAnAuthorCardWithAVeryMinimalHCard() { $source = "https://my-valid-source-url.com"; $target = "https://lewisdale.dev/post/a-post-page"; $content = << HTML; $mockClient = $this->createMock(HttpClientInterface::class); $mockResponse = $this->createMock(ResponseInterface::class); $mockGateway = $this->createMock(WebmentionGatewayInterface::class); $mockClient->expects($this->once()) ->method('request') ->with($this->identicalTo('GET'), $this->identicalTo($source)) ->will($this->returnValue($mockResponse)); $mockResponse->method('getStatusCode') ->will($this->returnValue(200)); $mockResponse->method('getContent') ->willReturn($content); $expected = new \Lewisdale\Webmentions\Models\Author( null, "microformats.org", "https://microformats.org/", "" ); $mockGateway->expects($this->once()) ->method('save') ->with($this->objectContains('author', $expected)); $endpoint = new Endpoint($mockClient, $mockGateway); $endpoint->receiveWebmention($source, $target); } 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; $mockClient = $this->createMock(HttpClientInterface::class); $mockResponse = $this->createMock(ResponseInterface::class); $mockGateway = $this->createMock(WebmentionGatewayInterface::class); $mockClient->expects($this->once()) ->method('request') ->with($this->identicalTo('GET'), $this->identicalTo($source)) ->will($this->returnValue($mockResponse)); $mockResponse->method('getStatusCode') ->will($this->returnValue(200)); $mockResponse->method('getContent') ->willReturn($content); $expected = new \Lewisdale\Webmentions\Models\Author( null, "Anne Author", "https://my-blog.com", "https://dummyimage.com/100x100/fff/aaa" ); $mockGateway->expects($this->once()) ->method('save') ->with($this->objectContains('author', $expected)); $endpoint = new Endpoint($mockClient, $mockGateway); $endpoint->receiveWebmention($source, $target); } }