Browse Source

Merge pull request #107 from Lohn/main

Updates to support php 8 anc CI
pull/108/head
Aaron Parecki 3 years ago
committed by GitHub
parent
commit
b136e424df
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 5909 additions and 4683 deletions
  1. +42
    -0
      .github/workflows/php.yml
  2. +2
    -0
      .gitignore
  3. +5
    -15
      README.md
  4. +13
    -11
      composer.json
  5. +1540
    -607
      composer.lock
  6. +1
    -2
      composer.production.json
  7. +3
    -37
      lib/XRay/Formats/Facebook.php
  8. +3
    -0
      lib/XRay/Formats/HTML.php
  9. +240
    -225
      tests/ActivityStreamsTest.php
  10. +197
    -182
      tests/AuthorTest.php
  11. +0
    -75
      tests/FacebookTest.php
  12. +523
    -493
      tests/FeedTest.php
  13. +227
    -188
      tests/FetchTest.php
  14. +27
    -22
      tests/FetchTestDisabled.php
  15. +234
    -217
      tests/FindFeedsTest.php
  16. +132
    -124
      tests/GitHubTest.php
  17. +61
    -50
      tests/HackernewsTest.php
  18. +37
    -31
      tests/HelpersTest.php
  19. +318
    -292
      tests/InstagramTest.php
  20. +57
    -50
      tests/LibraryTest.php
  21. +42
    -36
      tests/MediaTypeTest.php
  22. +1298
    -1196
      tests/ParseTest.php
  23. +415
    -389
      tests/SanitizeTest.php
  24. +165
    -150
      tests/TokenTest.php
  25. +319
    -287
      tests/TwitterTest.php
  26. +8
    -4
      tests/bootstrap.php

+ 42
- 0
.github/workflows/php.yml View File

@ -0,0 +1,42 @@
name: PHP Composer
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
build:
strategy:
matrix:
php-versions: ["7.2", "7.3", "7.4", "8.0"]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Setup PHP, with composer and extensions
uses: shivammathur/setup-php@v2 #https://github.com/shivammathur/setup-php
with:
php-version: ${{ matrix.php-versions }}
extensions: mbstring, simplexml, dom, curl
coverage: pcov
- name: Validate composer.json and composer.lock
run: composer validate --strict
- name: Cache Composer packages
id: composer-cache
uses: actions/cache@v2
with:
path: vendor
key: ${{ runner.os }}-php-${{ hashFiles('**/composer.lock') }}
restore-keys: |
${{ runner.os }}-php-
- name: Install dependencies
run: composer update --prefer-dist --no-progress
- name: Run test suite
run: composer run-script test

+ 2
- 0
.gitignore View File

@ -4,3 +4,5 @@ vendor/
php_errors.log
XRay-*.json
.gcloudignore
.phpunit.result.cache
.vscode

+ 5
- 15
README.md View File

@ -13,7 +13,7 @@ XRay will parse content in the following formats. First the URL is checked again
* GitHub
* XKCD
* Hackernews
* Facebook (public events)
* ~~Facebook (public events)~~ <REMOVED>
If the contents of the URL is XML or JSON, then XRay will parse the Atom, RSS or JSONFeed formats.
@ -245,7 +245,7 @@ url=https://aaronparecki.com/2016/01/16/11/
&body=<html>....</html>
```
or for Twitter/GitHub/Facebook where you might have JSON,
or for Twitter/GitHub where you might have JSON,
```
POST /parse
@ -282,9 +282,9 @@ url=https://aaronparecki.com/2016/01/16/11/
### API Authentication
XRay uses the Twitter, Github and Facebook APIs to fetch posts, and those API require authentication. In order to keep XRay stateless, it is required that you pass in the credentials to the parse call.
XRay uses the Twitter and Github APIs to fetch posts, and those API require authentication. In order to keep XRay stateless, it is required that you pass in the credentials to the parse call.
You should only send the credentials when the URL you are trying to parse is a Twitter URL, a GitHub URL or a Facebook URL, so you'll want to check for whether the hostname is `twitter.com`, `github.com`, etc. before you include credentials in this call.
You should only send the credentials when the URL you are trying to parse is a Twitter URL or a GitHub URL, so you'll want to check for whether the hostname is `twitter.com`, `github.com`, etc. before you include credentials in this call.
#### Twitter Authentication
@ -304,16 +304,6 @@ XRay uses the GitHub API to fetch GitHub URLs, which provides higher rate limits
* `github_access_token` - A GitHub access token
#### Facebook Authentication
XRay uses the Facebook API to fetch Facebook URLs. You can create a Facebook App on Facebooks developer website.
* facebook_app_id - Your application's App ID
* facebook_app_secret - Your application's App Secret
At this moment, XRay is able to get it's own access token from those credentials.
### Error Response
```json
@ -431,7 +421,7 @@ Other properties are returned in the response at the same level as the `data` pr
* `mf2+json`
* `feed+json`
* `xml`
* `instagram`/`facebook`/`github`/`xkcd`
* `instagram`/`github`/`xkcd`
#### Feeds

+ 13
- 11
composer.json View File

@ -7,13 +7,12 @@
"require": {
"mf2/mf2": "^0.4",
"ezyang/htmlpurifier": "^4.10",
"indieweb/link-rel-parser": "0.1.*",
"dg/twitter-php": "3.6.*",
"p3k/timezone": "*",
"p3k/http": ">=0.1.11",
"cebe/markdown": "1.1.*",
"p3k/picofeed": ">=0.1.39",
"facebook/graph-sdk": "^5.5",
"indieweb/link-rel-parser": "^0.1.0",
"dg/twitter-php": "^3.0.0",
"p3k/timezone": "^0.1.0",
"p3k/http": "^0.1.0",
"cebe/markdown": "^1.1.0",
"p3k/picofeed": "^0.1.0",
"masterminds/html5": "^2.3"
},
"autoload": {
@ -26,9 +25,9 @@
]
},
"require-dev": {
"league/plates": "3.*",
"league/route": "1.*",
"phpunit/phpunit": "4.8.*"
"league/plates": "^3.0",
"league/route": "^1.0",
"phpunit/phpunit": "^8.0.0|^9.0.0"
},
"autoload-dev": {
"files": [
@ -39,5 +38,8 @@
"controllers/Feeds.php",
"controllers/Certbot.php"
]
},
"scripts": {
"test": "vendor/bin/phpunit"
}
}
}

+ 1540
- 607
composer.lock
File diff suppressed because it is too large
View File


+ 1
- 2
composer.production.json View File

@ -15,7 +15,6 @@
"p3k/http": ">=0.1.8",
"cebe/markdown": "1.1.*",
"p3k/picofeed": ">=0.1.35",
"facebook/graph-sdk": "^5.5",
"masterminds/html5": "^2.3"
},
"autoload": {
@ -36,4 +35,4 @@
"require-dev": {
"phpunit/phpunit": "4.8.*"
}
}
}

+ 3
- 37
lib/XRay/Formats/Facebook.php View File

@ -79,46 +79,12 @@ class Facebook extends Format {
public static function fetch($url, $creds) {
$parts = self::extract_url_parts($url);
if(!$parts or $parts['api_uri'] == false) {
return [
'error' => 'unsupported_url',
'error_description' => 'This Facebook URL is not supported',
'error_code' => 400,
];
}
$fb = new \Facebook\Facebook(array(
'app_id' => $creds['facebook_app_id'],
'app_secret' => $creds['facebook_app_secret'],
'default_graph_version' => 'v2.9',
));
$fbApp = new \Facebook\FacebookApp($creds['facebook_app_id'], $creds['facebook_app_secret']);
$token = $fbApp->getAccessToken();
$request = new \Facebook\FacebookRequest($fbApp, $token, 'GET', $parts['api_uri']);
try {
$response = $fb->getClient()->sendRequest($request);
} catch(\Facebook\Exceptions\FacebookResponseException $e) {
return [
'error' => 'facebook_graph_error',
'error_description' => 'Graph returned an error: ' . $e->getMessage(),
'error_code' => 400,
];
} catch(\Facebook\Exceptions\FacebookSDKException $e) {
return [
'error' => 'facebook_sdk_error',
'error_description' => 'Facebook SDK returned an error: ' . $e->getMessage(),
'error_code' => 400,
];
}
//Disabled Function for now
//TODO: Search all references to this class and remove it.
return [
'code' => 200,
'body' => $response->getDecodedBody(),
'body' => '',
'url' => $url
];
}

+ 3
- 0
lib/XRay/Formats/HTML.php View File

@ -25,6 +25,9 @@ class HTML extends Format {
// attempt to parse the page as HTML
$doc = new DOMDocument();
if (empty($html)) {
$html=' '; // ugly hack to make DOMDocument happy
};
@$doc->loadHTML(self::toHtmlEntities($html));
if(!$doc) {

+ 240
- 225
tests/ActivityStreamsTest.php View File

@ -2,230 +2,245 @@
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
class ActivityStreamsTest extends PHPUnit_Framework_TestCase {
private $http;
public function setUp() {
$this->client = new Parse();
$this->client->http = new p3k\HTTP\Test(dirname(__FILE__).'/data/');
$this->client->mc = null;
}
private function parse($params) {
$request = new Request($params);
$response = new Response();
return $this->client->parse($request, $response);
}
public function testAuthorProfile() {
$url = 'http://activitystreams.example/aaronpk';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$this->assertEquals('activity+json', $data['source-format']);
$this->assertEquals('card', $data['data']['type']);
$this->assertEquals('aaronpk', $data['data']['name']);
$this->assertEquals('https://aaronparecki.com/images/profile.jpg', $data['data']['photo']);
$this->assertEquals('https://aaronparecki.com/', $data['data']['url']);
}
public function testNoteWithTags() {
$url = 'http://activitystreams.example/note.json';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$this->assertEquals('activity+json', $data['source-format']);
$this->assertEquals('note', $data['data']['post-type']);
$this->assertEquals($url, $data['data']['url']);
$this->assertEquals('2018-07-12T13:02:04-07:00', $data['data']['published']);
$this->assertEquals('This is the text content of an ActivityStreams note', $data['data']['content']['text']);
$this->assertArrayNotHasKey('html', $data['data']['content']);
$this->assertSame(['activitystreams'], $data['data']['category']);
$this->assertEquals('aaronpk', $data['data']['author']['name']);
$this->assertEquals('https://aaronparecki.com/images/profile.jpg', $data['data']['author']['photo']);
$this->assertEquals('https://aaronparecki.com/', $data['data']['author']['url']);
}
public function testArticle() {
$url = 'http://activitystreams.example/article.json';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$this->assertEquals('activity+json', $data['source-format']);
$this->assertEquals('article', $data['data']['post-type']);
$this->assertEquals($url, $data['data']['url']);
$this->assertEquals('An Article', $data['data']['name']);
$this->assertEquals('This is the content of an ActivityStreams article', $data['data']['content']['text']);
$this->assertEquals('<p>This is the content of an <b>ActivityStreams</b> article</p>', $data['data']['content']['html']);
$this->assertEquals('aaronpk', $data['data']['author']['name']);
$this->assertEquals('https://aaronparecki.com/images/profile.jpg', $data['data']['author']['photo']);
$this->assertEquals('https://aaronparecki.com/', $data['data']['author']['url']);
}
public function testPhoto() {
$url = 'http://activitystreams.example/photo.json';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$this->assertEquals('activity+json', $data['source-format']);
$this->assertEquals($url, $data['data']['url']);
$this->assertEquals('photo', $data['data']['post-type']);
$this->assertEquals('2018-07-12T13:02:04-07:00', $data['data']['published']);
$this->assertEquals('This is the text content of an ActivityStreams photo', $data['data']['content']['text']);
$this->assertArrayNotHasKey('html', $data['data']['content']);
$this->assertSame(['activitystreams'], $data['data']['category']);
$this->assertSame(['https://aaronparecki.com/2018/06/28/26/photo.jpg'], $data['data']['photo']);
}
public function testVideo() {
$url = 'http://activitystreams.example/video.json';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$this->assertEquals('activity+json', $data['source-format']);
$this->assertEquals('video', $data['data']['post-type']);
$this->assertEquals('2018-07-12T13:02:04-07:00', $data['data']['published']);
$this->assertSame(['https://aaronparecki.com/2018/07/21/19/video.mp4'], $data['data']['video']);
}
public function testReply() {
$url = 'http://activitystreams.example/reply.json';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$this->assertEquals('activity+json', $data['source-format']);
$this->assertEquals('reply', $data['data']['post-type']);
$this->assertEquals('2018-07-12T13:02:04-07:00', $data['data']['published']);
$this->assertArrayNotHasKey('category', $data['data']); // should not include the person-tag
// For now, don't fetch the reply context
$this->assertEquals(['http://activitystreams.example/note.json'], $data['data']['in-reply-to']);
}
public function testCustomEmoji() {
$url = 'http://activitystreams.example/custom-emoji.json';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$this->assertEquals('activity+json', $data['source-format']);
$this->assertEquals('note', $data['data']['post-type']);
$this->assertEquals("https://mastodon.social/@Gargron/100465999501820229", $data['data']['url']);
$this->assertEquals('2018-07-30T22:24:54+00:00', $data['data']['published']);
$this->assertEquals(':yikes:', $data['data']['content']['text']);
$this->assertEquals('<p><img src="https://files.mastodon.social/custom_emojis/images/000/031/275/original/yikes.png" alt=":yikes:" title=":yikes:" height="24" class="xray-emoji"></p>', $data['data']['content']['html']);
$this->assertEquals('Eugen', $data['data']['author']['name']);
$this->assertEquals('Gargron', $data['data']['author']['nickname']);
$this->assertEquals('https://files.mastodon.social/accounts/avatars/000/000/001/original/eb9e00274b135808.png', $data['data']['author']['photo']);
$this->assertEquals('https://mastodon.social/@Gargron', $data['data']['author']['url']);
}
public function testRelAlternatePriority() {
$url = 'http://source.example.com/rel-alternate-as2';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$this->assertEquals('activity+json', $data['source-format']);
$this->assertEquals('http://activitystreams.example/note.json', $data['parsed-url']);
$this->assertEquals('http://source.example.com/rel-alternate-as2', $data['url']);
$this->assertEquals('note', $data['data']['post-type']);
$this->assertEquals('2018-07-12T13:02:04-07:00', $data['data']['published']);
$this->assertEquals('This is the text content of an ActivityStreams note', $data['data']['content']['text']);
$this->assertArrayNotHasKey('html', $data['data']['content']);
$this->assertSame(['activitystreams'], $data['data']['category']);
}
public function testSensitiveContent() {
$url = 'http://activitystreams.example/sensitive.json';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$this->assertEquals('activity+json', $data['source-format']);
$this->assertEquals('note', $data['data']['post-type']);
$this->assertEquals('sensitive topic', $data['data']['summary']);
$this->assertEquals('This is the text content of a sensitive ActivityStreams note', $data['data']['content']['text']);
$this->assertArrayNotHasKey('name', $data['data']);
}
public function testRepost() {
$url = 'http://activitystreams.example/repost.json';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$this->assertEquals('activity+json', $data['source-format']);
$this->assertEquals('repost', $data['data']['post-type']);
$this->assertArrayNotHasKey('content', $data['data']);
$this->assertArrayNotHasKey('name', $data['data']);
$this->assertEquals('Gargron', $data['data']['author']['nickname']);
$this->assertEquals(['http://activitystreams.example/note.json'], $data['data']['repost-of']);
$this->assertArrayHasKey('http://activitystreams.example/note.json', $data['data']['refs']);
$this->assertEquals('This is the text content of an ActivityStreams note', $data['data']['refs']['http://activitystreams.example/note.json']['content']['text']);
}
public function testLike() {
$url = 'http://activitystreams.example/like.json';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$this->assertEquals('activity+json', $data['source-format']);
$this->assertEquals('like', $data['data']['post-type']);
$this->assertArrayNotHasKey('content', $data['data']);
$this->assertArrayNotHasKey('name', $data['data']);
$this->assertEquals('Gargron', $data['data']['author']['nickname']);
$this->assertEquals(['http://activitystreams.example/note.json'], $data['data']['like-of']);
$this->assertArrayHasKey('http://activitystreams.example/note.json', $data['data']['refs']);
$this->assertEquals('This is the text content of an ActivityStreams note', $data['data']['refs']['http://activitystreams.example/note.json']['content']['text']);
}
public function testNoteWrappedInCreate() {
$url = 'http://activitystreams.example/create.json';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$this->assertEquals('activity+json', $data['source-format']);
$this->assertEquals('reply', $data['data']['post-type']);
$this->assertEquals('https://toot.cat/@jamey/100471682482196371', $data['data']['url']);
$this->assertEquals('2018-07-31T22:30:09+00:00', $data['data']['published']);
$this->assertEquals('@darius Huh, I just have never encountered anyone using the phrase generically like that.But you might consider writing IndieWeb.org-style bots (Atom+WebSub, and optionally WebMention if you want them to be interactive), and then using https://fed.brid.gy/ as an alternative to implementing ActivityPub yourself...', $data['data']['content']['text']);
$this->assertEquals('https://social.tinysubversions.com/users/darius/statuses/100471614681787834', $data['data']['in-reply-to'][0]);
$this->assertEquals('Jamey Sharp', $data['data']['author']['name']);
$this->assertEquals('https://s3-us-west-2.amazonaws.com/tootcatapril2017/accounts/avatars/000/013/259/original/c904452a8411e4f5.jpg', $data['data']['author']['photo']);
$this->assertEquals('https://toot.cat/@jamey', $data['data']['author']['url']);
}
class ActivityStreamsTest extends PHPUnit\Framework\TestCase
{
private $http;
public function setUp(): void
{
$this->client = new Parse();
$this->client->http = new p3k\HTTP\Test(dirname(__FILE__).'/data/');
$this->client->mc = null;
}
private function parse($params)
{
$request = new Request($params);
$response = new Response();
return $this->client->parse($request, $response);
}
public function testAuthorProfile()
{
$url = 'http://activitystreams.example/aaronpk';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$this->assertEquals('activity+json', $data['source-format']);
$this->assertEquals('card', $data['data']['type']);
$this->assertEquals('aaronpk', $data['data']['name']);
$this->assertEquals('https://aaronparecki.com/images/profile.jpg', $data['data']['photo']);
$this->assertEquals('https://aaronparecki.com/', $data['data']['url']);
}
public function testNoteWithTags()
{
$url = 'http://activitystreams.example/note.json';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$this->assertEquals('activity+json', $data['source-format']);
$this->assertEquals('note', $data['data']['post-type']);
$this->assertEquals($url, $data['data']['url']);
$this->assertEquals('2018-07-12T13:02:04-07:00', $data['data']['published']);
$this->assertEquals('This is the text content of an ActivityStreams note', $data['data']['content']['text']);
$this->assertArrayNotHasKey('html', $data['data']['content']);
$this->assertSame(['activitystreams'], $data['data']['category']);
$this->assertEquals('aaronpk', $data['data']['author']['name']);
$this->assertEquals('https://aaronparecki.com/images/profile.jpg', $data['data']['author']['photo']);
$this->assertEquals('https://aaronparecki.com/', $data['data']['author']['url']);
}
public function testArticle()
{
$url = 'http://activitystreams.example/article.json';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$this->assertEquals('activity+json', $data['source-format']);
$this->assertEquals('article', $data['data']['post-type']);
$this->assertEquals($url, $data['data']['url']);
$this->assertEquals('An Article', $data['data']['name']);
$this->assertEquals('This is the content of an ActivityStreams article', $data['data']['content']['text']);
$this->assertEquals('<p>This is the content of an <b>ActivityStreams</b> article</p>', $data['data']['content']['html']);
$this->assertEquals('aaronpk', $data['data']['author']['name']);
$this->assertEquals('https://aaronparecki.com/images/profile.jpg', $data['data']['author']['photo']);
$this->assertEquals('https://aaronparecki.com/', $data['data']['author']['url']);
}
public function testPhoto()
{
$url = 'http://activitystreams.example/photo.json';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$this->assertEquals('activity+json', $data['source-format']);
$this->assertEquals($url, $data['data']['url']);
$this->assertEquals('photo', $data['data']['post-type']);
$this->assertEquals('2018-07-12T13:02:04-07:00', $data['data']['published']);
$this->assertEquals('This is the text content of an ActivityStreams photo', $data['data']['content']['text']);
$this->assertArrayNotHasKey('html', $data['data']['content']);
$this->assertSame(['activitystreams'], $data['data']['category']);
$this->assertSame(['https://aaronparecki.com/2018/06/28/26/photo.jpg'], $data['data']['photo']);
}
public function testVideo()
{
$url = 'http://activitystreams.example/video.json';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$this->assertEquals('activity+json', $data['source-format']);
$this->assertEquals('video', $data['data']['post-type']);
$this->assertEquals('2018-07-12T13:02:04-07:00', $data['data']['published']);
$this->assertSame(['https://aaronparecki.com/2018/07/21/19/video.mp4'], $data['data']['video']);
}
public function testReply()
{
$url = 'http://activitystreams.example/reply.json';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$this->assertEquals('activity+json', $data['source-format']);
$this->assertEquals('reply', $data['data']['post-type']);
$this->assertEquals('2018-07-12T13:02:04-07:00', $data['data']['published']);
$this->assertArrayNotHasKey('category', $data['data']); // should not include the person-tag
// For now, don't fetch the reply context
$this->assertEquals(['http://activitystreams.example/note.json'], $data['data']['in-reply-to']);
}
public function testCustomEmoji()
{
$url = 'http://activitystreams.example/custom-emoji.json';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$this->assertEquals('activity+json', $data['source-format']);
$this->assertEquals('note', $data['data']['post-type']);
$this->assertEquals("https://mastodon.social/@Gargron/100465999501820229", $data['data']['url']);
$this->assertEquals('2018-07-30T22:24:54+00:00', $data['data']['published']);
$this->assertEquals(':yikes:', $data['data']['content']['text']);
$this->assertEquals('<p><img src="https://files.mastodon.social/custom_emojis/images/000/031/275/original/yikes.png" alt=":yikes:" title=":yikes:" height="24" class="xray-emoji"></p>', $data['data']['content']['html']);
$this->assertEquals('Eugen', $data['data']['author']['name']);
$this->assertEquals('Gargron', $data['data']['author']['nickname']);
$this->assertEquals('https://files.mastodon.social/accounts/avatars/000/000/001/original/eb9e00274b135808.png', $data['data']['author']['photo']);
$this->assertEquals('https://mastodon.social/@Gargron', $data['data']['author']['url']);
}
public function testRelAlternatePriority()
{
$url = 'http://source.example.com/rel-alternate-as2';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$this->assertEquals('activity+json', $data['source-format']);
$this->assertEquals('http://activitystreams.example/note.json', $data['parsed-url']);
$this->assertEquals('http://source.example.com/rel-alternate-as2', $data['url']);
$this->assertEquals('note', $data['data']['post-type']);
$this->assertEquals('2018-07-12T13:02:04-07:00', $data['data']['published']);
$this->assertEquals('This is the text content of an ActivityStreams note', $data['data']['content']['text']);
$this->assertArrayNotHasKey('html', $data['data']['content']);
$this->assertSame(['activitystreams'], $data['data']['category']);
}
public function testSensitiveContent()
{
$url = 'http://activitystreams.example/sensitive.json';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$this->assertEquals('activity+json', $data['source-format']);
$this->assertEquals('note', $data['data']['post-type']);
$this->assertEquals('sensitive topic', $data['data']['summary']);
$this->assertEquals('This is the text content of a sensitive ActivityStreams note', $data['data']['content']['text']);
$this->assertArrayNotHasKey('name', $data['data']);
}
public function testRepost()
{
$url = 'http://activitystreams.example/repost.json';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$this->assertEquals('activity+json', $data['source-format']);
$this->assertEquals('repost', $data['data']['post-type']);
$this->assertArrayNotHasKey('content', $data['data']);
$this->assertArrayNotHasKey('name', $data['data']);
$this->assertEquals('Gargron', $data['data']['author']['nickname']);
$this->assertEquals(['http://activitystreams.example/note.json'], $data['data']['repost-of']);
$this->assertArrayHasKey('http://activitystreams.example/note.json', $data['data']['refs']);
$this->assertEquals('This is the text content of an ActivityStreams note', $data['data']['refs']['http://activitystreams.example/note.json']['content']['text']);
}
public function testLike()
{
$url = 'http://activitystreams.example/like.json';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$this->assertEquals('activity+json', $data['source-format']);
$this->assertEquals('like', $data['data']['post-type']);
$this->assertArrayNotHasKey('content', $data['data']);
$this->assertArrayNotHasKey('name', $data['data']);
$this->assertEquals('Gargron', $data['data']['author']['nickname']);
$this->assertEquals(['http://activitystreams.example/note.json'], $data['data']['like-of']);
$this->assertArrayHasKey('http://activitystreams.example/note.json', $data['data']['refs']);
$this->assertEquals('This is the text content of an ActivityStreams note', $data['data']['refs']['http://activitystreams.example/note.json']['content']['text']);
}
public function testNoteWrappedInCreate()
{
$url = 'http://activitystreams.example/create.json';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$this->assertEquals('activity+json', $data['source-format']);
$this->assertEquals('reply', $data['data']['post-type']);
$this->assertEquals('https://toot.cat/@jamey/100471682482196371', $data['data']['url']);
$this->assertEquals('2018-07-31T22:30:09+00:00', $data['data']['published']);
$this->assertEquals('@darius Huh, I just have never encountered anyone using the phrase generically like that.But you might consider writing IndieWeb.org-style bots (Atom+WebSub, and optionally WebMention if you want them to be interactive), and then using https://fed.brid.gy/ as an alternative to implementing ActivityPub yourself...', $data['data']['content']['text']);
$this->assertEquals('https://social.tinysubversions.com/users/darius/statuses/100471614681787834', $data['data']['in-reply-to'][0]);
$this->assertEquals('Jamey Sharp', $data['data']['author']['name']);
$this->assertEquals('https://s3-us-west-2.amazonaws.com/tootcatapril2017/accounts/avatars/000/013/259/original/c904452a8411e4f5.jpg', $data['data']['author']['photo']);
$this->assertEquals('https://toot.cat/@jamey', $data['data']['author']['url']);
}
}

+ 197
- 182
tests/AuthorTest.php View File

@ -2,186 +2,201 @@
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
class AuthorTest extends PHPUnit_Framework_TestCase {
private $http;
public function setUp() {
$this->client = new Parse();
$this->client->http = new p3k\HTTP\Test(dirname(__FILE__).'/data/');
$this->client->mc = null;
}
private function parse($params) {
$request = new Request($params);
$response = new Response();
return $this->client->parse($request, $response);
}
public function testHEntryAuthorIsName() {
$url = 'http://author.example.com/h-entry-author-is-name';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertEquals('mf2+html', $data->{'source-format'});
$this->assertEmpty($data->data->author->url);
$this->assertEquals('Author Name', $data->data->author->name);
$this->assertEmpty($data->data->author->photo);
}
public function testHEntryAuthorIsRelLinkToHCardOnPage() {
$url = 'http://author.example.com/h-entry-author-is-rel-link-to-h-card-on-page';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertEquals('http://author.example.com/about', $data->data->author->url);
$this->assertEquals('Author', $data->data->author->name);
$this->assertEquals('http://author.example.com/photo.jpg', $data->data->author->photo);
}
public function testHEntryAuthorIsRelLinkToHCardWithRelMe() {
$url = 'http://author.example.com/h-entry-author-is-rel-link-to-h-card-with-rel-me';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertEquals('http://author.example.com/about-rel-me', $data->data->author->url);
$this->assertEquals('Author Full Name', $data->data->author->name);
$this->assertEquals('http://author.example.com/photo.jpg', $data->data->author->photo);
}
public function testHEntryAuthorIsRelLinkToHCardWithUrlUid() {
$url = 'http://author.example.com/h-entry-author-is-rel-link-to-h-card-with-url-uid';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertEquals('http://author.example.com/about-url-uid', $data->data->author->url);
$this->assertEquals('Author Full Name', $data->data->author->name);
$this->assertEquals('http://author.example.com/photo.jpg', $data->data->author->photo);
}
public function testHEntryAuthorIsUrlToHCardOnPage() {
$url = 'http://author.example.com/h-entry-author-is-url-to-h-card-on-page';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertEquals('http://author.example.com/about', $data->data->author->url);
$this->assertEquals('Author', $data->data->author->name);
$this->assertEquals('http://author.example.com/photo.jpg', $data->data->author->photo);
}
public function testHEntryAuthorIsUrlToHCardWithMultipleLinks() {
$url = 'http://author.example.com/h-entry-author-is-url-to-h-card-with-multiple-links';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertEquals('http://author.example.com/about-with-multiple-urls', $data->data->author->url);
$this->assertEquals('Author Full Name', $data->data->author->name);
$this->assertEquals('http://author.example.com/photo.jpg', $data->data->author->photo);
}
public function testHEntryAuthorIsUrlToHCardWithNoURL() {
$url = 'http://author.example.com/h-entry-author-is-url-to-h-card-with-no-url';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertEquals('http://author.example.com/about-no-url', $data->data->author->url);
$this->assertEquals('Author Full Name', $data->data->author->name);
$this->assertEquals('http://author.example.com/photo.jpg', $data->data->author->photo);
}
public function testHEntryHasHCardAndUrlAuthor() {
$url = 'http://author.example.com/h-entry-has-h-card-and-url-author';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertEquals('http://author.example.com/about', $data->data->author->url);
$this->assertEquals('Author', $data->data->author->name);
$this->assertEquals('http://author.example.com/photo.jpg', $data->data->author->photo);
}
public function testHEntryHasHCardAuthor() {
$url = 'http://author.example.com/h-entry-has-h-card-author';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertEquals('http://author.example.com/about', $data->data->author->url);
$this->assertEquals('Author', $data->data->author->name);
$this->assertEquals('http://author.example.com/photo.jpg', $data->data->author->photo);
}
public function testPageIsHCard() {
$url = 'http://author.example.com/about';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertEquals('card', $data->data->type);
$this->assertEquals('http://author.example.com/about', $data->data->url);
$this->assertEquals('Author Full Name', $data->data->name);
$this->assertEquals('http://author.example.com/photo.jpg', $data->data->photo);
}
public function testPageIsHCardWithNoURL() {
$url = 'http://author.example.com/about-no-url';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertEquals('card', $data->data->type);
$this->assertEquals('Author Full Name', $data->data->name);
$this->assertEquals($url, $data->data->url);
$this->assertEquals('http://author.example.com/photo.jpg', $data->data->photo);
}
public function testHEntryAuthorIs0() {
$url = 'http://author.example.com/author-name-is-0';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertEquals('card', $data->data->type);
$this->assertEquals('http://author.example.com/photo.jpg', $data->data->photo);
$this->assertEquals('0', $data->data->name);
}
/*
public function testHFeedHasHCardAuthor() {
class AuthorTest extends PHPUnit\Framework\TestCase
{
private $http;
public function setUp(): void
{
$this->client = new Parse();
$this->client->http = new p3k\HTTP\Test(dirname(__FILE__).'/data/');
$this->client->mc = null;
}
private function parse($params)
{
$request = new Request($params);
$response = new Response();
return $this->client->parse($request, $response);
}
public function testHEntryAuthorIsName()
{
$url = 'http://author.example.com/h-entry-author-is-name';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertEquals('mf2+html', $data->{'source-format'});
$this->assertEmpty($data->data->author->url);
$this->assertEquals('Author Name', $data->data->author->name);
$this->assertEmpty($data->data->author->photo);
}
public function testHEntryAuthorIsRelLinkToHCardOnPage()
{
$url = 'http://author.example.com/h-entry-author-is-rel-link-to-h-card-on-page';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertEquals('http://author.example.com/about', $data->data->author->url);
$this->assertEquals('Author', $data->data->author->name);
$this->assertEquals('http://author.example.com/photo.jpg', $data->data->author->photo);
}
public function testHEntryAuthorIsRelLinkToHCardWithRelMe()
{
$url = 'http://author.example.com/h-entry-author-is-rel-link-to-h-card-with-rel-me';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertEquals('http://author.example.com/about-rel-me', $data->data->author->url);
$this->assertEquals('Author Full Name', $data->data->author->name);
$this->assertEquals('http://author.example.com/photo.jpg', $data->data->author->photo);
}
public function testHEntryAuthorIsRelLinkToHCardWithUrlUid()
{
$url = 'http://author.example.com/h-entry-author-is-rel-link-to-h-card-with-url-uid';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertEquals('http://author.example.com/about-url-uid', $data->data->author->url);
$this->assertEquals('Author Full Name', $data->data->author->name);
$this->assertEquals('http://author.example.com/photo.jpg', $data->data->author->photo);
}
public function testHEntryAuthorIsUrlToHCardOnPage()
{
$url = 'http://author.example.com/h-entry-author-is-url-to-h-card-on-page';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertEquals('http://author.example.com/about', $data->data->author->url);
$this->assertEquals('Author', $data->data->author->name);
$this->assertEquals('http://author.example.com/photo.jpg', $data->data->author->photo);
}
public function testHEntryAuthorIsUrlToHCardWithMultipleLinks()
{
$url = 'http://author.example.com/h-entry-author-is-url-to-h-card-with-multiple-links';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertEquals('http://author.example.com/about-with-multiple-urls', $data->data->author->url);
$this->assertEquals('Author Full Name', $data->data->author->name);
$this->assertEquals('http://author.example.com/photo.jpg', $data->data->author->photo);
}
public function testHEntryAuthorIsUrlToHCardWithNoURL()
{
$url = 'http://author.example.com/h-entry-author-is-url-to-h-card-with-no-url';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertEquals('http://author.example.com/about-no-url', $data->data->author->url);
$this->assertEquals('Author Full Name', $data->data->author->name);
$this->assertEquals('http://author.example.com/photo.jpg', $data->data->author->photo);
}
public function testHEntryHasHCardAndUrlAuthor()
{
$url = 'http://author.example.com/h-entry-has-h-card-and-url-author';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertEquals('http://author.example.com/about', $data->data->author->url);
$this->assertEquals('Author', $data->data->author->name);
$this->assertEquals('http://author.example.com/photo.jpg', $data->data->author->photo);
}
public function testHEntryHasHCardAuthor()
{
$url = 'http://author.example.com/h-entry-has-h-card-author';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertEquals('http://author.example.com/about', $data->data->author->url);
$this->assertEquals('Author', $data->data->author->name);
$this->assertEquals('http://author.example.com/photo.jpg', $data->data->author->photo);
}
public function testPageIsHCard()
{
$url = 'http://author.example.com/about';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertEquals('card', $data->data->type);
$this->assertEquals('http://author.example.com/about', $data->data->url);
$this->assertEquals('Author Full Name', $data->data->name);
$this->assertEquals('http://author.example.com/photo.jpg', $data->data->photo);
}
public function testPageIsHCardWithNoURL()
{
$url = 'http://author.example.com/about-no-url';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertEquals('card', $data->data->type);
$this->assertEquals('Author Full Name', $data->data->name);
$this->assertEquals($url, $data->data->url);
$this->assertEquals('http://author.example.com/photo.jpg', $data->data->photo);
}
public function testHEntryAuthorIs0()
{
$url = 'http://author.example.com/author-name-is-0';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertEquals('card', $data->data->type);
$this->assertEquals('http://author.example.com/photo.jpg', $data->data->photo);
$this->assertEquals('0', $data->data->name);
}
/*
public function testHFeedHasHCardAuthor() {
$url = 'http://author.example.com/h-feed-has-h-card-author';
$response = $this->parse(['url' => $url]);
@ -192,7 +207,7 @@ class AuthorTest extends PHPUnit_Framework_TestCase {
$this->assertEquals('http://author.example.com/about', $data->data->author->url);
$this->assertEquals('Author', $data->data->author->name);
$this->assertEquals('http://author.example.com/photo.jpg', $data->data->author->photo);
}
*/
}
*/
}

+ 0
- 75
tests/FacebookTest.php View File

@ -1,75 +0,0 @@
<?php
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
class FacebookTest extends PHPUnit_Framework_TestCase {
private $http;
public function setUp() {
$this->client = new Parse();
$this->client->mc = null;
}
private function parse($params) {
$request = new Request($params);
$response = new Response();
$result = $this->client->parse($request, $response);
$body = $result->getContent();
$this->assertEquals(200, $result->getStatusCode());
return json_decode($body, true);
}
private function loadFbObject($id) {
return file_get_contents(dirname(__FILE__).'/data/graph.facebook.com/'.$id.'.json');
}
public function testFacebookEventWithHCard() {
$url = 'https://www.facebook.com/events/446197069049722/';
$json = $this->loadFbObject('446197069049722');
$data = $this->parse(['url' => $url, 'body' => $json]);
$this->assertArrayHasKey('code', $data);
$this->assertEquals('facebook', $data['source-format']);
$this->assertEquals('event', $data['data']['type']);
$this->assertEquals('event', $data['data']['post-type']);
$this->assertEquals('IndieWeb Summit', $data['data']['name']);
$this->assertEquals('2017-06-24T09:00:00-0700', $data['data']['start']);
$this->assertEquals('2017-06-25T18:00:00-0700', $data['data']['end']);
$this->assertContains('The seventh annual gathering for independent web creators of all kinds,', $data['data']['summary']);
$this->assertEquals('https://facebook.com/332204056925945', $data['data']['location']);
$card = $data['data']['refs'][0];
$this->assertEquals('card', $card['type']);
$this->assertEquals('https://facebook.com/332204056925945', $card['url']);
$this->assertEquals('Mozilla PDX', $card['name']);
$this->assertEquals('97209', $card['postal-code']);
$this->assertEquals('Portland', $card['locality']);
$this->assertEquals('OR', $card['region']);
$this->assertEquals('1120 NW Couch St, Ste 320', $card['street-address']);
$this->assertEquals('United States', $card['country']);
$this->assertEquals('45.5233192', $card['latitude']);
$this->assertEquals('-122.6824722', $card['longitude']);
}
public function testFacebookEvent() {
$url = 'https://www.facebook.com/events/1596554663924436/';
$json = $this->loadFbObject('1596554663924436');
$data = $this->parse(['url' => $url, 'body' => $json]);
$this->assertArrayHasKey('code', $data);
$this->assertEquals('facebook', $data['source-format']);
$this->assertEquals('event', $data['data']['type']);
$this->assertEquals('event', $data['data']['post-type']);
$this->assertEquals('Homebrew Website Club', $data['data']['name']);
$this->assertEquals('2015-04-22T19:00:00-0400', $data['data']['start']);
$this->assertContains('Are you building your own website? Indie reader?', $data['data']['summary']);
$this->assertEquals('Charging Bull - WeeWork - 25 Broadway, New York, NY 10004', $data['data']['location']);
}
}

+ 523
- 493
tests/FeedTest.php
File diff suppressed because it is too large
View File


+ 227
- 188
tests/FetchTest.php View File

@ -2,192 +2,231 @@
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
class FetchTest extends PHPUnit_Framework_TestCase {
private $http;
public function setUp() {
$this->client = new Parse();
$this->client->http = new p3k\HTTP\Test(dirname(__FILE__).'/data/');
$this->client->mc = null;
}
private function parse($params) {
$request = new Request($params);
$response = new Response();
return $this->client->parse($request, $response);
}
public function testRedirectLimit() {
$url = 'http://redirect.example.com/3';
$response = $this->parse([
'url' => $url,
'max_redirects' => 1
]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertObjectHasAttribute('error', $data);
$this->assertEquals('too_many_redirects', $data->error);
$url = 'http://redirect.example.com/2';
$response = $this->parse([
'url' => $url,
'max_redirects' => 1
]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertObjectHasAttribute('error', $data);
$this->assertEquals('too_many_redirects', $data->error);
}
public function testRedirectUnderLimit() {
$url = 'http://redirect.example.com/2';
$response = $this->parse([
'url' => $url,
'max_redirects' => 2
]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertObjectNotHasAttribute('error', $data);
$this->assertEquals(200, $data->code);
$this->assertEquals('The Final Page', $data->data->name);
$this->assertEquals('http://redirect.example.com/0', $data->url);
}
public function testReturnsHTTPStatusCode() {
$url = 'http://redirect.example.com/code-418';
$response = $this->parse([
'url' => $url
]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertObjectNotHasAttribute('error', $data);
$this->assertEquals($url, $data->url);
$this->assertEquals(418, $data->code);
}
public function testReturnsForbidden() {
$url = 'http://redirect.example.com/code-403';
$response = $this->parse([
'url' => $url
]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertObjectHasAttribute('error', $data);
$this->assertEquals('forbidden', $data->error);
$this->assertEquals($url, $data->url);
$this->assertEquals(403, $data->code);
}
public function testReturnsUnauthorized() {
$url = 'http://redirect.example.com/code-401';
$response = $this->parse([
'url' => $url
]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertObjectHasAttribute('error', $data);
$this->assertEquals('unauthorized', $data->error);
$this->assertEquals($url, $data->url);
$this->assertEquals(401, $data->code);
}
public function testDeleted() {
$url = 'http://source.example.com/deleted-gone';
$response = $this->parse([
'url' => $url
]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertObjectNotHasAttribute('error', $data);
$this->assertEquals(410, $data->code);
$this->assertEquals('This post has been deleted.', $data->data->content->text);
}
public function testDeletedEmptyBody() {
$url = 'http://source.example.com/deleted-empty';
$response = $this->parse([
'url' => $url
]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertObjectNotHasAttribute('error', $data);
$this->assertEquals(410, $data->code);
$this->assertEquals('unknown', $data->data->type);
}
public function testDeletedTargetProvided() {
$url = 'http://source.example.com/deleted-gone';
$response = $this->parse([
'url' => $url,
'target' => 'http://example.com/'
]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertObjectHasAttribute('error', $data);
$this->assertEquals('no_link_found', $data->error);
$this->assertEquals(410, $data->code);
}
public function testMetaEquivDeleted() {
$url = 'http://source.example.com/deleted';
$response = $this->parse([
'url' => $url
]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertObjectNotHasAttribute('error', $data);
$this->assertEquals(410, $data->code);
$this->assertEquals('This post has been deleted.', $data->data->content->text);
}
public function testMetaEquivDeletedCaps() {
$url = 'http://source.example.com/deleted-2';
$response = $this->parse([
'url' => $url
]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertObjectNotHasAttribute('error', $data);
$this->assertEquals(410, $data->code);
$this->assertEquals('This post has been deleted.', $data->data->content->text);
}
public function testMetaEquivDeletedTargetProvided() {
// for example when verifying a webmention but the source was replaced with an html deleted page
$url = 'http://source.example.com/deleted';
$response = $this->parse([
'url' => $url,
'target' => 'http://example.com/'
]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertObjectHasAttribute('error', $data);
$this->assertEquals('no_link_found', $data->error);
$this->assertEquals(410, $data->code);
}
class FetchTest extends PHPUnit\Framework\TestCase
{
private $http;
public function setUp(): void
{
$this->client = new Parse();
$this->client->http = new p3k\HTTP\Test(dirname(__FILE__).'/data/');
$this->client->mc = null;
}
private function parse($params)
{
$request = new Request($params);
$response = new Response();
return $this->client->parse($request, $response);
}
public function testRedirectLimit()
{
$url = 'http://redirect.example.com/3';
$response = $this->parse(
[
'url' => $url,
'max_redirects' => 1
]
);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertObjectHasAttribute('error', $data);
$this->assertEquals('too_many_redirects', $data->error);
$url = 'http://redirect.example.com/2';
$response = $this->parse(
[
'url' => $url,
'max_redirects' => 1
]
);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertObjectHasAttribute('error', $data);
$this->assertEquals('too_many_redirects', $data->error);
}
public function testRedirectUnderLimit()
{
$url = 'http://redirect.example.com/2';
$response = $this->parse(
[
'url' => $url,
'max_redirects' => 2
]
);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertObjectNotHasAttribute('error', $data);
$this->assertEquals(200, $data->code);
$this->assertEquals('The Final Page', $data->data->name);
$this->assertEquals('http://redirect.example.com/0', $data->url);
}
public function testReturnsHTTPStatusCode()
{
$url = 'http://redirect.example.com/code-418';
$response = $this->parse(
[
'url' => $url
]
);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertObjectNotHasAttribute('error', $data);
$this->assertEquals($url, $data->url);
$this->assertEquals(418, $data->code);
}
public function testReturnsForbidden()
{
$url = 'http://redirect.example.com/code-403';
$response = $this->parse(
[
'url' => $url
]
);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertObjectHasAttribute('error', $data);
$this->assertEquals('forbidden', $data->error);
$this->assertEquals($url, $data->url);
$this->assertEquals(403, $data->code);
}
public function testReturnsUnauthorized()
{
$url = 'http://redirect.example.com/code-401';
$response = $this->parse(
[
'url' => $url
]
);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertObjectHasAttribute('error', $data);
$this->assertEquals('unauthorized', $data->error);
$this->assertEquals($url, $data->url);
$this->assertEquals(401, $data->code);
}
public function testDeleted()
{
$url = 'http://source.example.com/deleted-gone';
$response = $this->parse(
[
'url' => $url
]
);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertObjectNotHasAttribute('error', $data);
$this->assertEquals(410, $data->code);
$this->assertEquals('This post has been deleted.', $data->data->content->text);
}
public function testDeletedEmptyBody()
{
$url = 'http://source.example.com/deleted-empty';
$response = $this->parse(
[
'url' => $url
]
);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertObjectNotHasAttribute('error', $data);
$this->assertEquals(410, $data->code);
$this->assertEquals('unknown', $data->data->type);
}
public function testDeletedTargetProvided()
{
$url = 'http://source.example.com/deleted-gone';
$response = $this->parse(
[
'url' => $url,
'target' => 'http://example.com/'
]
);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertObjectHasAttribute('error', $data);
$this->assertEquals('no_link_found', $data->error);
$this->assertEquals(410, $data->code);
}
public function testMetaEquivDeleted()
{
$url = 'http://source.example.com/deleted';
$response = $this->parse(
[
'url' => $url
]
);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertObjectNotHasAttribute('error', $data);
$this->assertEquals(410, $data->code);
$this->assertEquals('This post has been deleted.', $data->data->content->text);
}
public function testMetaEquivDeletedCaps()
{
$url = 'http://source.example.com/deleted-2';
$response = $this->parse(
[
'url' => $url
]
);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertObjectNotHasAttribute('error', $data);
$this->assertEquals(410, $data->code);
$this->assertEquals('This post has been deleted.', $data->data->content->text);
}
public function testMetaEquivDeletedTargetProvided()
{
// for example when verifying a webmention but the source was replaced with an html deleted page
$url = 'http://source.example.com/deleted';
$response = $this->parse(
[
'url' => $url,
'target' => 'http://example.com/'
]
);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertObjectHasAttribute('error', $data);
$this->assertEquals('no_link_found', $data->error);
$this->assertEquals(410, $data->code);
}
}

+ 27
- 22
tests/FetchTestDisabled.php View File

@ -2,32 +2,37 @@
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
class FetchTest extends PHPUnit_Framework_TestCase {
class FetchTest extends PHPUnit\Framework\TestCase
{
private $http;
private $http;
public function setUp() {
$this->http = new p3k\HTTP();
}
public function setUp(): void
{
$this->http = new p3k\HTTP();
}
public function testTimeout() {
$url = 'https://nghttp2.org/httpbin/delay/2';
$this->http->timeout = 1;
$response = $this->http->get($url);
$this->assertEquals('timeout', $response['error']);
}
public function testTimeout()
{
$url = 'https://nghttp2.org/httpbin/delay/2';
$this->http->timeout = 1;
$response = $this->http->get($url);
$this->assertEquals('timeout', $response['error']);
}
public function testRedirectLimit() {
$url = 'https://nghttp2.org/httpbin/redirect/3';
$this->http->max_redirects = 1;
$response = $this->http->get($url);
$this->assertEquals('too_many_redirects', $response['error']);
}
public function testRedirectLimit()
{
$url = 'https://nghttp2.org/httpbin/redirect/3';
$this->http->max_redirects = 1;
$response = $this->http->get($url);
$this->assertEquals('too_many_redirects', $response['error']);
}
public function testNoError() {
$url = 'https://nghttp2.org/httpbin/ip';
$response = $this->http->get($url);
$this->assertEquals('', $response['error']);
}
public function testNoError()
{
$url = 'https://nghttp2.org/httpbin/ip';
$response = $this->http->get($url);
$this->assertEquals('', $response['error']);
}
}

+ 234
- 217
tests/FindFeedsTest.php View File

@ -2,221 +2,238 @@
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
class FindFeedsTest extends PHPUnit_Framework_TestCase {
private $http;
public function setUp() {
$this->client = new Feeds();
$this->client->http = new p3k\HTTP\Test(dirname(__FILE__).'/data/');
$this->client->mc = null;
}
private function parse($params) {
$request = new Request($params);
$response = new Response();
return $this->client->find($request, $response);
}
// h-feed with no alternates
public function testMf2HFeed() {
$url = 'http://feed.example.com/h-feed-with-child-author';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$feeds = json_decode($body)->feeds;
$this->assertEquals(1, count($feeds));
$this->assertEquals('http://feed.example.com/h-feed-with-child-author', $feeds[0]->url);
$this->assertEquals('microformats', $feeds[0]->type);
}
// h-feed that links to Atom alternate
public function testMf2WithAtomAlternate() {
$url = 'http://feed.example.com/h-feed-with-atom-alternate';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$feeds = json_decode($body)->feeds;
$this->assertEquals(2, count($feeds));
// Should rank h-feed above Atom
$this->assertEquals('http://feed.example.com/h-feed-with-atom-alternate', $feeds[0]->url);
$this->assertEquals('microformats', $feeds[0]->type);
$this->assertEquals('http://feed.example.com/atom', $feeds[1]->url);
$this->assertEquals('atom', $feeds[1]->type);
}
// h-feed that links to RSS alternate
public function testMf2WithRSSAlternate() {
$url = 'http://feed.example.com/h-feed-with-rss-alternate';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$feeds = json_decode($body)->feeds;
$this->assertEquals(2, count($feeds));
// Should rank JSONFeed above Atom
$this->assertEquals('http://feed.example.com/h-feed-with-rss-alternate', $feeds[0]->url);
$this->assertEquals('microformats', $feeds[0]->type);
$this->assertEquals('http://feed.example.com/podcast.xml', $feeds[1]->url);
$this->assertEquals('rss', $feeds[1]->type);
}
// No mf2 but links to Atom alternate
public function testNoMf2() {
$url = 'http://feed.example.com/html-with-atom-alternate';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$feeds = json_decode($body)->feeds;
$this->assertEquals(1, count($feeds));
$this->assertEquals('http://feed.example.com/atom', $feeds[0]->url);
$this->assertEquals('atom', $feeds[0]->type);
}
public function testNoMf2WithJSONAndAtom() {
$url = 'http://feed.example.com/html-with-json-and-atom';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$feeds = json_decode($body)->feeds;
$this->assertEquals(2, count($feeds));
// Should rank JSONFeed above Atom
$this->assertEquals('http://feed.example.com/jsonfeed', $feeds[0]->url);
$this->assertEquals('jsonfeed', $feeds[0]->type);
$this->assertEquals('http://feed.example.com/atom', $feeds[1]->url);
$this->assertEquals('atom', $feeds[1]->type);
}
// input URL is an Atom feed
public function testInputIsAtom() {
$url = 'http://feed.example.com/atom';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$feeds = json_decode($body)->feeds;
$this->assertEquals(1, count($feeds));
$this->assertEquals('http://feed.example.com/atom', $feeds[0]->url);
$this->assertEquals('atom', $feeds[0]->type);
}
// input URL is an RSS feed with xml content type
public function testInputIsRSSWithXML() {
$url = 'http://feed.example.com/rss-xml-content-type';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$feeds = json_decode($body)->feeds;
$this->assertEquals(1, count($feeds));
$this->assertEquals('http://feed.example.com/rss-xml-content-type', $feeds[0]->url);
$this->assertEquals('rss', $feeds[0]->type);
}
// input URL redirects to an Atom feed
public function testInputIsRedirectToAtom() {
$url = 'http://feed.example.com/redirect-to-atom';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$feeds = json_decode($body)->feeds;
$this->assertEquals(1, count($feeds));
$this->assertEquals('http://feed.example.com/atom', $feeds[0]->url);
$this->assertEquals('atom', $feeds[0]->type);
}
// input URL is a temporary redirect to another page.
// report the original input URL
public function testInputIsTemporaryRedirect() {
$url = 'http://feed.example.com/temporary-redirect';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$feeds = json_decode($body)->feeds;
$this->assertEquals(1, count($feeds));
$this->assertEquals('http://feed.example.com/temporary-redirect', $feeds[0]->url);
$this->assertEquals('microformats', $feeds[0]->type);
}
public function testInputIsPermanentRedirect() {
$url = 'http://feed.example.com/permanent-redirect';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$feeds = json_decode($body)->feeds;
$this->assertEquals(1, count($feeds));
$this->assertEquals('http://feed.example.com/permanent-redirect-target', $feeds[0]->url);
$this->assertEquals('microformats', $feeds[0]->type);
}
// input URL is an RSS feed
public function testInputIsRSS() {
$url = 'http://feed.example.com/rss';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$feeds = json_decode($body)->feeds;
$this->assertEquals(1, count($feeds));
$this->assertEquals('http://feed.example.com/rss', $feeds[0]->url);
$this->assertEquals('rss', $feeds[0]->type);
}
// input URL is a JSON feed
public function testInputIsJSONFeed() {
$url = 'http://feed.example.com/jsonfeed';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$feeds = json_decode($body)->feeds;
$this->assertEquals(1, count($feeds));
$this->assertEquals('http://feed.example.com/jsonfeed', $feeds[0]->url);
$this->assertEquals('jsonfeed', $feeds[0]->type);
}
public function testInputIsMicroformats2JSON() {
$url = 'http://feed.example.com/microformats2-json';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$feeds = json_decode($body)->feeds;
$this->assertEquals(1, count($feeds));
$this->assertEquals('http://feed.example.com/microformats2-json', $feeds[0]->url);
$this->assertEquals('microformats', $feeds[0]->type);
}
public function testInputIsMF2JSON() {
$url = 'http://feed.example.com/mf2-json';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$feeds = json_decode($body)->feeds;
$this->assertEquals(1, count($feeds));
$this->assertEquals('http://feed.example.com/mf2-json', $feeds[0]->url);
$this->assertEquals('microformats', $feeds[0]->type);
}
class FindFeedsTest extends PHPUnit\Framework\TestCase
{
private $http;
public function setUp(): void
{
$this->client = new Feeds();
$this->client->http = new p3k\HTTP\Test(dirname(__FILE__).'/data/');
$this->client->mc = null;
}
private function parse($params)
{
$request = new Request($params);
$response = new Response();
return $this->client->find($request, $response);
}
// h-feed with no alternates
public function testMf2HFeed()
{
$url = 'http://feed.example.com/h-feed-with-child-author';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$feeds = json_decode($body)->feeds;
$this->assertEquals(1, count($feeds));
$this->assertEquals('http://feed.example.com/h-feed-with-child-author', $feeds[0]->url);
$this->assertEquals('microformats', $feeds[0]->type);
}
// h-feed that links to Atom alternate
public function testMf2WithAtomAlternate()
{
$url = 'http://feed.example.com/h-feed-with-atom-alternate';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$feeds = json_decode($body)->feeds;
$this->assertEquals(2, count($feeds));
// Should rank h-feed above Atom
$this->assertEquals('http://feed.example.com/h-feed-with-atom-alternate', $feeds[0]->url);
$this->assertEquals('microformats', $feeds[0]->type);
$this->assertEquals('http://feed.example.com/atom', $feeds[1]->url);
$this->assertEquals('atom', $feeds[1]->type);
}
// h-feed that links to RSS alternate
public function testMf2WithRSSAlternate()
{
$url = 'http://feed.example.com/h-feed-with-rss-alternate';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$feeds = json_decode($body)->feeds;
$this->assertEquals(2, count($feeds));
// Should rank JSONFeed above Atom
$this->assertEquals('http://feed.example.com/h-feed-with-rss-alternate', $feeds[0]->url);
$this->assertEquals('microformats', $feeds[0]->type);
$this->assertEquals('http://feed.example.com/podcast.xml', $feeds[1]->url);
$this->assertEquals('rss', $feeds[1]->type);
}
// No mf2 but links to Atom alternate
public function testNoMf2()
{
$url = 'http://feed.example.com/html-with-atom-alternate';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$feeds = json_decode($body)->feeds;
$this->assertEquals(1, count($feeds));
$this->assertEquals('http://feed.example.com/atom', $feeds[0]->url);
$this->assertEquals('atom', $feeds[0]->type);
}
public function testNoMf2WithJSONAndAtom()
{
$url = 'http://feed.example.com/html-with-json-and-atom';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$feeds = json_decode($body)->feeds;
$this->assertEquals(2, count($feeds));
// Should rank JSONFeed above Atom
$this->assertEquals('http://feed.example.com/jsonfeed', $feeds[0]->url);
$this->assertEquals('jsonfeed', $feeds[0]->type);
$this->assertEquals('http://feed.example.com/atom', $feeds[1]->url);
$this->assertEquals('atom', $feeds[1]->type);
}
// input URL is an Atom feed
public function testInputIsAtom()
{
$url = 'http://feed.example.com/atom';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$feeds = json_decode($body)->feeds;
$this->assertEquals(1, count($feeds));
$this->assertEquals('http://feed.example.com/atom', $feeds[0]->url);
$this->assertEquals('atom', $feeds[0]->type);
}
// input URL is an RSS feed with xml content type
public function testInputIsRSSWithXML()
{
$url = 'http://feed.example.com/rss-xml-content-type';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$feeds = json_decode($body)->feeds;
$this->assertEquals(1, count($feeds));
$this->assertEquals('http://feed.example.com/rss-xml-content-type', $feeds[0]->url);
$this->assertEquals('rss', $feeds[0]->type);
}
// input URL redirects to an Atom feed
public function testInputIsRedirectToAtom()
{
$url = 'http://feed.example.com/redirect-to-atom';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$feeds = json_decode($body)->feeds;
$this->assertEquals(1, count($feeds));
$this->assertEquals('http://feed.example.com/atom', $feeds[0]->url);
$this->assertEquals('atom', $feeds[0]->type);
}
// input URL is a temporary redirect to another page.
// report the original input URL
public function testInputIsTemporaryRedirect()
{
$url = 'http://feed.example.com/temporary-redirect';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$feeds = json_decode($body)->feeds;
$this->assertEquals(1, count($feeds));
$this->assertEquals('http://feed.example.com/temporary-redirect', $feeds[0]->url);
$this->assertEquals('microformats', $feeds[0]->type);
}
public function testInputIsPermanentRedirect()
{
$url = 'http://feed.example.com/permanent-redirect';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$feeds = json_decode($body)->feeds;
$this->assertEquals(1, count($feeds));
$this->assertEquals('http://feed.example.com/permanent-redirect-target', $feeds[0]->url);
$this->assertEquals('microformats', $feeds[0]->type);
}
// input URL is an RSS feed
public function testInputIsRSS()
{
$url = 'http://feed.example.com/rss';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$feeds = json_decode($body)->feeds;
$this->assertEquals(1, count($feeds));
$this->assertEquals('http://feed.example.com/rss', $feeds[0]->url);
$this->assertEquals('rss', $feeds[0]->type);
}
// input URL is a JSON feed
public function testInputIsJSONFeed()
{
$url = 'http://feed.example.com/jsonfeed';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$feeds = json_decode($body)->feeds;
$this->assertEquals(1, count($feeds));
$this->assertEquals('http://feed.example.com/jsonfeed', $feeds[0]->url);
$this->assertEquals('jsonfeed', $feeds[0]->type);
}
public function testInputIsMicroformats2JSON()
{
$url = 'http://feed.example.com/microformats2-json';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$feeds = json_decode($body)->feeds;
$this->assertEquals(1, count($feeds));
$this->assertEquals('http://feed.example.com/microformats2-json', $feeds[0]->url);
$this->assertEquals('microformats', $feeds[0]->type);
}
public function testInputIsMF2JSON()
{
$url = 'http://feed.example.com/mf2-json';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$feeds = json_decode($body)->feeds;
$this->assertEquals(1, count($feeds));
$this->assertEquals('http://feed.example.com/mf2-json', $feeds[0]->url);
$this->assertEquals('microformats', $feeds[0]->type);
}
}

+ 132
- 124
tests/GitHubTest.php View File

@ -2,130 +2,138 @@
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
class GitHubTest extends PHPUnit_Framework_TestCase {
private $http;
public function setUp() {
$this->client = new Parse();
$this->client->http = new p3k\HTTP\Test(dirname(__FILE__).'/data/');
$this->client->mc = null;
}
private function parse($params) {
$request = new Request($params);
$response = new Response();
return $this->client->parse($request, $response);
}
public function testGitHubPull() {
// Original URL: https://github.com/idno/Known/pull/1690
$url = 'https://github.com/idno/Known/pull/1690';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$this->assertEquals(200, $data['code']);
$this->assertEquals('github', $data['source-format']);
$this->assertEquals('entry', $data['data']['type']);
$this->assertEquals('reply', $data['data']['post-type']);
$this->assertEquals('https://github.com/idno/Known', $data['data']['in-reply-to'][0]);
$this->assertEquals('2017-04-10T17:44:57Z', $data['data']['published']);
$this->assertEquals('aaronpk', $data['data']['author']['name']);
$this->assertEquals('https://github.com/aaronpk', $data['data']['author']['url']);
$this->assertEquals('https://avatars2.githubusercontent.com/u/113001?v=3', $data['data']['author']['photo']);
$this->assertEquals('#1690 fixes bookmark Microformats markup', $data['data']['name']);
$this->assertContains('<h2>Here\'s what I fixed or added:</h2>', $data['data']['content']['html']);
$this->assertContains('## Here\'s what I fixed or added:', $data['data']['content']['text']);
}
public function testGitHubIssue() {
$url = 'https://github.com/aaronpk/XRay/issues/25';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$this->assertEquals(200, $data['code']);
$this->assertEquals('github', $data['source-format']);
$this->assertEquals('entry', $data['data']['type']);
$this->assertEquals('reply', $data['data']['post-type']);
$this->assertEquals('https://github.com/aaronpk/XRay/issues', $data['data']['in-reply-to'][0]);
$this->assertEquals('2017-01-26T14:13:42Z', $data['data']['published']);
$this->assertEquals('sebsel', $data['data']['author']['name']);
$this->assertEquals('https://github.com/sebsel', $data['data']['author']['url']);
$this->assertEquals('https://avatars3.githubusercontent.com/u/16517999?v=3', $data['data']['author']['photo']);
$this->assertEquals('#25 Post type discovery', $data['data']['name']);
$this->assertContains('<blockquote>', $data['data']['content']['html']);
$this->assertContains('<a href="https://www.w3.org/TR/post-type-discovery/">', $data['data']['content']['html']);
$this->assertContains('> sebsel', $data['data']['content']['text']);
}
public function testGitHubIssueWithCategory() {
$url = 'https://github.com/aaronpk/XRay/issues/20';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$this->assertEquals(200, $data['code']);
$this->assertEquals('github', $data['source-format']);
$this->assertEquals('entry', $data['data']['type']);
$this->assertContains('silo', $data['data']['category']);
}
public function testGitHubRepo() {
$url = 'https://github.com/aaronpk/XRay';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$this->assertEquals(200, $data['code']);
$this->assertEquals('github', $data['source-format']);
$this->assertEquals('repo', $data['data']['type']);
$this->assertArrayNotHasKey('post-type', $data['data']);
$this->assertEquals('2016-02-19T16:53:20Z', $data['data']['published']);
$this->assertEquals('aaronpk', $data['data']['author']['name']);
$this->assertEquals('https://github.com/aaronpk', $data['data']['author']['url']);
$this->assertEquals('https://avatars2.githubusercontent.com/u/113001?v=3', $data['data']['author']['photo']);
$this->assertEquals('XRay', $data['data']['name']);
$this->assertEquals('X-Ray returns structured data from any URL', $data['data']['summary']);
}
public function testGitHubIssueComment() {
$url = 'https://github.com/aaronpk/XRay/issues/25#issuecomment-275433926';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$this->assertEquals(200, $data['code']);
$this->assertEquals('github', $data['source-format']);
$this->assertEquals('entry', $data['data']['type']);
$this->assertEquals('reply', $data['data']['post-type']);
$this->assertEquals('https://github.com/aaronpk/XRay/issues/25', $data['data']['in-reply-to'][0]);
$this->assertEquals('2017-01-26T16:24:37Z', $data['data']['published']);
$this->assertEquals('sebsel', $data['data']['author']['name']);
$this->assertEquals('https://avatars3.githubusercontent.com/u/16517999?v=3', $data['data']['author']['photo']);
$this->assertEquals('https://github.com/sebsel', $data['data']['author']['url']);
$this->assertContains('<p>Well it\'s just that php-comments does more than XRay does currently. But that\'s no good reason.</p>', $data['data']['content']['html']);
$this->assertContains('<code class="language-php">', $data['data']['content']['html']);
$this->assertContains('```php', $data['data']['content']['text']);
$this->assertNotContains('name', $data['data']);
$this->assertContains('https://github.com/aaronpk/XRay/issues/25', $data['data']['in-reply-to']);
}
class GitHubTest extends PHPUnit\Framework\TestCase
{
private $http;
public function setUp(): void
{
$this->client = new Parse();
$this->client->http = new p3k\HTTP\Test(dirname(__FILE__).'/data/');
$this->client->mc = null;
}
private function parse($params)
{
$request = new Request($params);
$response = new Response();
return $this->client->parse($request, $response);
}
public function testGitHubPull()
{
// Original URL: https://github.com/idno/Known/pull/1690
$url = 'https://github.com/idno/Known/pull/1690';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$this->assertEquals(200, $data['code']);
$this->assertEquals('github', $data['source-format']);
$this->assertEquals('entry', $data['data']['type']);
$this->assertEquals('reply', $data['data']['post-type']);
$this->assertEquals('https://github.com/idno/Known', $data['data']['in-reply-to'][0]);
$this->assertEquals('2017-04-10T17:44:57Z', $data['data']['published']);
$this->assertEquals('aaronpk', $data['data']['author']['name']);
$this->assertEquals('https://github.com/aaronpk', $data['data']['author']['url']);
$this->assertEquals('https://avatars2.githubusercontent.com/u/113001?v=3', $data['data']['author']['photo']);
$this->assertEquals('#1690 fixes bookmark Microformats markup', $data['data']['name']);
$this->assertStringContainsString('<h2>Here\'s what I fixed or added:</h2>', $data['data']['content']['html']);
$this->assertStringContainsString('## Here\'s what I fixed or added:', $data['data']['content']['text']);
}
public function testGitHubIssue()
{
$url = 'https://github.com/aaronpk/XRay/issues/25';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$this->assertEquals(200, $data['code']);
$this->assertEquals('github', $data['source-format']);
$this->assertEquals('entry', $data['data']['type']);
$this->assertEquals('reply', $data['data']['post-type']);
$this->assertEquals('https://github.com/aaronpk/XRay/issues', $data['data']['in-reply-to'][0]);
$this->assertEquals('2017-01-26T14:13:42Z', $data['data']['published']);
$this->assertEquals('sebsel', $data['data']['author']['name']);
$this->assertEquals('https://github.com/sebsel', $data['data']['author']['url']);
$this->assertEquals('https://avatars3.githubusercontent.com/u/16517999?v=3', $data['data']['author']['photo']);
$this->assertEquals('#25 Post type discovery', $data['data']['name']);
$this->assertStringContainsString('<blockquote>', $data['data']['content']['html']);
$this->assertStringContainsString('<a href="https://www.w3.org/TR/post-type-discovery/">', $data['data']['content']['html']);
$this->assertStringContainsString('> sebsel', $data['data']['content']['text']);
}
public function testGitHubIssueWithCategory()
{
$url = 'https://github.com/aaronpk/XRay/issues/20';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$this->assertEquals(200, $data['code']);
$this->assertEquals('github', $data['source-format']);
$this->assertEquals('entry', $data['data']['type']);
$this->assertContains('silo', $data['data']['category']);
}
public function testGitHubRepo()
{
$url = 'https://github.com/aaronpk/XRay';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$this->assertEquals(200, $data['code']);
$this->assertEquals('github', $data['source-format']);
$this->assertEquals('repo', $data['data']['type']);
$this->assertArrayNotHasKey('post-type', $data['data']);
$this->assertEquals('2016-02-19T16:53:20Z', $data['data']['published']);
$this->assertEquals('aaronpk', $data['data']['author']['name']);
$this->assertEquals('https://github.com/aaronpk', $data['data']['author']['url']);
$this->assertEquals('https://avatars2.githubusercontent.com/u/113001?v=3', $data['data']['author']['photo']);
$this->assertEquals('XRay', $data['data']['name']);
$this->assertEquals('X-Ray returns structured data from any URL', $data['data']['summary']);
}
public function testGitHubIssueComment()
{
$url = 'https://github.com/aaronpk/XRay/issues/25#issuecomment-275433926';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$this->assertEquals(200, $data['code']);
$this->assertEquals('github', $data['source-format']);
$this->assertEquals('entry', $data['data']['type']);
$this->assertEquals('reply', $data['data']['post-type']);
$this->assertEquals('https://github.com/aaronpk/XRay/issues/25', $data['data']['in-reply-to'][0]);
$this->assertEquals('2017-01-26T16:24:37Z', $data['data']['published']);
$this->assertEquals('sebsel', $data['data']['author']['name']);
$this->assertEquals('https://avatars3.githubusercontent.com/u/16517999?v=3', $data['data']['author']['photo']);
$this->assertEquals('https://github.com/sebsel', $data['data']['author']['url']);
$this->assertStringContainsString('<p>Well it\'s just that php-comments does more than XRay does currently. But that\'s no good reason.</p>', $data['data']['content']['html']);
$this->assertStringContainsString('<code class="language-php">', $data['data']['content']['html']);
$this->assertStringContainsString('```php', $data['data']['content']['text']);
$this->assertNotContains('name', $data['data']);
$this->assertContains('https://github.com/aaronpk/XRay/issues/25', $data['data']['in-reply-to']);
}
}

+ 61
- 50
tests/HackernewsTest.php View File

@ -2,76 +2,87 @@
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
class HackernewsTest extends PHPUnit_Framework_TestCase {
class HackernewsTest extends PHPUnit\Framework\TestCase
{
private $http;
private $http;
public function setUp() {
$this->client = new Parse();
$this->client->http = new p3k\HTTP\Test(dirname(__FILE__).'/data/');
$this->client->mc = null;
}
public function setUp(): void
{
$this->client = new Parse();
$this->client->http = new p3k\HTTP\Test(dirname(__FILE__).'/data/');
$this->client->mc = null;
}
private function parse($params) {
$request = new Request($params);
$response = new Response();
return $this->client->parse($request, $response);
}
private function parse($params)
{
$request = new Request($params);
$response = new Response();
return $this->client->parse($request, $response);
}
public function testSubmission() {
$url = 'https://news.ycombinator.com/item?id=14516538';
$response = $this->parse(['url' => $url]);
public function testSubmission()
{
$url = 'https://news.ycombinator.com/item?id=14516538';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$this->assertEquals(200, $data['code']);
$this->assertEquals('hackernews', $data['source-format']);
$this->assertEquals(200, $data['code']);
$this->assertEquals('hackernews', $data['source-format']);
$this->assertEquals('entry', $data['data']['type']);
$this->assertEquals('article', $data['data']['post-type']);
$this->assertEquals('2017-06-08T19:32:12+00:00', $data['data']['published']);
$this->assertEquals('vkb', $data['data']['author']['name']);
$this->assertEquals('https://news.ycombinator.com/user?id=vkb', $data['data']['author']['url']);
$this->assertEquals('What are we doing about Facebook, Google, and the closed internet?', $data['data']['name']);
$this->assertEquals('There have been many, many posts about how toxic advertising and Facebook are (I\'ve written many myself[1][2][3]) for our internet ecosystem today.<p>What projects or companies are you working on to combat filter bubbles, walled gardens, emotional manipulation, and the like, and how can the HN community help you in your goals?</p><p>[1]http://veekaybee.github.io/facebook-is-collecting-this/
$this->assertEquals('entry', $data['data']['type']);
$this->assertEquals('article', $data['data']['post-type']);
$this->assertEquals('2017-06-08T19:32:12+00:00', $data['data']['published']);
$this->assertEquals('vkb', $data['data']['author']['name']);
$this->assertEquals('https://news.ycombinator.com/user?id=vkb', $data['data']['author']['url']);
$this->assertEquals('What are we doing about Facebook, Google, and the closed internet?', $data['data']['name']);
$this->assertEquals(
'There have been many, many posts about how toxic advertising and Facebook are (I\'ve written many myself[1][2][3]) for our internet ecosystem today.<p>What projects or companies are you working on to combat filter bubbles, walled gardens, emotional manipulation, and the like, and how can the HN community help you in your goals?</p><p>[1]http://veekaybee.github.io/facebook-is-collecting-this/
[2]http://veekaybee.github.io/content-is-dead/
[3] http://veekaybee.github.io/who-is-doing-this-to-my-internet/</p>', $data['data']['content']['html']);
$this->assertEquals('There have been many, many posts about how toxic advertising and Facebook are (I\'ve written many myself[1][2][3]) for our internet ecosystem today.
[3] http://veekaybee.github.io/who-is-doing-this-to-my-internet/</p>', $data['data']['content']['html']
);
$this->assertEquals(
'There have been many, many posts about how toxic advertising and Facebook are (I\'ve written many myself[1][2][3]) for our internet ecosystem today.
What projects or companies are you working on to combat filter bubbles, walled gardens, emotional manipulation, and the like, and how can the HN community help you in your goals?
[1]http://veekaybee.github.io/facebook-is-collecting-this/
[2]http://veekaybee.github.io/content-is-dead/
[3] http://veekaybee.github.io/who-is-doing-this-to-my-internet/', $data['data']['content']['text']);
}
[3] http://veekaybee.github.io/who-is-doing-this-to-my-internet/', $data['data']['content']['text']
);
}
public function testComment() {
$url = 'https://news.ycombinator.com/item?id=14516923';
$response = $this->parse(['url' => $url]);
public function testComment()
{
$url = 'https://news.ycombinator.com/item?id=14516923';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$this->assertEquals(200, $data['code']);
$this->assertEquals('hackernews', $data['source-format']);
$this->assertEquals(200, $data['code']);
$this->assertEquals('hackernews', $data['source-format']);
$this->assertEquals('entry', $data['data']['type']);
$this->assertEquals('reply', $data['data']['post-type']);
$this->assertEquals('2017-06-08T20:23:20+00:00', $data['data']['published']);
$this->assertEquals('aaronpk', $data['data']['author']['name']);
$this->assertEquals('https://news.ycombinator.com/user?id=aaronpk', $data['data']['author']['url']);
$this->assertEquals('https://news.ycombinator.com/item?id=14516538', $data['data']['in-reply-to'][0]);
$this->assertArrayNotHasKey('name', $data['data']);
$this->assertEquals('I am a member of the W3C Social Web Working Group (<a href="https://www.w3.org/wiki/Socialwg">https://www.w3.org/wiki/Socialwg</a>), and have been organizing IndieWebCamp (<a href="https://indieweb.org/">https://indieweb.org/</a>) conferences in this space for the last 7 years. We\'ve been making a lot of progress:<p>* <a href="https://www.w3.org/TR/webmention/">https://www.w3.org/TR/webmention/</a> - cross-site commenting</p><p>* <a href="https://www.w3.org/TR/micropub/">https://www.w3.org/TR/micropub/</a> - API for apps to create posts on various servers</p><p>* <a href="https://www.w3.org/TR/websub/">https://www.w3.org/TR/websub/</a> - realtime subscriptions to feeds</p><p>* More: <a href="https://indieweb.org/specs">https://indieweb.org/specs</a></p><p>We focus on making sure there are a plurality of implementations and approaches rather than trying to build a single software solution to solve everything.</p><p>Try commenting on my copy of this post on my website by sending me a webmention! <a href="https://aaronparecki.com/2017/06/08/9/indieweb">https://aaronparecki.com/2017/06/08/9/indieweb</a></p>', $data['data']['content']['html']);
$this->assertEquals('I am a member of the W3C Social Web Working Group (https://www.w3.org/wiki/Socialwg), and have been organizing IndieWebCamp (https://indieweb.org/) conferences in this space for the last 7 years. We\'ve been making a lot of progress:
$this->assertEquals('entry', $data['data']['type']);
$this->assertEquals('reply', $data['data']['post-type']);
$this->assertEquals('2017-06-08T20:23:20+00:00', $data['data']['published']);
$this->assertEquals('aaronpk', $data['data']['author']['name']);
$this->assertEquals('https://news.ycombinator.com/user?id=aaronpk', $data['data']['author']['url']);
$this->assertEquals('https://news.ycombinator.com/item?id=14516538', $data['data']['in-reply-to'][0]);
$this->assertArrayNotHasKey('name', $data['data']);
$this->assertEquals('I am a member of the W3C Social Web Working Group (<a href="https://www.w3.org/wiki/Socialwg">https://www.w3.org/wiki/Socialwg</a>), and have been organizing IndieWebCamp (<a href="https://indieweb.org/">https://indieweb.org/</a>) conferences in this space for the last 7 years. We\'ve been making a lot of progress:<p>* <a href="https://www.w3.org/TR/webmention/">https://www.w3.org/TR/webmention/</a> - cross-site commenting</p><p>* <a href="https://www.w3.org/TR/micropub/">https://www.w3.org/TR/micropub/</a> - API for apps to create posts on various servers</p><p>* <a href="https://www.w3.org/TR/websub/">https://www.w3.org/TR/websub/</a> - realtime subscriptions to feeds</p><p>* More: <a href="https://indieweb.org/specs">https://indieweb.org/specs</a></p><p>We focus on making sure there are a plurality of implementations and approaches rather than trying to build a single software solution to solve everything.</p><p>Try commenting on my copy of this post on my website by sending me a webmention! <a href="https://aaronparecki.com/2017/06/08/9/indieweb">https://aaronparecki.com/2017/06/08/9/indieweb</a></p>', $data['data']['content']['html']);
$this->assertEquals(
'I am a member of the W3C Social Web Working Group (https://www.w3.org/wiki/Socialwg), and have been organizing IndieWebCamp (https://indieweb.org/) conferences in this space for the last 7 years. We\'ve been making a lot of progress:
* https://www.w3.org/TR/webmention/ - cross-site commenting
* https://www.w3.org/TR/micropub/ - API for apps to create posts on various servers
* https://www.w3.org/TR/websub/ - realtime subscriptions to feeds
* More: https://indieweb.org/specs
We focus on making sure there are a plurality of implementations and approaches rather than trying to build a single software solution to solve everything.
Try commenting on my copy of this post on my website by sending me a webmention! https://aaronparecki.com/2017/06/08/9/indieweb', $data['data']['content']['text']);
}
Try commenting on my copy of this post on my website by sending me a webmention! https://aaronparecki.com/2017/06/08/9/indieweb', $data['data']['content']['text']
);
}
}

+ 37
- 31
tests/HelpersTest.php View File

@ -1,33 +1,39 @@
<?php
class HelpersTest extends PHPUnit_Framework_TestCase {
class HelpersTest extends PHPUnit\Framework\TestCase
{
public function testLowercaseHostname() {
$url = 'http://Example.com/';
$result = p3k\XRay\normalize_url($url);
$this->assertEquals('http://example.com/', $result);
}
public function testLowercaseHostname()
{
$url = 'http://Example.com/';
$result = p3k\XRay\normalize_url($url);
$this->assertEquals('http://example.com/', $result);
}
public function testAddsSlashToBareDomain() {
$url = 'http://example.com';
$result = p3k\XRay\normalize_url($url);
$this->assertEquals('http://example.com/', $result);
}
public function testAddsSlashToBareDomain()
{
$url = 'http://example.com';
$result = p3k\XRay\normalize_url($url);
$this->assertEquals('http://example.com/', $result);
}
public function testDoesNotModify() {
$url = 'https://example.com/';
$result = p3k\XRay\normalize_url($url);
$this->assertEquals('https://example.com/', $result);
}
public function testDoesNotModify()
{
$url = 'https://example.com/';
$result = p3k\XRay\normalize_url($url);
$this->assertEquals('https://example.com/', $result);
}
public function testURLEquality() {
$url1 = 'https://example.com/';
$url2 = 'https://example.com';
$result = p3k\XRay\urls_are_equal($url1, $url2);
$this->assertEquals(true, $result);
}
public function testURLEquality()
{
$url1 = 'https://example.com/';
$url2 = 'https://example.com';
$result = p3k\XRay\urls_are_equal($url1, $url2);
$this->assertEquals(true, $result);
}
public function testFindMicroformatsByType() {
$html = <<<EOF
public function testFindMicroformatsByType()
{
$html = <<<EOF
<div class="h-feed">
<div class="u-author h-card">
<a href="/1" class="u-url p-name">Author</a>
@ -46,12 +52,12 @@ class HelpersTest extends PHPUnit_Framework_TestCase {
</div>
EOF;
$mf2 = \Mf2\parse($html);
$hcards = \p3k\XRay\Formats\Mf2::findAllMicroformatsByType($mf2, 'h-card');
$this->assertEquals('/1', $hcards[0]['properties']['url'][0]);
$this->assertEquals('/2', $hcards[1]['properties']['url'][0]);
$this->assertEquals('/3', $hcards[2]['properties']['url'][0]);
$this->assertEquals('/4', $hcards[3]['properties']['url'][0]);
}
$mf2 = \Mf2\parse($html);
$hcards = \p3k\XRay\Formats\Mf2::findAllMicroformatsByType($mf2, 'h-card');
$this->assertEquals('/1', $hcards[0]['properties']['url'][0]);
$this->assertEquals('/2', $hcards[1]['properties']['url'][0]);
$this->assertEquals('/3', $hcards[2]['properties']['url'][0]);
$this->assertEquals('/4', $hcards[3]['properties']['url'][0]);
}
}

+ 318
- 292
tests/InstagramTest.php View File

@ -2,297 +2,323 @@
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
class InstagramTest extends PHPUnit_Framework_TestCase {
private $http;
public function setUp() {
$this->client = new Parse();
$this->client->http = new p3k\HTTP\Test(dirname(__FILE__).'/data/');
$this->client->mc = null;
}
private function parse($params) {
$request = new Request($params);
$response = new Response();
return $this->client->parse($request, $response);
}
public function testInstagramPhoto() {
// Original URL: https://www.instagram.com/p/BO5rYVElvJq/
$url = 'https://www.instagram.com/p/BO5rYVElvJq/';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$this->assertEquals(200, $data['code']);
$this->assertEquals('instagram', $data['source-format']);
$this->assertEquals('entry', $data['data']['type']);
$this->assertEquals('photo', $data['data']['post-type']);
$this->assertEquals('2017-01-05T23:31:32+00:00', $data['data']['published']);
$this->assertContains('planning', $data['data']['category']);
$this->assertContains('2017', $data['data']['category']);
$this->assertEquals('Kind of crazy to see the whole year laid out like this. #planning #2017', $data['data']['content']['text']);
$this->assertEquals(1, count($data['data']['photo']));
$this->assertEquals(['https://instagram.fsjc1-3.fna.fbcdn.net/vp/af9471f885e6197478d71807a7cbf297/5CBA6E5F/t51.2885-15/e35/15803256_1832278043695907_4846092951052353536_n.jpg?_nc_ht=instagram.fsjc1-3.fna.fbcdn.net'], $data['data']['photo']);
$this->assertEquals('https://www.instagram.com/aaronpk/', $data['data']['author']['url']);
$this->assertEquals('Aaron Parecki', $data['data']['author']['name']);
$this->assertEquals('https://instagram.fsjc1-3.fna.fbcdn.net/vp/a2909937316893f18760f1077ca88fa1/5CBB520A/t51.2885-19/s150x150/14240576_268350536897085_1129715662_a.jpg?_nc_ht=instagram.fsjc1-3.fna.fbcdn.net', $data['data']['author']['photo']);
$this->assertArrayNotHasKey('meta', $data['data']); // make sure this does not include alt text (autogenerated placeholder from instagram)
}
public function testBGDpqNoiMJ0() {
// https://www.instagram.com/p/BGDpqNoiMJ0/
$url = 'http://www.instagram.com/BGDpqNoiMJ0';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$this->assertEquals(200, $data['code']);
$this->assertEquals('instagram', $data['source-format']);
$this->assertEquals('entry', $data['data']['type']);
$this->assertEquals('photo', $data['data']['post-type']);
$this->assertSame([
'type' => 'card',
'name' => 'pk_spam',
'nickname' => 'pk_spam',
'url' => 'https://www.instagram.com/pk_spam/',
'photo' => 'https://scontent-frx5-1.cdninstagram.com/vp/f17e1275a70fc32e93cbf434ddc32bcd/5B6CCC7A/t51.2885-19/11906329_960233084022564_1448528159_a.jpg',
], $data['data']['author']);
$this->assertSame([
'muffins',
'https://www.instagram.com/indiewebcat/'
], $data['data']['category']);
$this->assertEquals('Meow #muffins', $data['data']['content']['text']);
$this->assertSame(['https://instagram.fsea1-1.fna.fbcdn.net/vp/9433ea494a8b055bebabf70fd81cfa32/5B51F092/t51.2885-15/e35/13266755_877794672348882_1908663476_n.jpg'], $data['data']['photo']);
$this->assertEquals('2016-05-30T20:46:22-07:00', $data['data']['published']);
$this->assertEquals('https://www.instagram.com/explore/locations/359000003/', $data['data']['location'][0]);
$this->assertSame([
'type' => 'card',
'name' => 'Burnside 26',
'url' => 'https://www.instagram.com/explore/locations/359000003/',
'latitude' => 45.52322,
'longitude' => -122.63885
], $data['data']['refs']['https://www.instagram.com/explore/locations/359000003/']);
}
public function testInstagramVideo() {
// Original URL: https://www.instagram.com/p/BO_RN8AFZSx/
$url = 'https://www.instagram.com/p/BO_RN8AFZSx/';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$this->assertEquals(200, $data['code']);
$this->assertEquals('instagram', $data['source-format']);
$this->assertEquals('entry', $data['data']['type']);
$this->assertEquals('video', $data['data']['post-type']);
$this->assertContains('100daysofmusic', $data['data']['category']);
$this->assertEquals('Day 18. Maple and Spruce #100daysofmusic #100daysproject #the100dayproject https://aaronparecki.com/2017/01/07/14/day18', $data['data']['content']['text']);
$this->assertEquals(1, count($data['data']['photo']));
$this->assertEquals(['https://instagram.fsjc1-3.fna.fbcdn.net/vp/a77f8672f977413d2eb5239cd6d5c4cf/5C3A4ADF/t51.2885-15/e15/15624670_548881701986735_8264383763249627136_n.jpg?_nc_ht=instagram.fsjc1-3.fna.fbcdn.net'], $data['data']['photo']);
$this->assertEquals(1, count($data['data']['video']));
$this->assertEquals(['https://instagram.fsjc1-3.fna.fbcdn.net/vp/90ed8fe576cba16e258c0f4cfc05299a/5C3A129E/t50.2886-16/15921147_1074837002642259_2269307616507199488_n.mp4?_nc_ht=instagram.fsjc1-3.fna.fbcdn.net'], $data['data']['video']);
$this->assertEquals('https://www.instagram.com/aaronpk/', $data['data']['author']['url']);
$this->assertEquals('Aaron Parecki', $data['data']['author']['name']);
$this->assertEquals('https://instagram.fsjc1-3.fna.fbcdn.net/vp/a2909937316893f18760f1077ca88fa1/5CBB520A/t51.2885-19/s150x150/14240576_268350536897085_1129715662_a.jpg?_nc_ht=instagram.fsjc1-3.fna.fbcdn.net', $data['data']['author']['photo']);
}
public function testInstagramPhotoWithPersonTag() {
// Original URL: https://www.instagram.com/p/BNfqVfVlmkj/
$url = 'https://www.instagram.com/p/BNfqVfVlmkj/';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$this->assertEquals(200, $data['code']);
$this->assertEquals('instagram', $data['source-format']);
$this->assertEquals(2, count($data['data']['category']));
$this->assertEquals(['type'=>'card','name'=>'KmikeyM™️','nickname'=>'kmikeym','url'=>'https://www.instagram.com/kmikeym/','photo'=>'https://instagram.fsjc1-3.fna.fbcdn.net/vp/ea5b988b616dbcc778b3013bf2426d70/5CCAC7FC/t51.2885-19/s320x320/20634957_814691788710973_2275383796935163904_a.jpg?_nc_ht=instagram.fsjc1-3.fna.fbcdn.net','note'=>"The world’s first publicly traded person.\n\nAcct in collaboration with @norbertoinc\n\nBecome a shareholder today!\n"], $data['data']['refs']['https://www.instagram.com/kmikeym/']);
$this->assertContains('https://www.instagram.com/kmikeym/', $data['data']['category']);
$this->assertArrayHasKey('https://www.instagram.com/kmikeym/', $data['data']['refs']);
}
public function testInstagramPhotoWithVenue() {
// Original URL: https://www.instagram.com/p/BN3Z5salSys/
$url = 'https://www.instagram.com/p/BN3Z5salSys/';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$this->assertEquals(200, $data['code']);
$this->assertEquals('instagram', $data['source-format']);
$this->assertEquals(1, count($data['data']['location']));
$this->assertContains('https://www.instagram.com/explore/locations/109284789535230/', $data['data']['location']);
$this->assertArrayHasKey('https://www.instagram.com/explore/locations/109284789535230/', $data['data']['refs']);
$venue = $data['data']['refs']['https://www.instagram.com/explore/locations/109284789535230/'];
$this->assertEquals('XOXO Outpost', $venue['name']);
$this->assertEquals('45.5261002', $venue['latitude']);
$this->assertEquals('-122.6558081', $venue['longitude']);
// Setting a venue should set the timezone
$this->assertEquals('2016-12-10T21:48:56-08:00', $data['data']['published']);
}
public function testTwoPhotos() {
// Original URL: https://www.instagram.com/p/BZWmUB_DVtp/
$url = 'https://www.instagram.com/p/BZWmUB_DVtp/';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$this->assertEquals(200, $data['code']);
$this->assertEquals('instagram', $data['source-format']);
$this->assertEquals(2, count($data['data']['photo']));
$this->assertEquals('https://instagram.fsjc1-3.fna.fbcdn.net/vp/6b09c3d5490ee3efb55849858a9ec014/5CBFBC38/t51.2885-15/e35/21827424_134752690591737_8093088291252862976_n.jpg?_nc_ht=instagram.fsjc1-3.fna.fbcdn.net', $data['data']['photo'][0]);
$this->assertEquals('https://instagram.fsjc1-3.fna.fbcdn.net/vp/8b1b2e6efa86a4856ec37a60f0fa77f5/5CC2D34D/t51.2885-15/e35/21909774_347707439021016_5237540582556958720_n.jpg?_nc_ht=instagram.fsjc1-3.fna.fbcdn.net', $data['data']['photo'][1]);
$this->assertArrayNotHasKey('video', $data['data']);
$this->assertEquals(2, count($data['data']['category']));
$this->assertArrayNotHasKey('meta', $data['data']);
}
public function testMixPhotosAndVideos() {
// Original URL: https://www.instagram.com/p/BZWmpecjBwN/
$url = 'https://www.instagram.com/p/BZWmpecjBwN/';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$this->assertEquals(200, $data['code']);
$this->assertEquals('instagram', $data['source-format']);
$this->assertEquals('photo', $data['data']['post-type']); // we discard videos in this case right now
$this->assertEquals(3, count($data['data']['photo']));
$this->assertEquals('https://instagram.fsjc1-3.fna.fbcdn.net/vp/ee1a28763918069f3e54dad35be24ad8/5CCFBAB8/t51.2885-15/e35/21878922_686481254874005_8468823712617988096_n.jpg?_nc_ht=instagram.fsjc1-3.fna.fbcdn.net', $data['data']['photo'][0]);
$this->assertEquals('https://instagram.fsjc1-3.fna.fbcdn.net/vp/ddc0ebe969bb1f9e6bf8adada0892c90/5C39EBC9/t51.2885-15/e15/21910026_1507234999368159_6974261907783942144_n.jpg?_nc_ht=instagram.fsjc1-3.fna.fbcdn.net', $data['data']['photo'][1]);
$this->assertEquals('https://instagram.fsjc1-3.fna.fbcdn.net/vp/bfe032af795427443ea448840df1c3a4/5CCC8C88/t51.2885-15/e35/21878800_273567963151023_7672178549897297920_n.jpg?_nc_ht=instagram.fsjc1-3.fna.fbcdn.net', $data['data']['photo'][2]);
$this->assertArrayNotHasKey('video', $data['data']);
$this->assertEquals(2, count($data['data']['category']));
}
public function testInstagramProfile() {
$url = 'https://www.instagram.com/aaronpk/';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$this->assertEquals(200, $data['code']);
$this->assertEquals('instagram', $data['source-format']);
$this->assertSame([
'type' => 'card',
'name' => 'Aaron Parecki',
'nickname' => 'aaronpk',
'url' => 'https://www.instagram.com/aaronpk/',
'photo' => 'https://instagram.fsjc1-3.fna.fbcdn.net/vp/45aee453740a714bf408f8947f89da8e/5CCB4B8E/t51.2885-19/s320x320/14240576_268350536897085_1129715662_a.jpg?_nc_ht=instagram.fsjc1-3.fna.fbcdn.net',
'note' => '🔒 oauth.net 🎥 backpedal.tv 🎙 streampdx.com 📡 w7apk.com'
], $data['data']);
}
public function testInstagramProfileWithBio() {
$url = 'https://www.instagram.com/pk_spam/';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$this->assertEquals(200, $data['code']);
$this->assertEquals('instagram', $data['source-format']);
$this->assertSame([
'type' => 'card',
'name' => 'pk_spam',
'nickname' => 'pk_spam',
'url' => 'https://www.instagram.com/pk_spam/',
'photo' => 'https://scontent-frx5-1.cdninstagram.com/vp/74112f515c64726429c69fedcb927c2d/5CB64CF1/t51.2885-19/44884218_345707102882519_2446069589734326272_n.jpg?_nc_ht=scontent-frx5-1.cdninstagram.com',
'note' => 'My website is https://aaronparecki.com.dev/ and http://aaronpk.micro.blog/about/ and https://tiny.xyz.dev/'
], $data['data']);
}
public function testInstagramProfileFeed() {
$url = 'https://www.instagram.com/pk_spam/';
$response = $this->parse(['url' => $url, 'expect' => 'feed']);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$this->assertEquals(200, $data['code']);
$this->assertEquals('instagram', $data['source-format']);
$this->assertEquals('feed', $data['data']['type']);
$this->assertEquals(12, count($data['data']['items']));
$this->assertEquals('https://www.instagram.com/p/BsdlOmLh_IX/', $data['data']['items'][0]['url']);
$this->assertEquals('https://www.instagram.com/p/BGFdtAViMJy/', $data['data']['items'][11]['url']);
}
public function testInstagramPhotoWithAltText() {
$url = 'https://www.instagram.com/p/BsdjKytBZyx/';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$this->assertEquals(200, $data['code']);
$this->assertEquals('instagram', $data['source-format']);
$this->assertEquals('Pink text on a white background that says "Photo with alt text"', $data['data']['meta']['https://instagram.fsjc1-3.fna.fbcdn.net/vp/a7e61adf3d84f07863ffdb99f0fdcc86/5CD9B7F3/t51.2885-15/e35/47692478_2276538359047529_8318084305806697090_n.jpg?_nc_ht=instagram.fsjc1-3.fna.fbcdn.net']['alt']);
}
public function testInstagramMultiPhotoWithAltText() {
$url = 'https://www.instagram.com/p/BsdlOmLh_IX/';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$this->assertEquals(200, $data['code']);
$this->assertEquals('instagram', $data['source-format']);
$this->assertEquals('A large pink "1" in a circle with a small green "2" behind it', $data['data']['meta']['https://instagram.fsjc1-3.fna.fbcdn.net/vp/90bf019b7396d7bc2b1ee02170902a2e/5CCC9B87/t51.2885-15/e35/47692921_321791688431421_3314633848293773579_n.jpg?_nc_ht=instagram.fsjc1-3.fna.fbcdn.net']['alt']);
$this->assertEquals('A large green "2" in a circle with a small pink "1" behind it', $data['data']['meta']['https://instagram.fsjc1-3.fna.fbcdn.net/vp/a6c93d8fcd5ad0e3b60f2ac0695eb34e/5CC3898E/t51.2885-15/e35/49663055_349750985612151_2949260446582336214_n.jpg?_nc_ht=instagram.fsjc1-3.fna.fbcdn.net']['alt']);
}
public function testInstagramPhotoAutogeneratedAltText() {
$url = 'https://www.instagram.com/p/Bq8U12UAcdq/';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$this->assertEquals(200, $data['code']);
$this->assertEquals('instagram', $data['source-format']);
$this->assertEquals('Image may contain: one or more people and hat', $data['data']['meta']['https://instagram.fsjc1-3.fna.fbcdn.net/vp/7f8954f33de897c0c57656b798637f4c/5CC3DF9F/t51.2885-15/e35/45605085_1989380037822519_4707213851165118070_n.jpg?_nc_ht=instagram.fsjc1-3.fna.fbcdn.net']['alt']);
}
class InstagramTest extends PHPUnit\Framework\TestCase
{
private $http;
public function setUp(): void
{
$this->client = new Parse();
$this->client->http = new p3k\HTTP\Test(dirname(__FILE__).'/data/');
$this->client->mc = null;
}
private function parse($params)
{
$request = new Request($params);
$response = new Response();
return $this->client->parse($request, $response);
}
public function testInstagramPhoto()
{
// Original URL: https://www.instagram.com/p/BO5rYVElvJq/
$url = 'https://www.instagram.com/p/BO5rYVElvJq/';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$this->assertEquals(200, $data['code']);
$this->assertEquals('instagram', $data['source-format']);
$this->assertEquals('entry', $data['data']['type']);
$this->assertEquals('photo', $data['data']['post-type']);
$this->assertEquals('2017-01-05T23:31:32+00:00', $data['data']['published']);
$this->assertContains('planning', $data['data']['category']);
$this->assertContains('2017', $data['data']['category']);
$this->assertEquals('Kind of crazy to see the whole year laid out like this. #planning #2017', $data['data']['content']['text']);
$this->assertEquals(1, count($data['data']['photo']));
$this->assertEquals(['https://instagram.fsjc1-3.fna.fbcdn.net/vp/af9471f885e6197478d71807a7cbf297/5CBA6E5F/t51.2885-15/e35/15803256_1832278043695907_4846092951052353536_n.jpg?_nc_ht=instagram.fsjc1-3.fna.fbcdn.net'], $data['data']['photo']);
$this->assertEquals('https://www.instagram.com/aaronpk/', $data['data']['author']['url']);
$this->assertEquals('Aaron Parecki', $data['data']['author']['name']);
$this->assertEquals('https://instagram.fsjc1-3.fna.fbcdn.net/vp/a2909937316893f18760f1077ca88fa1/5CBB520A/t51.2885-19/s150x150/14240576_268350536897085_1129715662_a.jpg?_nc_ht=instagram.fsjc1-3.fna.fbcdn.net', $data['data']['author']['photo']);
$this->assertArrayNotHasKey('meta', $data['data']); // make sure this does not include alt text (autogenerated placeholder from instagram)
}
public function testBGDpqNoiMJ0()
{
// https://www.instagram.com/p/BGDpqNoiMJ0/
$url = 'http://www.instagram.com/BGDpqNoiMJ0';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$this->assertEquals(200, $data['code']);
$this->assertEquals('instagram', $data['source-format']);
$this->assertEquals('entry', $data['data']['type']);
$this->assertEquals('photo', $data['data']['post-type']);
$this->assertSame(
[
'type' => 'card',
'name' => 'pk_spam',
'nickname' => 'pk_spam',
'url' => 'https://www.instagram.com/pk_spam/',
'photo' => 'https://scontent-frx5-1.cdninstagram.com/vp/f17e1275a70fc32e93cbf434ddc32bcd/5B6CCC7A/t51.2885-19/11906329_960233084022564_1448528159_a.jpg',
], $data['data']['author']
);
$this->assertSame(
[
'muffins',
'https://www.instagram.com/indiewebcat/'
], $data['data']['category']
);
$this->assertEquals('Meow #muffins', $data['data']['content']['text']);
$this->assertSame(['https://instagram.fsea1-1.fna.fbcdn.net/vp/9433ea494a8b055bebabf70fd81cfa32/5B51F092/t51.2885-15/e35/13266755_877794672348882_1908663476_n.jpg'], $data['data']['photo']);
$this->assertEquals('2016-05-30T20:46:22-07:00', $data['data']['published']);
$this->assertEquals('https://www.instagram.com/explore/locations/359000003/', $data['data']['location'][0]);
$this->assertSame(
[
'type' => 'card',
'name' => 'Burnside 26',
'url' => 'https://www.instagram.com/explore/locations/359000003/',
'latitude' => 45.52322,
'longitude' => -122.63885
], $data['data']['refs']['https://www.instagram.com/explore/locations/359000003/']
);
}
public function testInstagramVideo()
{
// Original URL: https://www.instagram.com/p/BO_RN8AFZSx/
$url = 'https://www.instagram.com/p/BO_RN8AFZSx/';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$this->assertEquals(200, $data['code']);
$this->assertEquals('instagram', $data['source-format']);
$this->assertEquals('entry', $data['data']['type']);
$this->assertEquals('video', $data['data']['post-type']);
$this->assertContains('100daysofmusic', $data['data']['category']);
$this->assertEquals('Day 18. Maple and Spruce #100daysofmusic #100daysproject #the100dayproject https://aaronparecki.com/2017/01/07/14/day18', $data['data']['content']['text']);
$this->assertEquals(1, count($data['data']['photo']));
$this->assertEquals(['https://instagram.fsjc1-3.fna.fbcdn.net/vp/a77f8672f977413d2eb5239cd6d5c4cf/5C3A4ADF/t51.2885-15/e15/15624670_548881701986735_8264383763249627136_n.jpg?_nc_ht=instagram.fsjc1-3.fna.fbcdn.net'], $data['data']['photo']);
$this->assertEquals(1, count($data['data']['video']));
$this->assertEquals(['https://instagram.fsjc1-3.fna.fbcdn.net/vp/90ed8fe576cba16e258c0f4cfc05299a/5C3A129E/t50.2886-16/15921147_1074837002642259_2269307616507199488_n.mp4?_nc_ht=instagram.fsjc1-3.fna.fbcdn.net'], $data['data']['video']);
$this->assertEquals('https://www.instagram.com/aaronpk/', $data['data']['author']['url']);
$this->assertEquals('Aaron Parecki', $data['data']['author']['name']);
$this->assertEquals('https://instagram.fsjc1-3.fna.fbcdn.net/vp/a2909937316893f18760f1077ca88fa1/5CBB520A/t51.2885-19/s150x150/14240576_268350536897085_1129715662_a.jpg?_nc_ht=instagram.fsjc1-3.fna.fbcdn.net', $data['data']['author']['photo']);
}
public function testInstagramPhotoWithPersonTag()
{
// Original URL: https://www.instagram.com/p/BNfqVfVlmkj/
$url = 'https://www.instagram.com/p/BNfqVfVlmkj/';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$this->assertEquals(200, $data['code']);
$this->assertEquals('instagram', $data['source-format']);
$this->assertEquals(2, count($data['data']['category']));
$this->assertEquals(['type'=>'card','name'=>'KmikeyM™️','nickname'=>'kmikeym','url'=>'https://www.instagram.com/kmikeym/','photo'=>'https://instagram.fsjc1-3.fna.fbcdn.net/vp/ea5b988b616dbcc778b3013bf2426d70/5CCAC7FC/t51.2885-19/s320x320/20634957_814691788710973_2275383796935163904_a.jpg?_nc_ht=instagram.fsjc1-3.fna.fbcdn.net','note'=>"The world’s first publicly traded person.\n\nAcct in collaboration with @norbertoinc\n\nBecome a shareholder today!\n"], $data['data']['refs']['https://www.instagram.com/kmikeym/']);
$this->assertContains('https://www.instagram.com/kmikeym/', $data['data']['category']);
$this->assertArrayHasKey('https://www.instagram.com/kmikeym/', $data['data']['refs']);
}
public function testInstagramPhotoWithVenue()
{
// Original URL: https://www.instagram.com/p/BN3Z5salSys/
$url = 'https://www.instagram.com/p/BN3Z5salSys/';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$this->assertEquals(200, $data['code']);
$this->assertEquals('instagram', $data['source-format']);
$this->assertEquals(1, count($data['data']['location']));
$this->assertContains('https://www.instagram.com/explore/locations/109284789535230/', $data['data']['location']);
$this->assertArrayHasKey('https://www.instagram.com/explore/locations/109284789535230/', $data['data']['refs']);
$venue = $data['data']['refs']['https://www.instagram.com/explore/locations/109284789535230/'];
$this->assertEquals('XOXO Outpost', $venue['name']);
$this->assertEquals('45.5261002', $venue['latitude']);
$this->assertEquals('-122.6558081', $venue['longitude']);
// Setting a venue should set the timezone
$this->assertEquals('2016-12-10T21:48:56-08:00', $data['data']['published']);
}
public function testTwoPhotos()
{
// Original URL: https://www.instagram.com/p/BZWmUB_DVtp/
$url = 'https://www.instagram.com/p/BZWmUB_DVtp/';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$this->assertEquals(200, $data['code']);
$this->assertEquals('instagram', $data['source-format']);
$this->assertEquals(2, count($data['data']['photo']));
$this->assertEquals('https://instagram.fsjc1-3.fna.fbcdn.net/vp/6b09c3d5490ee3efb55849858a9ec014/5CBFBC38/t51.2885-15/e35/21827424_134752690591737_8093088291252862976_n.jpg?_nc_ht=instagram.fsjc1-3.fna.fbcdn.net', $data['data']['photo'][0]);
$this->assertEquals('https://instagram.fsjc1-3.fna.fbcdn.net/vp/8b1b2e6efa86a4856ec37a60f0fa77f5/5CC2D34D/t51.2885-15/e35/21909774_347707439021016_5237540582556958720_n.jpg?_nc_ht=instagram.fsjc1-3.fna.fbcdn.net', $data['data']['photo'][1]);
$this->assertArrayNotHasKey('video', $data['data']);
$this->assertEquals(2, count($data['data']['category']));
$this->assertArrayNotHasKey('meta', $data['data']);
}
public function testMixPhotosAndVideos()
{
// Original URL: https://www.instagram.com/p/BZWmpecjBwN/
$url = 'https://www.instagram.com/p/BZWmpecjBwN/';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$this->assertEquals(200, $data['code']);
$this->assertEquals('instagram', $data['source-format']);
$this->assertEquals('photo', $data['data']['post-type']); // we discard videos in this case right now
$this->assertEquals(3, count($data['data']['photo']));
$this->assertEquals('https://instagram.fsjc1-3.fna.fbcdn.net/vp/ee1a28763918069f3e54dad35be24ad8/5CCFBAB8/t51.2885-15/e35/21878922_686481254874005_8468823712617988096_n.jpg?_nc_ht=instagram.fsjc1-3.fna.fbcdn.net', $data['data']['photo'][0]);
$this->assertEquals('https://instagram.fsjc1-3.fna.fbcdn.net/vp/ddc0ebe969bb1f9e6bf8adada0892c90/5C39EBC9/t51.2885-15/e15/21910026_1507234999368159_6974261907783942144_n.jpg?_nc_ht=instagram.fsjc1-3.fna.fbcdn.net', $data['data']['photo'][1]);
$this->assertEquals('https://instagram.fsjc1-3.fna.fbcdn.net/vp/bfe032af795427443ea448840df1c3a4/5CCC8C88/t51.2885-15/e35/21878800_273567963151023_7672178549897297920_n.jpg?_nc_ht=instagram.fsjc1-3.fna.fbcdn.net', $data['data']['photo'][2]);
$this->assertArrayNotHasKey('video', $data['data']);
$this->assertEquals(2, count($data['data']['category']));
}
public function testInstagramProfile()
{
$url = 'https://www.instagram.com/aaronpk/';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$this->assertEquals(200, $data['code']);
$this->assertEquals('instagram', $data['source-format']);
$this->assertSame(
[
'type' => 'card',
'name' => 'Aaron Parecki',
'nickname' => 'aaronpk',
'url' => 'https://www.instagram.com/aaronpk/',
'photo' => 'https://instagram.fsjc1-3.fna.fbcdn.net/vp/45aee453740a714bf408f8947f89da8e/5CCB4B8E/t51.2885-19/s320x320/14240576_268350536897085_1129715662_a.jpg?_nc_ht=instagram.fsjc1-3.fna.fbcdn.net',
'note' => '🔒 oauth.net 🎥 backpedal.tv 🎙 streampdx.com 📡 w7apk.com'
], $data['data']
);
}
public function testInstagramProfileWithBio()
{
$url = 'https://www.instagram.com/pk_spam/';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$this->assertEquals(200, $data['code']);
$this->assertEquals('instagram', $data['source-format']);
$this->assertSame(
[
'type' => 'card',
'name' => 'pk_spam',
'nickname' => 'pk_spam',
'url' => 'https://www.instagram.com/pk_spam/',
'photo' => 'https://scontent-frx5-1.cdninstagram.com/vp/74112f515c64726429c69fedcb927c2d/5CB64CF1/t51.2885-19/44884218_345707102882519_2446069589734326272_n.jpg?_nc_ht=scontent-frx5-1.cdninstagram.com',
'note' => 'My website is https://aaronparecki.com.dev/ and http://aaronpk.micro.blog/about/ and https://tiny.xyz.dev/'
], $data['data']
);
}
public function testInstagramProfileFeed()
{
$url = 'https://www.instagram.com/pk_spam/';
$response = $this->parse(['url' => $url, 'expect' => 'feed']);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$this->assertEquals(200, $data['code']);
$this->assertEquals('instagram', $data['source-format']);
$this->assertEquals('feed', $data['data']['type']);
$this->assertEquals(12, count($data['data']['items']));
$this->assertEquals('https://www.instagram.com/p/BsdlOmLh_IX/', $data['data']['items'][0]['url']);
$this->assertEquals('https://www.instagram.com/p/BGFdtAViMJy/', $data['data']['items'][11]['url']);
}
public function testInstagramPhotoWithAltText()
{
$url = 'https://www.instagram.com/p/BsdjKytBZyx/';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$this->assertEquals(200, $data['code']);
$this->assertEquals('instagram', $data['source-format']);
$this->assertEquals('Pink text on a white background that says "Photo with alt text"', $data['data']['meta']['https://instagram.fsjc1-3.fna.fbcdn.net/vp/a7e61adf3d84f07863ffdb99f0fdcc86/5CD9B7F3/t51.2885-15/e35/47692478_2276538359047529_8318084305806697090_n.jpg?_nc_ht=instagram.fsjc1-3.fna.fbcdn.net']['alt']);
}
public function testInstagramMultiPhotoWithAltText()
{
$url = 'https://www.instagram.com/p/BsdlOmLh_IX/';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$this->assertEquals(200, $data['code']);
$this->assertEquals('instagram', $data['source-format']);
$this->assertEquals('A large pink "1" in a circle with a small green "2" behind it', $data['data']['meta']['https://instagram.fsjc1-3.fna.fbcdn.net/vp/90bf019b7396d7bc2b1ee02170902a2e/5CCC9B87/t51.2885-15/e35/47692921_321791688431421_3314633848293773579_n.jpg?_nc_ht=instagram.fsjc1-3.fna.fbcdn.net']['alt']);
$this->assertEquals('A large green "2" in a circle with a small pink "1" behind it', $data['data']['meta']['https://instagram.fsjc1-3.fna.fbcdn.net/vp/a6c93d8fcd5ad0e3b60f2ac0695eb34e/5CC3898E/t51.2885-15/e35/49663055_349750985612151_2949260446582336214_n.jpg?_nc_ht=instagram.fsjc1-3.fna.fbcdn.net']['alt']);
}
public function testInstagramPhotoAutogeneratedAltText()
{
$url = 'https://www.instagram.com/p/Bq8U12UAcdq/';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$this->assertEquals(200, $data['code']);
$this->assertEquals('instagram', $data['source-format']);
$this->assertEquals('Image may contain: one or more people and hat', $data['data']['meta']['https://instagram.fsjc1-3.fna.fbcdn.net/vp/7f8954f33de897c0c57656b798637f4c/5CC3DF9F/t51.2885-15/e35/45605085_1989380037822519_4707213851165118070_n.jpg?_nc_ht=instagram.fsjc1-3.fna.fbcdn.net']['alt']);
}
}

+ 57
- 50
tests/LibraryTest.php View File

@ -1,67 +1,74 @@
<?php
class LibraryTest extends PHPUnit_Framework_TestCase {
class LibraryTest extends PHPUnit\Framework\TestCase
{
public function testInputIsParsedMf2Array() {
$html = '<div class="h-entry"><p class="p-content p-name">Hello World</p><img src="/photo.jpg"></p></div>';
$mf2 = Mf2\parse($html, 'http://example.com/entry');
public function testInputIsParsedMf2Array()
{
$html = '<div class="h-entry"><p class="p-content p-name">Hello World</p><img src="/photo.jpg"></p></div>';
$mf2 = Mf2\parse($html, 'http://example.com/entry');
$xray = new p3k\XRay();
$data = $xray->process('http://example.com/entry', $mf2);
$xray = new p3k\XRay();
$data = $xray->process('http://example.com/entry', $mf2);
$this->assertEquals('Hello World', $data['data']['content']['text']);
$this->assertEquals('http://example.com/photo.jpg', $data['data']['photo'][0]);
}
$this->assertEquals('Hello World', $data['data']['content']['text']);
$this->assertEquals('http://example.com/photo.jpg', $data['data']['photo'][0]);
}
public function testInputIsParsedMf2JSON() {
$html = '<div class="h-entry"><p class="p-content p-name">Hello World</p><img src="/photo.jpg"></p></div>';
$mf2 = Mf2\parse($html, 'http://example.com/entry');
public function testInputIsParsedMf2JSON()
{
$html = '<div class="h-entry"><p class="p-content p-name">Hello World</p><img src="/photo.jpg"></p></div>';
$mf2 = Mf2\parse($html, 'http://example.com/entry');
$xray = new p3k\XRay();
$data = $xray->process('http://example.com/entry', json_encode($mf2));
$xray = new p3k\XRay();
$data = $xray->process('http://example.com/entry', json_encode($mf2));
$this->assertEquals('Hello World', $data['data']['content']['text']);
$this->assertEquals('http://example.com/photo.jpg', $data['data']['photo'][0]);
}
$this->assertEquals('Hello World', $data['data']['content']['text']);
$this->assertEquals('http://example.com/photo.jpg', $data['data']['photo'][0]);
}
public function testInputIsParsedMf2HCard() {
$url = 'https://waterpigs.co.uk/';
$html = '<a class="h-card" href="https://waterpigs.co.uk/">Barnaby Walters</a>';
$mf2 = Mf2\parse($html, $url);
public function testInputIsParsedMf2HCard()
{
$url = 'https://waterpigs.co.uk/';
$html = '<a class="h-card" href="https://waterpigs.co.uk/">Barnaby Walters</a>';
$mf2 = Mf2\parse($html, $url);
$xray = new p3k\XRay();
$data = $xray->process($url, $mf2);
$this->assertEquals('card', $data['data']['type']);
$this->assertEquals('Barnaby Walters', $data['data']['name']);
}
$xray = new p3k\XRay();
$data = $xray->process($url, $mf2);
$this->assertEquals('card', $data['data']['type']);
$this->assertEquals('Barnaby Walters', $data['data']['name']);
}
public function testNoHEntryMarkupMF2JSON() {
$url = 'http://example.com/';
$html = '<p><a href="http://target.example.com/">Target</a></p>';
$mf2 = Mf2\parse($html, $url);
public function testNoHEntryMarkupMF2JSON()
{
$url = 'http://example.com/';
$html = '<p><a href="http://target.example.com/">Target</a></p>';
$mf2 = Mf2\parse($html, $url);
$xray = new p3k\XRay();
$data = $xray->process($url, $mf2);
$this->assertEquals('unknown', $data['data']['type']);
}
$xray = new p3k\XRay();
$data = $xray->process($url, $mf2);
$this->assertEquals('unknown', $data['data']['type']);
}
public function testNoHEntryMarkup() {
$url = 'http://example.com/';
$html = '<p><a href="http://target.example.com/">Target</a></p>';
public function testNoHEntryMarkup()
{
$url = 'http://example.com/';
$html = '<p><a href="http://target.example.com/">Target</a></p>';
$xray = new p3k\XRay();
$data = $xray->parse($url, $html);
$this->assertEquals('unknown', $data['data']['type']);
}
$xray = new p3k\XRay();
$data = $xray->parse($url, $html);
$this->assertEquals('unknown', $data['data']['type']);
}
public function testNoHEntryMarkupWithTarget() {
$url = 'http://example.com/';
$html = '<p><a href="http://target.example.com/">Target</a></p>';
public function testNoHEntryMarkupWithTarget()
{
$url = 'http://example.com/';
$html = '<p><a href="http://target.example.com/">Target</a></p>';
$xray = new p3k\XRay();
$data = $xray->parse($url, $html, ['target' => 'http://target.example.com/']);
$this->assertEquals('unknown', $data['data']['type']);
$this->assertArrayNotHasKey('error', $data);
$this->assertArrayNotHasKey('html', $data);
}
$xray = new p3k\XRay();
$data = $xray->parse($url, $html, ['target' => 'http://target.example.com/']);
$this->assertEquals('unknown', $data['data']['type']);
$this->assertArrayNotHasKey('error', $data);
$this->assertArrayNotHasKey('html', $data);
}
}

+ 42
- 36
tests/MediaTypeTest.php View File

@ -1,44 +1,50 @@
<?php
class MediaTypeTest extends PHPUnit_Framework_TestCase {
class MediaTypeTest extends PHPUnit\Framework\TestCase
{
public function testParseTextHtml() {
$type = new p3k\XRay\MediaType('text/html');
$this->assertEquals('text', $type->type);
$this->assertEquals('html', $type->subtype);
$this->assertEquals('html', $type->format);
$this->assertEquals(null, $type->charset);
}
public function testParseTextHtml()
{
$type = new p3k\XRay\MediaType('text/html');
$this->assertEquals('text', $type->type);
$this->assertEquals('html', $type->subtype);
$this->assertEquals('html', $type->format);
$this->assertEquals(null, $type->charset);
}
public function testParseTextHtmlUtf8() {
$type = new p3k\XRay\MediaType('text/html; charset=UTF-8');
$this->assertEquals('text', $type->type);
$this->assertEquals('html', $type->subtype);
$this->assertEquals('html', $type->format);
$this->assertEquals('UTF-8', $type->charset);
}
public function testParseTextHtmlUtf8()
{
$type = new p3k\XRay\MediaType('text/html; charset=UTF-8');
$this->assertEquals('text', $type->type);
$this->assertEquals('html', $type->subtype);
$this->assertEquals('html', $type->format);
$this->assertEquals('UTF-8', $type->charset);
}
public function testParseTextHtmlUtf8Extra() {
$type = new p3k\XRay\MediaType('text/html; hello=world; charset=UTF-8');
$this->assertEquals('text', $type->type);
$this->assertEquals('html', $type->subtype);
$this->assertEquals('html', $type->format);
$this->assertEquals('UTF-8', $type->charset);
}
public function testParseTextHtmlUtf8Extra()
{
$type = new p3k\XRay\MediaType('text/html; hello=world; charset=UTF-8');
$this->assertEquals('text', $type->type);
$this->assertEquals('html', $type->subtype);
$this->assertEquals('html', $type->format);
$this->assertEquals('UTF-8', $type->charset);
}
public function testParseApplicationJson() {
$type = new p3k\XRay\MediaType('application/json');
$this->assertEquals('application', $type->type);
$this->assertEquals('json', $type->subtype);
$this->assertEquals('json', $type->format);
$this->assertEquals(null, $type->charset);
}
public function testParseApplicationJson()
{
$type = new p3k\XRay\MediaType('application/json');
$this->assertEquals('application', $type->type);
$this->assertEquals('json', $type->subtype);
$this->assertEquals('json', $type->format);
$this->assertEquals(null, $type->charset);
}
public function testParseApplicationJsonFeed() {
$type = new p3k\XRay\MediaType('application/feed+json');
$this->assertEquals('application', $type->type);
$this->assertEquals('feed+json', $type->subtype);
$this->assertEquals('json', $type->format);
$this->assertEquals(null, $type->charset);
}
public function testParseApplicationJsonFeed()
{
$type = new p3k\XRay\MediaType('application/feed+json');
$this->assertEquals('application', $type->type);
$this->assertEquals('feed+json', $type->subtype);
$this->assertEquals('json', $type->format);
$this->assertEquals(null, $type->charset);
}
}

+ 1298
- 1196
tests/ParseTest.php
File diff suppressed because it is too large
View File


+ 415
- 389
tests/SanitizeTest.php View File

@ -2,193 +2,205 @@
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
class SanitizeTest extends PHPUnit_Framework_TestCase {
private $http;
public function setUp() {
$this->client = new Parse();
$this->client->http = new p3k\HTTP\Test(dirname(__FILE__).'/data/');
$this->client->mc = null;
}
private function parse($params) {
$request = new Request($params);
$response = new Response();
return $this->client->parse($request, $response);
}
public function testAllowsWhitelistedTags() {
$url = 'http://sanitize.example/entry-with-valid-tags';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$html = $data['data']['content']['html'];
$this->assertEquals('entry', $data['data']['type']);
$this->assertContains('This content has only valid tags.', $html);
$this->assertContains('<a href="http://sanitize.example/example">links</a>,', $html, '<a> missing');
$this->assertContains('<abbr>abbreviations</abbr>,', $html, '<abbr> missing');
$this->assertContains('<b>bold</b>,', $html, '<b> missing');
$this->assertContains('<code>inline code</code>,', $html, '<code> missing');
$this->assertContains('<del>delete</del>,', $html, '<del> missing');
$this->assertContains('<em>emphasis</em>,', $html, '<em> missing');
$this->assertContains('<i>italics</i>,', $html, '<i> missing');
$this->assertContains('<img src="http://sanitize.example/example.jpg" alt="images are allowed" />', $html, '<img> missing');
$this->assertContains('<q>inline quote</q>,', $html, '<q> missing');
$this->assertContains('<strike>strikethrough</strike>,', $html, '<strike> missing');
$this->assertContains('<strong>strong text</strong>,', $html, '<strong> missing');
$this->assertContains('<time datetime="2016-01-01">time elements</time>', $html, '<time> missing');
$this->assertContains('<blockquote>Blockquote tags are okay</blockquote>', $html);
$this->assertContains('<pre>preformatted text is okay too', $html, '<pre> missing');
$this->assertContains('for code examples and such</pre>', $html, '<pre> missing');
$this->assertContains('<p>Paragraph tags are allowed</p>', $html, '<p> missing');
$this->assertContains('<h1>One</h1>', $html, '<h1> missing');
$this->assertContains('<h2>Two</h2>', $html, '<h2> missing');
$this->assertContains('<h3>Three</h3>', $html, '<h3> missing');
$this->assertContains('<h4>Four</h4>', $html, '<h4> missing');
$this->assertContains('<h5>Five</h5>', $html, '<h5> missing');
$this->assertContains('<h6>Six</h6>', $html, '<h6> missing');
$this->assertContains('<ul>', $html, '<ul> missing');
$this->assertContains('<li>One</li>', $html, '<li> missing');
$this->assertContains('<p>We should allow<br />break<br />tags too</p>', $html, '<br> missing');
}
public function testRemovesUnsafeTags() {
$url = 'http://sanitize.example/entry-with-unsafe-tags';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$html = $data['data']['content']['html'];
$text = $data['data']['content']['text'];
$this->assertEquals('entry', $data['data']['type']);
$this->assertNotContains('<script>', $html);
$this->assertNotContains('<style>', $html);
$this->assertNotContains('visiblity', $html); // from the CSS
$this->assertNotContains('alert', $html); // from the JS
$this->assertNotContains('visiblity', $text);
$this->assertNotContains('alert', $text);
}
public function testAllowsMF2Classes() {
$url = 'http://sanitize.example/entry-with-mf2-classes';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$html = $data['data']['content']['html'];
$this->assertEquals('entry', $data['data']['type']);
$this->assertContains('<h2 class="p-name">Hello World</h2>', $html);
$this->assertContains('<h3>Utility Class</h3>', $html);
}
public function testEscapingHTMLTagsInText() {
$url = 'http://sanitize.example/html-escaping-in-text';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$this->assertEquals('entry', $data['data']['type']);
$this->assertEquals('This content has some HTML escaped entities such as & ampersand, " quote, escaped <code> HTML tags, an ümlaut, an @at sign.', $data['data']['content']['text']);
}
public function testEscapingHTMLTagsInHTML() {
$url = 'http://sanitize.example/html-escaping-in-html';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$this->assertEquals('entry', $data['data']['type']);
$this->assertArrayNotHasKey('name', $data['data']);
$this->assertEquals('This content has some HTML escaped entities such as & ampersand, " quote, escaped <code> HTML tags, an ümlaut, an @at sign.', $data['data']['content']['text']);
$this->assertEquals('This content has some <i>HTML escaped</i> entities such as &amp; ampersand, " quote, escaped &lt;code&gt; HTML tags, an ümlaut, an @at sign.', $data['data']['content']['html']);
}
public function testAllowIframeVideo() {
$url = 'http://sanitize.example/entry-with-iframe-video';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$data = json_decode($body, true);
$html = $data['data']['content']['html'];
$this->assertNotContains('<iframe', $html);
$response = $this->parse(['url' => $url, 'allow-iframe-video' => 'true']);
$body = $response->getContent();
$data = json_decode($body, true);
$html = $data['data']['content']['html'];
$this->assertContains('youtube.com', $html);
$this->assertNotContains('https://attack-domain.com', $html);
$this->assertNotContains('<iframe width="580" height="345"', $html);
}
public function testSanitizeJavascriptURLs() {
$url = 'http://sanitize.example/h-entry-with-javascript-urls';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$this->assertEquals('entry', $data['data']['type']);
$this->assertEquals('', $data['data']['author']['url']);
$this->assertArrayNotHasKey('url', $data['data']);
$this->assertArrayNotHasKey('photo', $data['data']);
$this->assertArrayNotHasKey('audio', $data['data']);
$this->assertArrayNotHasKey('video', $data['data']);
$this->assertArrayNotHasKey('syndication', $data['data']);
$this->assertArrayNotHasKey('in-reply-to', $data['data']);
$this->assertArrayNotHasKey('like-of', $data['data']);
$this->assertArrayNotHasKey('repost-of', $data['data']);
$this->assertArrayNotHasKey('bookmark-of', $data['data']);
$this->assertEquals('Author', $data['data']['author']['name']);
$this->assertEquals('', $data['data']['author']['photo']);
}
public function testSanitizeEmailAuthorURL() {
$url = 'http://sanitize.example/h-entry-with-email-author';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertEquals('entry', $data->data->type);
$this->assertEquals('', $data->data->author->url);
$this->assertEquals('Author', $data->data->author->name);
$this->assertEquals('http://sanitize.example/photo.jpg', $data->data->author->photo);
}
public function testPhotoInContentNoAlt() {
// https://github.com/aaronpk/XRay/issues/52
$url = 'http://sanitize.example/photo-in-content';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertObjectNotHasAttribute('name', $data->data);
$this->assertEquals('http://target.example.com/photo.jpg', $data->data->photo[0]);
$this->assertEquals('This is a photo post with an img tag inside the content.', $data->data->content->text);
$this->assertEquals('This is a photo post with an <code>img</code> tag inside the content.', $data->data->content->html);
}
/*
// Commented out until #56 is resolved
// https://github.com/aaronpk/XRay/issues/56
public function testPhotoInTextContentNoAlt() {
class SanitizeTest extends PHPUnit\Framework\TestCase
{
private $http;
public function setUp(): void
{
$this->client = new Parse();
$this->client->http = new p3k\HTTP\Test(dirname(__FILE__).'/data/');
$this->client->mc = null;
}
private function parse($params)
{
$request = new Request($params);
$response = new Response();
return $this->client->parse($request, $response);
}
public function testAllowsWhitelistedTags()
{
$url = 'http://sanitize.example/entry-with-valid-tags';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$html = $data['data']['content']['html'];
$this->assertEquals('entry', $data['data']['type']);
$this->assertStringContainsString('This content has only valid tags.', $html);
$this->assertStringContainsString('<a href="http://sanitize.example/example">links</a>,', $html, '<a> missing');
$this->assertStringContainsString('<abbr>abbreviations</abbr>,', $html, '<abbr> missing');
$this->assertStringContainsString('<b>bold</b>,', $html, '<b> missing');
$this->assertStringContainsString('<code>inline code</code>,', $html, '<code> missing');
$this->assertStringContainsString('<del>delete</del>,', $html, '<del> missing');
$this->assertStringContainsString('<em>emphasis</em>,', $html, '<em> missing');
$this->assertStringContainsString('<i>italics</i>,', $html, '<i> missing');
$this->assertStringContainsString('<img src="http://sanitize.example/example.jpg" alt="images are allowed" />', $html, '<img> missing');
$this->assertStringContainsString('<q>inline quote</q>,', $html, '<q> missing');
$this->assertStringContainsString('<strike>strikethrough</strike>,', $html, '<strike> missing');
$this->assertStringContainsString('<strong>strong text</strong>,', $html, '<strong> missing');
$this->assertStringContainsString('<time datetime="2016-01-01">time elements</time>', $html, '<time> missing');
$this->assertStringContainsString('<blockquote>Blockquote tags are okay</blockquote>', $html);
$this->assertStringContainsString('<pre>preformatted text is okay too', $html, '<pre> missing');
$this->assertStringContainsString('for code examples and such</pre>', $html, '<pre> missing');
$this->assertStringContainsString('<p>Paragraph tags are allowed</p>', $html, '<p> missing');
$this->assertStringContainsString('<h1>One</h1>', $html, '<h1> missing');
$this->assertStringContainsString('<h2>Two</h2>', $html, '<h2> missing');
$this->assertStringContainsString('<h3>Three</h3>', $html, '<h3> missing');
$this->assertStringContainsString('<h4>Four</h4>', $html, '<h4> missing');
$this->assertStringContainsString('<h5>Five</h5>', $html, '<h5> missing');
$this->assertStringContainsString('<h6>Six</h6>', $html, '<h6> missing');
$this->assertStringContainsString('<ul>', $html, '<ul> missing');
$this->assertStringContainsString('<li>One</li>', $html, '<li> missing');
$this->assertStringContainsString('<p>We should allow<br />break<br />tags too</p>', $html, '<br> missing');
}
public function testRemovesUnsafeTags()
{
$url = 'http://sanitize.example/entry-with-unsafe-tags';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$html = $data['data']['content']['html'];
$text = $data['data']['content']['text'];
$this->assertEquals('entry', $data['data']['type']);
$this->assertStringNotContainsString('<script>', $html);
$this->assertStringNotContainsString('<style>', $html);
$this->assertStringNotContainsString('visiblity', $html); // from the CSS
$this->assertStringNotContainsString('alert', $html); // from the JS
$this->assertStringNotContainsString('visiblity', $text);
$this->assertStringNotContainsString('alert', $text);
}
public function testAllowsMF2Classes()
{
$url = 'http://sanitize.example/entry-with-mf2-classes';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$html = $data['data']['content']['html'];
$this->assertEquals('entry', $data['data']['type']);
$this->assertStringContainsString('<h2 class="p-name">Hello World</h2>', $html);
$this->assertStringContainsString('<h3>Utility Class</h3>', $html);
}
public function testEscapingHTMLTagsInText()
{
$url = 'http://sanitize.example/html-escaping-in-text';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$this->assertEquals('entry', $data['data']['type']);
$this->assertEquals('This content has some HTML escaped entities such as & ampersand, " quote, escaped <code> HTML tags, an ümlaut, an @at sign.', $data['data']['content']['text']);
}
public function testEscapingHTMLTagsInHTML()
{
$url = 'http://sanitize.example/html-escaping-in-html';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$this->assertEquals('entry', $data['data']['type']);
$this->assertArrayNotHasKey('name', $data['data']);
$this->assertEquals('This content has some HTML escaped entities such as & ampersand, " quote, escaped <code> HTML tags, an ümlaut, an @at sign.', $data['data']['content']['text']);
$this->assertEquals('This content has some <i>HTML escaped</i> entities such as &amp; ampersand, " quote, escaped &lt;code&gt; HTML tags, an ümlaut, an @at sign.', $data['data']['content']['html']);
}
public function testAllowIframeVideo()
{
$url = 'http://sanitize.example/entry-with-iframe-video';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$data = json_decode($body, true);
$html = $data['data']['content']['html'];
$this->assertStringNotContainsString('<iframe', $html);
$response = $this->parse(['url' => $url, 'allow-iframe-video' => 'true']);
$body = $response->getContent();
$data = json_decode($body, true);
$html = $data['data']['content']['html'];
$this->assertStringContainsString('youtube.com', $html);
$this->assertStringNotContainsString('https://attack-domain.com', $html);
$this->assertStringNotContainsString('<iframe width="580" height="345"', $html);
}
public function testSanitizeJavascriptURLs()
{
$url = 'http://sanitize.example/h-entry-with-javascript-urls';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$this->assertEquals('entry', $data['data']['type']);
$this->assertEquals('', $data['data']['author']['url']);
$this->assertArrayNotHasKey('url', $data['data']);
$this->assertArrayNotHasKey('photo', $data['data']);
$this->assertArrayNotHasKey('audio', $data['data']);
$this->assertArrayNotHasKey('video', $data['data']);
$this->assertArrayNotHasKey('syndication', $data['data']);
$this->assertArrayNotHasKey('in-reply-to', $data['data']);
$this->assertArrayNotHasKey('like-of', $data['data']);
$this->assertArrayNotHasKey('repost-of', $data['data']);
$this->assertArrayNotHasKey('bookmark-of', $data['data']);
$this->assertEquals('Author', $data['data']['author']['name']);
$this->assertEquals('', $data['data']['author']['photo']);
}
public function testSanitizeEmailAuthorURL()
{
$url = 'http://sanitize.example/h-entry-with-email-author';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertEquals('entry', $data->data->type);
$this->assertEquals('', $data->data->author->url);
$this->assertEquals('Author', $data->data->author->name);
$this->assertEquals('http://sanitize.example/photo.jpg', $data->data->author->photo);
}
public function testPhotoInContentNoAlt()
{
// https://github.com/aaronpk/XRay/issues/52
$url = 'http://sanitize.example/photo-in-content';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertObjectNotHasAttribute('name', $data->data);
$this->assertEquals('http://target.example.com/photo.jpg', $data->data->photo[0]);
$this->assertEquals('This is a photo post with an img tag inside the content.', $data->data->content->text);
$this->assertEquals('This is a photo post with an <code>img</code> tag inside the content.', $data->data->content->html);
}
/*
// Commented out until #56 is resolved
// https://github.com/aaronpk/XRay/issues/56
public function testPhotoInTextContentNoAlt() {
$url = 'http://sanitize.example/photo-in-text-content';
$response = $this->parse(['url' => $url]);
@ -200,158 +212,169 @@ class SanitizeTest extends PHPUnit_Framework_TestCase {
$this->assertEquals('http://target.example.com/photo.jpg', $data->data->photo[0]);
$this->assertEquals('This is a photo post with an img tag inside the content.', $data->data->content->text);
$this->assertEquals('This is a photo post with an <code>img</code> tag inside the content.', $data->data->content->html);
}
*/
public function testRelativePhotoInContent() {
$url = 'http://sanitize.example/photo-in-content-relative';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertContains('http://sanitize.example/photo1.jpg', $data->data->content->html);
}
public function testRelativePhotoProperty() {
$url = 'http://sanitize.example/photo-relative';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertEquals('http://sanitize.example/photo.jpg', $data->data->photo[0]);
}
public function testPhotoInContentEmptyAltAttribute() {
// https://github.com/aaronpk/XRay/issues/52
$url = 'http://sanitize.example/photo-in-content-empty-alt';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertObjectNotHasAttribute('name', $data->data);
$this->assertEquals('http://target.example.com/photo.jpg', $data->data->photo[0]);
$this->assertEquals('This is a photo post with an img tag inside the content.', $data->data->content->text);
$this->assertEquals('This is a photo post with an <code>img</code> tag inside the content.', $data->data->content->html);
}
public function testPhotoInContentWithAlt() {
// https://github.com/aaronpk/XRay/issues/52
$url = 'http://sanitize.example/photo-in-content-with-alt';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertObjectNotHasAttribute('name', $data->data);
$this->assertEquals('http://target.example.com/photo.jpg', $data->data->photo[0]);
$this->assertEquals('This is a photo post with an img tag inside the content.', $data->data->content->text);
$this->assertEquals('This is a photo post with an <code>img</code> tag inside the content.', $data->data->content->html);
}
public function testPhotoInContentWithNameAndNoText() {
$url = 'http://sanitize.example/cleverdevil';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertObjectHasAttribute('name', $data->data);
$this->assertEquals('Oh, how well they know me! 🥃', $data->data->name);
$this->assertObjectNotHasAttribute('content', $data->data);
$this->assertEquals('https://cleverdevil.io/file/5bf2fa91c3d4c592f9978200923cb56e/thumb.jpg', $data->data->photo[0]);
}
public function testPhotoWithDupeNameAndAlt1() {
// https://github.com/aaronpk/XRay/issues/57
$url = 'http://sanitize.example/photo-with-dupe-name-alt';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertObjectHasAttribute('name', $data->data);
$this->assertEquals('Photo caption', $data->data->name);
$this->assertObjectNotHasAttribute('content', $data->data);
$this->assertEquals('http://sanitize.example/photo.jpg', $data->data->photo[0]);
}
public function testPhotoWithDupeNameAndAlt2() {
// This is simliar to adactio's markup
// https://adactio.com/notes/13301
$url = 'http://sanitize.example/photo-with-dupe-name-alt-2';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertObjectHasAttribute('content', $data->data);
$this->assertEquals('Photo caption', $data->data->content->text);
$this->assertObjectNotHasAttribute('name', $data->data);
$this->assertEquals('http://sanitize.example/photo.jpg', $data->data->photo[0]);
}
public function testPhotoInContentWithNoText() {
$url = 'http://sanitize.example/photo-in-content-with-alt-no-text';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$this->assertEquals('<p><img src="http://sanitize.example/photo.jpg" alt="test" /></p>', $data['data']['content']['html']);
$this->assertEquals('', $data['data']['content']['text']);
}
public function testPhotoInContentWithPNoAlt() {
$url = 'http://sanitize.example/photo-in-content-with-p-no-alt';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$this->assertEquals('<p><img src="http://sanitize.example/photo.jpg" alt="photo.jpg" /></p>', $data['data']['content']['html']);
$this->assertEquals('', $data['data']['content']['text']);
}
public function testPhotoInContentNoPWithURLPhoto() {
$url = 'http://sanitize.example/photo-in-content-no-p-with-url-photo';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$this->assertEquals('<img src="http://sanitize.example/photo.jpg" alt="test" />', $data['data']['content']['html']);
$this->assertEquals('', $data['data']['content']['text']);
}
public function testPhotoInContentNoPWithAlt() {
// This h-entry has no u-url so has an implied u-photo. we don't actually care what happens with it because
// this should never happen in the wild
$url = 'http://sanitize.example/photo-in-content-no-p-with-alt';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
}
/*
// TODO: add support for embedded video and audio tags in html content
public function testContentIsOnlyVideo() {
}
*/
public function testRelativePhotoInContent()
{
$url = 'http://sanitize.example/photo-in-content-relative';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertStringContainsString('http://sanitize.example/photo1.jpg', $data->data->content->html);
}
public function testRelativePhotoProperty()
{
$url = 'http://sanitize.example/photo-relative';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertEquals('http://sanitize.example/photo.jpg', $data->data->photo[0]);
}
public function testPhotoInContentEmptyAltAttribute()
{
// https://github.com/aaronpk/XRay/issues/52
$url = 'http://sanitize.example/photo-in-content-empty-alt';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertObjectNotHasAttribute('name', $data->data);
$this->assertEquals('http://target.example.com/photo.jpg', $data->data->photo[0]);
$this->assertEquals('This is a photo post with an img tag inside the content.', $data->data->content->text);
$this->assertEquals('This is a photo post with an <code>img</code> tag inside the content.', $data->data->content->html);
}
public function testPhotoInContentWithAlt()
{
// https://github.com/aaronpk/XRay/issues/52
$url = 'http://sanitize.example/photo-in-content-with-alt';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertObjectNotHasAttribute('name', $data->data);
$this->assertEquals('http://target.example.com/photo.jpg', $data->data->photo[0]);
$this->assertEquals('This is a photo post with an img tag inside the content.', $data->data->content->text);
$this->assertEquals('This is a photo post with an <code>img</code> tag inside the content.', $data->data->content->html);
}
public function testPhotoInContentWithNameAndNoText()
{
$url = 'http://sanitize.example/cleverdevil';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertObjectHasAttribute('name', $data->data);
$this->assertEquals('Oh, how well they know me! 🥃', $data->data->name);
$this->assertObjectNotHasAttribute('content', $data->data);
$this->assertEquals('https://cleverdevil.io/file/5bf2fa91c3d4c592f9978200923cb56e/thumb.jpg', $data->data->photo[0]);
}
public function testPhotoWithDupeNameAndAlt1()
{
// https://github.com/aaronpk/XRay/issues/57
$url = 'http://sanitize.example/photo-with-dupe-name-alt';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertObjectHasAttribute('name', $data->data);
$this->assertEquals('Photo caption', $data->data->name);
$this->assertObjectNotHasAttribute('content', $data->data);
$this->assertEquals('http://sanitize.example/photo.jpg', $data->data->photo[0]);
}
public function testPhotoWithDupeNameAndAlt2()
{
// This is simliar to adactio's markup
// https://adactio.com/notes/13301
$url = 'http://sanitize.example/photo-with-dupe-name-alt-2';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertObjectHasAttribute('content', $data->data);
$this->assertEquals('Photo caption', $data->data->content->text);
$this->assertObjectNotHasAttribute('name', $data->data);
$this->assertEquals('http://sanitize.example/photo.jpg', $data->data->photo[0]);
}
public function testPhotoInContentWithNoText()
{
$url = 'http://sanitize.example/photo-in-content-with-alt-no-text';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$this->assertEquals('<p><img src="http://sanitize.example/photo.jpg" alt="test" /></p>', $data['data']['content']['html']);
$this->assertEquals('', $data['data']['content']['text']);
}
public function testPhotoInContentWithPNoAlt()
{
$url = 'http://sanitize.example/photo-in-content-with-p-no-alt';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$this->assertEquals('<p><img src="http://sanitize.example/photo.jpg" alt="photo.jpg" /></p>', $data['data']['content']['html']);
$this->assertEquals('', $data['data']['content']['text']);
}
public function testPhotoInContentNoPWithURLPhoto()
{
$url = 'http://sanitize.example/photo-in-content-no-p-with-url-photo';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$this->assertEquals('<img src="http://sanitize.example/photo.jpg" alt="test" />', $data['data']['content']['html']);
$this->assertEquals('', $data['data']['content']['text']);
}
public function testPhotoInContentNoPWithAlt()
{
// This h-entry has no u-url so has an implied u-photo. we don't actually care what happens with it because
// this should never happen in the wild
$url = 'http://sanitize.example/photo-in-content-no-p-with-alt';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
}
/*
// TODO: add support for embedded video and audio tags in html content
public function testContentIsOnlyVideo() {
$url = 'http://sanitize.example/content-is-only-video';
$response = $this->parse(['url' => $url]);
@ -360,55 +383,58 @@ class SanitizeTest extends PHPUnit_Framework_TestCase {
$data = json_decode($body, true);
print_r($data);
}
*/
public function testPhotosWithAlt() {
// https://github.com/microformats/microformats2-parsing/issues/16
$url = 'http://sanitize.example/photos-with-alt';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertEquals('🌆 Made it to the first #NPSF #earlygang of the year, did in-betweeners abs, and 6:30 workout with a brutal burnout that was really its own workout. But wow pretty sunrise. Plus 50+ deg F? I’ll take it. #100PDPD'."\n\n".'#justshowup #darknesstodawn #wakeupthesun #fromwhereirun #NovemberProject #sunrise #latergram #nofilter', $data->data->content->text);
$this->assertObjectNotHasAttribute('name', $data->data);
$this->assertEquals('https://igx.4sqi.net/img/general/original/476_g7yruXflacsGr7PyVmECefyTBMB_R99zmPQxW7pftzA.jpg', $data->data->photo[0]);
$this->assertEquals('https://igx.4sqi.net/img/general/original/476_zM3UgU9JHNhom907Ac_1WCEcUhGOJZaNWGlRmev86YA.jpg', $data->data->photo[1]);
}
// Ignoring this issue for now. This should not happen in the wild.
// https://github.com/aaronpk/XRay/issues/55
// Skipping the implied photo check because in the wild, h-entrys should not exist withou a u-url, which stops implied parsing.
public function testEntryWithImgNoImpliedPhoto() {
// See https://github.com/microformats/microformats2-parsing/issues/6#issuecomment-357286985
// and https://github.com/aaronpk/XRay/issues/52#issuecomment-357269683
// and https://github.com/microformats/microformats2-parsing/issues/16
$url = 'http://sanitize.example/entry-with-img-no-implied-photo';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertObjectNotHasAttribute('photo', $data->data);
$this->assertObjectNotHasAttribute('name', $data->data);
$this->assertEquals('This is a photo post with an img tag inside the content, which does not have a u-photo class so should not be removed.', $data->data->content->text);
$this->assertEquals('This is a photo post with an <code>img</code> tag inside the content, which does not have a u-photo class so should not be removed. <img src="http://target.example.com/photo.jpg" alt="a photo" />', $data->data->content->html);
}
public function testWhitespaceWithBreakTags() {
$url = 'http://sanitize.example/entry-with-br-tags';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertEquals('This content has two break tags to indicate a paragraph break.<br /><br />This is how tantek\'s autolinker works.', $data->data->content->html);
$this->assertEquals("This content has two break tags to indicate a paragraph break.\n\nThis is how tantek's autolinker works.", $data->data->content->text);
}
}
*/
public function testPhotosWithAlt()
{
// https://github.com/microformats/microformats2-parsing/issues/16
$url = 'http://sanitize.example/photos-with-alt';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertEquals('🌆 Made it to the first #NPSF #earlygang of the year, did in-betweeners abs, and 6:30 workout with a brutal burnout that was really its own workout. But wow pretty sunrise. Plus 50+ deg F? I’ll take it. #100PDPD'."\n\n".'#justshowup #darknesstodawn #wakeupthesun #fromwhereirun #NovemberProject #sunrise #latergram #nofilter', $data->data->content->text);
$this->assertObjectNotHasAttribute('name', $data->data);
$this->assertEquals('https://igx.4sqi.net/img/general/original/476_g7yruXflacsGr7PyVmECefyTBMB_R99zmPQxW7pftzA.jpg', $data->data->photo[0]);
$this->assertEquals('https://igx.4sqi.net/img/general/original/476_zM3UgU9JHNhom907Ac_1WCEcUhGOJZaNWGlRmev86YA.jpg', $data->data->photo[1]);
}
// Ignoring this issue for now. This should not happen in the wild.
// https://github.com/aaronpk/XRay/issues/55
// Skipping the implied photo check because in the wild, h-entrys should not exist withou a u-url, which stops implied parsing.
public function testEntryWithImgNoImpliedPhoto()
{
// See https://github.com/microformats/microformats2-parsing/issues/6#issuecomment-357286985
// and https://github.com/aaronpk/XRay/issues/52#issuecomment-357269683
// and https://github.com/microformats/microformats2-parsing/issues/16
$url = 'http://sanitize.example/entry-with-img-no-implied-photo';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertObjectNotHasAttribute('photo', $data->data);
$this->assertObjectNotHasAttribute('name', $data->data);
$this->assertEquals('This is a photo post with an img tag inside the content, which does not have a u-photo class so should not be removed.', $data->data->content->text);
$this->assertEquals('This is a photo post with an <code>img</code> tag inside the content, which does not have a u-photo class so should not be removed. <img src="http://target.example.com/photo.jpg" alt="a photo" />', $data->data->content->html);
}
public function testWhitespaceWithBreakTags()
{
$url = 'http://sanitize.example/entry-with-br-tags';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertEquals('This content has two break tags to indicate a paragraph break.<br /><br />This is how tantek\'s autolinker works.', $data->data->content->html);
$this->assertEquals("This content has two break tags to indicate a paragraph break.\n\nThis is how tantek's autolinker works.", $data->data->content->text);
}
}

+ 165
- 150
tests/TokenTest.php View File

@ -2,155 +2,170 @@
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
class TokenTest extends PHPUnit_Framework_TestCase {
private $http;
public function setUp() {
$this->client = new Token();
$this->client->http = new p3k\HTTP\Test(dirname(__FILE__).'/data/');
}
private function token($params) {
$request = new Request($params);
$response = new Response();
return $this->client->token($request, $response);
}
public function testMissingURL() {
$response = $this->token([]);
$body = $response->getContent();
$this->assertEquals(400, $response->getStatusCode());
$data = json_decode($body);
$this->assertObjectHasAttribute('error', $data);
$this->assertEquals('invalid_request', $data->error);
}
public function testInvalidURL() {
$url = 'ftp://example.com/foo';
$response = $this->token(['source' => $url, 'code' => '1234']);
$body = $response->getContent();
$this->assertEquals(400, $response->getStatusCode());
$data = json_decode($body);
$this->assertObjectHasAttribute('error', $data);
$this->assertEquals('invalid_url', $data->error);
}
public function testMissingCode() {
$response = $this->token(['source' => 'http://example.com/']);
$body = $response->getContent();
$this->assertEquals(400, $response->getStatusCode());
$data = json_decode($body);
$this->assertObjectHasAttribute('error', $data);
$this->assertEquals('invalid_request', $data->error);
}
public function testNoLinkHeaders() {
$url = 'http://private.example.com/no-link-headers';
$response = $this->token(['source' => $url, 'code' => '1234']);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertObjectHasAttribute('error', $data);
$this->assertEquals('no_token_endpoint', $data->error);
}
public function testNoTokenEndpointOneLinkHeader() {
$url = 'http://private.example.com/no-token-endpoint-one-link-header';
$response = $this->token(['source' => $url, 'code' => '1234']);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertObjectHasAttribute('error', $data);
$this->assertEquals('no_token_endpoint', $data->error);
}
public function testNoTokenEndpointTwoLinkHeaders() {
$url = 'http://private.example.com/no-token-endpoint-two-link-headers';
$response = $this->token(['source' => $url, 'code' => '1234']);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertObjectHasAttribute('error', $data);
$this->assertEquals('no_token_endpoint', $data->error);
}
public function testTokenEndpointInOAuth2Rel() {
$url = 'http://private.example.com/oauth2-token-endpoint';
$response = $this->token(['source' => $url, 'code' => '1234']);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertObjectNotHasAttribute('error', $data);
$this->assertEquals('1234', $data->access_token);
}
public function testTokenEndpointInIndieAuthRel() {
$url = 'http://private.example.com/token-endpoint';
$response = $this->token(['source' => $url, 'code' => '1234']);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertObjectNotHasAttribute('error', $data);
$this->assertEquals('1234', $data->access_token);
}
public function testTokenEndpointWithMultipleRelLinks() {
$url = 'http://private.example.com/multiple-rels';
$response = $this->token(['source' => $url, 'code' => '1234']);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertObjectNotHasAttribute('error', $data);
$this->assertEquals('1234', $data->access_token);
}
public function testBadTokenEndpointResponse() {
$url = 'http://private.example.com/token-endpoint-bad-response';
$response = $this->token(['source' => $url, 'code' => '1234']);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertObjectHasAttribute('error', $data);
$this->assertEquals('this-string-passed-through-from-token-endpoint', $data->error);
}
public function testTokenEndpointTimeout() {
$url = 'http://private.example.com/token-endpoint-timeout';
$response = $this->token(['source' => $url, 'code' => '1234']);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertObjectHasAttribute('error', $data);
$this->assertEquals('timeout', $data->error);
}
public function testTokenEndpointReturnsNotJSON() {
$url = 'http://private.example.com/token-endpoint-notjson';
$response = $this->token(['source' => $url, 'code' => '1234']);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$this->assertEquals('text/plain', $response->headers->get('content-type'));
$this->assertEquals('Invalid request', $body);
}
class TokenTest extends PHPUnit\Framework\TestCase
{
private $http;
public function setUp(): void
{
$this->client = new Token();
$this->client->http = new p3k\HTTP\Test(dirname(__FILE__).'/data/');
}
private function token($params)
{
$request = new Request($params);
$response = new Response();
return $this->client->token($request, $response);
}
public function testMissingURL()
{
$response = $this->token([]);
$body = $response->getContent();
$this->assertEquals(400, $response->getStatusCode());
$data = json_decode($body);
$this->assertObjectHasAttribute('error', $data);
$this->assertEquals('invalid_request', $data->error);
}
public function testInvalidURL()
{
$url = 'ftp://example.com/foo';
$response = $this->token(['source' => $url, 'code' => '1234']);
$body = $response->getContent();
$this->assertEquals(400, $response->getStatusCode());
$data = json_decode($body);
$this->assertObjectHasAttribute('error', $data);
$this->assertEquals('invalid_url', $data->error);
}
public function testMissingCode()
{
$response = $this->token(['source' => 'http://example.com/']);
$body = $response->getContent();
$this->assertEquals(400, $response->getStatusCode());
$data = json_decode($body);
$this->assertObjectHasAttribute('error', $data);
$this->assertEquals('invalid_request', $data->error);
}
public function testNoLinkHeaders()
{
$url = 'http://private.example.com/no-link-headers';
$response = $this->token(['source' => $url, 'code' => '1234']);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertObjectHasAttribute('error', $data);
$this->assertEquals('no_token_endpoint', $data->error);
}
public function testNoTokenEndpointOneLinkHeader()
{
$url = 'http://private.example.com/no-token-endpoint-one-link-header';
$response = $this->token(['source' => $url, 'code' => '1234']);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertObjectHasAttribute('error', $data);
$this->assertEquals('no_token_endpoint', $data->error);
}
public function testNoTokenEndpointTwoLinkHeaders()
{
$url = 'http://private.example.com/no-token-endpoint-two-link-headers';
$response = $this->token(['source' => $url, 'code' => '1234']);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertObjectHasAttribute('error', $data);
$this->assertEquals('no_token_endpoint', $data->error);
}
public function testTokenEndpointInOAuth2Rel()
{
$url = 'http://private.example.com/oauth2-token-endpoint';
$response = $this->token(['source' => $url, 'code' => '1234']);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertObjectNotHasAttribute('error', $data);
$this->assertEquals('1234', $data->access_token);
}
public function testTokenEndpointInIndieAuthRel()
{
$url = 'http://private.example.com/token-endpoint';
$response = $this->token(['source' => $url, 'code' => '1234']);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertObjectNotHasAttribute('error', $data);
$this->assertEquals('1234', $data->access_token);
}
public function testTokenEndpointWithMultipleRelLinks()
{
$url = 'http://private.example.com/multiple-rels';
$response = $this->token(['source' => $url, 'code' => '1234']);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertObjectNotHasAttribute('error', $data);
$this->assertEquals('1234', $data->access_token);
}
public function testBadTokenEndpointResponse()
{
$url = 'http://private.example.com/token-endpoint-bad-response';
$response = $this->token(['source' => $url, 'code' => '1234']);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertObjectHasAttribute('error', $data);
$this->assertEquals('this-string-passed-through-from-token-endpoint', $data->error);
}
public function testTokenEndpointTimeout()
{
$url = 'http://private.example.com/token-endpoint-timeout';
$response = $this->token(['source' => $url, 'code' => '1234']);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body);
$this->assertObjectHasAttribute('error', $data);
$this->assertEquals('timeout', $data->error);
}
public function testTokenEndpointReturnsNotJSON()
{
$url = 'http://private.example.com/token-endpoint-notjson';
$response = $this->token(['source' => $url, 'code' => '1234']);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$this->assertEquals('text/plain', $response->headers->get('content-type'));
$this->assertEquals('Invalid request', $body);
}
}

+ 319
- 287
tests/TwitterTest.php View File

@ -2,299 +2,331 @@
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
class TwitterTest extends PHPUnit_Framework_TestCase {
public function setUp() {
$this->client = new Parse();
$this->client->mc = null;
}
private function parse($params) {
$request = new Request($params);
$response = new Response();
$result = $this->client->parse($request, $response);
$body = $result->getContent();
$this->assertEquals(200, $result->getStatusCode());
return json_decode($body, true);
}
private function loadTweet($id) {
$url = 'https://twitter.com/_/status/'.$id;
$json = file_get_contents(dirname(__FILE__).'/data/api.twitter.com/'.$id.'.json');
$parsed = json_decode($json);
$url = 'https://twitter.com/'.$parsed->user->screen_name.'/status/'.$id;
return [$url, $json];
}
public function testBasicProfileInfo() {
list($url, $json) = $this->loadTweet('818912506496229376');
$data = $this->parse(['url' => $url, 'body' => $json]);
$this->assertEquals('twitter', $data['source-format']);
$this->assertEquals('entry', $data['data']['type']);
$this->assertEquals('aaronpk dev', $data['data']['author']['name']);
$this->assertEquals('pkdev', $data['data']['author']['nickname']);
$this->assertEquals('https://twitter.com/pkdev', $data['data']['author']['url']);
$this->assertEquals('Portland, OR', $data['data']['author']['location']);
$this->assertEquals('Dev account for testing Twitter things. Follow me here: https://twitter.com/aaronpk', $data['data']['author']['bio']);
$this->assertEquals('https://pbs.twimg.com/profile_images/638125135904436224/qd_d94Qn_normal.jpg', $data['data']['author']['photo']);
}
public function testProfileWithNonExpandedURL() {
list($url, $json) = $this->loadTweet('791704641046052864');
$data = $this->parse(['url' => $url, 'body' => $json]);
$this->assertEquals('https://twitter.com/agiletortoise', $data['data']['author']['url']);
}
public function testBasicTestStuff() {
list($url, $json) = $this->loadTweet('818913630569664512');
$data = $this->parse(['url' => $url, 'body' => $json]);
$this->assertEquals(null, $data['code']); // no code is expected if we pass in the body
$this->assertEquals('twitter', $data['source-format']);
$this->assertEquals('https://twitter.com/pkdev/status/818913630569664512', $data['url']);
$this->assertEquals('entry', $data['data']['type']);
$this->assertEquals('note', $data['data']['post-type']);
$this->assertEquals('A tweet with a URL https://indieweb.org/ #and #some #hashtags', $data['data']['content']['text']);
$this->assertContains('and', $data['data']['category']);
$this->assertContains('some', $data['data']['category']);
$this->assertContains('hashtags', $data['data']['category']);
// Published date should be set to the timezone of the user
$this->assertEquals('2017-01-10T12:13:18-08:00', $data['data']['published']);
}
public function testPositiveTimezone() {
list($url, $json) = $this->loadTweet('719914707566649344');
$data = $this->parse(['url' => $url, 'body' => $json]);
$this->assertEquals("2016-04-12T16:46:56+01:00", $data['data']['published']);
}
public function testTweetWithEmoji() {
list($url, $json) = $this->loadTweet('818943244553699328');
$data = $this->parse(['url' => $url, 'body' => $json]);
$this->assertEquals('twitter', $data['source-format']);
$this->assertEquals('entry', $data['data']['type']);
$this->assertEquals('Here 🎉 have an emoji', $data['data']['content']['text']);
}
public function testHTMLEscaping() {
list($url, $json) = $this->loadTweet('818928092383166465');
$data = $this->parse(['url' => $url, 'body' => $json]);
$this->assertEquals('entry', $data['data']['type']);
$this->assertEquals('Double escaping &amp; & amp', $data['data']['content']['text']);
}
public function testTweetWithPhoto() {
list($url, $json) = $this->loadTweet('818912506496229376');
$data = $this->parse(['url' => $url, 'body' => $json]);
$this->assertEquals('entry', $data['data']['type']);
$this->assertEquals('photo', $data['data']['post-type']);
$this->assertEquals('Tweet with a photo and a location', $data['data']['content']['text']);
$this->assertEquals('https://pbs.twimg.com/media/C11cfRJUoAI26h9.jpg', $data['data']['photo'][0]);
}
public function testTweetWithTwoPhotos() {
list($url, $json) = $this->loadTweet('818935308813103104');
$data = $this->parse(['url' => $url, 'body' => $json]);
$this->assertEquals('entry', $data['data']['type']);
$this->assertEquals('photo', $data['data']['post-type']);
$this->assertEquals('Two photos', $data['data']['content']['text']);
$this->assertContains('https://pbs.twimg.com/media/C11xS1wUcAAeaKF.jpg', $data['data']['photo']);
$this->assertContains('https://pbs.twimg.com/media/C11wtndUoAE1WfE.jpg', $data['data']['photo']);
}
public function testTweetWithVideo() {
list($url, $json) = $this->loadTweet('818913178260160512');
$data = $this->parse(['url' => $url, 'body' => $json]);
$this->assertEquals('entry', $data['data']['type']);
$this->assertEquals('video', $data['data']['post-type']);
$this->assertEquals('Tweet with a video', $data['data']['content']['text']);
$this->assertEquals('https://pbs.twimg.com/ext_tw_video_thumb/818913089248595970/pr/img/qVoEjF03Y41SKpNt.jpg', $data['data']['photo'][0]);
$this->assertEquals('https://video.twimg.com/ext_tw_video/818913089248595970/pr/vid/1280x720/qP-sDx-Q0Hs-ckVv.mp4', $data['data']['video'][0]);
}
public function testTweetWithGif() {
list($url, $json) = $this->loadTweet('tweet-with-gif');
$data = $this->parse(['url' => $url, 'body' => $json]);
$this->assertEquals('entry', $data['data']['type']);
$this->assertEquals('reply', $data['data']['post-type']);
$this->assertEquals('https://twitter.com/SwiftOnSecurity/status/1018178408398966784', $data['data']['in-reply-to'][0]);
$this->assertEquals('Look! A distraction 🐁', $data['data']['content']['text']);
$this->assertEquals('https://video.twimg.com/tweet_video/DiFOUuYV4AAUsgL.mp4', $data['data']['video'][0]);
$this->assertEquals('https://pbs.twimg.com/tweet_video_thumb/DiFOUuYV4AAUsgL.jpg', $data['data']['photo'][0]);
}
public function testTweetWithLocation() {
list($url, $json) = $this->loadTweet('818912506496229376');
$data = $this->parse(['url' => $url, 'body' => $json]);
$this->assertEquals('entry', $data['data']['type']);
$this->assertEquals('Tweet with a photo and a location', $data['data']['content']['text']);
$this->assertEquals('https://api.twitter.com/1.1/geo/id/ac88a4f17a51c7fc.json', $data['data']['location']);
$location = $data['data']['refs']['https://api.twitter.com/1.1/geo/id/ac88a4f17a51c7fc.json'];
$this->assertEquals('adr', $location['type']);
$this->assertEquals('Portland', $location['locality']);
$this->assertEquals('United States', $location['country-name']);
$this->assertEquals('Portland, OR', $location['name']);
}
public function testRetweet() {
list($url, $json) = $this->loadTweet('818913351623245824');
$data = $this->parse(['url' => $url, 'body' => $json]);
$this->assertEquals('twitter', $data['source-format']);
$this->assertEquals('entry', $data['data']['type']);
$this->assertEquals('repost', $data['data']['post-type']);
$this->assertArrayNotHasKey('content', $data['data']);
$repostOf = 'https://twitter.com/aaronpk/status/817414679131660288';
$this->assertEquals($repostOf, $data['data']['repost-of']);
$tweet = $data['data']['refs'][$repostOf];
$this->assertEquals('Yeah that\'s me http://xkcd.com/1782/', $tweet['content']['text']);
}
public function testRetweetWithPhoto() {
list($url, $json) = $this->loadTweet('820039442773798912');
$data = $this->parse(['url' => $url, 'body' => $json]);
$this->assertEquals('entry', $data['data']['type']);
$this->assertEquals('repost', $data['data']['post-type']);
$this->assertArrayNotHasKey('content', $data['data']);
$this->assertArrayNotHasKey('photo', $data['data']);
$repostOf = 'https://twitter.com/phlaimeaux/status/819943954724556800';
$this->assertEquals($repostOf, $data['data']['repost-of']);
$tweet = $data['data']['refs'][$repostOf];
$this->assertEquals('this headline is such a rollercoaster', $tweet['content']['text']);
}
public function testQuotedTweet() {
list($url, $json) = $this->loadTweet('818913488609251331');
$data = $this->parse(['url' => $url, 'body' => $json]);
$this->assertEquals('entry', $data['data']['type']);
$this->assertEquals('note', $data['data']['post-type']);
$this->assertEquals('Quoted tweet with a #hashtag https://twitter.com/aaronpk/status/817414679131660288', $data['data']['content']['text']);
$this->assertEquals('https://twitter.com/aaronpk/status/817414679131660288', $data['data']['quotation-of']);
$tweet = $data['data']['refs']['https://twitter.com/aaronpk/status/817414679131660288'];
$this->assertEquals('Yeah that\'s me http://xkcd.com/1782/', $tweet['content']['text']);
}
public function testTruncatedQuotedTweet() {
list($url, $json) = $this->loadTweet('tweet-with-truncated-quoted-tweet');
$data = $this->parse(['url' => $url, 'body' => $json]);
$this->assertEquals('entry', $data['data']['type']);
$this->assertEquals('.@stream_pdx is a real treasure of our city.', $data['data']['content']['text']);
$this->assertEquals('https://twitter.com/PDXStephenG/status/964598574322339841', $data['data']['quotation-of']);
$tweet = $data['data']['refs']['https://twitter.com/PDXStephenG/status/964598574322339841'];
$this->assertEquals('Hey @OregonGovBrown @tedwheeler day 16 of #BHM is for @stream_pdx. An amazing podcast trailer run by @tyeshasnow helping to democratize story telling in #PDX. Folks can get training in the production of podcasts. @siliconflorist #SupportBlackBusiness', $tweet['content']['text']);
$this->assertEquals("Hey <a href=\"https://twitter.com/OregonGovBrown\">@OregonGovBrown</a> <a href=\"https://twitter.com/tedwheeler\">@tedwheeler</a> day 16 of #BHM is for <a href=\"https://twitter.com/stream_pdx\">@stream_pdx</a>. An amazing podcast trailer run by <a href=\"https://twitter.com/tyeshasnow\">@tyeshasnow</a> helping to democratize story telling in #PDX. Folks can get training in the production of podcasts. <a href=\"https://twitter.com/siliconflorist\">@siliconflorist</a> #SupportBlackBusiness", $tweet['content']['html']);
}
public function testTweetWithHTML() {
list($url, $json) = $this->loadTweet('tweet-with-html');
$data = $this->parse(['url' => $url, 'body' => $json]);
$this->assertContains('<script>', $data['data']['content']['text']);
$this->assertContains('&lt;script&gt;', $data['data']['content']['html']);
}
public function testStreamingTweetWithLink() {
list($url, $json) = $this->loadTweet('streaming-tweet-with-link');
$data = $this->parse(['url' => $url, 'body' => $json]);
$this->assertEquals('twitter', $data['source-format']);
$this->assertEquals('what happens if i include a link like https://kmikeym.com', $data['data']['content']['text']);
$this->assertEquals('what happens if i include a link like <a href="https://kmikeym.com">https://kmikeym.com</a>', $data['data']['content']['html']);
}
public function testStreamingTweetWithMentions() {
list($url, $json) = $this->loadTweet('streaming-tweet-with-mentions');
$data = $this->parse(['url' => $url, 'body' => $json]);
$this->assertEquals('Offer accepted! @aaronpk bought 1 shares from @coledrobison at $6.73 https://kmikeym.com/trades', $data['data']['content']['text']);
$this->assertEquals('Offer accepted! <a href="https://twitter.com/aaronpk">@aaronpk</a> bought 1 shares from <a href="https://twitter.com/coledrobison">@coledrobison</a> at $6.73 <a href="https://kmikeym.com/trades">https://kmikeym.com/trades</a>', $data['data']['content']['html']);
}
public function testStreamingTweetTruncated() {
list($url, $json) = $this->loadTweet('streaming-tweet-truncated');
$data = $this->parse(['url' => $url, 'body' => $json]);
$this->assertEquals("#indieweb community. Really would like to see a Micropub client for Gratitude logging and also a Mastodon poster similar to the twitter one.\nFeel like I could (maybe) rewrite previous open code to do some of this :)", $data['data']['content']['text']);
$this->assertEquals('#indieweb community. Really would like to see a Micropub client for Gratitude logging and also a Mastodon poster similar to the twitter one.<br>
Feel like I could (maybe) rewrite previous open code to do some of this :)', $data['data']['content']['html']);
}
public function testStreamingTweetTruncatedWithPhoto() {
list($url, $json) = $this->loadTweet('streaming-tweet-truncated-with-photo');
$data = $this->parse(['url' => $url, 'body' => $json]);
$this->assertEquals("#MicrosoftFlow ninja-tip.\nI'm getting better at custom-connector and auth. Thanks @skillriver \nThis is OAuth2 with MSA/Live (not AzureAD) which I need to do MVP timesheets.\nStill dislike Swagger so I don't know why I bother with this. I'm just that lazy doing this manually", $data['data']['content']['text']);
$this->assertEquals(4, count($data['data']['photo']));
$this->assertEquals('https://pbs.twimg.com/media/DWZ-5UPVAAAQOWY.jpg', $data['data']['photo'][0]);
$this->assertEquals('https://pbs.twimg.com/media/DWaAhZ2UQAAIEoS.jpg', $data['data']['photo'][3]);
}
public function testStreamingTweetTruncatedWithVideo() {
list($url, $json) = $this->loadTweet('streaming-tweet-truncated-with-video');
$data = $this->parse(['url' => $url, 'body' => $json]);
$this->assertEquals("hi @aaronpk Ends was a great job I was just talking to her about the house I think she is just talking to you about that stuff like that you don't have any idea of how to make to your job so you don't want me going back on your own to make it happen", $data['data']['content']['text']);
$this->assertEquals(1, count($data['data']['video']));
$this->assertEquals('https://video.twimg.com/ext_tw_video/965608338917548032/pu/vid/720x720/kreAfCMf-B1dLqBH.mp4', $data['data']['video'][0]);
}
public function testTweetWithNewlines() {
list($url, $json) = $this->loadTweet('tweet-with-newlines');
$data = $this->parse(['url' => $url, 'body' => $json]);
$this->assertEquals(4, substr_count($data['data']['content']['text'], "\n"));
$this->assertEquals(4, substr_count($data['data']['content']['html'], "<br>\n"));
$this->assertEquals("🌈🌈 I’ve watched the sun rise at Corona Heights countless times, but never before have I seen a #rainbow at #sunrise.
class TwitterTest extends PHPUnit\Framework\TestCase
{
public function setUp(): void
{
$this->client = new Parse();
$this->client->mc = null;
}
private function parse($params)
{
$request = new Request($params);
$response = new Response();
$result = $this->client->parse($request, $response);
$body = $result->getContent();
$this->assertEquals(200, $result->getStatusCode());
return json_decode($body, true);
}
private function loadTweet($id)
{
$url = 'https://twitter.com/_/status/'.$id;
$json = file_get_contents(dirname(__FILE__).'/data/api.twitter.com/'.$id.'.json');
$parsed = json_decode($json);
$url = 'https://twitter.com/'.$parsed->user->screen_name.'/status/'.$id;
return [$url, $json];
}
public function testBasicProfileInfo()
{
list($url, $json) = $this->loadTweet('818912506496229376');
$data = $this->parse(['url' => $url, 'body' => $json]);
$this->assertEquals('twitter', $data['source-format']);
$this->assertEquals('entry', $data['data']['type']);
$this->assertEquals('aaronpk dev', $data['data']['author']['name']);
$this->assertEquals('pkdev', $data['data']['author']['nickname']);
$this->assertEquals('https://twitter.com/pkdev', $data['data']['author']['url']);
$this->assertEquals('Portland, OR', $data['data']['author']['location']);
$this->assertEquals('Dev account for testing Twitter things. Follow me here: https://twitter.com/aaronpk', $data['data']['author']['bio']);
$this->assertEquals('https://pbs.twimg.com/profile_images/638125135904436224/qd_d94Qn_normal.jpg', $data['data']['author']['photo']);
}
public function testProfileWithNonExpandedURL()
{
list($url, $json) = $this->loadTweet('791704641046052864');
$data = $this->parse(['url' => $url, 'body' => $json]);
$this->assertEquals('https://twitter.com/agiletortoise', $data['data']['author']['url']);
}
public function testBasicTestStuff()
{
list($url, $json) = $this->loadTweet('818913630569664512');
$data = $this->parse(['url' => $url, 'body' => $json]);
$this->assertEquals(null, $data['code']); // no code is expected if we pass in the body
$this->assertEquals('twitter', $data['source-format']);
$this->assertEquals('https://twitter.com/pkdev/status/818913630569664512', $data['url']);
$this->assertEquals('entry', $data['data']['type']);
$this->assertEquals('note', $data['data']['post-type']);
$this->assertEquals('A tweet with a URL https://indieweb.org/ #and #some #hashtags', $data['data']['content']['text']);
$this->assertContains('and', $data['data']['category']);
$this->assertContains('some', $data['data']['category']);
$this->assertContains('hashtags', $data['data']['category']);
// Published date should be set to the timezone of the user
$this->assertEquals('2017-01-10T12:13:18-08:00', $data['data']['published']);
}
public function testPositiveTimezone()
{
list($url, $json) = $this->loadTweet('719914707566649344');
$data = $this->parse(['url' => $url, 'body' => $json]);
$this->assertEquals("2016-04-12T16:46:56+01:00", $data['data']['published']);
}
public function testTweetWithEmoji()
{
list($url, $json) = $this->loadTweet('818943244553699328');
$data = $this->parse(['url' => $url, 'body' => $json]);
$this->assertEquals('twitter', $data['source-format']);
$this->assertEquals('entry', $data['data']['type']);
$this->assertEquals('Here 🎉 have an emoji', $data['data']['content']['text']);
}
public function testHTMLEscaping()
{
list($url, $json) = $this->loadTweet('818928092383166465');
$data = $this->parse(['url' => $url, 'body' => $json]);
$this->assertEquals('entry', $data['data']['type']);
$this->assertEquals('Double escaping &amp; & amp', $data['data']['content']['text']);
}
public function testTweetWithPhoto()
{
list($url, $json) = $this->loadTweet('818912506496229376');
$data = $this->parse(['url' => $url, 'body' => $json]);
$this->assertEquals('entry', $data['data']['type']);
$this->assertEquals('photo', $data['data']['post-type']);
$this->assertEquals('Tweet with a photo and a location', $data['data']['content']['text']);
$this->assertEquals('https://pbs.twimg.com/media/C11cfRJUoAI26h9.jpg', $data['data']['photo'][0]);
}
public function testTweetWithTwoPhotos()
{
list($url, $json) = $this->loadTweet('818935308813103104');
$data = $this->parse(['url' => $url, 'body' => $json]);
$this->assertEquals('entry', $data['data']['type']);
$this->assertEquals('photo', $data['data']['post-type']);
$this->assertEquals('Two photos', $data['data']['content']['text']);
$this->assertContains('https://pbs.twimg.com/media/C11xS1wUcAAeaKF.jpg', $data['data']['photo']);
$this->assertContains('https://pbs.twimg.com/media/C11wtndUoAE1WfE.jpg', $data['data']['photo']);
}
public function testTweetWithVideo()
{
list($url, $json) = $this->loadTweet('818913178260160512');
$data = $this->parse(['url' => $url, 'body' => $json]);
$this->assertEquals('entry', $data['data']['type']);
$this->assertEquals('video', $data['data']['post-type']);
$this->assertEquals('Tweet with a video', $data['data']['content']['text']);
$this->assertEquals('https://pbs.twimg.com/ext_tw_video_thumb/818913089248595970/pr/img/qVoEjF03Y41SKpNt.jpg', $data['data']['photo'][0]);
$this->assertEquals('https://video.twimg.com/ext_tw_video/818913089248595970/pr/vid/1280x720/qP-sDx-Q0Hs-ckVv.mp4', $data['data']['video'][0]);
}
public function testTweetWithGif()
{
list($url, $json) = $this->loadTweet('tweet-with-gif');
$data = $this->parse(['url' => $url, 'body' => $json]);
$this->assertEquals('entry', $data['data']['type']);
$this->assertEquals('reply', $data['data']['post-type']);
$this->assertEquals('https://twitter.com/SwiftOnSecurity/status/1018178408398966784', $data['data']['in-reply-to'][0]);
$this->assertEquals('Look! A distraction 🐁', $data['data']['content']['text']);
$this->assertEquals('https://video.twimg.com/tweet_video/DiFOUuYV4AAUsgL.mp4', $data['data']['video'][0]);
$this->assertEquals('https://pbs.twimg.com/tweet_video_thumb/DiFOUuYV4AAUsgL.jpg', $data['data']['photo'][0]);
}
public function testTweetWithLocation()
{
list($url, $json) = $this->loadTweet('818912506496229376');
$data = $this->parse(['url' => $url, 'body' => $json]);
$this->assertEquals('entry', $data['data']['type']);
$this->assertEquals('Tweet with a photo and a location', $data['data']['content']['text']);
$this->assertEquals('https://api.twitter.com/1.1/geo/id/ac88a4f17a51c7fc.json', $data['data']['location']);
$location = $data['data']['refs']['https://api.twitter.com/1.1/geo/id/ac88a4f17a51c7fc.json'];
$this->assertEquals('adr', $location['type']);
$this->assertEquals('Portland', $location['locality']);
$this->assertEquals('United States', $location['country-name']);
$this->assertEquals('Portland, OR', $location['name']);
}
public function testRetweet()
{
list($url, $json) = $this->loadTweet('818913351623245824');
$data = $this->parse(['url' => $url, 'body' => $json]);
$this->assertEquals('twitter', $data['source-format']);
$this->assertEquals('entry', $data['data']['type']);
$this->assertEquals('repost', $data['data']['post-type']);
$this->assertArrayNotHasKey('content', $data['data']);
$repostOf = 'https://twitter.com/aaronpk/status/817414679131660288';
$this->assertEquals($repostOf, $data['data']['repost-of']);
$tweet = $data['data']['refs'][$repostOf];
$this->assertEquals('Yeah that\'s me http://xkcd.com/1782/', $tweet['content']['text']);
}
public function testRetweetWithPhoto()
{
list($url, $json) = $this->loadTweet('820039442773798912');
$data = $this->parse(['url' => $url, 'body' => $json]);
$this->assertEquals('entry', $data['data']['type']);
$this->assertEquals('repost', $data['data']['post-type']);
$this->assertArrayNotHasKey('content', $data['data']);
$this->assertArrayNotHasKey('photo', $data['data']);
$repostOf = 'https://twitter.com/phlaimeaux/status/819943954724556800';
$this->assertEquals($repostOf, $data['data']['repost-of']);
$tweet = $data['data']['refs'][$repostOf];
$this->assertEquals('this headline is such a rollercoaster', $tweet['content']['text']);
}
public function testQuotedTweet()
{
list($url, $json) = $this->loadTweet('818913488609251331');
$data = $this->parse(['url' => $url, 'body' => $json]);
$this->assertEquals('entry', $data['data']['type']);
$this->assertEquals('note', $data['data']['post-type']);
$this->assertEquals('Quoted tweet with a #hashtag https://twitter.com/aaronpk/status/817414679131660288', $data['data']['content']['text']);
$this->assertEquals('https://twitter.com/aaronpk/status/817414679131660288', $data['data']['quotation-of']);
$tweet = $data['data']['refs']['https://twitter.com/aaronpk/status/817414679131660288'];
$this->assertEquals('Yeah that\'s me http://xkcd.com/1782/', $tweet['content']['text']);
}
public function testTruncatedQuotedTweet()
{
list($url, $json) = $this->loadTweet('tweet-with-truncated-quoted-tweet');
$data = $this->parse(['url' => $url, 'body' => $json]);
$this->assertEquals('entry', $data['data']['type']);
$this->assertEquals('.@stream_pdx is a real treasure of our city.', $data['data']['content']['text']);
$this->assertEquals('https://twitter.com/PDXStephenG/status/964598574322339841', $data['data']['quotation-of']);
$tweet = $data['data']['refs']['https://twitter.com/PDXStephenG/status/964598574322339841'];
$this->assertEquals('Hey @OregonGovBrown @tedwheeler day 16 of #BHM is for @stream_pdx. An amazing podcast trailer run by @tyeshasnow helping to democratize story telling in #PDX. Folks can get training in the production of podcasts. @siliconflorist #SupportBlackBusiness', $tweet['content']['text']);
$this->assertEquals("Hey <a href=\"https://twitter.com/OregonGovBrown\">@OregonGovBrown</a> <a href=\"https://twitter.com/tedwheeler\">@tedwheeler</a> day 16 of #BHM is for <a href=\"https://twitter.com/stream_pdx\">@stream_pdx</a>. An amazing podcast trailer run by <a href=\"https://twitter.com/tyeshasnow\">@tyeshasnow</a> helping to democratize story telling in #PDX. Folks can get training in the production of podcasts. <a href=\"https://twitter.com/siliconflorist\">@siliconflorist</a> #SupportBlackBusiness", $tweet['content']['html']);
}
public function testTweetWithHTML()
{
list($url, $json) = $this->loadTweet('tweet-with-html');
$data = $this->parse(['url' => $url, 'body' => $json]);
$this->assertStringContainsString('<script>', $data['data']['content']['text']);
$this->assertStringContainsString('&lt;script&gt;', $data['data']['content']['html']);
}
public function testStreamingTweetWithLink()
{
list($url, $json) = $this->loadTweet('streaming-tweet-with-link');
$data = $this->parse(['url' => $url, 'body' => $json]);
$this->assertEquals('twitter', $data['source-format']);
$this->assertEquals('what happens if i include a link like https://kmikeym.com', $data['data']['content']['text']);
$this->assertEquals('what happens if i include a link like <a href="https://kmikeym.com">https://kmikeym.com</a>', $data['data']['content']['html']);
}
public function testStreamingTweetWithMentions()
{
list($url, $json) = $this->loadTweet('streaming-tweet-with-mentions');
$data = $this->parse(['url' => $url, 'body' => $json]);
$this->assertEquals('Offer accepted! @aaronpk bought 1 shares from @coledrobison at $6.73 https://kmikeym.com/trades', $data['data']['content']['text']);
$this->assertEquals('Offer accepted! <a href="https://twitter.com/aaronpk">@aaronpk</a> bought 1 shares from <a href="https://twitter.com/coledrobison">@coledrobison</a> at $6.73 <a href="https://kmikeym.com/trades">https://kmikeym.com/trades</a>', $data['data']['content']['html']);
}
public function testStreamingTweetTruncated()
{
list($url, $json) = $this->loadTweet('streaming-tweet-truncated');
$data = $this->parse(['url' => $url, 'body' => $json]);
$this->assertEquals("#indieweb community. Really would like to see a Micropub client for Gratitude logging and also a Mastodon poster similar to the twitter one.\nFeel like I could (maybe) rewrite previous open code to do some of this :)", $data['data']['content']['text']);
$this->assertEquals(
'#indieweb community. Really would like to see a Micropub client for Gratitude logging and also a Mastodon poster similar to the twitter one.<br>
Feel like I could (maybe) rewrite previous open code to do some of this :)', $data['data']['content']['html']
);
}
public function testStreamingTweetTruncatedWithPhoto()
{
list($url, $json) = $this->loadTweet('streaming-tweet-truncated-with-photo');
$data = $this->parse(['url' => $url, 'body' => $json]);
$this->assertEquals("#MicrosoftFlow ninja-tip.\nI'm getting better at custom-connector and auth. Thanks @skillriver \nThis is OAuth2 with MSA/Live (not AzureAD) which I need to do MVP timesheets.\nStill dislike Swagger so I don't know why I bother with this. I'm just that lazy doing this manually", $data['data']['content']['text']);
$this->assertEquals(4, count($data['data']['photo']));
$this->assertEquals('https://pbs.twimg.com/media/DWZ-5UPVAAAQOWY.jpg', $data['data']['photo'][0]);
$this->assertEquals('https://pbs.twimg.com/media/DWaAhZ2UQAAIEoS.jpg', $data['data']['photo'][3]);
}
public function testStreamingTweetTruncatedWithVideo()
{
list($url, $json) = $this->loadTweet('streaming-tweet-truncated-with-video');
$data = $this->parse(['url' => $url, 'body' => $json]);
$this->assertEquals("hi @aaronpk Ends was a great job I was just talking to her about the house I think she is just talking to you about that stuff like that you don't have any idea of how to make to your job so you don't want me going back on your own to make it happen", $data['data']['content']['text']);
$this->assertEquals(1, count($data['data']['video']));
$this->assertEquals('https://video.twimg.com/ext_tw_video/965608338917548032/pu/vid/720x720/kreAfCMf-B1dLqBH.mp4', $data['data']['video'][0]);
}
public function testTweetWithNewlines()
{
list($url, $json) = $this->loadTweet('tweet-with-newlines');
$data = $this->parse(['url' => $url, 'body' => $json]);
$this->assertEquals(4, substr_count($data['data']['content']['text'], "\n"));
$this->assertEquals(4, substr_count($data['data']['content']['html'], "<br>\n"));
$this->assertEquals(
"🌈🌈 I’ve watched the sun rise at Corona Heights countless times, but never before have I seen a #rainbow at #sunrise.
#CoronaHeights #SanFrancisco #SF #wakeupthesun #fromwhereirun #nofilter
Woke up this morning feeling compelled to run to Corona… http://tantek.com/2018/049/t3/rainbow-at-sunrise", $data['data']['content']['text']);
}
Woke up this morning feeling compelled to run to Corona… http://tantek.com/2018/049/t3/rainbow-at-sunrise", $data['data']['content']['text']
);
}
public function testStreamingTweetReply() {
list($url, $json) = $this->loadTweet('streaming-tweet-reply');
$data = $this->parse(['url' => $url, 'body' => $json]);
public function testStreamingTweetReply()
{
list($url, $json) = $this->loadTweet('streaming-tweet-reply');
$data = $this->parse(['url' => $url, 'body' => $json]);
$this->assertEquals('twitter', $data['source-format']);
$this->assertEquals('https://twitter.com/anomalily/status/967024586423386112', $data['data']['in-reply-to'][0]);
}
$this->assertEquals('twitter', $data['source-format']);
$this->assertEquals('https://twitter.com/anomalily/status/967024586423386112', $data['data']['in-reply-to'][0]);
}
public function testTweetReply() {
list($url, $json) = $this->loadTweet('967046438822674432');
$data = $this->parse(['url' => $url, 'body' => $json]);
public function testTweetReply()
{
list($url, $json) = $this->loadTweet('967046438822674432');
$data = $this->parse(['url' => $url, 'body' => $json]);
$this->assertEquals('twitter', $data['source-format']);
$this->assertEquals('https://twitter.com/anomalily/status/967024586423386112', $data['data']['in-reply-to'][0]);
}
$this->assertEquals('twitter', $data['source-format']);
$this->assertEquals('https://twitter.com/anomalily/status/967024586423386112', $data['data']['in-reply-to'][0]);
}
}

+ 8
- 4
tests/bootstrap.php View File

@ -4,10 +4,14 @@ require __DIR__ . '/../vendor/autoload.php';
// Load config file if present, otherwise use default
if(file_exists(dirname(__FILE__).'/../config.php')) {
require dirname(__FILE__).'/../config.php';
include dirname(__FILE__).'/../config.php';
} else {
class Config {
public static $cache = false;
}
class Config
{
public static $cache = false;
public static $base = '';
public static $admins = [];
}
}

Loading…
Cancel
Save